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以上不需要再手动添加需要引用的库了,只需要导入头文件就可以了

1
2
3
#import <passkit passkit.h="">                                 //用户绑定的银行卡信息
#import <passkit pkpaymentauthorizationviewcontroller.h="">    //Apple pay的展示控件
#import <addressbook addressbook.h="">                         //用户联系信息相关</addressbook></passkit></passkit>
  • 设备Applepay权限检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

1
2
3
4
5
6
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为可选,目前国内的话还是使用两者吧
  • 设置发票配送信息和货物配送地址信息,用户设置后可以通过代理回调代理获取信息的更新

1
2
3
4
5
// payRequest.requiredBillingAddressFields = PKAddressFieldEmail;   
//如果需要邮寄账单可以选择进行设置,默认PKAddressFieldNone(不邮寄账单)
//楼主感觉账单邮寄地址可以事先让用户选择是否需要,否则会增加客户的输入麻烦度,体验不好,
  payRequest.requiredShippingAddressFields = PKAddressFieldPostalAddress|PKAddressFieldPhone|PKAddressFieldName;
  //送货地址信息,这里设置需要地址和联系方式和姓名,如果需要进行设置,默认PKAddressFieldNone(没有送货地址)

送货信息页面展示

设置货物的配送方式,不需要不配置

1
2
3
4
5
6
7
8
9
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--十进制数

添加账单列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;

显示购物信息并进行支付

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
5
PKPaymentToken *payToken = payment.token;
//支付凭据,发给服务端进行验证支付是否真实有效
PKContact *billingContact = payment.billingContact;     //账单信息
PKContact *shippingContact = payment.shippingContact;   //送货信息
PKContact *shippingMethod = payment.shippingMethod;     //送货方式

PKContact 联系人信息

1
2
3
4
5
NSPersonNameComponents *name = contact.name;                //联系人姓名
CNPostalAddress *postalAddress = contact.postalAddress;     //联系人地址
NSString *emailAddress = contact.emailAddress;              //联系人邮箱
CNPhoneNumber *phoneNumber = contact.phoneNumber;           //联系人手机
NSString *supplementarySubLocality = contact.supplementarySubLocality;  //补充信息,地址详细描述,其他备注等等,iOS9.2及以上才有
  • 代理说明

送货地址回调

1
2
3
4
5
6
7
-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
                didSelectShippingContact:(PKContact *)contact
                              completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<pkshippingmethod *> * _Nonnull, NSArray<pkpaymentsummaryitem *> * _Nonnull))completion{
  //contact送货地址信息,PKContact类型
  //送货信息选择回调,如果需要根据送货地址调整送货方式,比如普通地区包邮+极速配送,偏远地区只有付费普通配送,进行支付金额重新计算,可以实现该代理,返回给系统:shippingMethods配送方式,summaryItems账单列表,如果不支持该送货信息返回想要的PKPaymentAuthorizationStatus
  completion(PKPaymentAuthorizationStatusSuccess, shippingMethods, summaryItems);
}</pkpaymentsummaryitem *></pkshippingmethod *>

送货方式回调

1
2
3
4
5
6
7
8
9
10
11
12
13
-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
                 didSelectShippingMethod:(PKShippingMethod *)shippingMethod
                              completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<pkpaymentsummaryitem *> * _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);
}</pkpaymentsummaryitem *>

支付卡选择回调

1
2
3
4
-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectPaymentMethod:(PKPaymentMethod *)paymentMethod completion:(void (^)(NSArray<pkpaymentsummaryitem *> * _Nonnull))completion{
  //支付银行卡回调,如果需要根据不同的银行调整付费金额,可以实现该代理
  completion(summaryItems);
}</pkpaymentsummaryitem *>

送货地址回调,已弃用

1
2
3
-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingAddress:(ABRecordRef)address completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<pkshippingmethod *> * _Nonnull, NSArray<pkpaymentsummaryitem *> * _Nonnull))completion{
  //送货地址回调,已弃用
}</pkpaymentsummaryitem *></pkshippingmethod *>

付款成功苹果服务器返回信息回调,做服务器验证

1
2
3
4
5
6
7
8
9
10
11
12
13
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);
  });
}

支付完成回调

