微信支付的那些坑

支付签名验证失败,我弄了2天.

微信支付

其实微信支付的流程相对来说还算比较简单,先接单的介绍一下流程然后再说说可能会出现的问题.还有吐槽一下微信的官方文档都9102年了文档里面的示例还是Xcode7,并且API也变了.

####1.导入微信的SDK
墙裂建议使用pod,在podfile里面添加一下路径,然后pod install 就OK了

1
pod 'WechatOpenSDK'

####2.注册APPID
这个APPID一般是公司负责申请商家的时候会创建对应的APPID格式为”wx一串数字”,安卓跟iOS可以共用一个APPID.
在APPdelegate里面包含一下wxAPI的头文件,然后直接注册一下就行了.关于什么是UNIVERSAL_LINK请移步至

1
2
3
4
5
6
7
8
  #import "WXApi.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
//向微信注册
[WXApi registerApp:APP_ID universalLink:UNIVERSAL_LINK];
return YES;
}

####3.开始支付
下面就要开始支付流程了,首先需要我们根据自己的商品生成对应的订单,这时候自己家的后台会给微信后台完成统一下单的流程(具体不需要我们移动端知道),接下来就会我们自己的后台会把微信后台生成的对应的数据传到我们APP端.

1
2
3
4
5
6
7
8
9
10
11
12
//具体需要的参数有这几个,PayReq这个是微信的类,直接把对应的参数写上就可以了,调一下sendReq这个就可以了,如果参数没有问的话就会打开微信的APP开始正常的支付流程.
PayReq* req = [[PayReq alloc] init];
req.partnerId = wxPay.partnerid;
req.prepayId = wxPay.prepayid;
req.nonceStr = wxPay.nonceStr;
NSInteger timeStamp = [wxPay.timeStamp intValue];
req.timeStamp = (UInt32)timeStamp;
req.package = wxPay.prePayPackage;
req.sign = wxPay.paySign;

[WXApi sendReq:req completion:^(BOOL success) {
}];

接下来重点来了重点就是调起微信之后支付可能会报一些错误,比如: 支付验证签名失败 没错就是这个问题困扰了我两天,下面我们分析一下这个问题的原因:
1.这个签名就是后台传过来的,那么这个签名是怎么生成的呢?
生成的时候有两种方式一种是MD5 另外一种是HMAC-SHA256这个微信文档里面有说明
生成的时候是根据下面这几个参数加上商家的key生成的一共是6个参数

1
2
3
4
5
6
7
8
9
10
/** 商家向财付通申请的商家id */
@property (nonatomic, copy) NSString *partnerId;
/** 预支付订单 */
@property (nonatomic, copy) NSString *prepayId;
/** 随机串,防重发 */
@property (nonatomic, copy) NSString *nonceStr;
/** 时间戳,防重发 */
@property (nonatomic, assign) UInt32 timeStamp;
/** 商家根据财付通文档填写的数据和签名 */
@property (nonatomic, copy) NSString *package;

按理说这个sign的生成跟我们APP没有啥关系我只需要发给微信,微信负责验证一下就完事了,结果问题出就出在这,里面有个参数timeStamp注意一下他的类型UInt32,它能存在的最大的数是2147483647(2的32次方-1),每个公司所用的后台语言不同就会导致这个时间戳的长度不同,如果他生成的是13位的直接传给你的话,你转成UInt32你就会发现你的timeStamp这个参数的值就变成一个固定的了,这样就会导致你的sign给微信的时候验证肯定是不通过的,有小伙伴说了那我直接除个1000不就完事了吗,你大可试试你会发现微信依旧无情的告诉你 支付签名验证失败,为什么呢以为这个sign是根据的参数生成的,后台用的13位的时间戳生成的,所以你验证是不可能通过的,这时候只需要让后台把这个参数除以1000然后再生成sign就解决了,至于我是咋找到这个的说来话长.

####4.支付完成,完成回调处理