美文网首页iOS程序员的业余沙龙iOS支付资料iOS调试技巧
ApplePay 接入教程及开发过程需要注意的点

ApplePay 接入教程及开发过程需要注意的点

作者: 乌龙谦 | 来源:发表于2016-04-07 14:53 被阅读3088次

    运行环境##

    iphone 6 以及以上,iOS 9.2 以上。目前不支持企业证书添加。
    支持模拟器测试。

    环境配置##

    1、 Xcode 7.2.1 以及以上打开项目,在 Capabilities里将Apple Pay设置为on,如下图,请忽略 Merchant IDmerchant.com.Carman.Paydemo这一项,一会我会详细介绍。

    图片-1

    这时你会发现 项目 下 会自动 生成一个 类似证书的东西

    图片-2

    这一步做了什么?
    1、自动导入了需要的库文件。
    2、添加了一个权限文件(图片-2).

    2、 图一我们看到了有个 Merchant ID 选项,而且新建时候是没有配置的,那么需要到哪里去配置呢?
    1、访问苹果开发账号,证书中心。
    Identifiers -->Merchant IDs
    输入描述 和 ID,ID 必须以merchant. 开头

    图-3

    Continue 到下一步,前方高能警报,嘀嘀嘀~~~~ 坑一出现:报错!!!!!!!

    图-4
    说明苹果对这个ID 格式是有要求的。多试几次。其实仔细看 图 -3 底下有一行小字,We recommend using a reverse-domain name style string (i.e.,merchant.com.example.merchantname). 最好按照官方要求 merchant.com.example.merchantname 这个格式来。 图 -5

    一步一步往下走。
    这时候 会提示你 Identifier:merchant.com.Demo.applepaydemo已经生成。

    图-6
    点击 Done
    图 -7
    根据上面的提示,点击Edit,接下去应该是需要建证书了。
    首次添加时候 会询问你是否 在中国使用。选择 YES(截图是默认状态-NO),一直 continue 。
    图-8

    3、新建证书
    创建 ** Creating a Certificate Signing Request (CSR) CSR 证书,**
    Keychain Access > Certificate Assistant > Request a Certificate from a Certificate Authority.
    打开钥匙串访问 如下图操作

    图-9
    生成 CertificateSigningRequest.certSigningRequest(名称可以自定义)
    图-10

    上传 生成证书


    图-11

    满怀信心,觉得即将成功是么?

    图-12
    此证书是由未知颁发机构签名的!!!什么鬼呀,老子的账号明明是正规渠道申请的!
    还好有解决方案---点我解决.
    点击下载红线项,删除老的证书,重新导入 G2 证书
    图-13
    以上,ApplePay 所需的环境就算全部配置完成了。
    总结一下就一条:生成了 Merchant ID 证书
    再看 项目 工程,已经自动生成了 Merchant ID 值,打钩就可以了,如果没有生成,再检查下 项目的 Bundle identifier是否和证书一致。
    图-14

    代码集成##

    首先我们来看下模拟器上Demo 运行的结果:

    图-15
    这里要说的 重点不在下半部分,而是 Buy with XXPay 这个按钮,我们知道苹果是一个有情(偏)怀(执)的处女座公司,对很多的设计或则交互都有自己的一套规则,ApplePay 的响应 按钮也不例外。不要以为随便 弄个 设计个按钮 就能上线了,这个时候 美工和老板说了都不算,要听苹果的ApplePay 设计规范。不然审核也过不了。

    1、
    导入头文件,(xcode 7.0 以上已经自动帮我们导入了库,所以我们只需要导入头文件即可)

    #import <PassKit/PassKit.h>
    

    2、
    PKPaymentAuthorizationViewController Apple pay的展示控件,也是核心类。直接看代码

    - (void)actionApplePay:(UIButton *)button {
    
      if ([PKPaymentAuthorizationViewController canMakePayments]) {
    
        NSLog(@"Woo! Can make payments!");
    
        if ([PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[
              PKPaymentNetworkChinaUnionPay,
              PKPaymentNetworkMasterCard,
              PKPaymentNetworkVisa
            ]]) {
    
        } else {
          NSLog(@"用户未添加银行卡");
          return;
        }
    
        PKPaymentRequest *request = [[PKPaymentRequest alloc] init];
    
        PKPaymentSummaryItem *widget1 = [PKPaymentSummaryItem
            summaryItemWithLabel:@"Widget 1"
                          amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]];
    
        PKPaymentSummaryItem *widget2 = [PKPaymentSummaryItem
            summaryItemWithLabel:@"Widget 2"
                          amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]];
    
        PKPaymentSummaryItem *total = [PKPaymentSummaryItem
            summaryItemWithLabel:@"Grand Total"
                          amount:[NSDecimalNumber decimalNumberWithString:@"0.02"]];
    
        request.paymentSummaryItems = @[ widget1, widget2, total ];
        request.countryCode = @"CN";
        request.currencyCode = @"CHW";
    
        //能支付的币种
        request.supportedNetworks = @[
          PKPaymentNetworkChinaUnionPay,
          PKPaymentNetworkMasterCard,
          PKPaymentNetworkVisa
        ];
          
        //Merchant ID
        request.merchantIdentifier = @"merchant.com.Carman.Paydemo";
    
        // 询问你的付款处理器 (PKMerchantCapabilityCredit
        // 信用卡,PKMerchantCapabilityDebit 借记卡)
    
        /*
         PKMerchantCapabilityCredit NS_ENUM_AVAILABLE_IOS(9_0)   = 1UL << 2,   //
         支持信用卡
         PKMerchantCapabilityDebit  NS_ENUM_AVAILABLE_IOS(9_0)   = 1UL << 3    //
         支持借记卡
         */
        request.merchantCapabilities = PKMerchantCapabilityCredit;
        // 添加联系人邮箱 及送货地址信息
        //request.requiredShippingAddressFields = PKAddressFieldAll;
    
        PKPaymentAuthorizationViewController *paymentPane =
            [[PKPaymentAuthorizationViewController alloc]
                initWithPaymentRequest:request];
        paymentPane.delegate = self;
        [self presentViewController:paymentPane animated:TRUE completion:nil];
    
      } else {
        NSLog(@"设备不支持支付");
      }
    }
    

    1、[PKPaymentAuthorizationViewController canMakePayments] 判断设备支持不支持 ApplePay。中国区 是 iphone 6 及以上,iOS9.2
    2、canMakePaymentsUsingNetworks: 判断 设备上用户有没有添加银行卡,如果没添加,不写这个判断,真机上会crash。
    PKPaymentNetworkChinaUnionPay //中国银联卡
    PKPaymentNetworkMasterCard //Master卡
    PKPaymentNetworkVisa //Visa卡

    3、支付的类目以及总额

    PKPaymentRequest *request = [[PKPaymentRequest alloc] init];
    
        PKPaymentSummaryItem *widget1 = [PKPaymentSummaryItem
            summaryItemWithLabel:@"Widget 1"
                          amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]];
    
        PKPaymentSummaryItem *widget2 = [PKPaymentSummaryItem
            summaryItemWithLabel:@"Widget 2"
                          amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]];
    
        PKPaymentSummaryItem *total = [PKPaymentSummaryItem
            summaryItemWithLabel:@"Grand Total"
                          amount:[NSDecimalNumber decimalNumberWithString:@"0.02"]];
    
        request.paymentSummaryItems = @[ widget1, widget2, total ];
    

    4、countryCode 国家 code ,中国的是 CN ,不太清楚定义的可以查看 countryCode查询网站
    5、currencyCode 支付币种 ,人民币 CHW
    6、supportedNetworks 能支持的卡种,同 2
    7、merchantIdentifier ,终于出现这货了,申请半天的 Merchant ID ,请注意保持一致。
    8、
    merchantCapabilities
    询问你的付款处理器
    PKMerchantCapabilityCredit //支持信用卡
    PKMerchantCapabilityDebit //支持借记卡
    9、requiredShippingAddressFields 添加联系人信息

    typedef NS_OPTIONS(NSUInteger, PKAddressField) {
        PKAddressFieldNone                              = 0UL,      // No address fields required.
        PKAddressFieldPostalAddress                     = 1UL << 0, // Full street address including name, street, city, state/province, postal code, country.
        PKAddressFieldPhone                             = 1UL << 1,
        PKAddressFieldEmail                             = 1UL << 2,
        PKAddressFieldName NS_ENUM_AVAILABLE_IOS(8_3)   = 1UL << 3,
        PKAddressFieldAll                               = (PKAddressFieldPostalAddress|PKAddressFieldPhone|PKAddressFieldEmail|PKAddressFieldName)
    } NS_ENUM_AVAILABLE(NA, 8_0);
    

    10、调起 ** PKPaymentAuthorizationViewController**

     PKPaymentAuthorizationViewController *paymentPane =
            [[PKPaymentAuthorizationViewController alloc]
                initWithPaymentRequest:request];
        paymentPane.delegate = self;
          
        [self presentViewController:paymentPane animated:TRUE completion:nil];
    

    当然,我们要实现<PKPaymentAuthorizationViewControllerDelegate> 代理

    @interface ViewController : UIViewController<PKPaymentAuthorizationViewControllerDelegate>
    @end
    

    实现 PKPaymentAuthorizationViewControllerDelegate##

    必须实现的两个代理:

    #pragma mark-- PKPaymentAuthorizationViewControllerDelegate
    - (void)
        paymentAuthorizationViewController:
            (PKPaymentAuthorizationViewController *)controller
                       didAuthorizePayment:(PKPayment *)payment
                                completion:
                                    (void (^)(PKPaymentAuthorizationStatus status))
                                        completion {
      NSLog(@"Payment was authorized: %@", payment);
    
      // do an async call to the server to complete the payment.
      // See PKPayment class reference for object parameters that can be passed
      BOOL asyncSuccessful = FALSE;
    
      if (asyncSuccessful) {
        completion(PKPaymentAuthorizationStatusSuccess);
    
        NSLog(@"支付成功");
    
      } else {
        completion(PKPaymentAuthorizationStatusFailure);
        NSLog(@"支付失败");
      }
    }
    
    - (void)paymentAuthorizationViewControllerDidFinish:
            (PKPaymentAuthorizationViewController *)controller {
      // hide the payment window
      [controller dismissViewControllerAnimated:TRUE completion:nil];
    }
    

    1、paymentAuthorizationViewController:didAuthorizePayment:
    completion

    支付 状态回调在这里处理,支付成功和失败,订单的地址 以及和 服务器传输数据-token。
    2、paymentAuthorizationViewControllerDidFinish:支付结束,关闭 支付弹框。
    3、可选的另外的代理 回调 请参考Apple Pay接入详细教程 一文

    我们主要来看下** PKPayment** 对象

    图-16

    token 支付成功之后的回执,需要上传给服务器。
    billingAddress 用户账单地址
    billingContact 用户账单信息
    shippingAddress 送货地址
    shippingContact 送货信息
    shippingMethod 送货方式
    以上的 信息 可以根据自己的需求 上传到服务器

     - (void) paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
    
    didAuthorizePayment:(PKPayment *)payment
    
    completion:(void (^)(PKPaymentAuthorizationStatus))completion
    
    {
    
    NSError *error;
    
    ABMultiValueRef addressMultiValue = ABRecordCopyValue(payment.billingAddress, kABPersonAddressProperty);
    
    NSDictionary *addressDictionary = (__bridge_transfer NSDictionary *) ABMultiValueCopyValueAtIndex(addressMultiValue, 0);
    
    NSData *json = [NSJSONSerialization dataWithJSONObject:addressDictionary options:NSJSONWritingPrettyPrinted error: &error];
    
    // ... Send payment token, shipping and billing address, and order information to your server ...
    
    PKPaymentAuthorizationStatus status; // From your server
    
    completion(status);
    
    }
    

    更深入了解可以参看官方文档

    钱去哪了##

    目前为止,我们完成了客户端的ApplePay 代码集成,假设回调的信息也成功上传 服务器,服务器也成功对订单进行了处理,那么用户支付的钱去哪了?
    1、钱去了商家的 AppStore 账号?
    苹果账号的申请一般都是用信用卡支付 ,业务的收入不太可能直接打到信用卡里。
    2、商家 AppStore 账号绑定了商家的银行卡?
    我们生成 Merchant ID 证书的时候 并没有这一步。

    支付供应商##

    苹果官方文档 Apple Pay 入门 明确指出:

    图-17

    就是说,苹果官方强烈建议开发者接入他合作的支付供应商SDK 来支持ApplePay,这样就能理解了,开发者到支付供应商网站注册相关信息,绑定商户ID ,银行卡等,这样用户的钱就到了商户在支付供应商注册的账号里面。我们可以把支付供应商 理解成付款处理结构。 坑爹呀,上面的集成都白写了!!!

    苹果官方在中国合作的指定付款处理结构有 (参考ApplePay 介绍):

    中国银联
    连连支付
    首信易支付
    易宝支付
    银联商务

    这里选择中国银联的sdk 进行介绍,有兴趣的同学可以自行去研究另外几个供应商的支付SDK。

    中国银联##

    选择中国银联 接入 有个很大的好处 -- 文档非常的详细。
    1、中国银联商户入网新手指南
    https://merchant.unionpay.com/join/help/director
    2、银联商家服务
    https://open.unionpay.com/ajweb/product/detail?id=80
    3、银联Apple Pay控件开发包
    https://open.unionpay.com/ajweb/help/file/techFile?productId=80

    银联Apple Pay控件开发包####

    下载 银联的Apple Pay 控件开发包,里面有非常详细的 介绍,如何接入ApplePay。


    图-18

    银联支付控件 SDK 模式 Apple Pay 支付的实现方式###

    图-19

    1-2、 商户生成订单,通过商户SERVER端将订单信息发送给银联支付网关;
    3-4、银联支付网关记录订单信息,返回用来标识订单的 TN 号,经由商户 SERVER 返回至给商户 APP;
    5、 商户 APP 调用银联 SDK,将 TN 号传递给银联 SDK
    6、 银联 SDK 向 Apple 公司的 PASSKIT FRAMEWORK 发起支付请求;
    7、 接口返回加密的支付 Token 信息;
    8-9、银联 SDK 将支付 Token 传递给银联支付网关,完成交易认证;
    10-12、银联将支付结果返回给商户 APP,商户 SERVER,商户 APP 负责提示用户交易结果。

    集成的测试代码介绍##

    1-2步、商户生成订单,通过商户SERVER端将订单信息发送给银联支付网关; 代码如下:

    - (void) pmPayAction:(id)sender {
        //使用PM环境
        self.tnMode = @"01";
        NSURL* url = [NSURL URLWithString:@"http://101.231.204.84:8091/sim/getacptn"];
        
        NSMutableURLRequest * urlRequest=[NSMutableURLRequest requestWithURL:url];
        NSURLConnection* urlConn = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
        [urlConn start];
        [self showAlertWait];
    }
    

    1、 self.tnMode = @"01"; //接入模式,标识商户以何种方式调用支付控件,00生产环境,01测试环境
    2、http://101.231.204.84:8091/sim/getacptn //银联提供测试的 URL

    3-9 步:代码如下:

    #pragma mark - connection
    
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response
    {
        NSHTTPURLResponse* rsp = (NSHTTPURLResponse*)response;
        NSInteger code = [rsp statusCode];
        if (code != 200)
        {
            
            [self showAlertMessage:kErrorNet];
            [connection cancel];
        }
        else
        {
            UPRelease(_responseData);
            _responseData = [[NSMutableData alloc] init];
        }
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        [_responseData appendData:data];
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        [self hideAlert];
        NSString* tn = [[NSMutableString alloc] initWithData:_responseData encoding:NSUTF8StringEncoding];
        if (tn != nil && tn.length > 0)
        {
            if([PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[PKPaymentNetworkChinaUnionPay]])
            {
    
                [UPAPayPlugin startPay:tn mode:self.tnMode viewController:self delegate:self andAPMechantID:kAppleMerchantID];
            }
    
        }
        [tn release];
    }
    
    -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
        [self showAlertMessage:kErrorNet];
    }
    

    1、** [UPAPayPlugin startPay:tn mode:self.tnMode viewController:self delegate:self andAPMechantID:kAppleMerchantID];**
    1、tn / /订单信息
    2、self.tnMode //接入模式,标识商户以何种方式调用支付控件,00生产环境,01测试环境
    3、kAppleMerchantID //苹果公司分配的商户号,表示调用Apple Pay所需要的MerchantID;(接入银联支付时候,该 MerchantID 需要商家向银联申请生成)

    图 -20

    10-12步,银联将支付结果返回给商户 APP,商户 SERVER,商户 APP 负责提示用户交易结果。 回调处理。

    #pragma mark -
    #pragma mark 响应控件返回的支付结果
    #pragma mark -
    - (void)UPAPayPluginResult:(UPPayResult *)result
    {
        if(result.paymentResultStatus == UPPaymentResultStatusSuccess) {
            NSString *otherInfo = result.otherInfo?result.otherInfo:@"";
            NSString *successInfo = [NSString stringWithFormat:@"支付成功\n%@",otherInfo];
            [self showAlertMessage:successInfo];
        }
        else if(result.paymentResultStatus == UPPaymentResultStatusCancel){
    
            [self showAlertMessage:@"支付取消"];
        }
        else if (result.paymentResultStatus == UPPaymentResultStatusFailure) {
            
            NSString *errorInfo = [NSString stringWithFormat:@"%@",result.errorDescription];
            [self showAlertMessage:errorInfo];
        }
        else if (result.paymentResultStatus == UPPaymentResultStatusUnknownCancel)  {
            
            //TODO UPPAymentResultStatusUnknowCancel表示发起支付以后用户取消,导致支付状态不确认,需要查询商户后台确认真实的支付结果
            NSString *errorInfo = [NSString stringWithFormat:@"支付过程中用户取消了,请查询后台确认订单"];
            [self showAlertMessage:errorInfo];
            
        }
    }
    

    运行效果###

    图-21 图-22

    相关文章

      网友评论

      • 还是个少年:大神请问下CSR在applepay的过程中是怎么样使用的?
      • F麦子:iOS 网页APP能使用银联sdk吗
      • 不会算卦的杨大仙:大佬 跟银联签约后applePay能在海外用他们的卡支付吗
      • 我在普陀山下:接入银联必须要自己的服务端集成吗?
      • catYuan:想问一下 银联这个自助测试 怎么做? Apple Pay必须在银联服务平台上面做自助测试才能正式上线吗?
        catYuan:@乌龙谦 多谢回复。 是这样的
        乌龙谦:最终没有上线,应该是需要在银联平台联调成功之后才能上线。
      • 932fbdf94c70:demo可以共享出来吗
        乌龙谦:@wahtung 找不到了:sob::sob::sob:

      本文标题:ApplePay 接入教程及开发过程需要注意的点

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