Apple Pay運行環境:iPhone6以上設備,操作系統最低iOS9.0以上,部分信息設置需要iOS9.2以上。目前還不支持企業證書添加。
環境搭建好后可以在模擬器上面運行,xcode7.2.1+iPhone6SP9.2系統下,系統會綁定幾種虛擬的銀行卡,和幾個聯系人,方便調試,支付也不會發生真實的付款,真的很方便。
準備工作
在接入Apple Pay之前,首先要申請MerchantID及對應證書。
工程設置
bundleID設置
Capability中啟用Apple Pay權限,并選擇merchantID。
之后項目會多一個Applepay的配置文件ApplePayYasin.entitlements
17if(![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
7//設置幣種、國家碼及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;//設置支持的交易處理協議,3DS必須支持,EMV為可選,目前國內的話還是使用兩者吧
設置發票配送信息和貨物配送地址信息,用戶設置后可以通過代理回調代理獲取信息的更新
//?payRequest.requiredBillingAddressFields?=?PKAddressFieldEmail;
//如果需要郵寄賬單可以選擇進行設置,默認PKAddressFieldNone(不郵寄賬單)
//樓主感覺賬單郵寄地址可以事先讓用戶選擇是否需要,否則會增加客戶的輸入麻煩度,體驗不好,
payRequest.requiredShippingAddressFields?=?PKAddressFieldPostalAddress|PKAddressFieldPhone|PKAddressFieldName;
//送貨地址信息,這里設置需要地址和聯系方式和姓名,如果需要進行設置,默認PKAddressFieldNone(沒有送貨地址)
送貨信息頁面展示
設置貨物的配送方式,不需要不配置
10//設置兩種配送方式
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為該條賬單為最終價格還是估算價格(比如出租車價格預估)
1
2+?(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--十進制數
添加賬單列表:
18NSDecimalNumber?*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;
顯示購物信息并進行支付
1
2
3
4//ApplePay控件
PKPaymentAuthorizationViewController?*view?=?[[PKPaymentAuthorizationViewController?alloc]initWithPaymentRequest:payRequest];
view.delegate?=?self;
[self?presentViewController:view?animated:YES?completion:nil];
PKPaymentAuthorizationViewControllerDelegate代理
這里還有兩個類要介紹
PKPayment 支付成功信息
1
2
3
4
5PKPaymentToken?*payToken?=?payment.token;
//支付憑據,發給服務端進行驗證支付是否真實有效
PKContact?*billingContact?=?payment.billingContact;//賬單信息
PKContact?*shippingContact?=?payment.shippingContact;//送貨信息
PKContact?*shippingMethod?=?payment.shippingMethod;//送貨方式
PKContact 聯系人信息
5NSPersonNameComponents?*name?=?contact.name;//聯系人姓名
CNPostalAddress?*postalAddress?=?contact.postalAddress;//聯系人地址
NSString?*emailAddress?=?contact.emailAddress;//聯系人郵箱
CNPhoneNumber?*phoneNumber?=?contact.phoneNumber;//聯系人手機
NSString?*supplementarySubLocality?=?contact.supplementarySubLocality;//補充信息,地址詳細描述,其他備注等等,iOS9.2及以上才有
代理說明
送貨地址回調
7-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController?*)controller
didSelectShippingContact:(PKContact?*)contact
completion:(void?(^)(PKPaymentAuthorizationStatus,?NSArray?*?_Nonnull,?NSArray?*?_Nonnull))completion{
//contact送貨地址信息,PKContact類型
//送貨信息選擇回調,如果需要根據送貨地址調整送貨方式,比如普通地區包郵+極速配送,偏遠地區只有付費普通配送,進行支付金額重新計算,可以實現該代理,返回給系統:shippingMethods配送方式,summaryItems賬單列表,如果不支持該送貨信息返回想要的PKPaymentAuthorizationStatus
completion(PKPaymentAuthorizationStatusSuccess,?shippingMethods,?summaryItems);
}
送貨方式回調
13-(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);
}
支付卡選擇回調
4-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController?*)controller?didSelectPaymentMethod:(PKPaymentMethod?*)paymentMethod?completion:(void?(^)(NSArray?*?_Nonnull))completion{
//支付銀行卡回調,如果需要根據不同的銀行調整付費金額,可以實現該代理
completion(summaryItems);
}
送貨地址回調,已棄用
1
2
3-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController?*)controller?didSelectShippingAddress:(ABRecordRef)address?completion:(void?(^)(PKPaymentAuthorizationStatus,?NSArray?*?_Nonnull,?NSArray?*?_Nonnull))completion{
//送貨地址回調,已棄用
}
付款成功蘋果服務器返回信息回調,做服務器驗證
14-(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);
});
}
支付完成回調
3-(void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController?*)controller{
[controller?dismissViewControllerAnimated:YES?completion:nil];
}
例
#import "ViewController.h"#import@interface ViewController ()@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//1、判斷當前設備是否支持蘋果支付
// 2、判斷是否添加銀行卡
if (![PKPaymentAuthorizationViewController class]) {
//PKPaymentAuthorizationViewController需iOS8.0以上支持
NSLog(@"操作系統不支持ApplePay,請升級至9.0以上版本,且iPhone6以上設備才支持");
return;
}
else if (![PKPaymentAuthorizationViewController canMakePayments]) {
NSLog(@"當前設備不支持applepay");
}
//PKPaymentNetworkChinaUnionPay? 銀聯卡 。PKPaymentNetworkVisa vsa 卡
//檢查用戶是否可進行某種卡的支付,是否支持Amex、MasterCard、Visa與銀聯四種卡,,根據自己項目的需要進行檢測
else if (![PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[PKPaymentNetworkChinaUnionPay,PKPaymentNetworkVisa]])
{
// 如果沒有添加銀行卡,創建一個跳轉按鈕,跳轉到添加銀行卡的界面
PKPaymentButton *button=[PKPaymentButton buttonWithType:PKPaymentButtonTypeSetUp style:PKPaymentButtonStyleWhiteOutline];
button.center=self.view.center;
[self.view addSubview:button];
[button addTarget:self action:@selector(jumpAddBank) forControlEvents:UIControlEventTouchUpInside];
}
else
{
// 創建一個夠買按鈕,當用戶點擊按鈕時,購買一個商品
PKPaymentButton *button=[PKPaymentButton buttonWithType:PKPaymentButtonTypeBuy style:PKPaymentButtonStyleBlack];
button.center=self.view.center;
[self.view addSubview:button];
[button addTarget:self action:@selector(clickBuy) forControlEvents:UIControlEventTouchUpInside];
}
}
#pragma mark - 點擊去購買
-(void)clickBuy
{
// 1、創建一個支付請求
PKPaymentRequest *request=[[PKPaymentRequest alloc]init];
// 配置支付請求
//1.1 配置商家ID
request.merchantIdentifier=@"merchant.com.cym.weiliaopay";
//1.2 配置國家代碼,以及貨幣代碼
request.countryCode=@"CN";
request.currencyCode=@"CNY";
// 1.3 支付的銀行卡
request.supportedNetworks=@[PKPaymentNetworkChinaUnionPay,PKPaymentNetworkVisa];
// 1.4配置商戶的處理方式//設置支持的交易處理協議,3DS必須支持,EMV為可選,目前國內的話還是使用兩者吧
request.merchantCapabilities=PKMerchantCapability3DS|PKMerchantCapabilityEMV;
// 1.5 配置購買的商品列表
NSDecimalNumber *price=[NSDecimalNumber decimalNumberWithString:@"0.01"];
PKPaymentSummaryItem *item=[PKPaymentSummaryItem summaryItemWithLabel:@"汽車保養" amount:price];
request.paymentSummaryItems=@[item];
//配置請求的附加項
//1、是否顯示發票收貨地址 。顯示哪些選項
//? ? request.requiredBillingAddressFields=PKAddressFieldAll;
//? ? // 2、是否顯示快遞地址,顯示哪些選項
//? ? request.requiredShippingAddressFields=PKAddressFieldAll;
//2、 驗證用戶的支付授權
PKPaymentAuthorizationViewController *PayVC=[[PKPaymentAuthorizationViewController alloc]initWithPaymentRequest:request];
PayVC.delegate=self;
[self presentViewController:PayVC animated:YES completion:nil];
}
#pragma mark? -代理方法
//如果當用戶授權成功,就會調用這個方法
/*
參數一:授權控制器
參數二:支付對象
參數三:系統給定的一個回調代碼塊,我們需要執行這個代碼塊,來告訴系統當前的的支付狀態是否成功
*/
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
didAuthorizePayment:(PKPayment *)payment
completion:(void (^)(PKPaymentAuthorizationStatus status))completion
{
NSLog(@"token=%@",payment.token);
// 一般在此外,拿到支付信息,發送給服務器處理,處理完畢之后,服務器返回一個狀態,告訴客戶端,是否支付成功,然后由客戶端進行處理
BOOL isSuccess=YES;
if (isSuccess)
{
completion(PKPaymentAuthorizationStatusSuccess);
}
else
{
completion(PKPaymentAuthorizationStatusFailure);
}
}
#pragma mari 當用戶授權成功,或者取消授權時調用
- (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - 添加銀行卡界面
-(void)jumpAddBank
{
// 跳轉到添加銀行卡界面
PKPassLibrary *pl=[[PKPassLibrary alloc]init];
[pl openPaymentSetup];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end