微信支付失败-1彻底扫坑

原创 2016年01月17日 19:40:31

http://bbs.csdn.net/topics/391865275

由于服务器返回的sign 不知道对应的timestamp,所以不能用它的,用本地自己的timestamp等参数生成sign,然后拿着这些参数请求支付接口,就可以了。

另外,注意要是签名包

private void genPayReq(WeChatPayModel weChatPayModel) {

        req.appId = weChatPayModel.getAppid();
        req.partnerId = weChatPayModel.getMchId();
        req.prepayId = weChatPayModel.getPrepayId();
        req.packageValue = "Sign=WXPay";
        req.nonceStr = weChatPayModel.getNonceStr();
        req.timeStamp = String.valueOf(genTimeStamp());
        List<NameValuePair> signParams = new LinkedList<NameValuePair>();
        signParams.add(new BasicNameValuePair("appid", req.appId));
        signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
        signParams.add(new BasicNameValuePair("package", req.packageValue));
        signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
        signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
        signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));

        req.sign = genAppSign(signParams);
    }

    private long genTimeStamp() {
        return System.currentTimeMillis() / 1000;
    }

    private String genAppSign(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < params.size(); i++) {
            sb.append(params.get(i).getName());
            sb.append('=');
            sb.append(params.get(i).getValue());
            sb.append('&');
        }
        sb.append("key=");
        sb.append(PayConfig.WECHAT_API_KEY);

        String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        Log.e("orion", appSign);
        return appSign;
    }


http://www.eoeandroid.com/thread-918154-1-1.html?_dsign=88b40678

由于公司运营需要,Android客户端要增加微信支付。在看了几遍官方文档之后,加上之前有集成微信分享的经验,所以很快就把调用微信支付的代码写好了,待微信支付相关接口完成后联调时,才发现山高路远坑深啊!从下午2点半开始调试,一直折腾到快6点,那个微信支付界面才“千呼万唤始出来”,更坑爹的是,压根儿就不是我客户端的问题,而是后台接口那边sign生成时出了问题。在解决问题的过程中,看到网上太多关于微信支付各种问题的帖子,但遗憾的是并没有找到真正有效的解决方案,所以就来彻底扫一下Android集成微信支付中的坑。

首先讲一下我们的逻辑,如微信支付开发文档(https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=8_5)中Android部分描述的那样,由服务器端请求微信支付平台生成prepayid,大家一般也都是这么做的,发现网上有一部分人从服务器端拿到prepayid后,在客户端自己拼字符串参数,然后调用算法生成sign,这样是可以,但是安全性不好,而且客户端逻辑也变复杂了,估计大家是按照官方demo写的,至于其demo暂时就不评价了,下面会提及。我们的做法是所有的必要参数,如partnerId、prapayId、packageValue、nonceStr、timeStamp、sign等都是由服务器端生成,至于appId自己写在客户端也行,服务器端传过来也行,因为之前微信分享appId是写在客户端了,因此微信支付就没让服务器端返回appId这个参数。其实微信支付官方文档也是这样建议的,原文为“商户服务器生成支付订单,先调用统一下单API(详见第7节)生成预付单,获取到prepay_id后将参数再次签名传输给APP发起支付”。App端拿到上述6个主要参数后,加上appId,一共7个,就可以调起支付了。

如上所述,客户端的逻辑就这么简单,所以当调试时竟然调不出支付界面,真觉得不可思议。我遇到的问题是这样的:当发起支付时调不出微信支付界面,直接响应WXPayEntryActivity中的onResp回调,并且errCode始终返回-1。如果微信未登录,则会调起登陆界面,登陆完成后还是调不起来,errCode依然返回-1。

我们客户端的实现逻辑基本跟官方文档一致(注意官方文档有个书写错误,在调用支付部分代码最后一行的参数中,request写成了req,后面也会提到),主要核心代码如下:

1.首先注册,其中api为IWXAPI的实例

[java] view plaincopy
  1. api = WXAPIFactory.createWXAPI(context, APP_ID, false);  
  2. api.registerApp(APP_ID);  
2.从服务端拿到上述必要参数后,调支付即可,其中params是自定义的用来保存从服务端获取的所有的对象

