支付宝APP接入的那些坑们

APP相比较于WAP和WEB,最大的区别就是没有服务端的同步回应了,因为是在APP上付的,所有同步回应是在APP上的客户端的,这样就意味着不能在本机做测试,只有部署在线上的服务才行(WEB方式的话同步的return是通过浏览器的redirect实现的,于是可以写自己的本机IP,浏览器跳转就是我本地的服务了,这样测试起来很简单)。那格式什么的我就只能参考文档了。文档上是这么写的。

http://notify.java.jpxx.org/index.jsp?discount=0.00&payment_type=1&subject=测试&trade_no=2013082244524842&buyer_email=dlwdgl@gmail.com&gmt_create=2013-08-22 14:45:23¬ify_type=trade_status_sync&quantity=1&out_trade_no=082215222612710&seller_id=2088501624816263¬ify_time=2013-08-22 14:45:24&body=测试测试&trade_status=TRADE_SUCCESS&is_total_fee_adjust=N&total_fee=1.00&gmt_payment=2013-08-22 14:45:24&seller_email=xxx@alipay.com&price=1.00&buyer_id=2088602315385429¬ify_id=64ce1b6ab92d00ede0ee56ade98fdf2f4c&use_coupon=N&sign_type=RSA&sign=1glihU9DPWee+UJ82u3+mw3Bdnr9u01at0M/xJnPsGuHh+JA5bk3zbWaoWhU6GmLab3dIM4JNdktTcEUI9/FBGhgfLO39BKX/eBCFQ3bXAmIZn4l26fiwoO613BptT44GTEtnPiQ6+tnLsGlVSrFZaLB9FVhrGfipH2SWJcnwYs=

URL参数,恩。POST请求,恩。等等,sign里面有+号!!+号!! 没有URL Encode!! 我一边咒骂支付宝傻逼,一边写把等号替换为+的代码... ...然后去上线运行打log的时候我发现...次奥 有Encode的呀.... ....有Encode的呀... ...你这和文档不一样啊。。。文档明明这么写的啊。。。

突然觉得自己傻逼了.... ....而且我感觉这个放在URL参数里导致文档和实际不一样,那干脆不如放在requestBody里好了,避免框架自己做encode decode,多方便...

移动端行为不一致

后来我觉得用异步不是很靠谱,于是让移动端把同步回应的结果也发过来,因为我看到文档上是这么写的:

ResultStatus={9000};memo={};result={partner="2088101568358171"&seller_id="xxx@alipay.com"&out_trade_no="0819145412-6177"&subject="测试"&body="测试测试"&total_fee="0.01"¬ify_url="http://notify.msp.hk/notify.htm"&service="mobile.securitypay.pay"&payment_type="1"&_input_charset="utf-8"&it_b_pay="30m"&success="true"&sign_type="RSA"&sign="hkFZr+zE9499nuqDNLZEF7W75RFFPsly876QuRSeN8WMaUgcdR00IKy5ZyBJ4eldhoJ/2zghqrD4E2G2mNjs3aE+HCLiBXrPDNdLKCZgSOIqmv46TfPTEqopYfhs+o5fZzXxt34fwdrzN4mX6S13cr3UwmEV4L3Ffir/02RBVtU="}

(iOS和android类似所以贴一份)

那个result里面包含的信息也可以给服务端进行验签、更新表单等操作。

然后我后端实现好了,让安卓和iOS传回来,安卓一切正常,iOS验签死活通不过,我就让iOS把他在console里打印出来的内容给我,我自己调试。发现还是不行,我就怀疑是不是支付宝返回来的东西本身就是验签验不过的啊... ...然后和iOS的同事调试了好久... ...最后一个一个字符和安卓的回应比较过去.... ....发现

notify_time=2015-10-19+16:01:20

这个时间中间为毛是个+,自己手动改成空格之后就过了......是个+号,说明空格被encode了...但这是他console打出来和watch的时候就有的... ...我不知道是支付宝那边弄的,还是xcode的问题,因为安卓是好的... ...iOS这边的空格被encode了.... ....

以为这么就好了嘛?? 安卓试了有支付宝和没支付宝APP的情况,返回内容都是一样的。很好,测试通过。

然后iOS....在没有支付宝APP的情况,使用支付宝SDK内嵌的支付的情况...上面的返回数据result是空的!!只有格ResultStatus。让iOS反复检查,后来在网上找了下发现 http://blog.sina.com.cn/s/blog_702e40a80101knln.html,

我的妈阿,对返回值作了改变,为啥文档又没说明,让我等苦逼的程序猿白白折磨了一两天,情何以堪呢。客气的将我的想法提了给支付宝的技术支持,回复说:不要太相信demo。

还是一样的问题,文档没说!

文档坑爹,demo坑爹,剩下的就是自己debug,看日志,做处理了。

哎,写文档什么的还是得走心啊。

如果直接使用ios客户端签名无任何问题,可以直接支付,但是如果将需要签名的字符串通过接口请求传给java签名就会出一个问题,请求服务端签名时,我们可以直接将客户端的order转换成字符串传过去,这样在服务端就只需要调用一个签名方法即可,下面我来说下报的这个错-->ALI40247,网上找了关于这个错的原因, 对比了发现并不是这些原因导致的,之后发现是-->java的签名与objective-c的签名结果不一样,都是使用的相同的加密串官方demo签名方法,为什么出现签名不一样,最后发现虽然oc和java的签名结果不一样,但是有一个规律-->java中签名的"/"符号在oc签名中是用"%"号代替,然后java的rsa签名结果都有一个"=",但是在ios中这个"="等于 "%3D",开始我说了直接用ios 客户端签名是可以直接支付的,那么只要java返回的签名与ios一样就行了,虽然他们签名结果不一样,但是现在发现一个固定的规律,所以只需要将java服务端返回的签名中的特殊符号替换成ios签名中的特殊符号就行了

推荐阅读更多精彩内容