在这里简单喷下,其实微信支付,平台上提供的demo挺恶心的,有好多抗
相对于支付宝来说,微信挺麻烦的,特别的是申请的key吧,也让人觉得晕,让我就注册了好几个平台。在这里简单给大家说说
我们的做法是所有的必要参数,如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
- api = WXAPIFactory.createWXAPI(context, APP_ID, false);
- api.registerApp(APP_ID);
2. 从服务端拿到上述必要参数后,调支付即可,其中params是自定义的用来保存从服务端获取的所有的对象
先看下demo里的代码
String url = "http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php?plat=android"; Button payBtn = (Button) findViewById(R.id.appay_btn); payBtn.setEnabled(false); Toast.makeText(PayActivity.this, "获取订单中...", Toast.LENGTH_SHORT).show(); try{ byte[] buf = Util.httpGet(url); if (buf != null && buf.length > 0) { String content = new String(buf); Log.e("get server pay params:",content); JSONObject json = new JSONObject(content); if(null != json && !json.has("retcode") ){ PayReq req = new PayReq(); //req.appId = "wxf8b4f85f3a794e77"; // 测试用appId req.appId = json.getString("appid"); req.partnerId = json.getString("partnerid"); req.prepayId = json.getString("prepayid"); req.nonceStr = json.getString("noncestr"); req.timeStamp = json.getString("timestamp"); req.packageValue = json.getString("package"); req.sign = json.getString("sign"); req.extData = "app data"; // optional Toast.makeText(PayActivity.this, "正常调起支付", Toast.LENGTH_SHORT).show(); // 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信 api.sendReq(req); }else{ Log.d("PAY_GET", "返回错误"+json.getString("retmsg")); Toast.makeText(PayActivity.this, "返回错误"+json.getString("retmsg"), Toast.LENGTH_SHORT).show(); } }else{ Log.d("PAY_GET", "服务器请求错误"); Toast.makeText(PayActivity.this, "服务器请求错误", Toast.LENGTH_SHORT).show(); } }catch(Exception e){ Log.e("PAY_GET", "异常:"+e.getMessage()); Toast.makeText(PayActivity.this, "异常:"+e.getMessage(), Toast.LENGTH_SHORT).show(); } payBtn.setEnabled(true);对于
String url = "http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php?plat=android";
这里需要服务器端返回,看上面的json解析就知道,当然了 demo里面的url返回的是null
在这里appid可以直接写,
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误导了
上面基本上就ok了,如果有什么问题可以相互探讨