iOS開發(fā)------Apple Pay(PassKit.framework篇)

俗話說凡事應(yīng)有始有終,所以還是決定趁空余時(shí)間將這篇Apple Pay(PassKit.framework篇)補(bǔ)充完整,萬一有相同疑問的小伙伴呢,好有個(gè)參考,也不枉花費(fèi)的時(shí)間。說實(shí)話,網(wǎng)上其實(shí)有很多介紹Apple Pay的文章,但總是感覺不太詳細(xì),在探索的過程中沒有給我太大的幫助,便把更多的時(shí)間執(zhí)著于開發(fā)文檔,由于樓主的英文能力不是很強(qiáng),也算是花了不少的時(shí)間。如果該文有什么錯(cuò)誤或者誤解,請(qǐng)指正,3Q。

工程的所有代碼已上傳至GitHub(僅供大家研究):https://github.com/RITL/RITLApplePayTest??

啟用Apple Pay

在配置完所有的證書之后,首先記得要在Xcode的項(xiàng)目中啟用Apple Pay模塊。具體位置在TARGET->Capablitiles->Apple Pay,如果配置好了Merchant IDs,那就等一小會(huì)就會(huì)自動(dòng)刷新,只需要打上勾即可,如圖。

支付驗(yàn)證控制器 -PKPaymentAuthorizationViewController

顧名思義,它就是一個(gè)支付驗(yàn)證的控制器,上圖中模態(tài)彈出的控制器其實(shí)就是PKPaymentAuthorizationViewController.

類方法-Function

下面是開發(fā)文檔中的方法,并通過我的個(gè)人理解做的介紹:

//驗(yàn)證是否能夠進(jìn)行NFC支付操作--建議模態(tài)彈出控制器的時(shí)候驗(yàn)證一下
+ (BOOL)canMakePayments;
//驗(yàn)證是否能夠支持特定的支付途徑,它的定義存在"PKConstants.h"文件中,下面會(huì)介紹一下
+ (BOOL)canMakePaymentsUsingNetworks:(NSArray *)supportedNetworks;
//iOS9_0之后才有的方法,不過個(gè)人覺得不太需要擔(dān)心,畢竟銀聯(lián)支持Apple Pay是iOS9_2之后的
//出了能夠驗(yàn)證特定的支付途徑之外,還可以驗(yàn)證支付卡的類型
+ (BOOL)canMakePaymentsUsingNetworks:(NSArray *)supportedNetworks                         capabilities:(PKMerchantCapability)capabilties NS_AVAILABLE_IOS(9_0);//代理屬性,對(duì)應(yīng)的協(xié)議

后面也會(huì)有記錄

@property (nonatomic, assign, nullable) id

 delegate;//唯一正確的初始化方法(后面的宏告訴我這是指定的初始化方法)//記得是參數(shù)是nonull(非nil)修飾的呢,如果此參數(shù)不正確,那么初始化方法返回的就是nil

- (instancetype)initWithPaymentRequest:(PKPaymentRequest *)request NS_DESIGNATED_INITIALIZER;

?

支持的支付途徑-SupportedNetworks

下面是定義在PKConstants.h里面的支持的支付途徑

//美國運(yùn)通(表示沒聽說過0.0 可能和中國的銀聯(lián)差不多吧)
extern NSString * const PKPaymentNetworkAmex NS_AVAILABLE(NA, 8_0);//中國銀聯(lián)(這個(gè)熟,可以看出要在中國使用銀聯(lián)支持的Apple Pay至少要9.2系統(tǒng))extern NSString * const PKPaymentNetworkChinaUnionPay NS_AVAILABLE(NA, 9_2);//萬事達(dá)信用卡
extern NSString * const PKPaymentNetworkMasterCard NS_AVAILABLE(NA, 8_0);//商城的信用卡和借記卡
extern NSString * const PKPaymentNetworkPrivateLabel NS_AVAILABLE(NA, 9_0);//Visa卡extern NSString * const PKPaymentNetworkVisa NS_AVAILABLE(NA, 8_0);//下面兩個(gè)不太懂,看不明白..如果有知道的小伙伴們請(qǐng)告知一下
extern NSString * const PKPaymentNetworkDiscover NS_AVAILABLE(NA, 9_0);
extern NSString * const PKPaymentNetworkInterac NS_AVAILABLE(NA, 9_2);

