Skip to content

ApplePay-纯API模式集成

该文档介绍纯API模式下,使用ApplePay的集成步骤。

纯API集成模式下,商户需要自行构建相关的支付页面,如:收银页、支付结果页等;此外,还需要商户进行复杂的证书配置以及加解密处理。因此,该模式需要商户投入更多的研发成本。

关于纯API集成模式的更多信息,请查看集成模式概览

1. 交互流程

2. 集成准备

  • 根据配置与签名引导,获取PayerMax侧的商户自助平台账号、获取商户appId和密钥、配置异步通知地址、配置公钥和私钥。

  • 进行ApplePay的相关证书配置流程,主要包括:

    • 创建商户IDs

    • 注册并验证商户域名

    • 创建 Payment Processing Certificate

    • 创建 Merchant Identity Certificate

注意:

若商户已完成ApplePay的相关证书配置流程,可直接按照步骤3.4进行对接即可。

2.1 创建商户IDs

登录 Apple Developer,添加 Merchant ID。进入对应模块 Certificates, Identifiers & Profiles -> Identifiers -> Merchant IDs

2.2 注册并验证商户域名

使用ApplePay的页面必须使用HTTPS访问,该页面的域名必须有SSL证书。ApplePay会在处理过程中验证该域名证书的有效性,证书过期则无法提供服务。

  1. 域名不能位于代理服务器或者重定向后,并且允许Apple服务器访问,详情请参考Allow Apple IP Addresses for Domain Verification

  2. 一个Merchant ID下可以添加多个域名。

  1. 添加域名后下载域名验证文件,将下载到的域名验证文件上传到自己服务上。确保可以通过 https://yourdomain.com/.well-known/apple-developer-merchantid-domain-association.txt 访问到该文件。Apple通过访问该文件来验证配置域名的合法性。
  • 使用自己的真实域名替换yourdomain.com

  • 在你的Web服务器根目录下创建一个文件夹.well-known并将下载到的文件放在该文件夹中。

  1. 配置好域名验证文件后在Apple Developer后台进行域名有效性验证。

验证通过后操作界面会展示验证有效期,该有效期等同于域名SSL证书的有效期。示例中的域名证书有效期如下:

注意:

示例图片中时间差异是因为两者采用了不同的时区展示。

  1. 证书过期更新:

特别提醒:

Apple 会在域名SSL证书过期前的30天15天7 天分别去检查你的域名证书是否更新。

  • 如果你在证书过期前完成了更新,Apple检测到了更新后的证书并且域名验证没问题,那么你不需要做任何额外的事情;

  • 如果没有在证书过期前完成更新,则要重新下载域名认证文件并再次完成验证(参考第2、3步)。

最佳实践是在域名证书过期前的7天之前完成证书更新,这样在7天的检查中可以拿到更新后的证书信息。

2.3 创建 Payment Processing Certificate

该证书用于Server端和ApplePay的交互,属于正常HTTPS请求的客户端证书。操作步骤请参考Apple官方文档

2.3.1 生成 Certificate Signing Request (CSR)

两种方式,一种是参考Apple官方文档,使用Keychain Access生成,还有一种是使用命令行生成。接下来主要介绍第二种方式。

  1. 需要先安装OpenSSL

  2. 生成私钥,需使用ECC算法,256长度:

openssl ecparam -genkey -name prime256v1 -out applepay-ppc-ecc-256-private.key

会得到applepay-ppc-ecc-256-private.key文件,这个就是私钥,需要保存到系统中,后续解密Token会用到。

  1. 生成csr文件:
openssl req -new -key applepay-ppc-ecc-256-private.key -out applepay-pcc-ecc-256.csr

需要填写公司相关的信息,例如:

会得到applepay-pcc-ecc-256.csr文件。

2.3.2 上传证书

  • Merchant Id 详情页中的 Apple Pay Payment Processing Certificate 部分,点击 Create Certificate 创建证书:
  • 选择上一步创建的CSR文件
  • 上传完成后点击 Continue。成功后Apple会生成证书,点击 Download 下载证书。

2.4 创建 Merchant Identity Certificate

调用Apple Pay的create sesion接口是SSL双向认证,需要使用客户端证书,就是Merchant Identity Certificate。创建这个证书也需要生成私钥CSR等步骤。

2.4.1 生成私钥

这里是要生成RSA 2048的私钥:

openssl genrsa -out applepay-mic-rsa-2048-private.key 2048

得到applepay-mic-rsa-2048-private.key私钥文件,这个私钥需要保存好,后续在调用接口时会用到。

2.4.2 生成 CSR

openssl req -new -key applepay-mic-rsa-2048-private.key -out applepay-mic-rsa-2048.csr

这里一样需要填写证书所有者的信息。填写完成后会得到applepay-mic-rsa-2048.csr文件。

2.4.3 上传 CSR

打开 Merchant Id 的详情页,找到 Apple Pay Merchant Identity Certificate 章节:

点击 Create Certificate 按钮,选择上一步生成的CSR文件ContinueContinue,然后就能得到证书。

保存好证书,后续支付处理过程中会使用到。

3. 集成步骤

