关于iOS支付的小结

作者: xymspace | 来源:发表于2017-06-07 15:22 被阅读35次

    项目中碰到过的支付方式一直以来没有系统的梳理过,今天就开发过程中的问题来做一次详细的总结,为今后的使用提供参考。

    目前为止较为广泛使用的支付方式:

    三方支付:

    • 微信支付
    • 支付宝支付
    • 银行支付
    • 内购(简称 IAP)

    • 感想: 所有三方支付最好写一个单例来封装,便于维护

    微信支付

    关于微信支付后的回调处理

    • 问题触发场景:当我们使用微信支付成功后,没有在微信App内,点击完成按钮,跳转到我们自己的App,而是点击了系统提供的左上角快捷键返回到了我们自己的App。
    • 场景导致的bug:由于没有点击完成按钮,微信SDK无法调用其回调接口:
    -(void)onResp:(BaseResp*)resp{
                  if ([resp isKindOfClass:[PayResp class]]){
                      PayResp*response=(PayResp*)resp;
                      switch(response.errCode){
                          case WXSuccess:
                                    //服务器端查询支付通知或查询API返回的结果再提示成功
                                    NSlog(@"支付成功");
                            break;
                            default:
                            NSlog(@"支付失败,retcode=%d",resp.errCode);
                            break;
                      }
                        }
                    }
    

    如此一来,我们就无法完整的处理微信支付流程了。

    • 解决方案:app每次从后台进入时会调用applicationWillEnterForeground(注:应用将要进入前台)方法,我们可以在这里发送一个微信支付的通知,并在相应的界面获取该通知,在通知方法里,向服务端发送微信支付结果请求,获取支付结果。
    #pragma mark - AppDelegate中发送通知
    
    - (void)applicationWillEnterForeground:(UIApplication *)application 
    {
        DTLog(@"applicationWillEnterForeground");
    
        [[NSNotificationCenter defaultCenter] postNotificationName:@"wxPayBack" object:nil];
    }
    
    #pragma mark - 相关接收通知的controller
    // 考虑到添加时机的问题,最好是在获取订单信息的回调中添加该通知,确保该通知回调一定会被执行
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wxPayBack) name:@"wxPayBack" object:nil];
    
    - (void)wxPayBack
    {
    //判断订单号是否存在,以及当前回调是否为微信支付(若有其它支付,也会调起该通知),然后通过订单号向服务端发起支付结果请求
        if (订单号.length > 0 && _isWxPay)
        {
            [self judgeWxPayStationWithWxPayOrder:订单号];
        }
    }
    
    #pragma mark - 对请求结果的处理
    - (void)judgeWxPayStationWithWxPayOrder:(NSString *)wxOrder
    {
        NSDictionary *dic = 请求体参数;
        [[NetWorkManager shareManager] postDataSourceFromURL:请求订单信息的接口 Dic:dic Success:^(NSDictionary *success) {
            
            // 参考微信SDK自定义PayResp对象
            PayResp *resp = [[PayResp alloc] init];
            resp.errCode = 0;
            resp.errStr = nil;
            resp.type = 0;
            NSString *state = success[支付结果对应的key];
            if (![state isEqualToString:支付成功对应的值])
            {
                resp.errCode = 0;
            }
            [self wxPaySResp:resp];
    
        } AndFail:^(NSError *fail) {
            
        }];
    }
    
    - (void)wxPaySResp:(PayResp *)resp
    {
        NSString *strTitle = nil;
        if ([resp isKindOfClass:[PayResp class]]) {
            
            switch (resp.errCode) {
                case WXSuccess:
                {
                    strTitle = @"支付成功!";
                    break;
                }
                case WXErrCodeUserCancel: //用户点击取消并返回
                    strTitle = @"您未成功支付";
                    break;
                default:
                    break;
            }
        }
        if (strTitle != nil)
        {
            弹出相应的提示
        }
    }
    

    • 微信支付流程(客户端具体实现)
    • 下载对应iOS平台的Demo,添加依赖库,修改plist
    • 真机测试时,需要在build setting里修改bitcode为NO
    • 设置project——>info——>URL types——>新增微信URLSchemes
    • 商户APP工程中引入微信lib库和头文件,调用API前,需要先向微信注册APPID(在APPDelete中注册即可)
    
    -(BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    [WXApi registerApp: @"自己的appid替换" withDescription: @"自己定义一个描述"];
    }
    
    
    • 向服务端发起请求,获取订单号——>通过商品价格等参数拼接请求体发起订单号请求
      • 在订单号返回成功的回调中添加微信客户端回调通知
      • 在点击微信支付后,拼接请求体(请求体中包含订单号)发起支付请求
      • 支付回调成功处,设置PayReq对象,调起微信客户端(最好增加客户端是否安装的判断)
    • 微信客户端调起自己的app,此时获取到微信支付处理的通知,接下来处理该通知(处理细节请在上面查看)

    名称 描述 解决方案
    0 成功 展示成功页面
    -1 错误 可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。
    -2 用户取消 无需处理。发生场景:用户不支付了,点击取消,返回APP。
    支付宝支付
    • 支付宝支付,分为网页快捷支付、支付宝客户端支付两种情况
    • 支付宝支付流程(客户端具体实现)
    • 下载对应iOS平台的Demo,添加依赖库

    • 设置project——>info——>URL types——>新增支付宝URLSchemes

    • 向服务端发起请求,获取订单号——>通过商品价格等参数拼接请求体发起订单号请求

      • 在点击支付宝支付后,拼接请求体order(请求体中包含订单号、服务端提供的notifyURL)发起支付宝签名请求
      • 获取签名请求成功回调中,处理订单字符串、回调URLScheme(保证支付处理完成回调到自己的app),使用[AlipaySDK defaultService]调起支付宝处理支付
      • 支付处理完成,APPDelegate中,处理一次回调,然后在调起支付宝的controller中进行第二次回调处理
    - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options
    {
        if ([[url absoluteString] hasPrefix:URLScheme])
        {
        // 支付宝客户端二次回调条件
            [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
              
            }];
            
            [[AlipaySDK defaultService] processAuth_V2Result:url standbyCallback:^(NSDictionary *resultDic) {
                NSLog(@"result = %@",resultDic);
                // 解析 auth code
                NSString *result = resultDic[@"result"];
                NSString *authCode = nil;
                if (result.length>0) {
                    NSArray *resultArr = [result componentsSeparatedByString:@"&"];
                    for (NSString *subResult in resultArr) {
                        if (subResult.length > 10 && [subResult hasPrefix:@"auth_code="]) {
                            authCode = [subResult substringFromIndex:10];
                            break;
                        }
                    }
                }
                NSLog(@"授权结果 authCode = %@", authCode?:@"");
            }];
            
        }
    }
    
    

    银联支付

    银联移动支付平台地址:https://open.unionpay.com/ajweb/product/detail?id=3 下载SDK

    1. 导入SDK
      SDK包括两个文件:UPPaymentControl.h文件和libPaymentControl.a,将SDK目录添加到工程.

    2. 添加依赖
      使用UPPaymentControl需要添加CFNetwork.framework、SystemConfiguration.framework 、libz、libPaymentControl.a到工程中,

    3. 修改配置
      3.1 在工程info.plist设置中添加一个URL Types回调协议(在UPPayDemo工程中使用“UPPayDemo”作为协议),用于在支付完成后返回商户客户端。
      3.2 在Xcode7.0之后的版本中进行http请求时,需要在工程对应的plist文件中添加
      NSAppTransportSecurity Dictionary
      并同时设置里面
      NSAllowsArbitraryLoads 属性值为 YES.
      3.3 添加协议白名单
      在Xcode7.0之后的版本中进行开发,需要在工程对应的plist文件中,添加LSApplicationQueriesSchemes Array并加入uppaysdk、uppaywallet、uppayx1、uppayx2、uppayx3五个item
      或者直接添加如下代码到plist文件中:

    <key>LSApplicationQueriesSchemes</key>
         <array>
            <string>uppaysdk</string>
            <string>uppaywallet</string>
            <string>uppayx1</string>
            <string>uppayx2</string>
            <string>uppayx3</string>
         </array>
    

    3.4 修改编译选项
    选择工程targets——>build settings ->Linking->other linker flags
    如果该设置和其他第三方库冲突,或银联客户端莫名失败,则可尝试去掉-ObjC,改为-force_load+空格+控件路径,如:-force_load $(PROJECT_DIR)/xxxx/ libPaymentControl.a
    3.5 凡是引入银联头文件UPPaymentControl.h,需要将源文件后缀.m改为.mm

    1. 接口说明
      4.1 支付接口


      支付接口.png

      4.2 回调接口


      返回接口.png
    内购
    • 内购需要在开发者账号发布app界面,添加内购物品
    • 完善银行卡信息
    • 添加测试人员账号
    • 在app中添加内购代码

    内购实现流程

    1. 客户端向自己公司服务端请求productIds(可能是多个商品)
    2. 使用这些produceId创建SKProductsRequest对象,调用start方法,设置该对象代理,在代理方法中获取可以销售的product(代理方法中获取创建UI所需要的数据)
    3. 当用户点击某个商品后,我们客户端获取被点击商品的SKProduct对象,创建SKPayment票据对象(使用SKProduct对象创建),添加SKPayment对象的监听者,将票据添加到购买队列,在监听商品更新信息回调方法中获取商品购买状态
    4. 如果商品返回状态为:成功 | 失败 | 恢复,那么将该票据从队列移除,成功购买,应返回给本公司服务器商品购买成功信息,用于下次更新商品状态

    相关文章

      网友评论

        本文标题:关于iOS支付的小结

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