iOS开发支付集成之微信支付

作者: Ke_Wang | 来源:发表于2016-02-18 14:02 被阅读40363次

    这一篇是《iOS开发之支付》这一部分的继支付宝支付集成银联支付集成第三篇,微信支付。在集成的时候建议都要去下载最新版的SDK,因为我知道的前不久支付宝,银联都更新了一次,微信的不太清楚更新了没。

    在被支付宝、银联坑过之后,发现其实微信支付的集成并没有想象中的那么困难,像支付宝那样简单地调用个方法就行,重要的难的部分都是后台来做的。微信支付也是需要签名的,也跟支付宝一样,可以在客户端签名,也可以在后台签名(当然,为了安全还是推荐在服务器上做签名,逻辑也比较好理解)。

    集成前首先要看看文档,
    开发文档在这里还有
    APP端开发步骤也是需要好好看看的。

    ps:在微信开发者平台注册APP这样的事一般的是经理给你做好的,这个可以忽略,如果需要做的话,可以参考这篇文章

    交互流程

    这个流程和支付宝的流程都差不多,理解了其实是一样的。

    微信支付流程

    首先需要理清楚流程

    1. 用户使用APP客户端,选择商品下单。
    2. 商户客户端(就是你做的APP)将用户的商品数据传给商户服务器,请求生成支付订单。
    3. 商户后台调用统一下单API向微信的服务器发送请求,微信服务器生成预付单,并生成一个prepay_id返回给商户后台。
    4. 商户后台将这个prepay_id返回给商户客户端。
    5. 用户点击确认支付,这时候商户客户端调用SDK打开微信客户端,进行微信支付。
    6. 微信客户端向微信服务器发起支付请求并返回支付结果(他们之间交互用的就是prepay_id这个参数,微信的服务器要验证微信客户端传过去的参数是否跟第三步中生成的那个id一致)。
    7. 用户输入支付密码后,微信客户端提交支付授权,跟微信服务器交互,完成支付
    8. 微信服务器给微信客户端发送支付结果提示,并异步给商户服务器发送支付结果通知。
    9. 商户客户端通过支付结果回调接口查询支付结果,并向后台检查支付结果是否正确,后台返回支付结果。
    10. 商户客户端显示支付结果,完成订单,发货。

    虽然看起来有点多,但是理解起来并不复杂,跟我们平时手机上买东西是一样的。我们客户端需要做的就是

    • 调起微信客户端发起支付
    • 显示支付结果

    集成过程

    首先是要下载SDK
    微信SDK下载

    建议头文件和示例都下载出来看看。(吐槽下,官方的示例难看死了,看的眼晕!注释都没几个。。。鄙视之)

    导入微信支付SDK库

    导入上面那个iOS头文件和库下载下载出来的SDK包的就行啦,我这里的是SDK1.6.2. 然后需要链接上依赖库,在Target —> BuildPhases —> Link Binary With Libraries— 点击+号 -> 搜索你需要的系统库。

    • SystemConfiguration.framework
    • libz.tbd
    • libsqlite3.0.tbd
    • CoreTelephony.framework
    • QuartzCore.framework
    设置URL Scheme

    在注册微信平台APP的时候,会给一个唯一识别标识符(APPID),在APP端开发步骤里面说得很清楚了,需要填在URL Schemes这个地方,

    URL scheme
    在Appdelegate中注册APPID

    如下:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
        /**
         *  向微信终端注册ID,这里的APPID一般建议写成宏,容易维护。@“测试demo”不需用管。这里的id是假的,需要改这里还有target里面的URL Type
         */
        [WXApi registerApp:@"wxd930ea5d5a258f4f" withDescription:@"测试demo"];
    
        return YES;
    }
    

    处理微信通过URL启动时传递的数据

    //前面的两个方法被iOS9弃用了,如果是Xcode7.2网上的话会出现无法进入进入微信的onResp回调方法,就是这个原因。本来我是不想写着两个旧方法的,但是一看官方的demo上写的这两个,我就也写了。。。。
    
    //9.0前的方法,为了适配低版本 保留
    - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
        return [WXApi handleOpenURL:url delegate:self];
    }
    
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
        return [WXApi handleOpenURL:url delegate:self];
    }
    
    //9.0后的方法
    - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
        //这里判断是否发起的请求为微信支付,如果是的话,用WXApi的方法调起微信客户端的支付页面(://pay 之前的那串字符串就是你的APPID,)
            return  [WXApi handleOpenURL:url delegate:self];
    }
    
    
    //微信SDK自带的方法,处理从微信客户端完成操作后返回程序之后的回调方法,显示支付结果的
    -(void) onResp:(BaseResp*)resp
    {  
        //启动微信支付的response
        NSString *payResoult = [NSString stringWithFormat:@errcode:%d, resp.errCode];
        if([resp isKindOfClass:[PayResp class]]){
            //支付返回结果,实际支付结果需要去微信服务器端查询
            switch (resp.errCode) {
                case 0:
                    payResoult = @支付结果:成功!;
                    break;
                case -1:
                    payResoult = @支付结果:失败!;
                    break;
                case -2:
                    payResoult = @用户已经退出支付!;
                    break;
                default:
                    payResoult = [NSString stringWithFormat:@支付结果:失败!retcode = %d, retstr = %@, resp.errCode,resp.errStr];
                    break;
            }
        }
    }
    
    
    最重要的来了!!

    调用微信支付前,需要下单、签名等操作,以便获取微信支付所必要的参数。为了提高安全性,下单、签名操作一般是在后台完成,在前台做的话被捕获改信息就不开心了。。。。。

    需要的参数包括:appid、partid(商户号)、prepayid(预支付订单ID)、noncestr(参与签名的随机字符串)、timestamp(参与签名的时间戳)、sign(签名字符串)这六个。
    在点击支付的控制器中使用核心代码来调起微信客户端支付,这些个参数都是后台传给你的。 加上了注释,应该很好理解的。

    #pragma mark 微信支付方法
    - (void)WXPay{
    
            //需要创建这个支付对象
            PayReq *req   = [[PayReq alloc] init];
            //由用户微信号和AppID组成的唯一标识,用于校验微信用户
            req.openID = @"";
        
            // 商家id,在注册的时候给的
            req.partnerId = @"";
            
            // 预支付订单这个是后台跟微信服务器交互后,微信服务器传给你们服务器的,你们服务器再传给你
            req.prepayId  = @"";
            
            // 根据财付通文档填写的数据和签名
            //这个比较特殊,是固定的,只能是即req.package = Sign=WXPay
            req.package   = @"";
            
            // 随机编码,为了防止重复的,在后台生成
            req.nonceStr  = @"";
            
            // 这个是时间戳,也是在后台生成的,为了验证支付的
            NSString * stamp = @"";
            req.timeStamp = stamp.intValue;
            
            // 这个签名也是后台做的
            req.sign = @"";
    
            //发送请求到微信,等待微信返回onResp
            [WXApi sendReq:req];
    }
    

    这个JSON里面的数据(上面的参数)就是后台需要传给你的,至于怎么来,也有后台的文档,让他去看下就行啦~~~

    {
      "appid": "wxb4ba3c02aa476ea1",
      "noncestr": "d1e6ecd5993ad2d06a9f50da607c971c",
      "package": "Sign=WXPay",
      "partnerid": "10000100",
      "prepayid": "wx20160218122935e3753eda1f0066087993",
      "timestamp": "1455769775",
      "sign": "F6DEE4ADD82217782919A1696500AF06"
    }
    

    到这里,不出意外的话应该都能正常的支付了。流程最重要,理解了就知道怎么做了,强烈建议需要做的朋友们先理理思路,不要急着下手。


    PS:这篇文章中,签名都是在后台做的,如果需要在你客户端做,可以参考下这篇文章,和这篇文章,他们的签名在客户端做的,写的也比较详细了。

    可能遇到的问题

    1.如果支付完成后,一直留在微信,那就检查下URLType中的Scheme设置问题。

    2.能够打开微信客户端,但是打开后只有中间一个白色的 “确定按钮”,点击后会回到客户端上,如果是这样,那应该是prepayid 参数的问题,过期了,或者不是真实的id。代码没有问题的。特别注意的是,微信要两次签名,两次~~~~

    3.如果APP里面使用了友盟或者ShareSDK做分享,那就不用再导入SDK了,否则会出现一些诡异的问题,例如无法调起手机微信客户端、无法调起微信客户端web页面,调起了但是一闪而过。。。这都基本上都是因为分享的SDK里面已经包括了微信的SDK。所以如果出现诡异的错误了看看是不是两个冲突了!

    4.微信支付的单位是分,被坑过的人都知道了。。。。哎,

    如果在集成过程中遇到什么问题,大家可以一起讨论下,我记录这些如果有什么错误的话也请告诉我!谢谢!

    相关文章

      网友评论

      • 你是我此世不渝的执着:APPid 未关联Paysignkey 是什么原因
      • 你是我此世不渝的执着:你好 支付的时候显示APPID未关联PaySignkey 是哪里出现了问题 急求
      • 擦啊啊啊啊:PayReq *request = [[PayReq alloc] init]; 初始化的时候报 Undefined symbols for architecture arm64:
        "_OBJC_CLASS_$_PayReq", referenced from:
        objc-class-ref in YFWXPayUtil.o
        ld: symbol(s) not found for architecture arm64
        clang: error: linker command failed with exit code 1 (use -v to see invocation)
        请问大神知道怎么解决吗
      • Look2021:虽然是2年前的了,但还是有用,给个赞👍
      • hmj1993:简主 我支付成功后没有回到原来的app 需要手动点击右上角才能回到原app
        Ke_Wang:@hmj1993 :joy: :joy: 这个我也忘了 你查下文档瞧瞧
        hmj1993:@WK_IOSDevelpoer scheme就是appdelegate里面注册的addid吧
        Ke_Wang:@hmj1993 返回不了 原APP,很大的原因是Scheme 这个问题,你查一下看看是不是写错了呀
      • hmj1993:简主 我跟着你的写但是微信都没调动 想问下 什么原因
      • Sanchain:有用
      • YYWJustGo:想请教下:我现在要做的功能是,当用户从APP提现的时候,我们调用微信客户端,把钱打到用户的微信钱包或者银行卡,请问这个怎么实现,也是跟支付这个一样吗?
        Ke_Wang:@YYWJustGo 这个在我理解的应该是不行的啊 。。。微信支付是用微信里面的钱去购买商品,需要有个客户订单号之类的东西的。。。。你这样的需求 你试试找找有没有微信转账的接口,那个应该是可以实现你这个需求的
      • Thinkdifferents:[WXApi registerApp:@"wxd930ea5d5a258f4f" withDescription:@"测试demo"];
        这一步之后直接就挂了
      • 刘超_a594:微信要两次签名是什么意思
        Ke_Wang:@刘超_a594 官网demo一般都是没问题的,我之前集成的时候 用官网demo就可以顺利支付一分钱。。。
        刘超_a594:@WK_IOSDevelpoer 昨天搞微信支付,发现签名报错,找了自己自己各种原因,后来还是发现是后台那边签名有问题。本地现在签名还能用吗,网上找的签名还是报错,官网demo为什么看不到支付模块
        Ke_Wang:@刘超_a594 客户端调用签名前,后台也会签名一次的
      • Ko_Neko:比较奇怪的是我使用微信的Demo,然后调用支付的参数换成自己APP的,但是URL scheme那里还是Demo里原本的设计,然后跳转支付后居然会跳转回我自己的APP。难道不是根据URLType那里配置的appid来跳转的吗?
        Ke_Wang:@Ko_Neko 一般跳转都是根据这个scheme 来的啊 。。。。。
        Ko_Neko:@WK_IOSDevelpoer 我没有更改demo里的scheme ,所以支付完按理说是要跳回demo的,但是我手机上装了自己的app,它居然跳回自己的app了。挺神奇的,难道是根据appdelegate里入口调用的appid来跳转的?
        Ke_Wang:@Ko_Neko 应该是根据scheme 来的,这个也得改了呀。。。
      • Jeffery_zc:如果在友盟做了分享,在微信申请了appid,在用微信支付的时候appid是不是要再申请?
        Ke_Wang:@伊男 :cold_sweat: 这两个应该不会冲突吧,他们是针对不同的方面的。。。我没试过。。。。:joy: :joy: 如果冲突的话 直接用友盟的包应该就可以了,。。。
        Jeffery_zc:@WK_IOSDevelpoer 友盟里面设置微信分享有一个设置appid的方法,微信支付里面也有一个,2者会不会冲突啊?友盟设置微信分享有个wechatsocialsdk,微信支付有个WeChatsdk,这2个sdk会不会冲突呢?在线等。。。
        Ke_Wang:@伊男 应该不用吧。。。。
      • 正义必胜biu:你好,微信支付里面不是还有out_trade_no、body、total_fee等需要的参数吗?我有点不明白,能帮我解答一下我的问题吗
      • a7c1709e0ce4:整个流程非常清晰,谢谢分享
      • reyzhang:我写了一篇关于微信支付二次封装的文章,有兴趣的可以查阅 http://www.jianshu.com/p/bfc466f2f446
      • f886718d8e26:你好 请问openID是必传的吗 但是微信官方文档的"APP端开发步骤"里没传这个参数 (然而安卓需要传appId)
      • DroisAndEthan:楼主,有没遇到过,当调到微信的时候,”支付验证签名失败“,我这都检查了两遍了,时间轴没问题,签名什么的也没问题,安卓那边已经可以用了,我这。。。
        DroisAndEthan:已经搞定了,我竟然,所有情况都过了一遍,找了一天,后来换个手机就好了(你说的那个转的,应该是13位的时间轴,iOS用的是10位,那个没问题)好尴尬:joy:
        Ke_Wang:@阿飞的隐喻 我记得好像是有个什么东西需要转一下,安卓的不需要转:joy::joy:好久了我也忘了:joy::joy:你查一下,
      • 哎呦我去叫什么呢:WXPay里面要传的参数都是后台返回的吗?req.openID是不是就是后台传的appid
      • 一只霸天犬v:请问楼主,那个时间戳是什么时候生成的啊? 是向后台调用接口的时候 后台生成的吗
        Ke_Wang:@小仙儿v额 就是 它会根据这个是时间戳来作为认定订单唯一性的一个依据呀 。。。。不同时间发出的订单 是不一样的,根据时间戳就可以判定了
        一只霸天犬v:@WK_IOSDevelpoer 这个有什么作用啊 怎么用 看文档就是一带而过说是防重发 但是还是有点不太懂
        Ke_Wang:@小仙儿v 是呀,后台生成的
      • attackGiant:mark
        写的很详细,涨姿势了
      • c2d2794a53c7:楼主你好,我的微信支付 报错 appid未关联paysignkey 这个是什么问题呢, 求告诉 谢谢
        你是我此世不渝的执着:@哎呦我去叫什么呢 你好 你解决了吗 我也报这个问题
        哎呦我去叫什么呢:你好解决了吗?我也是报这个,是什么原因啊
      • 0x00chen:楼主在吗?关于微信支付,我是在微信开放平台注册应用,但是公司给我的账号是直接搜“微信支付”这个网站的账号,微信登陆我用的shareSDK,支付到底用哪个啊
        Ke_Wang:@究极魔法师 应该不行。开通支付那个好像要收费的
        0x00chen:@WK_IOSDevelpoer 公司现在给我的是微信公众号,但是微信开放平台并没有开通支付功能,这样可以实现微信支付功能吗
        Ke_Wang:@究极魔法师 微信支付这个有可能是新出的,我当时的微信支付是在微信开放平台的呀
      • wang1992:我要弄一个在线充值的 微信用什么来接收我要充值的金额 像支付宝一样 就有一个用来接收的金额的参数
        1d95fecedf66:@wang1992 903664265.加我Q
        wang1992:@jiangqingchao 好的 谢谢!那你知道 9楼的问题怎么解决吗 就是怎样判断回调地址 是 支付宝的还是微信的
        1d95fecedf66:@wang1992 我觉得,你给后台发一个请求,带上金额的参数.然后后台的金额数就设置为你上传的参数,然后给你一个预订单的接口
      • 1d95fecedf66:在吗,boy
        1d95fecedf66:@jiangqingchao微信支付调出了微信,但是提示签名错误.这个不知道如何进行处理!!!
      • 21437ffdc572:所有东西都集成进去了 ,但是 [WXApi registerApp:@"wxd930ea5d5a258f4f" withDescription:@"测试demo"];
        这个注册时,就会奔溃为什么啊 :sob:
        21437ffdc572:@WK_IOSDevelpoer 大神我给你发个demo帮我看下吧,只有集成部分,不多的,回头给你发个红包 :relaxed:
        21437ffdc572:常见问题没有看到类似的,我是按照步骤一步一步来的, 提示对象被释放掉了。但是对象在哪里我都不知道,引用了空的, [WXApi registerApp:@"wxd930ea5d5a258f4f" withDescription:@"测试demo"]; 不加这一句 就能跑起来,但是不加不行啊 :sob:
        Ke_Wang:@风吹裤衩pp凉 注册APP 不行么 ? 你看是不是有冲突啊 你看看 文档上的 常见问题 看看其他人遇到了没有 我没见过这样的啊 。。。。
      • c6889486596e:请问下,
        //由用户微信号和AppID组成的唯一标识,用于校验微信用户
        req.openID = @"";这个参数怎么获得?如果是后台传过来的,请问有没有后台开发的文档,发一下看看,谢谢
        Ke_Wang:@knight_try 文档早就找不到了:joy::joy::joy:
      • cj2527:你好,微信官网的DEMO,支付取消,能跳转回来app界面。但支付成功,就一直在微信界面,就是那个支付成功的界面。手动点击,才能跳回app。
        Ke_Wang:@cj2527 你看看你的scheme是不是设置的 有问题。。。。
      • ForgetThatNight:如果同时写了支付宝支付和微信支付,那这个方法怎么区别是微信的回调还是支付宝的回调?- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
        return [WXApi handleOpenURL:url delegate:self];
        }

        - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
        return [WXApi handleOpenURL:url delegate:self];
        }
        Roader:返回的url里面包含scheme参数,是个字符串,你能跳回来就是因为这个scheme,通过
        if ([url.scheme isEqualToString:WEIXIN_APP_ID]) {
        return [WXApi handleOpenURL:url delegate:[WXApiManager sharedManager]];
        }
        ForgetThatNight:@wang1992 把微信支付写在后面就行了,进了支付宝就不会走后面了
        wang1992:@ForgetThatNight 解决了吗 我也是遇到这个问题了
      • 宁小缺:可以在调用之前进行注册么?
        宁小缺:@WK_IOSDevelpoer 可以在要调用之前在进行注册么 不在delegate里面注册
        Ke_Wang:@宁缺_勿犯 嗯,就在APPdelegate里面注册
      • 马什么梅:传的参数啥的签名咋做的啊。。。后台啥都没给啊 只给了appid token appsecret
        Ke_Wang:@马什么梅 那你们经理也不说啥么?前台签名可以破解的
        马什么梅:@WK_IOSDevelpoer 蛋疼后台不给 只能自己做了
        Ke_Wang:@马什么梅 参数一般在后台签名好了传过来:ideograph_advantage:
      • 8c74ca775cd8:非常感谢楼主, 本来看官方demo一脸懵逼, 现在懂了, 微信那帮渣渣, 注释不好好写
        Ke_Wang:@青山流云s 当年我也懵逼了好几天:joy::joy::joy:
      • 顺其自然JX:大神,我想问一下,客户端向服务器发送商品数据,和服务器签名后把信息返回给客服的是点击微信支付完成的吗?
        Ke_Wang:@顺其自然jx 一般都是点提交订单时候发给服务器:joy::joy:,然后回传回来签名过的字符串,然后点支付就可以支付了
      • 凯文Kevin21:可以,写的非常详细。。。Mark
      • Mars飘殇:想问下,那个openID是不是就是微信开放平台注册的appID,还有我现在做支付也出现调起微信,出现个白色确定按钮了。。。
        Ke_Wang:@Mars飘殇 那个参数不影响结婚,但是会有那个白色按钮的
        Mars飘殇:@WK_IOSDevelpoer 不是吧 我能跳转到微信 又能从微信跳转回来 而且设置的就是微信开放平台取的app ID呀
        Ke_Wang:@Mars飘殇 白色按钮就是Scheme那个参数的问题:joy:
      • 来宝:大神,请教一下,我也遇到调起支付之后,出现“确定按钮”,你上面提到需要两次签名是啥意思?是客户端做吗?
        Ke_Wang:@来宝 这个问题是你的scheme那个参数的问题,我也见过。。。
        来宝:安卓可以正常支付,ios也可以调起支付,但是会出来白色的“确定按钮”
        Ke_Wang:@来宝 签名最好是服务端做,那样比较安全,客户端也可以做,但是可以被截获篡改,看你们公司的要求了😂😂
      • 3fdbe0c8b63d:非常有用的流程图!

      本文标题:iOS开发支付集成之微信支付

      本文链接:https://www.haomeiwen.com/subject/ddvmkttx.html