商户需要自己获取ApplePay Token解密Token得到卡信息,然后将解密后的卡信息传递给PayerMax。

注意:

若商户已在自己收银台集成过Apple Pay,可直接按步骤3.4对接即可。

3.1 初始化页面时获取 Apple Pay Session

参考链接:

注意:

在调用Apple的接口获取session时,需要使用到SSL的客户端证书,即前面创建的Merchant Identity Certificate

3.2 用户支付获取 ApplePay Token

sessiononpaymentauthorized回调方法入参中可获取加密Token,详情请参考:onpaymentauthorized | Apple Developer

js
...
this.session = new window.ApplePaySession(APPLE_PAY_VERSION, this.payRequest);

...

this.session.onpaymentauthorized = (event) => {
  // event.payment.token 即为加密 token
};
...

拿到的 token 示例如下:

json
{
    "paymentData": {
        "data": "",
        "signature": "",
        "header": {
            "publicKeyHash": "",
            "ephemeralPublicKey": "",
            "transactionId": ""
        },
        "version": "EC_v1"
    },
    "paymentMethod": {
        "displayName": "Visa 8007",
        "network": "Visa",
        "type": "debit"
    },
    "transactionIdentifier": ""
}

3.3 解密 Apple Pay Token

json
{
    "applicationExpirationDate": "280228",
    "applicationPrimaryAccountNumber": "42710600003562",
    "currencyCode": "124",
    "deviceManufacturerIdentifier": "040010030273",
    "paymentData": {
        "eciIndicator": "5",
        "onlinePaymentCryptogram": "/wAAADcAv7mhHpQAAAAAgPdgE4A="
    },
    "paymentDataType": "3DSecure",
    "transactionAmount": "5564"
}

3.4 调用PayerMax进行支付

创建支付/orderAndPay API 接口请求,其中关键字段:

  • paymentDetail.paymentMethodTypeAPPLEPAY

  • paymentDetail.applePayPaymentTokenDecrypted:为解密后的支付信息

接口请求示例:

Apple Pay Token解密后的卡信息,传递给data.paymentDetail.applePayPaymentTokenDecrypted字段中。

json
{
  "version": "1.4",
  "keyVersion": "1",
  "requestTime": "2022-02-25T09:23:06.473+00:00",
  "appId": "6666c8b036a24579974497c2f9800001",
  "merchantNo": "020213834421234",
  "data": {
    "outTradeNo": "Test1645780876511",
    "subject": "this is subject",
    "totalAmount": 1,
    "currency": "AED",
    "country": "AE",
    "userId": "userId001",
    "integrate": "Direct_Payment",
    "expireTime": "1800",
    "paymentDetail": {
      "paymentMethodType": "APPLEPAY",
      "buyerInfo": {
        "firstName": "James",
        "lastName": "Smith",
        "phoneNo": "903124360628",
        "email": "james@google.com",
        "clientIp": "124.156.108.193",
        "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36"
      },
      "applePayPaymentTokenDecrypted": {
          "applicationExpirationDate": "2312",
          "applicationPrimaryAccountNumber": "4111111111111111",
          "currencyCode": "USD",
          "deviceManufacturerIdentifier": "A1B2C3D4",
          "paymentDataType": "3DSecure",
          "transactionAmount": "100.00",
          "paymentData": {
            "onlinePaymentCryptogram": "Aa0KZXFURkhF...",
            "eciIndicator": "07"
          },
          "network": "VISA",
          "type": "credit"
          "displayName": "Visa 0492"
     },
    "goodsDetails": [
      {
        "goodsId": "D002",
        "goodsName": "Key buckle",
        "quantity": "2",
        "price": "0.5",
        "goodsCurrency": "AED",
        "showUrl": "http://ttt.com",
        "goodsCategory": "电脑"
      }
    ],
    "shippingInfo": {
      "firstName": "James",
      "lastName": "Smith",
      "phoneNo": "903124360628",
      "email": "xxx@google.com",
      "address1": "address1",
      "city": "GAZIOSMANPASA/ANKAR",
      "country": "TR",
      "zipCode": "06700"
    },
    "billingInfo": {
      "firstName": "James",
      "lastName": "Smith",
      "phoneNo": "903124360628",
      "email": "xxx@google.com",
      "address1": "address1",
      "city": "GAZIOSMANPASA/ANKAR",
      "country": "TR",
      "zipCode": "06700"
    },
    "riskParams": {
      "registerName": "lily",
      "regTime": "2023-07-01 12:08:34",
      "liveCountry": "VN",
      "payerAccount": "987654XXX",
      "payerName": "lily",
      "taxId": "1234567890"
    },
    "language": "en",
    "reference": "020213827524152",
    "terminalType": "WAP",
    "frontCallbackUrl": "https://xxx.com",
    "notifyUrl": "https://yyy.com"
  }
}

接口响应示例:

json
{
  "code": "APPLY_SUCCESS",
  "msg": " Success.",
  "data": {
    "outTradeNo": "a1234934974321",
    "tradeToken": "T2025051210335071234567",
    "status": "SUCCESS"
  }
}

此页面的内容有帮助吗?

感谢您帮助改进 PayerMax 产品文档!

Last updated:

Released under the MIT License.