?

支持支付卡類型-Capabilties

定義在PKPaymentRequest.h的PKMerchantCapability(支付卡)類型

typedef NS_OPTIONS(NSUInteger, PKMerchantCapability) {
   PKMerchantCapability3DS,        //美國的一種卡類型,必須支持!
   PKMerchantCapabilityEMV,        //歐洲的卡
   PKMerchantCapabilityCredit,     //信用卡
   PKMerchantCapabilityDebit       //借記卡
} NS_ENUM_AVAILABLE(NA, 8_0);

?

支付請(qǐng)求-PKPaymentRequest

作為唯一指定PKPaymentAuthorizationViewController的初始化參數(shù),它的設(shè)置直接關(guān)系到控制器的生成。

過程中,如果發(fā)現(xiàn)初始化的控制器為nil,那么就需要回來看看這個(gè)參數(shù)是否設(shè)置正確,百分之90以上的概率就是它的初始化問題導(dǎo)致了控制器的初始化失敗。

下面是開發(fā)文檔中的PKPaymentRequest對(duì)象的屬性

必須設(shè)置的屬性

//必填,在開發(fā)者申請(qǐng)的證書merchantIdentifier的名字@property(nonatomic, copy)NSString*merchantIdentifier;//必填,要求兩字母的 ISO 3166 國家代碼,比如中國為"CN"@property(nonatomic, copy)NSString*countryCode;//必填,一個(gè)存放SupportedNetworks的數(shù)據(jù),具體值上面以列出@property(nonatomic, copy)NSArray *supportedNetworks;//必填,支持的Capabilties(支付卡類型),具體值上面以列出,可以通過|來支持多種類型@property(nonatomic,assign) PKMerchantCapability merchantCapabilities;//必填,存放PKPaymentSummaryItem(支付信息)的數(shù)組,并且最后一個(gè)必須為總價(jià)格,后面會(huì)有介紹@property(nonatomic, copy)NSArray *paymentSummaryItems;//必填,三字母的 ISO 4217 貨幣代碼,比如人民幣為"CNY"@property(nonatomic, copy)NSString*currencyCode;

可選設(shè)置的屬性

