iOS-Apple Pay準備工作-申請MerchantID及對應證書
在App中接入Apple Pay有兩種方式,一種是使用CUP SDK等第三方SDK束亏,另一種就是使用iOS的PassKit Framework和銀聯(lián)的接口接入席里。前一種方法叔磷,開發(fā)成本低,接入簡單奖磁,但對于Payment Sheet定制化程度不夠改基。而第二種開發(fā)成本較高。需要對Payment Sheet的邏輯和異常情況做好相應的UI處理咖为。同時在后臺也需要做好支付信息解密秕狰、銀聯(lián)接口的交互以及訂單狀態(tài)處理嵌洼。
這里主要介紹第二種方式,第一種方式可以到相關(guān)網(wǎng)站查看SDK集成指南封恰。
Demo 地址 https://github.com/alanwangke213/ApplePayDemo.git
Apple Pay 授權(quán)流程圖
授權(quán)流程圖
Apple Pay 的集成需要做好版本和機型的適配麻养。Apple Pay 只能運作于iPhone 9.2以上版本的iPhone6/6p及以上型號或版本在2.1以上的Apple Watch的設備上。
一诺舔、為App設置Apple Pay功能
1.在開發(fā)中賬號中注冊一個merchant ID鳖昌;
2.創(chuàng)建CSR(CertificateSigningRequest)證書并提交到開發(fā)中賬號中;
3.在Xcode的Capabilities里使能Apple Pay低飒,并添加merchant ID
Capabilities中使能Apple Pay
二许昨、Progress flow
1.加載內(nèi)購商品的支付方式時,如果當前設備不支持Apple Pay需要隱藏Apple Pay支付按鈕
applePayButton.hidden = ![PKPaymentAuthorizationViewController canMakePayments];
2.如果當前設備未設置/當前設備設置的支付銀行卡無法在商戶提供的支付平臺支付褥赊,則隱藏Apple Pay支付按鈕糕档,可以顯示Set Apple Pay按鈕(可選),提醒用戶進行設置Apple Pay拌喉。
applePayButton.hidden= ![PKPaymentAuthorizationViewControllercanMakePaymentsUsingNetworks:self.supportedPaymentNetworks];
applePaySetBtn.hidden = !applePaySetBtn.hidden;
注:顯示的Apple Pay按鈕和Set Apple Pay按鈕圖片需要按照官方文檔 要求設置
3.導入PassKit框架
Apple Pay 所需的類都包含在PassKit框架中速那,需要導入該框架
#import <PassKit/PassKit.>
4.創(chuàng)建一個PKPaymentRequest,該request需要包括所有商品和服務費用的,例如郵寄費尿背,稅或者折扣等
// 1. 創(chuàng)建 payment rquestPKPaymentRequest *request = [[PKPaymentRequest alloc] init];
request.merchantIdentifier = ApplePaySwagMerchantID;
request.supportedNetworks = self.supportedPaymentNetworks;
request.merchantCapabilities = PKMerchantCapabilityCredit|PKMerchantCapabilityDebit|PKMerchantCapability3DS|PKMerchantCapabilityEMV;
request.countryCode = @"CN";
request.currencyCode = @"CNY";
需要根據(jù)不同的商品類型來設置requiredShippingAddressFields端仰,如果使電子/虛擬商品(一般為提取/下載鏈接),則顯示聯(lián)系人郵箱田藐。如果為實物荔烧,則顯示聯(lián)系人地址、手機號以及郵箱
// 判斷requiredShippingAddressFields
switch (_swag.swagType) {
case Delivered:
request.requiredShippingAddressFields = PKAddressFieldAll;
break;
case Electronic:
request.requiredShippingAddressFields = PKAddressFieldEmail;
break;
}
根據(jù)不同的商品類型汽久,也判斷是否顯示郵寄方式:
// request 的 shippingMethods數(shù)組NSMutableArray <PKShippingMethod *>*shippingMethods = [NSMutableArray array];
switch (_swag.swagType) {
case Delivered:
for (ShippingMethod *shippingMethod in self.shipMethods) {
PKShippingMethod *method = [[PKShippingMethod alloc] init];
method.label = shippingMethod.title;
method.amount = shippingMethod.price;
method.identifier = shippingMethod.title;
method.detail = shippingMethod.methodDescription;
[shippingMethods addObject:method];
}
_shippingMethods = shippingMethods;
request.shippingMethods = shippingMethods;
break;
case Electronic:
break;
}
圖2A為實體商品鹤竭,顯示了送貨地址,郵寄方式以及收貨人聯(lián)系方式景醇,圖2B為虛擬物品臀稚,只顯示了用戶的郵箱
// 設置paymentSummaryItem數(shù)組
_paymentSummaryItems = [self calculateSummaryItemsFromSwag:_swag withShippingMethod:self.shippingMethods.firstObject];
request.paymentSummaryItems = _paymentSummaryItems;
用于顯示商品列表,其中paymentSummaryItem的lastObject為商家Item啡直,amount為所有商品烁涌、tax、shipping以及discounts的總和酒觅。
Demo中的calculateSummaryItemsFromSwag: withShippingMethod:方法提供了計算summaryItems數(shù)組的邏輯撮执。
5.展示支付授權(quán)界面PKAuthorizationViewController,該界面需要將request和需要的提示信息展示給用戶舷丹,例如shipping或者billing address抒钱。
// 授權(quán)控制權(quán)
PKPaymentAuthorizationViewController *paymentVC = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:request];
paymentVC.delegate = self;
[self presentViewController:paymentVC animated:YES completion:nil];
6.選擇付款卡會push出選擇付款卡控制器,顯示所有已綁定的銀行卡。當選擇卡片會調(diào)用代理方法
paymentAuthorizationViewController:didSelectPaymentMethod:completion:該方法谋币,需要實現(xiàn)completion完成回調(diào)仗扬,否則會卡在payment processing界面
付款卡列表
7.點擊送貨cell會push出送貨地址列表界面,選擇送貨地址后會調(diào)用paymentAuthorizationViewController:didSelectShippingMethod:completion:代理方法
收貨地址列表
該方法蕾额,也需要實現(xiàn)completion完成回調(diào)早芭,否則會卡在payment processing界面
8.點擊 郵寄方式cell會Push出Shipping method列表
郵寄方式列表
當選擇其它郵寄方式會調(diào)用 paymentAuthorizationViewController :didSelectShippingMethod : completion:代理方法,在方法中需要做好相關(guān)的request.paymentSummaryItems數(shù)組诅蝶,重新計算列表信息和總價退个。Demo中的calculateSummaryItemsFromSwag: withShippingMethod:方法提供了計算該數(shù)組的基本邏輯。
9.當用戶輸入TouchID调炬,且授權(quán)通過后语盈,Apple Pay 將使用Secure Element安全元件芯片處理銀行卡信息,再有secure enclave產(chǎn)生獨特的授權(quán)標志符
10.將授權(quán)標志符發(fā)送給蘋果的服務器缰泡,再使用MerChante identifier certificate進行二次加密后將token反回給app做其它處理刀荒。
11.在paymentAuthorizationViewController:didAuthorizePayment: completion:代理方法中可以獲取payment信息,其中包涵了payment token棘钞。
12.獲取到payment token后可以將其發(fā)送給后臺進行其他處理
授權(quán)處理中
授權(quán)失敗
授權(quán)成功
在授權(quán)成功之后將支付相關(guān)信息發(fā)送到Apple服務器進行加密缠借,再通過代理方法paymentAuthorizationViewController:didAuthorizePayment:completion:獲得到PKPayment中的PKPaymentToken。
這個是Apple Pay的授權(quán)流程的介紹武翎,后續(xù)的還需要將paymentToken中的paymentData字段數(shù)據(jù)(加密過的)發(fā)送到自己的服務器烈炭。服務器進行解密操作之后提取出需要的信息溶锭,組織好銀聯(lián)接口報文宝恶,完成交易。
上述的paymentData的內(nèi)容是Json格式的二進制流趴捅,服務器在收到數(shù)據(jù)后進行解析垫毙。其中的header.wrappedKey是使用非對稱加密算法加密過的對稱密鑰。使用在蘋果開發(fā)者后臺配置merchantID時的私鑰進行解密拱绑,會得到對稱密鑰综芥。使用對稱密鑰對data字段包含的加密數(shù)據(jù)進行解密,可以得到Apple返回的與支付相關(guān)的信息猎拨。此信息時加密的膀藐,包含了用戶支付的卡號和PIN碼等信息,理論上只有銀聯(lián)能解密出真正的內(nèi)容红省。商戶看不到具體的信息额各。服務器端將這些信息組織成銀聯(lián)需要的報文內(nèi)容,然后調(diào)用銀聯(lián)的扣款接口吧恃,完成扣款虾啦。
注意:paymentData里面有一個交易金額字段,該字段返回的數(shù)據(jù)并不是實際支付的金額。在組織銀聯(lián)報文的時候一定要注意不能直接使用該字段作為扣款金額的值傲醉。
在調(diào)用銀聯(lián)扣款接口的時候需要注意蝇闭,在組織好報文并調(diào)用銀聯(lián)接口發(fā)送給銀聯(lián)之后,銀聯(lián)的接口返回結(jié)果同時有同步和異步兩種方式硬毕。如果同步返回成功呻引,則表示銀聯(lián)成功收到并開始處理該扣款請求,并不代表扣款成功吐咳“撸扣款成功實在異步里返回的。比如挪丢,銀行卡被凍結(jié)蹂风,PIN錯誤,余額不足等原因可能造成扣款失敗乾蓬』葑模可以在調(diào)用銀聯(lián)扣款接口后,如果幾秒內(nèi)未收到異步回調(diào)任内,使用銀聯(lián)的交易流水號去輪詢調(diào)用銀聯(lián)的交易狀態(tài)接口來確保此次交易結(jié)果撵渡。