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

之前把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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,431评论 25 707
  • Apple Pay 一个方便 & 安全的移动支付技术,让用户完成他们的支付环节并把支付相关的信息告诉你 只可以购买...
    skingtree阅读 1,773评论 0 4
  • 移动支付的现状 今年二月份,苹果在中国大陆隆重推出了其手机支付工具,Apple Pay。该功能是苹果携手中国银联,...
    苦食轩主人阅读 1,058评论 2 2
  • 因为各种原因,笔者又踏上了寻找新工作机会的道路,10天左右下来面试了7家单位,顺利拿到了4家offer,今天得以有...
    君哥聊编程阅读 3,035评论 13 22
  • 我的一把吉他 那个小小的声洞 恰似一双你那 水汪汪的眼 能对我诉说着柔情蜜意 那些年,那些日子 那年有风有雨 吉他...
    蓝松在云端阅读 233评论 0 1