//表示必須需要填寫的訂單地址,默認(rèn)為PKAddressFieldNone(也就是什么也不寫),具體分類下面有介紹
@property (nonatomic, assign) PKAddressField requiredBillingAddressFields;//必須的收貨人聯(lián)系方式,默認(rèn)為PKAddressFieldNone
@property (nonatomic, assign) PKAddressField requiredShippingAddressFields;
typedef NS_OPTIONS(NSUInteger, PKAddressField) {
PKAddressFieldNone              //默認(rèn)是不需要任何地址
PKAddressFieldPostalAddress     // 一個(gè)完整的地址,包含國家,郵政編碼,省/區(qū),城市,街道,姓名等
PKAddressFieldPhone             //電話
PKAddressFieldEmail             //郵箱
PKAddressFieldName NS_ENUM_AVAILABLE_IOS(8_3)//姓名
PKAddressFieldAll                   //包含以上所有信息} NS_ENUM_AVAILABLE(NA, 8_0);
//賬單的地址,可能為nil,至于ABRecordRef為什么被廢棄,是ABAddressBook在iOS9.0已經(jīng)不被推薦使用了@property (nonatomic, assign, nullable) ABRecordRef billingAddress NS_DEPRECATED_IOS(8_0, 9_0, "Use billingContact instead");
@property (nonatomic, retain, nullable) PKContact *billingContact NS_AVAILABLE_IOS(9_0);//送貨聯(lián)系地址,可能為nil
@property (nonatomic, assign, nullable) ABRecordRef shippingAddress NS_DEPRECATED_IOS(8_0, 9_0, "Use shippingContact instead");
@property (nonatomic, retain, nullable) PKContact *shippingContact NS_AVAILABLE_IOS(9_0);//存放送貨方式的數(shù)組,比如順豐,RILT..等
@property (nonatomic, copy, nullable) NSArray

 *shippingMethods;//用以保存所需信息的屬性,可能為訂單或這書的唯一標(biāo)識(shí)符,它將被保存在PKPaymentToken中@property (nonatomic, copy, nullable) NSData *applicationData;

//送貨類型
@property (nonatomic, assign) PKShippingType shippingType NS_AVAILABLE_IOS(8_3);#pragma - 送貨方法 定義在"PKPaymentRequest.h"typedef NS_ENUM(NSUInteger, PKShippingType) {
PKShippingTypeShipping,     //默認(rèn)為第三方發(fā)貨,比如順豐、圓通等..
PKShippingTypeDelivery,     //賣家自己配送
PKShippingTypeStorePickup,  //場家直送
PKShippingTypeServicePickup //買家自提} NS_ENUM_AVAILABLE(NA, 8_3);

?

實(shí)例:PKPaymentRequest對(duì)象

- (PKPaymentRequest *)paymentRequest {
PKPaymentRequest * payRequest = [PKPaymentRequest new];    //相關(guān)配置
_payNetworks = @[PKPaymentNetworkVisa,PKPaymentNetworkChinaUnionPay,PKPaymentNetworkMasterCard];//支持的支付網(wǎng)絡(luò)
//證書identifier
payRequest.merchantIdentifier = @"merchant.com.yue.ApplePay";    //兩字母的 ISO 3166 國家代碼
payRequest.countryCode = @"CN";    //三字母的 ISO 4217 貨幣代碼
payRequest.currencyCode = @"CNY";    //支持的支付網(wǎng)絡(luò)
payRequest.supportedNetworks = _payNetworks;    //支持的銀行卡類型
payRequest.merchantCapabilities = PKMerchantCapability3DS | PKMerchantCapabilityDebit | PKMerchantCapabilityCredit | PKMerchantCapabilityEMV;    //支付信息
payRequest.paymentSummaryItems = self.paymentSummaryItems;    //必須要有的賬單地址選項(xiàng),默認(rèn)為None
payRequest.requiredBillingAddressFields = PKAddressFieldPostalAddress;    //必須要有的收貨人聯(lián)系方式選項(xiàng),默認(rèn)為None
payRequest.requiredShippingAddressFields = PKAddressFieldPhone | PKAddressFieldPostalAddress;    //送貨方式,默認(rèn)為nil
payRequest.shippingMethods = [self shippingMethods];    //送貨類型
payRequest.shippingType = PKShippingTypeDelivery;
payRequest.applicationData = [@"我是RITL,來收費(fèi)啦" dataUsingEncoding:NSUTF8StringEncoding];    return payRequest;
}

?

支付的文本對(duì)象-PKPaymentSummaryItem

也就是在上圖中單價(jià),數(shù)量等展示的選項(xiàng),下面是開發(fā)文檔中的方法以及屬性:

/*便利構(gòu)造器*/
+ (instancetype)summaryItemWithLabel:(NSString *)label amount:(NSDecimalNumber *)amount;
+ (instancetype)summaryItemWithLabel:(NSString *)label amount:(NSDecimalNumber *)amount type:(PKPaymentSummaryItemType)type NS_AVAILABLE(NA, 9_0);/*標(biāo)簽..比如單價(jià)、數(shù)量等..*/
@property (nonatomic, copy) NSString *label;/*當(dāng)前標(biāo)簽的數(shù)組,與NSNumber類型相似,存儲(chǔ)浮點(diǎn)型的對(duì)象(與Java中的大整數(shù)和大浮點(diǎn)型數(shù)字是一樣的)*/
@property (nonatomic, copy) NSDecimalNumber *amount;/*表示當(dāng)前ammount的類型*/@property (nonatomic, assign) PKPaymentSummaryItemType type NS_AVAILABLE(NA, 9_0);
typedef NS_ENUM(NSUInteger, PKPaymentSummaryItemType) {
PKPaymentSummaryItemTypeFinal,    //表示一個(gè)最終的數(shù)目,可以理解為一個(gè)確認(rèn)的數(shù)目,通常買東西都是固定的吧
PKPaymentSummaryItemTypePending   //表示一個(gè)預(yù)計(jì)的數(shù)目,可變的,比如我們打出租的時(shí)候,價(jià)格不是固定的起步價(jià)吧?} NS_ENUM_AVAILABLE(NA, 9_0);

?

實(shí)例:PKPaymentSummaryItem

- (NSArray

 *)paymentSummaryItems {

if (_paymentSummaryItems == nil)     {        //設(shè)置付款選項(xiàng)
PKPaymentSummaryItem * priceItem = [PKPaymentSummaryItem summaryItemWithLabel:@"單價(jià)" amount:[NSDecimalNumber decimalNumberWithString:self.priceTextField.text]];
PKPaymentSummaryItem * numberItem = [PKPaymentSummaryItem summaryItemWithLabel:@"數(shù)量" amount:[NSDecimalNumber decimalNumberWithString:self.numberTextField.text]];        //計(jì)算總價(jià)字符串,最后一個(gè)必須是總價(jià)
NSString * sumPrice = [NSString stringWithFormat:@"%@",@(self.priceTextField.text.integerValue * self.numberTextField.text.integerValue)];
PKPaymentSummaryItem * sumItem = [PKPaymentSummaryItem summaryItemWithLabel:@"RITL" amount:[NSDecimalNumber decimalNumberWithString:sumPrice]];
_paymentSummaryItems = @[priceItem,numberItem,sumItem];
}
return _paymentSummaryItems;
}

?

配送方法-PKShippingMethod

PKShippingMethod類繼承自PKPaymentSummaryItem類,但是多了兩個(gè)屬性:

@property (nonatomic, copy, nullable) NSString *identifier;//這個(gè)用來類似備注功能的屬性,可以不寫
@property (nonatomic, copy, nullable) NSString *detail;
實(shí)例:PKShippingMethod
/// 送貨方式,默認(rèn)為第一個(gè)
- (NSArray

 *)shippingMethods {

if (_shippingMethods == nil)     {
//設(shè)置收貨人送貨選項(xiàng)
PKShippingMethod * method1 = [PKShippingMethod shippingMethodWithLabel:@"順豐" amountString:@"20" identifier:@"shunfeng" detail:@"預(yù)計(jì)兩天后到達(dá)"];
PKShippingMethod * method2 = [PKShippingMethod shippingMethodWithLabel:@"圓通" amountString:@"18" identifier:@"yuantong" detail:@"預(yù)計(jì)一天后發(fā)貨"];
PKShippingMethod * method3 = [PKShippingMethod shippingMethodWithLabel:@"RITL" amountString:@"5" identifier:@"RITL" detail:@"估計(jì)就沒了.."];
_shippingMethods = @[method1,method2,method3];        //默認(rèn)
_payModel.shipMethod = method1;
}
return _shippingMethods;
}


?


驗(yàn)證控制器協(xié)議-PKPaymentAuthorizationViewControllerDelegate

必須實(shí)現(xiàn)的協(xié)議方法

/*  *   進(jìn)行驗(yàn)證并進(jìn)行回調(diào),并通過回調(diào)completion告知控制器是否成功,或失敗原因 *   與銀聯(lián)的交互應(yīng)該在此  */
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller                        didAuthorizePayment:(PKPayment *)payment                                 completion:(void (^)(PKPaymentAuthorizationStatus status))completion;/* 驗(yàn)證完畢或者直接點(diǎn)擊取消進(jìn)行的回調(diào) */- (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller;
可選實(shí)現(xiàn)的協(xié)議方法
//在Touchid 或者 password(有的銀行還是需要密碼驗(yàn)證的呢) 驗(yàn)證之后的回調(diào),點(diǎn)擊取消則不會(huì)響應(yīng)該方法
- (void)paymentAuthorizationViewControllerWillAuthorizePayment:(PKPaymentAuthorizationViewController *)controller NS_AVAILABLE_IOS(8_3) {  }
//選中一個(gè)送貨方式后進(jìn)行的回調(diào)
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller                    didSelectShippingMethod:(PKShippingMethod *)shippingMethod                                 completion:(void (^)(PKPaymentAuthorizationStatus status, NSArray

 *summaryItems))completion {

//用來記錄送貨方式
_payModel.shipMethod = shippingMethod;    //進(jìn)行回調(diào)更新數(shù)據(jù)
completion(PKPaymentAuthorizationStatusSuccess,@[shippingMethod]);
}
//選中一個(gè)送貨聯(lián)系人
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller                   didSelectShippingContact:(PKContact *)contact                                 completion:(void (^)(PKPaymentAuthorizationStatus status, NSArray

 *shippingMethods,                                                     NSArray

 *summaryItems))completion {

//記錄配送聯(lián)系人
_payModel.contact = contact;    //進(jìn)行回調(diào)更新數(shù)據(jù)
completion(PKPaymentAuthorizationStatusSuccess,self.shippingMethods,self.paymentSummaryItems);
}
// 選中一個(gè)新的支付方式
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller                     didSelectPaymentMethod:(PKPaymentMethod *)paymentMethod                                 completion:(void (^)(NSArray

 *summaryItems))completion {

//記錄支付方式
_payModel.paymentMethod = paymentMethod;    //進(jìn)行回調(diào)更新數(shù)據(jù)
completion(self.paymentSummaryItems);
}

?


真正實(shí)現(xiàn)銀聯(lián)交互

說白了,Apple Pay只是作為了一個(gè)支付入口,真正實(shí)現(xiàn)支付作用的還是服務(wù)端,至于如何真正的完成支付,請(qǐng)根據(jù)下面兩個(gè)鏈接進(jìn)行控件的下載以及CSR證書的配置(CSR證書如何使用,歡迎關(guān)注iOS開發(fā)——Apple Pay(證書配置篇)注冊(cè)App Pay RSA證書模塊),在此吐個(gè)槽,下面這兩個(gè)網(wǎng)址真TM難找…(為了避免好久之后網(wǎng)址不對(duì),記錄一下當(dāng)前時(shí)間2016-08-24)

下載Apple Pay的開發(fā)控件,壓縮文件里面有詳細(xì)的規(guī)范pdf

https://open.unionpay.com/ajweb/help/file/techFile?productId=80?

配置CSR的網(wǎng)址在下面,因?yàn)闃侵鳑]法申請(qǐng)商戶賬號(hào),所以想使用Apple Pay進(jìn)行支付的朋友們,注冊(cè)賬號(hào)完畢后進(jìn)行注冊(cè)吧.

https://merchant.unionpay.com?

文/作者:RITL

博客地址:http://blog.csdn.net/runintolove/article/details/52217360?



歡迎關(guān)注微信公眾號(hào):iOS面向編碼

QQ群:427763454

歡迎你的投稿,展示的你的技術(shù)文章:812920365@qq.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,491評(píng)論 3 416
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評(píng)論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,708評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,186評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,409評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,939評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,774評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,976評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評(píng)論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,209評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評(píng)論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,650評(píng)論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,958評(píng)論 2 373

推薦閱讀更多精彩內(nèi)容