1
2
3
-(void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller{
  [controller dismissViewControllerAnimated:YES completion:nil];
}

Apple Pay的更多相关文章

  1. Apple Pay 初探

    Apple Pay 一.概述 1.支付方式:Touch ID/ Passcode 2.设备要求:iPhone6以上(iphone:线上/线下 ipad:线上 watch:线下) 3.系统要求:iOS8 ...

  2. 【转】iOS开发 -- Apple Pay

    技术博客原地址:http://www.cnblogs.com/dashunzi/p/ApplePay.html#top 原技术博客中有源码和视频,有感兴趣的朋友可以研究一下! 一.什么是Apple P ...

  3. Apple Pay的快速实现

    一.在Apple开发者中心配置 AppleID 和 Merchant IDs 二.配置好证书后在Xcode中开启Apple Pay 三.代码实现 3.1 判断是否支持Apple Pay,如果支持又将支 ...

  4. 开发apple pay碰到的问题总结

    本来想简单总结一下Apple Pay 开发过程中的几个问题, 结果被下面这篇文章全碰上了, 干脆全文转载, 作者对相关资源整理得比较详细, 比较有参考价值 总的来说, 我们做过 APNs 推送的话, ...

  5. iOS Apple Pay

    iOS 苹果支付 需要证书支持支付功能 targets 打开支付功能按钮 //ApplePay#import <PassKit/PassKit.h>                     ...

  6. iOS开发 Apple Pay

    一.什么是Apple Pay? 1. 概念 Apple Pay,简单来说, 就是一种移动支付方式.通过Touch ID/ Passcode,用户可使用存储在iPhone 6, 6p等设备上的信用卡和借 ...

  7. Apple Pay(转)

    Apple Pay 是在 iOS 8 中第一次被介绍,它可以为你的应用中的实体商品和服务,提供简单.安全.私密的支付方式.它使得用户支付起来非常简便,只需按一下指纹就可以授权进行交易. Apple P ...

  8. 集成 Apple Pay

    作者感言 在中秋过后终于把国内的三大支付平台SDK集成都搞定了, 现在我们终于可以来研究Apple自家的支付Apple Pay最后:如果你有更好的建议或者对这篇文章有不满的地方, 请联系我, 我会参考 ...

  9. Apple Pay强势来袭,开发者应做的事情

    "iOS8.1就已经有这个功能了,只是木有现在这么的火,现在的趋势是要火的节奏,因此很多电商平台B2B,P2P,C2C,X2X都有可能需要这个屌丝的付款功能了,在此简单的研究一下." ...

随机推荐

  1. 简进祥--iOS开发基础知识

    1:App跳转至系统Settings 跳转在IOS8以上跟以下是有区别的,如果是IOS8以上可以如下设置: NSURL *url = [NSURL URLWithString:UIApplicatio ...

  2. double截取小数点位数

    (double)decimal.Round(decimal.Parse((planVoSt.TotalCompleteAmount / planVoSt.TotalUserCount).ToStrin ...

  3. Oracle触发器反向调用Java程序

    导入jar包 在oracle中导入需要的jar包,我们把编辑好的java类打成jar包,直接在oarcle里面写简单的调用就可以了, 1.操作系统需要拥有支持loadjava命令的jdk. 2.加载j ...

  4. 内部类访问外部类的变量必须是final吗,java静态方法中不能引用非静态变量,静态方法中不能创建内部类的实例

    内部类访问外部类的变量必须是final吗? 如下: package com.java.concurrent; class A { int i = 3; public void shout() { cl ...

  5. oninput等表单事件

    oninput等表单事件 过去我们常使用keydown和keyup辅助表单元素的处理,这要求处理时,表单元素必须处于激活(聚焦)状态.oninput事件可以实时监听文本框的输入变化.   现代浏览器支 ...

  6. 【BZOJ-3589】动态树 树链剖分 + 线段树 + 线段覆盖(特殊的技巧)

    3589: 动态树 Time Limit: 30 Sec  Memory Limit: 1024 MBSubmit: 405  Solved: 137[Submit][Status][Discuss] ...

  7. hdu 5229 找规律

    假设选择了字符串a和b: 假设两人都按照最聪明的策略,那么观察一下可以找出规律:当a和b的字符串长度之和为奇数的时候zcc会败. 另外当a==b的时候zcc也会败(当时做的时候忘了这个了T^T) 接下 ...

  8. HDU4612 Warm up

    Time Limit: 5000MS   Memory Limit: 65535KB   64bit IO Format: %I64d & %I64u Description N planet ...

  9. 64位CentOS源码编译方式安装wine

    说明:本文仅作本人笔记的之用,仅供参考.可能因不同环境而不同. 1. 从官网下载最新版的wine-1.6.2.tar.gz 2. 安装相关的包(这里是我安装的,可能由于不同系统已经安装的包不同而不一样 ...

  10. MOOCULUS微积分-2: 数列与级数学习笔记 5. Another comparison test

    此课程(MOOCULUS-2 "Sequences and Series")由Ohio State University于2014年在Coursera平台讲授. PDF格式教材下载 ...