最近的項(xiàng)目需求中有集成ApplePay的需求渡蜻,先前看了點(diǎn)資料褐荷,覺得過(guò)程so easy,沒(méi)太多需要注意的地方饭入,也就沒(méi)太當(dāng)回事嵌器,哪知到了真正集成的時(shí)候,簡(jiǎn)直……[ sàng xīn bìng kuáng ]
集成apple pay需要的資料:
https://developer.apple.com/apple-pay/
about Apple Pay
Apple Pay 安全性與隱私政策概覽
一谐丢、集成前置步驟
二爽航、集成
三、坑
一乾忱、集成前置步驟:
這里比較簡(jiǎn)單讥珍,主要是支付證書的配置,就不細(xì)寫了窄瘟,進(jìn)入開發(fā)者中心:
- 注冊(cè) Merchant IDs(商戶ID)衷佃,上傳CSR文件(鑰匙鏈證書助理生成),生成支付證書
- 在App IDs中創(chuàng)建或找到已有的App ID 進(jìn)行編輯Edit,打開Apple Pay功能蹄葱,Edit氏义,選中已經(jīng)生成好的Merchant ID(可以多選),點(diǎn)Continue
- 在Xcode中配置锄列,TARGETS -->Capabilities,找到Apple Pay 打開這個(gè)功能
如果這些步驟沒(méi)有問(wèn)題的話惯悠,那么現(xiàn)在的看到的是這樣:
如果Steps里面的3個(gè)小勾都有的話邻邮,那就說(shuō)明配置OK。
同時(shí)項(xiàng)目中出現(xiàn)了這個(gè)東東:
配置沒(méi)有問(wèn)題了吮螺,那么接下來(lái)就要寫代碼了
二饶囚、集成
1、對(duì)當(dāng)前支付環(huán)境進(jìn)行判斷鸠补,是否可以進(jìn)行蘋果支付
- (BOOL)isCanMakeApplePayments {
if (IOS9.2) {
if ([PKPaymentAuthorizationViewController canMakePayments]) {
if ([PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[PKPaymentNetworkChinaUnionPay]]) {
return YES;
} else {
return NO;
}
}
}
return NO;
}
2萝风、創(chuàng)建支付請(qǐng)求
PKPaymentRequest *request = [[PKPaymentRequest alloc] init];
// 配置商家ID
request.merchantIdentifier = @"merchant.mailegouapplepay.com";
// 配置貨幣代碼, 以及國(guó)家代碼
request.countryCode = @"CN";
request.currencyCode = @"CNY";
// 配置請(qǐng)求支持的支付網(wǎng)絡(luò) 銀聯(lián)
request.supportedNetworks = @[PKPaymentNetworkChinaUnionPay];
// 配置商戶的處理方式 3DS必須支持
request.merchantCapabilities = PKMerchantCapabilityEMV|PKMerchantCapability3DS;
// 配置購(gòu)買的商品列表
PKPaymentSummaryItem *orderAmout = [PKPaymentSummaryItem summaryItemWithLabel:@"訂單金額" amount:[NSDecimalNumber decimalNumberWithString:self.payModel.orderSum]];
PKPaymentSummaryItem *totalAmount = [PKPaymentSummaryItem summaryItemWithLabel:@"麥樂(lè)購(gòu)" amount:[NSDecimalNumber decimalNumberWithString:self.payModel.orderSum]];
// 注意: 支付列表最后一個(gè), 代表匯總
request.paymentSummaryItems = @[orderAmout,totalAmount];
以上這些配置是必須的,當(dāng)然還有一些可選的紫岩,比如物流信息规惰、發(fā)票地址等等,像下面這樣:
// 是否顯示發(fā)票收貨地址, 顯示哪些選項(xiàng)
request.requiredBillingAddressFields = PKAddressFieldAll;
// 是否顯示快遞地址, 顯示哪些選項(xiàng)
request.requiredShippingAddressFields = PKAddressFieldAll;
// 配置快遞方式NSArray<PKShippingMethod *>
NSDecimalNumber *price2 = [NSDecimalNumber decimalNumberWithString:@"18.0"]; // 郵費(fèi)
PKShippingMethod *method = [PKShippingMethod summaryItemWithLabel:@"順豐快遞" amount:price2];
method.detail = @"24小時(shí)內(nèi)送到";
method.identifier = @"shunfeng";
NSDecimalNumber *price3 = [NSDecimalNumber decimalNumberWithString:@"0.1"];
PKShippingMethod *method2 = [PKShippingMethod summaryItemWithLabel:@"韻達(dá)快遞" amount:price3];
method2.identifier = @"yunda";
method2.detail = @"送貨上門";
request.shippingMethods = @[method, method2];
// 配置快遞的類型
request.shippingType = PKShippingTypeStorePickup;
// 添加一些附加數(shù)據(jù)
request.applicationData = [@"buyID=12345" dataUsingEncoding:NSUTF8StringEncoding];
3泉蝌、配置完成歇万,驗(yàn)證支付授權(quán):
實(shí)現(xiàn) PKPaymentAuthorizationViewControllerDelegate 代理,必須實(shí)現(xiàn)的兩個(gè)代理方法為:
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
didAuthorizePayment:(PKPayment *)payment
completion:(void (^)(PKPaymentAuthorizationStatus status))completion
{
//支付所需要的token
NSData *data = payment.token.paymentData;
NSString *paymentDataStr = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
//收貨人地址
NSString *street = payment.shippingContact.postalAddress.street;
//收貨人電話
NSString *phone = payment.shippingContact.phoneNumber.stringValue;
//收貨人郵編
NSString *post = payment.shippingContact.postalAddress.postalCode;
//收貨人姓名
NSString *familyName = payment.shippingContact.name.familyName;
NSString *givenName = payment.shippingContact.name.givenName;
/** 支付完成后需要在此代理方法中告訴蘋果支付結(jié)果用于UI顯示勋陪,如:*/
// 支付成功 PKPaymentAuthorizationStatus是枚舉贪磺,里面有各種支付結(jié)果狀態(tài)
completion(PKPaymentAuthorizationStatusSuccess);
}
// 當(dāng)用戶授權(quán)成功, 或者取消授權(quán)時(shí)調(diào)用
- (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller {
[self dismissViewControllerAnimated:controller completion:nil];
}
三、坑
1诅愚、PKPaymentNetworkChinaUnionPay
if ([PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[PKPaymentNetworkChinaUnionPay]]) {
return YES;
}
PKPaymentNetworkChinaUnionPay這個(gè)字段是9.2增加的寒锚,也就是說(shuō)國(guó)內(nèi)使用銀聯(lián)渠道進(jìn)行apple pay SDK需要是9.2以上,在這個(gè)判斷之前需要對(duì)系統(tǒng)版本加以判斷违孝,以免程序崩潰刹前。
2、[PKPaymentAuthorizationViewController canMakePayments]
由于項(xiàng)目中比較復(fù)雜的業(yè)務(wù)邏輯和成年累月的積累雌桑,舊的結(jié)構(gòu)不好改動(dòng)喇喉,一開始這個(gè)判斷我是在選擇蘋果支付以后再去執(zhí)行,如果返回NO校坑,告訴用戶不可以進(jìn)行apple pay拣技,返回YES就繼續(xù),很驚奇的發(fā)現(xiàn)耍目,在我的手機(jī)上(iPhone6 9.2)上过咬,這個(gè)方法每次返回的不一樣,有時(shí)候YES 有時(shí)候NO制妄,即使我已經(jīng)在Wallet中綁上了符合要求的銀聯(lián)卡,在完全符合支付條件的情況下泵三,這個(gè)方法還是會(huì)返回NO耕捞,而且是一陣一陣的衔掸,某一個(gè)時(shí)間內(nèi),全部是NO俺抽。就像神經(jīng)病人發(fā)作一樣敞映。后面參考了一些別人Demo,我把這個(gè)判斷放在了ViewDidLoad磷斧。返回NO就隱藏apple pay的選項(xiàng),YES照常進(jìn)行振愿。這時(shí)這個(gè)方法的判斷結(jié)果基本都是準(zhǔn)確的,極偶爾的情況下會(huì)返回跟預(yù)想不一致的情況弛饭。到現(xiàn)在還沒(méi)有找到原因~~希望后面可以找到冕末。
3、代理方法不執(zhí)行
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
didAuthorizePayment:(PKPayment *)payment
completion:(void (^)(PKPaymentAuthorizationStatus status))completion;
這個(gè)代理方法是在彈出了PKPaymentAuthorizationViewController以后侣颂,按了正確的指紋或者輸入密碼后執(zhí)行的(某些銀行的卡還需要在輸入指紋后輸入銀行卡支付密碼)档桃。都輸入以后,等了2-3秒憔晒,PKPaymentAuthorizationViewController dismiss了藻肄,而上面的代理方法沒(méi)有執(zhí)行。這時(shí)第一就是檢查一下代理的設(shè)置是否正確拒担,如何確定呢嘹屯,就是看另一個(gè)代理方法
- (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller;
如果這個(gè)方法在取消時(shí)正常執(zhí)行,不要著急从撼,十有八九是蘋果的服務(wù)器抽抽了州弟,等一陣子就好了,等多長(zhǎng)時(shí)間估計(jì)喬布斯也不知道谋逻。
4呆馁、如圖所示
彈出PKPaymentAuthorizationViewController控制器后,下方一直顯示正在處理的字樣毁兆,而不是用Touch ID支付的指紋圖標(biāo)浙滤,經(jīng)常這個(gè)圈轉(zhuǎn)一會(huì)程序就崩潰掉了。這時(shí)需要看看是不是除了必須實(shí)現(xiàn)的這兩個(gè)代理方法气堕,是不是還實(shí)現(xiàn)了其它非必須實(shí)現(xiàn)的代理方法并且沒(méi)有按要求實(shí)現(xiàn)纺腊。因?yàn)閍pple pay這一塊的代理方法名字比較長(zhǎng),長(zhǎng)的也比較像茎芭,需要認(rèn)真檢查一下揖膜。
5、自己碰到的奇怪符號(hào)
后面返回的json中梅桩,有這樣一個(gè)東東
在控制臺(tái)里不顯示壹粟,復(fù)制出來(lái)也沒(méi)有,只有用Beyond Compare這個(gè)軟件才能看到。這個(gè)看不見的符號(hào)導(dǎo)致請(qǐng)求失敗趁仙。目前還不知道這個(gè)鬼符號(hào)是什么鬼洪添。
6、與第三方支付服務(wù)提供商對(duì)接
- 1雀费、一定要確認(rèn)好請(qǐng)求第三方sdk時(shí)的參數(shù)
比如我們這邊干奢,主要是跨境電商,對(duì)于我們對(duì)接的第三方支付服務(wù)提供商盏袄,就有跨鏡服務(wù)忿峻,跨鏡貿(mào)易等不同類型,需要傳的參數(shù)不一樣辕羽,而涉及到報(bào)關(guān)逛尚,國(guó)家政策調(diào)整,這些參數(shù)還會(huì)發(fā)生改變逛漫,而很多時(shí)候黑低,國(guó)企提供的集成文檔都不是最新的,很多東西沒(méi)有酌毡。所以當(dāng)支付請(qǐng)求失敗時(shí)克握,需要第一時(shí)間聯(lián)系支付服務(wù)提供商這邊的技術(shù)人員進(jìn)行確認(rèn),少走彎路枷踏。 - 2菩暗、溝通成本
與國(guó)企的工作人員進(jìn)行溝通時(shí),基本是問(wèn)一句回一句旭蠕,很多時(shí)間還不是及時(shí)回復(fù)停团,一個(gè)簡(jiǎn)單的問(wèn)題溝通下來(lái)的時(shí)間可能是幾天,(當(dāng)然現(xiàn)在很多公司都是這樣掏熬,不是單黑國(guó)企)如果公司離的不遠(yuǎn)佑稠,最好是將問(wèn)題匯總,登門當(dāng)面討論旗芬,效率會(huì)BIU BIU的上升舌胶。 -
3、上傳第三方支付服務(wù)商用到的私鑰
我們合作的首信易支付公司需要的私鑰是這樣的:
是從CSR文件生成時(shí)產(chǎn)生的專用密鑰這里導(dǎo)出p12用于上傳疮丛,而不是和平常見的推送之類的幔嫂,從證書處導(dǎo)出p12。各家公司要求不同誊薄,需要問(wèn)清楚履恩。