[java] view plaincopy
  1. if (api != null) {  
  2.     if (isWXAppInstalled()) {  
  3.         PayReq req = new PayReq();  
  4.         req.appId = APP_ID;  
  5.         req.partnerId = params.getPartnerId();  
  6.         req.prepayId = params.getPrepayId();  
  7.         req.packageValue = params.getPackageValue();  
  8.         req.nonceStr = params.getNonceStr();  
  9.         req.timeStamp = params.getTimeStamp();  
  10.         req.sign = params.getSign();  
  11.   
  12.         api.sendReq(req);  
  13.     }  
  14. }  
3.WXPayEntryActivity这个回调界面实际上不会影响前面的调起支付的逻辑,写过微信分享的应该知道,这个Activity一定要放到“App包名.wxapi”的package中,否则无法响应回调,当然别忘了在AndroidManifest.xml中注册。微信分享的回调WXEntryActivity也是这样的,放在同一个包即可。没错,微信就是这么霸道。

Android客户端的核心逻辑就是这些,下面来一一列举微信支付中的坑,或者叫注意点吧,有些是我知道因此没有亲自踩上去的也一并列出。

1.首先如果要使用微信支付的话,必须先到微信开放平台注册应用,具体地址为https://open.weixin.qq.com/,注册时需要填应用的包名和签名,注意这里的签名是App正式版的签名,可以找一个已上线的包或打一个正式包,使用微信提供的工具(签名工具下载地址为https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk)来获取,获取后填上即可。待审核通过后,会得到一个AppID和AppSecret,AppID分享和支付都要用到,AppSecret没什么实际用途,此时微信分享能力是直接拥有的,支付能力还要额外申请,其中涉及到财务信息等,最好让公司财务部门去申请,申请成功后会拿到一个商户id,后面生成sign时会用到。只有所有审核都通过后,才可调用微信支付功能,这点是前提。

2.微信分享和微信支付SDK是同一个架包,名为libammsdk.jar

3.官方开发文档中有一处错误,需要注意下,如下图最后一行参数req应该为request,照搬代码的估计IDE也不会放过你,哈哈。


4.测试微信支付时,务必对自己的App做正式签名,因为一开始就在微信平台注册过签名信息,微信SDK会做校验,只有这样才能调起微信分享和微信支付,直接debug版的包则绝对调不起来,这点务必注意,很多人是跌在这里了!当初做微信分享曾遇到过,所以会很留心,也因为如此,如果微信分享能调起来,微信支付不行,那就不要怀疑签名问题了

5.还是签名,网上有人说要注意大小写,这点其实是不必的。在微信开放平台看到审核通过的App的签名是大写的,而用微信签名获取工具获得的则显示小写,这个没关系,不要贸然改动平台注册信息,不然又可能导致漫长的审核等待,上面也说了,微信分享如可以,那就不是签名问题。

6.来说下官方demo,这东西害人不浅啊!很多人参考其写法,如生成sign放在客户端啊,调支付的Activity添加intent-filter啊,最主要的还是签名问题。其实客户端逻辑很简单,直接上手集成即可,demo看看逻辑就行,照抄小心掉坑里。

7.网上有人说需要给调用支付的Activity配置如下intent-filter(见下图),可能也是被demo误导了

[html] view plaincopy
  1. <intent-filter>  
  2.     <action android:name="android.intent.action.VIEW"/>  
  3.     <category android:name="android.intent.category.DEFAULT"/>  
  4.     <data android:scheme="appid"/>  
  5. </intent-filter>  

逻辑上来看,根本不会跳这个界面啊,所以当然是非必需的

8.对于errCode返回-1,有人说清除微信缓存或切换账户就好了,这种解决方案治标不治本啊,根本不能算解决方案。虽然我没遇到能用这方法解决的问题,但目测是签名的问题,建议还得找到真正的问题所在。

9.生成sign时特别需要注意,首先将key-value键值对拼成字符串,注意key都要小写,如appid,noncestr,package,partnerid,prepayid,timestamp,key,并且名字得按上述名称,我们遇到的错误就是因为partnerid写成了partnerId,prepayid写成了PrepayId,当然我们是在服务端写的,如果在客户端生成sign的话,也需要注意大小写及名称,详细信息请参考官方文档。还有这里的key并非AppID或AppSectet,而是在商户平台设置的,官方描述为“key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置”。对于noncestr,申请prepayid和生成sign时两次需要用到,由于iOS同事看到相关文章说noncestr前后需要一致,因此这个随机字符串我们是设置成一样的了,这样做Android平台也是OK的,不过个人感觉这里可以不一致,由于这个逻辑在服务器端,我并没有验证,方便的同学可以验证下。

