运行环境##
iphone 6 以及以上,iOS 9.2 以上。目前不支持企业证书添加。
支持模拟器测试。
环境配置##
1、 Xcode 7.2.1 以及以上打开项目,在 Capabilities里将Apple Pay设置为on,如下图,
2、 图一我们看到了有个 Merchant ID 选项,而且新建时候是没有配置的,那么需要到哪里去配置呢?
1、访问苹果开发账号,证书中心。
Identifiers -->Merchant IDs
输入描述 和 ID,ID 必须以merchant. 开头
Continue 到下一步,前方高能警报,嘀嘀嘀~~~~ 坑一出现:报错!!!!!!!
说明苹果对这个ID 格式是有要求的。多试几次。其实仔细看 图 -3 底下有一行小字,We recommend using a reverse-domain name style string (i.e.,merchant.com.example.merchantname).最好按照官方要求 merchant.com.example.merchantname这个格式来。
一步一步往下走。
这时候 会提示你 Identifier:merchant.com.Demo.applepaydemo已经生成。
点击 Done
根据上面的提示,点击Edit,接下去应该是需要建证书了。
首次添加时候 会询问你是否 在中国使用。选择 YES(截图是默认状态-NO),一直 continue 。
3、新建证书
创建 ** Creating a Certificate Signing Request (CSR) CSR 证书,**
生成CSR证书,这个证书一般是接入第三方银联生成的CSR ,上传到这里就行了
代码集成##
这里要说的 重点不在下半部分,而是 Buy with XXPay这个按钮,我们知道苹果是一个有情(偏)怀(执)的处女座公司,对很多的设计或则交互都有自己的一套规则,ApplePay 的响应 按钮也不例外。不要以为随便 弄个 设计个按钮 就能上线了,这个时候 美工和老板说了都不算,要听苹果的ApplePay 设计规范。不然审核也过不了。导入头文件,(xcode 7.0 以上已经自动帮我们导入了库,所以我们只需要导入头文件即可)
#import <PassKit/PassKit.h>
2、
PKPaymentAuthorizationViewController Apple pay的展示控件,也是核心类。直接看代码
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*supportedNetworkCards =@[PKPaymentNetworkAmex, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa, PKPaymentNetworkChinaUnionPay]; if(![PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:supportedNetworks]) { NSLog(@"没有绑定支付卡"); return; } NSLog(@"可以支付,开始建立支付请求");
- (void)actionApplePay:(UIButton *)button { if ([PKPaymentAuthorizationViewController canMakePayments]) { NSLog(@"Woo! Can make payments!"); if ([PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[ PKPaymentNetworkChinaUnionPay, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa ]]) { } else { NSLog(@"用户未添加银行卡"); return; } PKPaymentRequest *request = [[PKPaymentRequest alloc] init]; PKPaymentSummaryItem *widget1 = [PKPaymentSummaryItem summaryItemWithLabel:@"Widget 1" amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]]; PKPaymentSummaryItem *widget2 = [PKPaymentSummaryItem summaryItemWithLabel:@"Widget 2" amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]]; PKPaymentSummaryItem *total = [PKPaymentSummaryItem summaryItemWithLabel:@"Grand Total" amount:[NSDecimalNumber decimalNumberWithString:@"0.02"]]; request.paymentSummaryItems = @[ widget1, widget2, total ]; request.countryCode = @"CN"; request.currencyCode = @"CHW"; //能支付的币种 request.supportedNetworks = @[ PKPaymentNetworkChinaUnionPay, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa ]; //Merchant ID request.merchantIdentifier = @"merchant.com.Carman.Paydemo"; // 询问你的付款处理器 (PKMerchantCapabilityCredit // 信用卡,PKMerchantCapabilityDebit 借记卡) /* PKMerchantCapabilityCredit NS_ENUM_AVAILABLE_IOS(9_0) = 1UL << 2, // 支持信用卡 PKMerchantCapabilityDebit NS_ENUM_AVAILABLE_IOS(9_0) = 1UL << 3 // 支持借记卡 */ request.merchantCapabilities = PKMerchantCapabilityCredit; // 添加联系人邮箱 及送货地址信息 //request.requiredShippingAddressFields = PKAddressFieldAll; PKPaymentAuthorizationViewController *paymentPane = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:request]; paymentPane.delegate = self; [self presentViewController:paymentPane animated:TRUE completion:nil]; } else { NSLog(@"设备不支持支付"); } }1、[PKPaymentAuthorizationViewController canMakePayments] 判断设备支持不支持 ApplePay。中国区 是 iphone 6 及以上,iOS9.2
2、canMakePaymentsUsingNetworks: 判断 设备上用户有没有添加银行卡,如果没添加,不写这个判断,真机上会crash。
PKPaymentNetworkChinaUnionPay//中国银联卡
PKPaymentNetworkMasterCard//Master卡
PKPaymentNetworkVisa//Visa卡 3、支付的类目以及总额
PKPaymentRequest *request = [[PKPaymentRequest alloc] init]; PKPaymentSummaryItem *widget1 = [PKPaymentSummaryItem summaryItemWithLabel:@"Widget 1" amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]]; PKPaymentSummaryItem *widget2 = [PKPaymentSummaryItem summaryItemWithLabel:@"Widget 2" amount:[NSDecimalNumber decimalNumberWithString:@"0.01"]]; PKPaymentSummaryItem *total = [PKPaymentSummaryItem summaryItemWithLabel:@"Grand Total" amount:[NSDecimalNumber decimalNumberWithString:@"0.02"]]; request.paymentSummaryItems = @[ widget1, widget2, total ];4、countryCode国家 code ,中国的是 CN ,不太清楚定义的可以查看 countryCode查询网站
5、currencyCode支付币种 ,人民币 CHW
6、supportedNetworks能支持的卡种,同 2
7、merchantIdentifier,终于出现这货了,申请半天的 Merchant ID ,请注意保持一致。
8、merchantCapabilities询问你的付款处理器
PKMerchantCapabilityCredit//支持信用卡
PKMerchantCapabilityDebit//支持借记卡
9、requiredShippingAddressFields添加联系人信息
typedef NS_OPTIONS(NSUInteger, PKAddressField) { PKAddressFieldNone = 0UL, // No address fields required. PKAddressFieldPostalAddress = 1UL << 0, // Full street address including name, street, city, state/province, postal code, country. PKAddressFieldPhone = 1UL << 1, PKAddressFieldEmail = 1UL << 2, PKAddressFieldName NS_ENUM_AVAILABLE_IOS(8_3) = 1UL << 3, PKAddressFieldAll = (PKAddressFieldPostalAddress|PKAddressFieldPhone|PKAddressFieldEmail|PKAddressFieldName) } NS_ENUM_AVAILABLE(NA, 8_0);
10、调起 ** PKPaymentAuthorizationViewController**
PKPaymentAuthorizationViewController *paymentPane = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:request]; paymentPane.delegate = self; [self presentViewController:paymentPane animated:TRUE completion:nil];
当然,我们要实现<PKPaymentAuthorizationViewControllerDelegate> 代理
#pragma mark-- PKPaymentAuthorizationViewControllerDelegate - (void) paymentAuthorizationViewController: (PKPaymentAuthorizationViewController *)controller didAuthorizePayment:(PKPayment *)payment completion: (void (^)(PKPaymentAuthorizationStatus status)) completion { NSLog(@"Payment was authorized: %@", payment); // do an async call to the server to complete the payment. // See PKPayment class reference for object parameters that can be passed BOOL asyncSuccessful = FALSE; if (asyncSuccessful) { completion(PKPaymentAuthorizationStatusSuccess); NSLog(@"支付成功"); } else { completion(PKPaymentAuthorizationStatusFailure); NSLog(@"支付失败"); } } - (void)paymentAuthorizationViewControllerDidFinish: (PKPaymentAuthorizationViewController *)controller { // hide the payment window [controller dismissViewControllerAnimated:TRUE completion:nil]; }1、paymentAuthorizationViewController:didAuthorizePayment:
completion
支付 状态回调在这里处理,支付成功和失败,订单的地址 以及和 服务器传输数据-token。
2、paymentAuthorizationViewControllerDidFinish:支付结束,关闭 支付弹框。
token支付成功之后的回执,需要上传给服务器。
billingAddress用户账单地址
billingContact用户账单信息
shippingAddress送货地址
shippingContact送货信息
shippingMethod送货方式
以上的 信息 可以根据自己的需求 上传到服务器
银联Apple Pay控件开发包####
下载 银联的Apple Pay 控件开发包,里面有非常详细的 介绍,如何接入ApplePay。
银联支付控件 SDK 模式 Apple Pay 支付的实现方式###
1-2、 商户生成订单,通过商户SERVER端将订单信息发送给银联支付网关;3-4、银联支付网关记录订单信息,返回用来标识订单的 TN 号,经由商户 SERVER 返回至给商户 APP;
5、 商户 APP 调用银联 SDK,将 TN 号传递给银联 SDK
6、 银联 SDK 向 Apple 公司的 PASSKIT FRAMEWORK 发起支付请求;
7、 接口返回加密的支付 Token 信息;
8-9、银联 SDK 将支付 Token 传递给银联支付网关,完成交易认证;
10-12、银联将支付结果返回给商户 APP,商户 SERVER,商户 APP 负责提示用户交易结果。
- 添加银联SDK 并加入依赖的库文件
a、添加 Apple Pay 版本静态库文件
包含文件:
UPAPayPlugin.h
UPAPayPluginDelegate.h
libUPAPayPlugin.a
b、添加 CFNetwork.framework 、 libUPAPayPlugin.a 、 PassKit.framework 、 SystemConfiguration.framework 到商户 App 工程中
c、http 请求设置,设置NSAllowsArbitraryLoads 属性值为 YES
注意:
如果工程的 compile source as 选项的值不是 Objective–C++,则引用此头文件的文件类型都要 改为.mm
- 接口调用
a、商户 App 从商户服务器获取 tn,当 tn 不为空时,调用支付接口。
//当获得的tn不为空时,调用支付接口 if (tn != nil && tn.length > 0) { if([PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:@[PKPaymentNetworkChinaUnionPay]] ) { //调用银联支付控件 [UPAPayPlugin startPay:tn mode:self.testMode viewController:self delegate:self andAPMechantID:kAppleMechantID]; } }
处理支付结果
银联手机支付控件结果回调函数有四个支付状态返回值,在 UPPayResult 类中有关于 UPPaymentResultStatus 的详细说明。
商户 App 通过在工程中添加头文件 “UPAPayPluginDelegate.h”,然后在处理交易结果界面中根据该头文件中定义的回调函数:-(void)UPAPayPluginResult:(UPPayResult *)result 来实现回调方法,从而根据支付结果的不同进行相应的处理。
-(void)UPAPayPluginResult:(UPPayResult *)result { if(result.paymentResultStatus == UPPaymentResultStatusSuccess) { NSString *otherInfo = result.otherInfo?result.otherInfo:@""; NSString *successInfo = [NSString stringWithFormat:@"支付成功\n%@",otherInfo]; [self showAlertMessage:successInfo]; } else if(result.paymentResultStatus == UPPaymentResultStatusCancel){ [self showAlertMessage:@"支付取消"]; } else if (result.paymentResultStatus == UPPaymentResultStatusFailure) { NSString *errorInfo = [NSString stringWithFormat:@"%@",result.errorDescription]; [self showAlertMessage:errorInfo]; } else if (result.paymentResultStatus == UPPaymentResultStatusUnknownCancel) { //TODO UPPAymentResultStatusUnknowCancel表示发起支付以后用户取消,导致支付状态不确认,需要查询商户后台确认真实的支付结果 NSString *errorInfo = [NSString stringWithFormat:@"支付过程中用户取消了,请查询后台确认订单"]; [self showAlertMessage:errorInfo]; } }