Apple Pay接入詳細教程(轉)

一個蘿蔔壹個坑發表於2018-01-03

Apple Pay執行環境:iPhone6以上裝置,作業系統最低iOS9.0以上,部分資訊設定需要iOS9.2以上。目前還不支援企業證書新增。

環境搭建好後可以在模擬器上面執行,xcode7.2.1+iPhone6SP9.2系統下,系統會繫結幾種虛擬的銀行卡,和幾個聯絡人,方便除錯,支付也不會發生真實的付款,真的很方便。

準備工作

在接入Apple Pay之前,首先要申請MerchantID及對應證書。(請移步我寫的申請MerchantID及對應證書詳細圖文教程

工程設定

bundleID設定 

Apple Pay接入詳細教程(轉)

Capability中啟用Apple Pay許可權,並選擇merchantID。

Apple Pay接入詳細教程(轉)

之後專案會多一個Applepay的配置檔案ApplePayYasin.entitlements

Apple Pay接入詳細教程(轉)

需要引用的庫

Xcode7.0以上不需要再手動新增需要引用的庫了,只需要匯入標頭檔案就可以了

Apple Pay接入詳細教程(轉)

裝置Applepay許可權檢測

if (![PKPaymentAuthorizationViewController class]) {

//PKPaymentAuthorizationViewController需iOS8.0以上支援

NSLog(@"作業系統不支援ApplePay,請升級至9.0以上版本,且iPhone6以上裝置才支援");

return;

}

//檢查當前裝置是否可以支付

if (![PKPaymentAuthorizationViewController canMakePayments]) {

//支付需iOS9.0以上支援

NSLog(@"裝置不支援ApplePay,請升級至9.0以上版本,且iPhone6以上裝置才支援");

return;

}

//檢查使用者是否可進行某種卡的支付,是否支援Amex、MasterCard、Visa與銀聯四種卡,根據自己專案的需要進行檢測

NSArray *supportedNetworks = @[PKPaymentNetworkAmex, PKPaymentNetworkMasterCard,PKPaymentNetworkVisa,PKPaymentNetworkChinaUnionPay];

if (![PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:supportedNetworks]) {

NSLog(@"沒有繫結支付卡");

return;

}

建立支付請求PKPaymentRequest

初始化PKPaymentRequest

這裡需要注意RMB的幣種程式碼是CNY

//設定幣種、國家碼及merchant識別符號等基本資訊

PKPaymentRequest *payRequest = [[PKPaymentRequest alloc]init];

payRequest.countryCode = @"CN";//國家程式碼

payRequest.currencyCode = @"CNY";//RMB的幣種程式碼

payRequest.merchantIdentifier = @"merchant.ApplePayDemoYasin";//申請的merchantID

payRequest.supportedNetworks = supportedNetworks;//使用者可進行支付的銀行卡

payRequest.merchantCapabilities = PKMerchantCapability3DS|PKMerchantCapabilityEMV;

設定發票配送資訊和貨物配送地址資訊,使用者設定後可以通過代理回撥代理獲取資訊的更新

// payRequest.requiredBillingAddressFields = PKAddressFieldEmail;

//如果需要郵寄賬單可以選擇進行設定,預設PKAddressFieldNone(不郵寄賬單)

//樓主感覺賬單郵寄地址可以事先讓使用者選擇是否需要,否則會增加客戶的輸入麻煩度,體驗不好,

payRequest.requiredShippingAddressFields = PKAddressFieldPostalAddress|PKAddressFieldPhone|PKAddressFieldName;

//送貨地址資訊,這裡設定需要地址和聯絡方式和姓名,如果需要進行設定,預設PKAddressFieldNone(沒有送貨地址)


Apple Pay接入詳細教程(轉)

設定貨物的配送方式,不需要不配置

//設定兩種配送方式

PKShippingMethod *freeShipping = [PKShippingMethod summaryItemWithLabel:@"包郵"amount:[NSDecimalNumber zero]];

freeShipping.identifier = @"freeshipping";

freeShipping.detail = @"6-8 天 送達";

PKShippingMethod *expressShipping = [PKShippingMethod summaryItemWithLabel:@"極速送達"amount:[NSDecimalNumber decimalNumberWithString:@"10.00"]];

expressShipping.identifier = @"expressshipping";

expressShipping.detail = @"2-3 小時 送達";

payRequest.shippingMethods = @[freeShipping, expressShipping];


Apple Pay接入詳細教程(轉)


Apple Pay接入詳細教程(轉)

賬單資訊的設定

每條賬單的設定

賬單列表使用PKPaymentSummaryItem新增描述和價格,價格使用NSDecimalNumber。

PKPaymentSummaryItem初始化:

label為商品名字或者是描述,amount為商品價格,折扣為負數,type為該條賬單為最終價格還是估算價格(比如計程車價格預估)

+ (instancetype)summaryItemWithLabel:(NSString *)label amount:(NSDecimalNumber *)amount;

+ (instancetype)summaryItemWithLabel:(NSString *)label amount:(NSDecimalNumber *)amount type:(PKPaymentSummaryItemType)type NS_AVAILABLE(NA, 9_0);

NSDecimalNumber初始化:

NSDecimalNumber可以使用數字初始化,也可以使用字串。

使用方法請移步我寫的NSDecimalNumber--十進位制數

新增賬單列表:

NSDecimalNumber *subtotalAmount = [NSDecimalNumber decimalNumberWithMantissa:1275 exponent:-2 isNegative:NO];//12.75

PKPaymentSummaryItem *subtotal = [PKPaymentSummaryItem summaryItemWithLabel:@"商品價格"amount:subtotalAmount];

NSDecimalNumber *discountAmount = [NSDecimalNumber decimalNumberWithString:@"-12.74"];//-12.74

PKPaymentSummaryItem *discount = [PKPaymentSummaryItem summaryItemWithLabel:@"優惠折扣"amount:discountAmount];

NSDecimalNumber *methodsAmount = [NSDecimalNumber zero];

PKPaymentSummaryItem *methods = [PKPaymentSummaryItem summaryItemWithLabel:@"包郵"amount:methodsAmount];

NSDecimalNumber *totalAmount = [NSDecimalNumber zero];

totalAmount = [totalAmount decimalNumberByAdding:subtotalAmount];

totalAmount = [totalAmount decimalNumberByAdding:discountAmount];

totalAmount = [totalAmount decimalNumberByAdding:methodsAmount];

PKPaymentSummaryItem *total = [PKPaymentSummaryItem summaryItemWithLabel:@"Yasin"amount:totalAmount];//最後這個是支付給誰。哈哈,快支付給我

summaryItems = [NSMutableArray arrayWithArray:@[subtotal, discount, methods, total]];

//summaryItems為賬單列表,型別是 NSMutableArray,這裡設定成成員變數,在後續的代理回撥中可以進行支付金額的調整。

payRequest.paymentSummaryItems = summaryItems;

顯示購物資訊並進行支付

//ApplePay控制元件

PKPaymentAuthorizationViewController *view = [[PKPaymentAuthorizationViewController alloc]initWithPaymentRequest:payRequest];

view.delegate = self;

[self presentViewController:view animated:YES completion:nil];

PKPaymentAuthorizationViewControllerDelegate代理

這裡還有兩個類要介紹

PKPayment 支付成功資訊

PKPaymentToken *payToken = payment.token;

//支付憑據,發給服務端進行驗證支付是否真實有效

PKContact *billingContact = payment.billingContact;     //賬單資訊

PKContact *shippingContact = payment.shippingContact;   //送貨資訊

PKContact *shippingMethod = payment.shippingMethod;     //送貨方式

PKContact 聯絡人資訊

NSPersonNameComponents *name = contact.name;//聯絡人姓名

CNPostalAddress *postalAddress = contact.postalAddress;//聯絡人地址

NSString *emailAddress = contact.emailAddress;//聯絡人郵箱

CNPhoneNumber *phoneNumber = contact.phoneNumber;//聯絡人手機

NSString *supplementarySubLocality = contact.supplementarySubLocality;//補充資訊,地址詳細描述,其他備註等等,iOS9.2及以上才有

代理說明

送貨地址回撥

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller

didSelectShippingContact:(PKContact *)contact

completion:(void (^)(PKPaymentAuthorizationStatus, NSArray * _Nonnull, NSArray * _Nonnull))completion{

//contact送貨地址資訊,PKContact型別

//送貨資訊選擇回撥,如果需要根據送貨地址調整送貨方式,比如普通地區包郵+極速配送,偏遠地區只有付費普通配送,進行支付金額重新計算,可以實現該代理,返回給系統:shippingMethods配送方式,summaryItems賬單列表,如果不支援該送貨資訊返回想要的PKPaymentAuthorizationStatus

completion(PKPaymentAuthorizationStatusSuccess, shippingMethods, summaryItems);

}

送貨方式回撥

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller

didSelectShippingMethod:(PKShippingMethod *)shippingMethod

completion:(void (^)(PKPaymentAuthorizationStatus, NSArray * _Nonnull))completion{

//配送方式回撥,如果需要根據不同的送貨方式進行支付金額的調整,比如包郵和付費加速配送,可以實現該代理

PKShippingMethod *oldShippingMethod = [summaryItems objectAtIndex:2];

PKPaymentSummaryItem *total = [summaryItems lastObject];

total.amount = [total.amount decimalNumberBySubtracting:oldShippingMethod.amount];

total.amount = [total.amount decimalNumberByAdding:shippingMethod.amount];

[summaryItems replaceObjectAtIndex:2 withObject:shippingMethod];

[summaryItems replaceObjectAtIndex:3 withObject:total];

completion(PKPaymentAuthorizationStatusSuccess, summaryItems);

}

支付卡選擇回撥

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectPaymentMethod:(PKPaymentMethod *)paymentMethod completion:(void (^)(NSArray * _Nonnull))completion{

//支付銀行卡回撥,如果需要根據不同的銀行調整付費金額,可以實現該代理

completion(summaryItems);

}

送貨地址回撥,已棄用

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingAddress:(ABRecordRef)address completion:(void (^)(PKPaymentAuthorizationStatus, NSArray * _Nonnull, NSArray * _Nonnull))completion{

//送貨地址回撥,已棄用

}

付款成功蘋果伺服器返回資訊回撥,做伺服器驗證

-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller

didAuthorizePayment:(PKPayment *)payment

completion:(void (^)(PKPaymentAuthorizationStatus status))completion {

PKPaymentToken *payToken = payment.token;

//支付憑據,發給服務端進行驗證支付是否真實有效

PKContact *billingContact = payment.billingContact;//賬單資訊

PKContact *shippingContact = payment.shippingContact;//送貨資訊

PKContact *shippingMethod = payment.shippingMethod;//送貨方式

//等待伺服器返回結果後再進行系統block呼叫

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

//模擬伺服器通訊

completion(PKPaymentAuthorizationStatusSuccess);

});

}

支付完成回撥

1

2

3-(void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller{

[controller dismissViewControllerAnimated:YES completion:nil];

}

demo的話因為證書問題可能會報錯,不過大家可以看看程式碼。

相關文章