10.req.packageValue=”Sign=WXPay”,一般都是这样写死这个参数值。也有人说写成req.packageValue=”prepay_id=” + prepayid,经测试Android两种写法都是可以调起微信支付的,至少最新版本SDK是可以的,以后则不清楚,官方也建议写Sign=WXPay,据说iOS只支持这种写法。

11.对于IWXAPI实例的创建,官方代码为: IWXAPI api = WXAPIFactory.createWXAPI(context, null);这样写就可以,如果调用另一个工厂方法:IWXAPI api = WXAPIFactory.createWXAPI(context, APP_ID, false);也是OK的,我都测试过,总之这里不是问题的根源。

不得不再次吐槽一下Android微信支付,支付宝之类的支付集成是很简单的,微信支付却花了几个小时才搞定,上面罗列了一系列注意事项,都是前人踩过的坑,希望大家看到这篇文章后,可以用20分钟搞定微信支付,如果还有问题,欢迎回复探讨。



版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/nnmmbb/article/details/50533138

Android实现微信支付和踩过的深坑

微信支付,errCode = -1 的错误,解决办法,出现微信支付成功但是未回调。
  • qilin001cs
  • qilin001cs
  • 2017-07-23 15:10:21
  • 1846

android微信支付问题总结

Android快速实现微信支付 onPayFinish, errCode = -1  当你参数签名都没有问题的时候,出现这个提示,请按照如下操作: 在你的项目测试微信的组件(分享、支付等)的时候,...
  • jdsjlzx
  • jdsjlzx
  • 2015-08-11 16:26:49
  • 72072

Android微信支付的errCode=-1

关于Android微信支付的errCode=-1项目中有用到微信支付,之前不是我负责开发的,来这也没测过,昨天在测支付宝支付的问题,修复好之后顺便试了一下微信支付,神马情况,errCode=-1,微信...
  • reticent1
  • reticent1
  • 2016-08-05 09:22:37
  • 988

Android 微信支付快速集成案例及有效解决返回值-1

商户在微信开放平台申请开发应用后,微信开放平台会生成APP的唯一标识APPID。由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付。本文讲解Android微信支付...
  • LeoLeoHan
  • LeoLeoHan
  • 2015-09-01 15:15:29
  • 12833

Android集成微信支付的出现-1等错误需要注意的要点

一.前言1. 微信支付和支付宝支付是现在APP常用的支付方式,但是真正接入过两种支付方式的猿友会很明显的感觉到微信支付真心比支付宝麻烦很多,会出现很多莫名其妙的错误,但是官方的文档却很难给出较好的解决...
  • yili270
  • yili270
  • 2016-07-09 22:16:55
  • 1643

微信支付的坑 返回值 -1

最近在用android接入微信支付。。
  • zlj_fly
  • zlj_fly
  • 2014-11-04 18:12:58
  • 42706

如何集成android微信支付及各种问题(-1,签名错误,无法获得预支付id)的解决办法。

集成微信支付遇到的各种问题
  • gaoqingliang521
  • gaoqingliang521
  • 2017-05-31 16:12:31
  • 3283

android微信支付详解与坑

要想在自己的APP中实现APP支付必须申请开通支付功能,这些按着文档来吧,我还是直接说android中的问题吧。一、签名一定要在开放平台为自己的APP配置正确的包名和签名(签名:将APP打一个正式环境...
  • hello_1s
  • hello_1s
  • 2016-09-23 11:39:14
  • 10699

微信支付遇到的坑

1.首先,根据开发文档,申请APP_ID(至于怎么获得签名,这个下个签名工具就可以了) 获得了APP_ID之后,支付和分享都需要用到。此时分享就可以直接使用了。但是支付还需要申请。(如果此时微信分享不...
  • u012975370
  • u012975370
  • 2016-03-24 14:13:39
  • 2355

微信支付(不得不吐槽腾讯这个坑货)

谨以此文献给苦苦挣扎在微信支付给我们挖的坑中的程序猿和媛们,百度了很久很久,网络上也没有一个成功的微信支付demo,既然我做成了,本着跟大伙分享的原则,特此奉献出我开发过程中遇到的问题,这是本人亲测的...
  • baidu_17508977
  • baidu_17508977
  • 2015-03-21 17:36:48
  • 17941
收藏助手
不良信息举报
您举报文章:微信支付失败-1彻底扫坑
举报原因:
原因补充:

(最多只允许输入30个字)