标签:ios开发 apple-pay pkpayment passkit 应用内支付
自2014年苹果秋季发布会至今,Apple Pay推出已将近一年时间,我们对其便利性与安全性也早有耳闻,然而时至今日其使用范围仍然只限美国、英国两地区,对于在中国区的引入,我们只能报以期望。
总体来说,在应用内集成Apple Pay需要两个部分:交易授权与交易处理。交易授权在应用内进行,通过PassKit.framework所提供的接口向用户获取支付授权;而交易处理则需要授权后调用可受理交易的服务器接口,你可以选择某个支付平台来处理交易,或者也可以自己实现交易处理过程,苹果官方比较推荐前者。
在接入Apple Pay之前,首先要申请MerchantID及对应证书。
在应用内集成Apple Pay,还需要引用依赖库PassKit.framework,并且在Capability中启用Apple Pay权限(在这里需要配置merchantId)。
到这里我们的准备工作就完成了,接下来开始集成Apple Pay。
在真正创建支付请求之前,我们应该先对当前的支付环境进行检测,看看当前设备、系统及Apple Pay设置是否满足支付条件。
//检查当前设备是否可以支付
[PKPaymentAuthorizationViewController canMakePayments]
//检查用户是否可进行某种卡的支付,目前仅支持Amex、MasterCard与Visa三种卡
[PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks: @[PKPaymentNetworkAmex, PKPaymentNetworkMasterCard,PKPaymentNetworkVisa]]
在环境检测完成后即可创建支付请求。
PKPaymentRequest *request=[PKPaymentRequest new];
request.currencyCode = @"USD";
request.countryCode = @"US";
request.merchantIdentifier = @"merchant.com.example";
//小计
NSDecimalNumber *subtotalAmount = [NSDecimalNumber decimalNumberWithMantissa:1275 exponent:-2 isNegative:NO];
self.subtotal = [PKPaymentSummaryItem summaryItemWithLabel:@"Subtotal" amount:subtotalAmount];
//折扣
NSDecimalNumber *discountAmount = [NSDecimalNumber decimalNumberWithMantissa:200 exponent:-2 isNegative:YES];
self.discount = [PKPaymentSummaryItem summaryItemWithLabel:@"Discount" amount:discountAmount];
// 合计
NSDecimalNumber *totalAmount = [NSDecimalNumber zero];
totalAmount = [totalAmount decimalNumberByAdding:subtotalAmount];
totalAmount = [totalAmount decimalNumberByAdding:discountAmount];
self.total = [PKPaymentSummaryItem summaryItemWithLabel:@"My Company Name" amount:totalAmount];
//支付请求的支付总结属性是一个数组,数组中的最后一个PKPaymentSummaryItem为合计。
self.summaryItems = @[self.subtotal, self.discount, self.total];
request.paymentSummaryItems = self.summaryItems;
//设置支持卡种
request.supportedNetworks = @[PKPaymentNetworkAmex, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa];
// 设置支持的交易处理协议,3DS必须支持,EMV为可选
request.merchantCapabilities = PKMerchantCapability3DS | PKMerchantCapabilityEMV;
request.requiredBillingAddressFields = PKAddressFieldEmail;
request.requiredShippingAddressFields=PKAddressFieldPostalAddress;
ABRecordRef record = ABPersonCreate();
CFErrorRef error;
BOOL success;
success = ABRecordSetValue(record, kABPersonFirstNameProperty, @"John", &error);
if (!success) { /* ... handle error ... */ }
success = ABRecordSetValue(record, kABPersonLastNameProperty, @"Appleseed", &error); if (!success) { /* ... handle error ... */ }
ABMultiValueRef shippingAddress =
ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
NSDictionary *addressDictionary = @{
(NSString *) kABPersonAddressStreetKey: @"1234 Laurel Street",
(NSString *) kABPersonAddressCityKey: @"Atlanta", (NSString *) kABPersonAddressStateKey: @"GA", (NSString *) kABPersonAddressZIPKey: @"30303" };
ABMultiValueAddValueAndLabel(shippingAddress,
(__bridge CFDictionaryRef) addressDictionary,
kABOtherLabel,
nil);
success = ABRecordSetValue(record, kABPersonAddressProperty, shippingAddress,
&error);
if (!success) { /* ... handle error ... */ }
request.shippingAddress = record;
CFRelease(shippingAddress);
CFRelease(record);
NSDecimalNumber *freeAmount = [NSDecimalNumber decimalNumberWithString:@"0.00"];
PKShippingMethod *freeShipping = [PKShippingMethod summaryItemWithLabel:@"Free Shipping" amount:freeAmount];
freeShipping.detail = @"Arrives by July 2";
freeShipping.identifier = @"free";
NSDecimalNumber *standardAmount = [NSDecimalNumber decimalNumberWithString:@"3.21"];
PKShippingMethod *standardShipping = [PKShippingMethod summaryItemWithLabel:@"Standard Shipping" amount:standardAmount];
standardShipping.detail = @"Arrives by June 29";
standardShipping.identifier = @"standard";
NSDecimalNumber *expressAmount = [NSDecimalNumber decimalNumberWithString:@"24.63"];
PKShippingMethod *expressShipping = [PKShippingMethod summaryItemWithLabel:@"Express Shipping" amount:expressAmount];
expressShipping.detail = @"Ships within 24 hours";
expressShipping.identifier = @"express";
request.shippingMethods== @[freeShipping, standardShipping, expressShipping];
到这里,一个支付请求已经创建完成,接下来我们需要用它来创建一个PKPaymentAuthorizationViewController,并通过实现PKPaymentAuthorizationViewController的委托方法来获取授权。
PKPaymentAuthorizationViewController *viewController =
[[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:request];
if (!viewController) { /* ... Handle error ... */ }
viewController.delegate = self;
[self presentViewController:viewController animated:YES completion:nil];
实现支付授权的委托,也就是实现PKPaymentAuthorizationViewControllerDelegate协议,这里面有两个必选方法:
//完成授权后的回调方法,这里可以调用server的交易处理接口,并在处理完成后通过completion块通知PKPaymentAuthorizationViewController交易状态
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
didAuthorizePayment:(PKPayment *)payment
completion:(void (^)(PKPaymentAuthorizationStatus status))completion;
//交易完成后回调方法,这里就可以关掉PKPaymentAuthorizationViewController了
- (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller;
除此之外,还有三个可选方法:
//选择邮寄地址之后回调,这里可以根据所选地址更改邮寄方式及费用,并通过completion块更新PKPaymentAuthorizationViewController
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
didSelectShippingAddress:(ABRecordRef)address
completion:(void (^)(PKPaymentAuthorizationStatus status, NSArray *shippingMethods, NSArray *summaryItems))completion;
//选择邮寄方式后回调,这里可以根据所选邮寄方式更新费用信息,并通过completion块更新PKPaymentAuthorizationViewController
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
didSelectShippingMethod:(PKShippingMethod *)shippingMethod
completion:(void (^)(PKPaymentAuthorizationStatus status, NSArray *summaryItems))completion;
//输完指纹或密码之后,授权支付之前回调
-(void)paymentAuthorizationViewControllerWillAuthorizePayment:(PKPaymentAuthorizationViewController *)controller NS_AVAILABLE_IOS(8_3);
以下为委托方法的部分实现:
-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingAddress:(ABRecordRef)address completion:(void (^)(PKPaymentAuthorizationStatus, NSArray *, NSArray *))completion{
[self updateShippingMethods];
completion(PKPaymentAuthorizationStatusSuccess,self.shippingMethods,self.summaryItems);
}
-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingMethod:(PKShippingMethod *)shippingMethod completion:(void (^)(PKPaymentAuthorizationStatus, NSArray *))completion{
[self updateSummaryItems:shippingMethod.identifier];
completion(PKPaymentAuthorizationStatusSuccess,self.summaryItems);
}
-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didAuthorizePayment:(PKPayment *)payment completion:(void (^)(PKPaymentAuthorizationStatus))completion{
//在这里调用服务器处理交易,并获取交易状态
completion(PKPaymentAuthorizationStatusSuccess);
}
-(void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller{
[controller dismissViewControllerAnimated:true completion:nil];
}
-(void) updateShippingMethods{
NSDecimalNumber *freeAmount = [NSDecimalNumber decimalNumberWithString:@"0.00"];
PKShippingMethod *freeShipping = [PKShippingMethod summaryItemWithLabel:@"Free Shipping" amount:freeAmount];
freeShipping.detail = @"Arrives by July 2";
freeShipping.identifier = @"free";
NSDecimalNumber *standardAmount = [NSDecimalNumber decimalNumberWithString:@"3.21"];
PKShippingMethod *standardShipping = [PKShippingMethod summaryItemWithLabel:@"Standard Shipping" amount:standardAmount];
standardShipping.detail = @"Arrives by June 29";
standardShipping.identifier = @"standard";
NSDecimalNumber *expressAmount = [NSDecimalNumber decimalNumberWithString:@"24.63"];
PKShippingMethod *expressShipping = [PKShippingMethod summaryItemWithLabel:@"Express Shipping" amount:expressAmount];
expressShipping.detail = @"Ships within 24 hours";
expressShipping.identifier = @"express";
_shippingMethods= @[freeShipping, standardShipping, expressShipping];
}
-(void) updateSummaryItems:(NSString *)identifier{
if ([identifier isEqualToString:@""]) {
return;
}
NSDecimalNumber *shippingAmount;
if ([identifier isEqualToString:@"standard"]) {
shippingAmount=[NSDecimalNumber decimalNumberWithMantissa:321
exponent:-2 isNegative:NO];
}else if ([identifier isEqualToString:@"Express"]) {
shippingAmount=[NSDecimalNumber decimalNumberWithMantissa:2463
exponent:-2 isNegative:NO];
}
PKPaymentSummaryItem* shipping=[PKPaymentSummaryItem summaryItemWithLabel:@"Shipping"
amount:shippingAmount];
NSDecimalNumber *subtotalAmount = [NSDecimalNumber decimalNumberWithMantissa:1275
exponent:-2 isNegative:NO];
PKPaymentSummaryItem* subtotal = [PKPaymentSummaryItem summaryItemWithLabel:@"Subtotal"
amount:subtotalAmount];
NSDecimalNumber *discountAmount = [NSDecimalNumber decimalNumberWithMantissa:200
exponent:-2 isNegative:YES];
PKPaymentSummaryItem* discount = [PKPaymentSummaryItem summaryItemWithLabel:@"Discount"
amount:discountAmount];
NSDecimalNumber *totalAmount = [NSDecimalNumber zero];
totalAmount = [totalAmount decimalNumberByAdding:subtotalAmount];
totalAmount = [totalAmount decimalNumberByAdding:discountAmount];
totalAmount = [totalAmount decimalNumberByAdding:shippingAmount];
PKPaymentSummaryItem* total = [PKPaymentSummaryItem summaryItemWithLabel:@"Ipaynow"
amount:totalAmount];
_summaryItems=@[subtotal, shipping, discount, total];
}
以上,就是在应用内接入Apple Pay的主要内容。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:ios开发 apple-pay pkpayment passkit 应用内支付
原文地址:http://blog.csdn.net/l964968324/article/details/47283357