iOS集成微信支付的坑,让人摸不透的sign


集成iOS微信支付时遇到一个坑,记录一下。

由于公司业务需求,需要在现有App中添加微信支付功能。于是就开始集成微信的支付功能,先看了一遍官方的文档。然后当然是看官方提供的Demo工程了,于是就下了官方提供的示例工程:(https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=11_1下的https://pay.weixin.qq.com/wiki/doc/api/download/SDKSample_ios9_v2.0.2_V3_pay.zip)。下载下来,看了一下,果然简单,发现,支付最终是调用了WXApiRequestHandler中的这个方法

+ (NSString *)jumpToBizPay {

    //============================================================
    // V3&V4支付流程实现
    // 注意:参数配置请查看服务器端Demo
    // 更新时间:2015年11月20日
    //============================================================
    NSString *urlString   = @"http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php?plat=ios";
        //解析服务端返回json数据
        NSError *error;
        //加载一个NSURL对象
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
        //将请求的url数据放到NSData对象中
        NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
        if ( response != nil) {
            NSMutableDictionary *dict = NULL;
            //IOS5自带解析类NSJSONSerialization从response中解析出数据放到字典中
            dict = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];
            
            NSLog(@"url:%@",urlString);
            if(dict != nil){
                NSMutableString *retcode = [dict objectForKey:@"retcode"];
                if (retcode.intValue == 0){
                    NSMutableString *stamp  = [dict objectForKey:@"timestamp"];
                    
                    //调起微信支付
                    PayReq* req             = [[[PayReq alloc] init]autorelease];
                    req.partnerId           = [dict objectForKey:@"partnerid"];
                    req.prepayId            = [dict objectForKey:@"prepayid"];
                    req.nonceStr            = [dict objectForKey:@"noncestr"];
                    req.timeStamp           = stamp.intValue;
                    req.package             = [dict objectForKey:@"package"];
                    req.sign                = [dict objectForKey:@"sign"];
                    [WXApi sendReq:req];
                    //日志输出
                    NSLog(@"appid=%@\npartid=%@\nprepayid=%@\nnoncestr=%@\ntimestamp=%ld\npackage=%@\nsign=%@",[dict objectForKey:@"appid"],req.partnerId,req.prepayId,req.nonceStr,(long)req.timeStamp,req.package,req.sign );
                    return @"";
                }else{
                    return [dict objectForKey:@"retmsg"];
                }
            }else{
                return @"服务器返回错误,未获取到json对象";
            }
        }else{
            return @"服务器返回错误";
        }
}
最终也就是把服务器传过来的几个参数赋值,调用微信SDK接口就完事了。

于是就立刻跟服务器端同学按照demo的形式开发接口,调试。开始一切都挺顺利,调用服务器端下单接口,服务器下单,将结果订单号等参数返给客户端,都没问题,可是,最后一步,问题来了。而且是很诡异的问题:能调起微信App,但是,,在微信中却没有出现期待中的支付页面,而只是空白的页面中间有一个确定按钮,其他的啥都没有。点击该按钮,就会调回自己的App,返回错误码-2(用户取消的意思)。

相信很多同学也都遇到过类似的问题,可是我是头一次遇到啊。研究了服务器返回的各字段,该有的都有啊,包括sign字段(这个就是微信的坑所在,坑了我好长时间。。。),而且跟Demo中的测试数据格式都一样啊,没问题啊。于是,想尽各种办法,验证是不是少配置了什么东西,是不是哪里参数类型不对,等等。结果都一一排除,百思不得其解。没办法,去网上搜吧,肯定有人遇到过同样的问题。果然,有同学出现过类似问题,说问题所在是sign值生成的有问题。也就是sign生成的不对呗,可是我这里sign是服务器传过来的,于是就逼着服务器端的同学各种检查嘛。包括检查sign值生成算法,中间经历各种曲折,尝试。

最后,终于发现问题所在。不得不吐槽一下,真他妈坑人!!!

问题是这样的:开始的时候,服务器端的同学生成这个sign是用了好多字段,说白了就是他把下单的所有字段都参与了签名;而客户端所需的签名字段只有appId,partnerId,prepayId,nonceStr,timeStamp,package这些字段(注意这些字段名的大小写,这他妈简直就是坑中坑!!!!我哪来的这些字段名?官方文档上说的:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=8_3   步奏3是不是这么写的?)。好么,发现问题了,让服务器端同学改呗,应该没有问题了。可是,还是不对!!!这时候我已经快疯了,把微信支付SDK的开发者问候了个遍,你们能体会我当时的心情吗,这点代码,不到100行,弄了两天了。

发泄过后,平静下来,生活还是要继续(哈哈,有点装了,就是活还是得干啊)。于是又再次拿出官方的Demo研究,这次果然有了新收获。打印了一下Demo中下单接口返回的数据,跟我们服务的返回结果仔细对比一下,终于发现了问题所在啊。Demo中接口(http://wxpay.weixin.qq.com/pub_v2/app/app_pay.php?plat=ios)返回的数据是这样的

 {
    appid = wxb4ba3c02aa476ea1;
    noncestr = b56a56818039abe71c0d287ea67b19ce;
    package = "Sign=WXPay";
    partnerid = 10000100;
    prepayid = wx20151209170117f46f5ed25f0130700650;
    sign = 09F74D7C3F1BF3C0C329ED3C3EC2AC17;
    timestamp = 1449651677;
}
而我们的是这样的:

{
                appId = wx13******4cde9472;
                nonceStr = 1005d93c01faf80cbc2225c87314c033;
                packageValue = "Sign=WXPay";
                partnerId = 12******01;
                prepayId = wx20151209132826120c234c850066732593;
                sign = F83687699E7293828FE098F6DA2CA1CF;
                timeStamp = 1449638906;
            };

(忽视那些*,为了安全,我后续故意处理的)

发现没有,参数名大小写! 参数名大小写! 参数名大小写! 这XX就是关键所在啊!!!    于是后面的事大家应该都能想到了:让服务器同学全用小写的参数名,重新生成签名;服务器接口更新,客户端访问,解析,调起微信客户端,微信弹出支付页面,支付,完成。


事件就这么过去了,但是经历了这些坑,我不得不发出一些感慨:原来微信有些时候也是靠不住的;在各种抱怨微信SDK文档写的不专业,Demo给的不靠谱后,静下心来想想,发现其实有些时候自己还是太浮躁了,还是不够细心。于是决定写下这篇日志,以帮助其他同样被坑的同学,也提醒自己,记下曾摔的跟头。 编程路漫漫,吾将上下而求索,骚年继续努力吧!


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值