IOS Apple Pay

运行环境##

iphone 6 以及以上,iOS 9.2 以上。目前不支持企业证书添加。
支持模拟器测试。

环境配置##

1、 Xcode 7.2.1 以及以上打开项目,在 Capabilities里将Apple Pay设置为on,如下图,

 

IOS Apple Pay

2、 图一我们看到了有个 Merchant ID 选项,而且新建时候是没有配置的,那么需要到哪里去配置呢?
1、访问苹果开发账号,证书中心。
Identifiers -->Merchant IDs
输入描述 和 ID,ID 必须以merchant. 开头 

IOS Apple Pay

 

Continue 到下一步,前方高能警报,嘀嘀嘀~~~~ 坑一出现:报错!!!!!!!

IOS Apple Pay

 

说明苹果对这个ID 格式是有要求的。多试几次。其实仔细看 图 -3 底下有一行小字,We recommend using a reverse-domain name style string (i.e.,merchant.com.example.merchantname).最好按照官方要求 merchant.com.example.merchantname这个格式来。

IOS Apple Pay

 

 一步一步往下走。
这时候 会提示你 Identifier:merchant.com.Demo.applepaydemo已经生成。

 

IOS Apple Pay

 

 点击 Done 

IOS Apple Pay

 

 根据上面的提示,点击Edit,接下去应该是需要建证书了。
首次添加时候 会询问你是否 在中国使用。选择 YES(截图是默认状态-NO),一直 continue 。

 

IOS Apple Pay

3、新建证书
创建 ** Creating a Certificate Signing Request (CSR) CSR 证书,**
生成CSR证书,这个证书一般是接入第三方银联生成的CSR ,上传到这里就行了

 

IOS Apple Pay

 

代码集成##

这里要说的 重点不在下半部分,而是 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 支付的实现方式###

  IOS Apple Pay1-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];
        
    }
}

 

上一篇:uni-app中如何编写一个promise函数并调用


下一篇:php 微信公众号接入支付宝支付