美文网首页GitHub 中文社区iOS 开发每天分享优质文章程序员
Apple Pay ---官方文档整理思路以及疑惑点

Apple Pay ---官方文档整理思路以及疑惑点

作者: 李周 | 来源:发表于2017-07-30 20:48 被阅读438次

    之前把Apple Pay的文档全部翻译了一遍,最近也是接触到了真实的项目开发。发现开发的过程还是和官方文档中的介绍有偏差,所以我会先将官方文档中的步骤有疑惑的地方记录下来,然后介绍在实际开发中的不同点。


    1 Apple Pay 官方翻译文档

    2 Apple Pay开发流程

    3 Apple Pay实际开发


    1 Apple Pay 官方翻译文档

    官方与Apple Pay相关的文档主要包括 :
    Apple Pay Programming Guide(官方编程指南):详细的讲解了在应用中的Apple Pay开发流程以及一定的解释

    Apple Pay Programming Guide
    Apple Pay官方编程指南(中文翻译)

    PassKit (Apple Pay的支付框架):介绍了Apple Pay开发中所需要的类以及方法(已经有iOS 11的beta类和方法)

    PassKit
    PassKit(中文翻译)

    2 Apple Pay开发流程

    任何功能的开发都是需要在iTunes Connect中申请相关证书并且在Xcode 中将项目的Capabilities选项开启。以下是在代码开发的过程中的流程以及出现一些疑惑点:

    步骤一 判断用户是否能使用Apple Pay支付

    首先需要理解的是,用户不能使用Apple Pay支付有各种各种的原因,但是苹果为我们找到两类可控的原因:

    1.设备是否支持,是否开启家长控制

    [PKPaymentAuthorizationController canMakePayments];
    [PKPaymentAuthorizationViewController canMakePayments];
    

    2.是否在该网络下配置可供支付的卡

    [PKPaymentAuthorizationController canMakePaymentsUsingNetworks:@[PKPaymentNetworkVisa,PKPaymentNetworkChinaUnionPay,PKPaymentNetworkQuicPay]];
    [PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[PKPaymentNetworkVisa,PKPaymentNetworkChinaUnionPay,PKPaymentNetworkQuicPay]];
    

    直观的看到上面的两个代码会出现三个疑惑点:

    ① PKPaymentAuthorizationController 和PKPaymentAuthorizationViewController 分别用在什么地方?

    __WATCHOS_AVAILABLE(3.0) __IOS_AVAILABLE(10.0)
    @interface PKPaymentAuthorizationController : NSObject
    
    NS_CLASS_AVAILABLE_IOS(8_0)
    @interface PKPaymentAuthorizationViewController : UIViewController
    

    PKPaymentAuthorizationViewController和PKPaymentAuthorizationController扮演着相同的角色,而PKPaymentAuthorizationController并不依赖于UIKit框架。这就意味着AuthorizationController能用在视图控制器无法使用的地方(在watchOS或者 SiriKit extensions中)

    ② Apple Pay支持的Network包括哪些?

    typedef NSString * PKPaymentNetwork NS_EXTENSIBLE_STRING_ENUM;
    // American Express. 美国运通(外资信用卡)
    PKPaymentNetwork const PKPaymentNetworkAmex  
    //China Union Pay 中国银联
    PKPaymentNetwork const PKPaymentNetworkChinaUnionPay
    // Discover 发现卡(美国泛使)
    PKPaymentNetwork const PKPaymentNetworkDiscover 
    //加拿大Interac银行卡
    PKPaymentNetwork const PKPaymentNetworkInterac 
    // MasterCard 万事达
    PKPaymentNetwork const PKPaymentNetworkMasterCard 
    // Store credit and debit cards.信用卡和借记卡
    PKPaymentNetwork const PKPaymentNetworkPrivateLabel 
    // Visa.支付卡(全球)
    PKPaymentNetwork const PKPaymentNetworkVisa 
    //Japan Credit Bureau( 日本信用局)
    PKPaymentNetwork const PKPaymentNetworkJCB 
    // Suica 日本交通卡
    PKPaymentNetwork const PKPaymentNetworkSuica 
    //信用卡(日本)
    PKPaymentNetwork const PKPaymentNetworkQuicPay 
    (如果有人知道这两个的意思,可以告诉我)
    PKPaymentNetwork const PKPaymentNetworkIDCredit 
    PKPaymentNetwork const PKPaymentNetworkCarteBancaire 
    

    ③判断的顺序

    对于应用而言,第一当然是判断当前设备是否支持,如果支持再判断在应用支持的网络中是否配置了相应的支付卡

     if ([ApplePayManager isApplePaySupport]) {
            if ([ApplePayManager isContainApplePayCard]) {
                    NSLog(@"设备支持并且配置想要卡片");
            } else {
                   NSLog(@"设备支持但在支持的网络下未配置卡片");
            }
        } else {
                   NSLog(@"设备不支持或者家长控制");
        }
    
    

    步骤二 根据判断结果显示不同Apple Pay按钮

    对于设备硬件不支持或者家长控制的条件下,苹果官方推荐的做法是 ----- 不显示任何的按钮
    而对于设备支持的条件下,苹果要求通过PKPaymentButton类进行设置.

    NS_CLASS_AVAILABLE_IOS(8_3) @interface PKPaymentButton : UIButton
    + (instancetype)buttonWithType:(PKPaymentButtonType)buttonType style:(PKPaymentButtonStyle)buttonStyle;
    - (instancetype)initWithPaymentButtonType:(PKPaymentButtonType)type paymentButtonStyle:(PKPaymentButtonStyle)style NS_AVAILABLE_IOS(9_0) NS_DESIGNATED_INITIALIZER;
    @end
    

    PKPaymentButton支付按钮由两个属性:

    PKPaymentButtonType 按钮类型


    PKPaymentButtonType 按钮类型

    PKPaymentButtonStyle 按钮风格


    PKPaymentButtonStyle 按钮风格

    步骤三 点击按钮进行不同的处理

    对于在未提供支持网络下的卡片时,苹果推荐进入wallet中设置并且会自动检测是否登录iCloud账号。
    PKPassLibrary *library = [[PKPassLibrary alloc] init];
    [library openPaymentSetup];
    

    在这一步中会出现一个疑惑点:

    很多人知道在iTunes connect中添加沙盒测试账号,但是如何添加一张可使用的支付卡?

    Apple Pay Sandbox Testing

    ① 区域设置

    参考官方文档,会发现能进行沙盒测试的区域并不包括中国。所以如果设备的地区设置为中国,设置中根本没有wallet&Apple Pay一栏:


    测试区域并不包括中国

    并且打开钱包应用,发现也无法设置Apple Pay:


    钱包中并没有Apple Pay设置栏
    所以,测试的第一步,设置为苹果支持测试的区域。
    ① 添加测试卡

    设置好区域后,wallet&Apple Pay一栏会出现在设置界面中:


    wallet&Apple Pay出现了

    点击之后添加苹果推荐的测试卡号。但是我测试了好几十个都会出现以下的问题:


    添加测试卡出错

    去stack overflow上搜索答案的时候,发现有很多的人在不同区域都出现这样的问题。有些答案说要确认是测试账号或者重新登录再退出,但是试过都没有起作用,下面的答案可能有点解惑:
    stack overflow解答

    要使用真实的卡。苹果推荐不要使用开发者个人卡并且Apple Pay不支持国内的发卡行,所以使用该方法测试Apple Pay并不行的通。而且实际的开发中也并不会这么使用,具体的做法我会在后面说明。

    对于在支持网络下已配置卡时,便能直接发送请求

    PKPaymentRequest类主要的属性:

    @interface PKPaymentRequest : NSObject
    // 该平台支持的网络
    + (NSArray<PKPaymentNetwork> *)availableNetworks;
    //开发者申请的商业标识符
    @property (nonatomic, copy) NSString *merchantIdentifier;
    // 两位的ISO城市代码
    @property (nonatomic, copy) NSString *countryCode;
    // 商家支持的网络
    @property (nonatomic, copy) NSArray<PKPaymentNetwork> *supportedNetworks;
    // 商家支持的支持处理网络
    @property (nonatomic, assign) PKMerchantCapability merchantCapabilities;
    //PKPaymentSummaryItem对象显示给用户,最后一项应该是总额
    @property (nonatomic, copy) NSArray<PKPaymentSummaryItem *> *paymentSummaryItems;
    //三位的ISO货币代码
    @property (nonatomic, copy) NSString *currencyCode;
    //账单地址,默认为PKAddressFieldNone.
    @property (nonatomic, assign) PKAddressField requiredBillingAddressFields;
    @property (nonatomic, strong, nullable) PKContact *billingContact;
    //运输定制,默认为PKAddressFieldNone.
    @property (nonatomic, assign) PKAddressField requiredShippingAddressFields;
    @property (nonatomic, strong, nullable) PKContact *shippingContact 
    //商家支持的运输方法
    @property (nonatomic, copy, nullable) NSArray<PKShippingMethod *> *shippingMethods;
    //运输的显示模式,默认为PKShippingTypeShipping
    @property (nonatomic, assign) PKShippingType shippingType 
    
    ①举例而言,当用户想要购买一件300块打折50元的衬衫时:
     //shirt 300元 折扣为50元
            NSDecimalNumber *shirt = [NSDecimalNumber decimalNumberWithMantissa:300 exponent:0 isNegative:NO];
            NSDecimalNumber *discount = [NSDecimalNumber decimalNumberWithMantissa:50 exponent:0 isNegative:YES];
            NSDecimalNumber *total = [shirt decimalNumberByAdding:discount];
            
            PKPaymentSummaryItem *shirtItem = [PKPaymentSummaryItem summaryItemWithLabel:@"shirt" amount:shirt];
            PKPaymentSummaryItem *shirtDiscount = [PKPaymentSummaryItem summaryItemWithLabel:@"discount" amount:discount];
            PKPaymentSummaryItem *totalItem = [PKPaymentSummaryItem summaryItemWithLabel:@"李周" amount:total type:PKPaymentSummaryItemTypeFinal];
            
            PKPaymentRequest *request = [[PKPaymentRequest alloc] init];
            request.paymentSummaryItems = @[shirtItem,shirtDiscount,totalItem];
            request.supportedNetworks = @[PKPaymentNetworkVisa,PKPaymentNetworkChinaUnionPay,PKPaymentNetworkQuicPay];
            request.currencyCode = @"CNY";
            request.countryCode = @"CN";
            request.merchantIdentifier = @"merchant.com.lizhou.Payment";
            request.merchantCapabilities = PKMerchantCapability3DS | PKMerchantCapabilityEMV;
    

    上面的例子很容易理解,但是一眼看过去对merchantCapabilities属性有疑惑点:该值设置的到底是什么?

    该属性设置的是交易处理协议,苹果强调的是你必须支持3-D安全协议;可选是否支持EMV协议(国内要选择支持)。

    // 3-D Secure protocol.  (国外安全支付模式)Visa的
     PKMerchantCapability3DS
    //EMV protocol.协议(EMV标准,国际三大银行卡组织同时发起制定的银行卡从磁条卡向智能IC卡转移的技术标准)
     PKMerchantCapabilityEMV
    // Support for credit cards.支持信用卡
     PKMerchantCapabilityCredit
    // Support for debit cards.支持借记卡
     PKMerchantCapabilityDebit
    
    效果图
    ②添加运输的信息

    如果商家要求设置运输信息,包括姓名、联系电话、地址:

     request.requiredShippingAddressFields = PKAddressFieldPostalAddress | PKAddressFieldPhone | PKAddressFieldName;
    

    如果用户并没有设置过运输要求信息,则会出现以下界面:


    效果图

    当然,苹果推荐在出现支付界面前设置好一切信息,不要让用户做一些别的事情,以免取消支付。

    设置商家支持的运输方式:

      request.requiredShippingAddressFields = PKAddressFieldPostalAddress | PKAddressFieldPhone | PKAddressFieldName;
            PKShippingMethod *freeMethod = [PKShippingMethod summaryItemWithLabel:@"包邮" amount:[NSDecimalNumber zero]];
            freeMethod.identifier = @"Free";
            freeMethod.detail = @"最慢的咯";
            PKShippingMethod *YunMethod = [PKShippingMethod summaryItemWithLabel:@"韵达快递" amount:[NSDecimalNumber decimalNumberWithMantissa:10 exponent:0 isNegative:NO]];
            YunMethod.detail = @"2-3天哦";
            YunMethod.identifier = @"YunDa";
            request.shippingMethods = @[freeMethod,YunMethod];
    
    商家设置运输方式效果图

    最后介绍在弹出的支付弹窗中的一些操作回调方法:

    //在支付验证前,但是在用户输入密码或者Touch ID前
    - (void)paymentAuthorizationViewControllerWillAuthorizePayment:(PKPaymentAuthorizationViewController *)controller
    //选择送货地址回调
    - (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
                       didSelectShippingMethod:(PKShippingMethod *)shippingMethod
                                    completion:(void (^)(PKPaymentAuthorizationStatus status, NSArray<PKPaymentSummaryItem *> *summaryItems))completion;
    //选择送货方式回调
    - (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
                      didSelectShippingContact:(PKContact *)contact
                                    completion:(void (^)(PKPaymentAuthorizationStatus status, NSArray<PKShippingMethod *> *shippingMethods,
                                                         NSArray<PKPaymentSummaryItem *> *summaryItems))completion 
    //选择支付卡回调
    - (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
                        didSelectPaymentMethod:(PKPaymentMethod *)paymentMethod
                                    completion:(void (^)(NSArray<PKPaymentSummaryItem *> *summaryItems))completion 
    //付款成功,将数据发送给你的服务器
    - (void) paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
                            didAuthorizePayment:(PKPayment *)payment
                                     completion:(void (^)(PKPaymentAuthorizationStatus))completion
    //交易结束
    - (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller;
    
    

    3 Apple Pay实际开发

    其实看了上面官网的文档之后,我一直很好奇的是:

    钱到底是怎么没的?不需要和服务器进行沟通吗?

    后来才知道,Apple Pay只是一种支付的工具,并不参与到支付的流程中,也就是不会收取任何的费用。所以如果在国内需要使用银行卡进行Apple Pay的支付,可以去银联的官方进行产品签约,收取的手续费用当然是依据你们公司与银联的沟通情况。
    并且银联SDK内部直接对Apple Pay进行封装了,所以整个流程就是:
    ①应用内 ->订单相关数据 ->服务器 ->封装成订单 ->银联
    ②银联记录提供的订单并生成标识订单的TN号返回给服务器,发送给应用。
    ③应用调用银联SDK中的方法将TN号回传给银联,银联会将结果信息回传

    所以:
    1 在银联的SDK方法中很容易发现:如何在测试环境和生成环境中切换
    2 服务器向银联进行下单返回TN的时候还未进行支付,直到应用调用SDK中的方法才进行真正的支付
    3 银联对Apple pay支付进行了很强的封装,所以直接调用银联的返回结果状态进行判断即可


    其实之前老说Apple Pay、Apple Pay的,但是现在才能很明白其中的机制,才知道苹果提供的只是支付工具。所以在实际开发的时候一定要和相应的机构签约,而不是去想:Apple pay本身到底如何ba

    相关文章

      网友评论

      • nenhall:對公司來說使用它,需要去跟銀聯簽約?

      本文标题:Apple Pay ---官方文档整理思路以及疑惑点

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