Apple Pay運行環境:iPhone6以上設備,操作系統最低iOS9.0以上,部分信息設置需要iOS9.2以上。目前還不支持企業證書添加。
環境搭建好后可以在模擬器上面運行,xcode7.2.1+iPhone6SP9.2系統下,系統會綁定幾種虛擬的銀行卡,和幾個聯系人,方便調試,支付也不會發生真實的付款,真的很方便。
準備工作
在接入Apple Pay之前,首先要申請MerchantID及對應證書。(請移步我寫的申請MerchantID及對應證書詳細圖文教程)
工程設置
bundleID設置?
Capability中啟用Apple Pay權限,并選擇merchantID。
之后項目會多一個Applepay的配置文件ApplePayYasin.entitlements
需要引用的庫
Xcode7.0以上不需要再手動添加需要引用的庫了,只需要導入頭文件就可以了
設備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(沒有送貨地址)
設置貨物的配送方式,不需要不配置
//設置兩種配送方式
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];
賬單信息的設置
每條賬單的設置
賬單列表使用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的話因為證書問題可能會報錯,不過大家可以看看代碼。