前几天,公司想要集成第三方支付,花一会儿时间搞定了支付宝,然后开始搞微信,本来还以为会和支付宝一样,谁知道一搞就是2天,坑好多,这里必须记录下,避免忘记,要入坑的同志也可以借鉴下,说不定有帮助呢
首先声明我是使用最新的微信开发包进行的开发,这个版本与之前的不同,和支付宝类似,加密数据的功能转移到了服务器,本地app其实就是根管道,不做任何加解密,只是把服务器生成的加密数据传给sdk调起微信支付而已,虽然这样很安全(不暴露私钥及加密方式,关键是私钥),但还是很不爽嘛。这么做客户端的工作量其实就很小了,而且还有demo,研究了一下,发现此物略坑,第一次跑起来发现好像蛮简单的样子,然后照搬了demo代码,发现怎么跑不通,再试了下demo,出现
第一个坑,demo竟然调了一次再也调不通了!!!作为一个demo,你居然还是一次性的,网上有各种清缓存啥的,但是我用的是自己的微信,不敢轻举妄动。没办法只能自己断点调试demo了。
然后发现
第二个坑,微信的错误码就那么3个,这是有多偷懒,一个正常,一个用户自己取消操作,最后那个就是出现异常,你出现个异常还不告诉我为什么,你让我自己猜啊,而且关于结果返回微信和支付宝不同,支付宝是直接返回结果,微信走的是自己的统一风格(和分享一样),必须得在应用包名下建个wxapi文件夹,然后再里面塞个名字叫WXPayEntryActivity的类并实现IWXAPIEventHandler接口,可以从demo里拷,记得这个activity要注册一下,
友情提醒:别只复制黏贴,记得改appid
<activity这么搞肯定没错,结果就返回在这个接口的回调方法中,虽然比较奇葩(让我跳来跳去,写个业务代码我容易嘛我,而且回调的类竟然必须是activity),但也可以接受。
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="请填写自己应用的微信appid" />
<!--与appid相同-->
</intent-filter>
</activity>
但返回的结果只有一个错误码,我只知道出现异常,没有任何其他信息,这是碰到
最大的坑,也是觉得微信支付难调的主因,既然微信不给力了只能靠自己了,先自己查看demo,发现它的加密数据是从php的接口里拿的,json格式的,但我这里的json是和后台订的,那只有内容一样就好,json的key值不重要,只要把对应的值塞进PayReq对象给微信支付就好了。这里说下这几个字段的含义(前面的req是new出来的PayReq的对象):
req.appId当前app在微信支付中的appid,这个写死或从服务器拿都一样
req.partnerId商户id,就是收款方通常是你公司的微信号的商户id
req.prepayId预付订单id,这个是服务端用微信提供的接口生成订单的id
req.nonceStr这个是加密字符串,服务端生成咋们不管
req.timeStamp这个是服务端时间戳,精确到秒,demo的就是,别拿自己客户端的了
req.packageValue这个是固定值,Sign=WXPay,反正从服务端拿都没错
req.sign 服务端加过密之后的签名
req.extData这个是扩展字段,用来方便客户端传值的,毕竟获取结果要跳到其他类,和支付流程没关系不给无所谓
其实客户端的东西就这么点,基本都不会出错,然后死活调不通,后台出问题的几率就比较高,只能去找后台大哥相亲相爱去了,听后台同志说竟然微信支付木有demo,自己写的,你逗我,这出bug妥妥的嘛,还好后台也是java,咋也能帮得上忙,这里把经验总结下:
1. 后台其实分两步,第一步是生成预付订单,这里微信提供了签名验证工具可以比对签名是否正确,通常这里不容易出错,接口有返回通常就对了,获取到预付订单的id后,进行第二步,生成客户端加密数据,这个是我们最关心的了,这里字段较多容易出现失误,需要仔细比对,还有上面提到的除了extData以外,
从appId开始6个字段都必须包括进签名的内容中去,不然这个sign是没有意义的,除了sign出错,服务器给你的接口数据有没有给错也要检查,这里只需要仔细。
咋的经验就记录到这里,如果同志们有发现其他问题,方便的话也可以告诉我,我记录进去,方便后人