Apple pay 整体接入流程
一 . 简介
Apple Pay,是苹果公司在2014苹果秋季新品发布会上发布的一种基于NFC的手机支付功能,于2014年10月20日在美国正式上线。官网链接apple pay developer
二. 整个流程中如下:
- 客户端通过苹果API,在 APP 应用内展示 Apple Pay 支付控件。(注意: 和其他支付入口一样醒目)
- 用户在 Apple Pay 的支付控件上进行生物验证(指纹或者人脸识别)或者手机密码验证。
- 苹果在用户验证通过之后,会生成一个用户选中的银行卡相关的 PaymentToken 加密数据,Apple Pay 必须在有网情况下才能进行,苹果需要从开发者网站上使用证书的公钥进行加密,完成后通过 API 回调返回给客户端前端。
- 客户端获取到 PaymentToken 后,给服务端发送扣款请求,等待支付结果。
- 服务端收到客户端上送的 PaymentToken,解密 PaymentToken 取出一些关键字段信息,附带其他订单信息,再与支付供应商(如国内银联)进行通信发起扣款。
- 服务端收到扣款结果后,再返支付结果给手机客户端,最终通知用户支付结果。
Apple Pay 数据加密
Apple Pay 中传输中的 PaymentToken 有着一套非常完善的加密安全机制。
国外统一用的是 ECC 加密方式,只有中国用的是 RSA 加密方式,详见官方PaymentToken说明。PaymentToken数据是 JSON 数据格式,其中包含了苹果加密后的支付信息数据。
三 . APP 接入 Apple Pay
1、证书的准备;
2、APP工程配置和证书使用;
3、API 调用;
1. 证书准备
开发者需要在苹果开发者网站上提交 Apple Pay 的证书。
生成Apple Pay 证书首先需要准备一个 CSR 文件,通过 mac 电脑的钥匙串应用可以快速生成,这个 CSR 文件就是一个文本文件CertificateSigningRequest.certSigningRequest。
需要将这个 CSR 文件上传到苹果开发者网站上:
生成 Apple Pay 证书的 CSR 文件时注意: 中国区生成 CSR 时需要使用 RSA 加密方式。 非中国区生成 CSR 时需要使用 ECC 加密方式。
CSR 中包含公钥信息,生成同时,mac 电脑钥匙串应用里会生成对应的私钥。 上传 CSR 到苹果开发者网站生成证书完成后,下载安装到 mac 上,可以在钥匙串应用里面看到私钥,并可以导出私钥,用于解密。
ApplePay 的证书生成流程官方和网上都有流程介绍,这里不再赘述。
2. 工程配置和证书使用
在苹果开发者账号网站上可以看到,每一个 Apple Pay 证书都对应和关联一个 MerchantId,每一个 Apple Pay 证书在实际使用过程中,对应一套密钥,对应一套支付扣款通道。苹果下发的 PaymentToken 加密时,就是根据 APP 调用 API 时传入的 MerchantId 找到对应的公钥进行加密处理。
客户端调用ApplePay API 时,需要指定证书的 MerchantId,建议不要客户端写死在本地,最好由服务端下发,做成灵活可配置的,这样可以进行支付通道切换。
证书生成之后,需要在 Xcode 工程文件的 Targets 的 capability 里,打开 Apple Pay的开关,并勾选证书对应的 MerchantId,否则打出的APP 安装包 ipa 无法唤起 Apple Pay 的支付页面。
Apple Pay 证书有时效性,一般两年后会过期,需要更换密钥。证书过期的处理,具体操作可以在苹果开发者网站上执行。
在下图所示页面更换证书时,先绑定新的 CSR 生成新证书,Activate 之后,线上就会切换到新证书模式了。
3. 关联Merchant ID
直接在现有项目中添加Apple Pay 相关内容,自动关联,如图!

四. 实际代码片段如:
/// 判断是否支持支付功能
if PKPaymentAuthorizationViewController.canMakePayments() {
let request = PKPaymentRequest()
let payItem = PKPaymentSummaryItem(label: "typeOne", amount: NSDecimalNumber(string: "87.9"))
let total = PKPaymentSummaryItem(label: "sum", amount: NSDecimalNumber(string: "87.9"))
request.paymentSummaryItems = [payItem, total]
request.countryCode = "US"
request.currencyCode = "USD"
if #available(iOS 9.2, *) {
request.supportedNetworks = [PKPaymentNetwork.amex,
PKPaymentNetwork.chinaUnionPay,
PKPaymentNetwork.discover,
PKPaymentNetwork.interac,
PKPaymentNetwork.masterCard,
PKPaymentNetwork.privateLabel,
PKPaymentNetwork.visa]
} else {
// Fallback on earlier versions
}
request.merchantIdentifier = "merchant.com.youshang.Kuaidi4Courier"
request.merchantCapabilities = .capabilityEMV
let paymentAuthorizationController = PKPaymentAuthorizationViewController(paymentRequest: request)
paymentAuthorizationController?.delegate = self
return paymentAuthorizationController
} else {
return nil
}
实现 PKPaymentAuthorizationViewControllerDelegate 代理方法 optional func paymentAuthorizationViewControllerWillAuthorizePayment(_ controller: PKPaymentAuthorizationViewController). 和 func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) 两个代理方法实现