集成步骤
1. 实现流程
对接前:需要提供 https 域名给 payermax 配置(正式环境和测试环境共两个域名),用于 ApplePay 发起支付。
特别提醒:
- 测试时,
127.0.0.1
、局域网
、localhost
都无法拉起 ApplePay; - ApplePay 域名认证有效期与域名 SSL 证书有效期一致,详情请参考Apple官网说明;
- 商户需要在其域名SSL证书过期
15天前
或更早提前完成证书更新,并通知PayerMax;若有效期小于7天后
才完成证书更新,需联系PayerMax重新认证域名; - 域名认证仍有效的情况续期操作不影响正常交易,但若域名认证已过期会导致交易失败。
(a) 商户提供其测试环境和产线环境域名给 PayerMax;
(b) PayerMax 将为商户生成各域名对应证书;
(c)商户将证书文件 apple-developer-merchantid-domain-association.txt 添加到 ./well-known 路径下;
注意:
请注意证书配置路径。
(4) 商户配置好了证书后,通知 PayerMax 验证域名证书,PayerMax将在Apple开发者后台操作域名证书验证。
如果验证失败:
- 可能证书路径配置错误:
请再次检查路径是否正确;
- 可能域名防火墙拦截了苹果检查服务:请配置链接页面域名至服务器白名单,可参考下方截图;
- 可能已经配置过其他MerchantID的证书:
可使用新域名,或在原开发者账号上删除对应域名证书。
1.1 获取 clientKey 和 sessionKey
接口详细说明请参阅:接口参数。
(a) 请求API;环境及地址如下:
请求环境 | 请求地址 |
Test | https://pay-gate-uat.payermax.com/aggregate-pay/api/gateway/applyDropinSession |
Live | https://pay-gate.payermax.com/aggregate-pay/api/gateway/applyDropinSession |
(b) 从返回值获取 clientKey 和 sessionKey。
注意:
服务端获取到的clientKey
、sessionKey
返回给前端用于组件初始化。
请求Header示例:
{
'Content-Type': 'application/json;charset=utf-8',
'Accept': 'application/json',
'sign': <参考:https://docs-v2.payermax.com/doc-center/developer/config-settings.html>
};
请求Body示例:
request.body =
{
"version": "1.1",
"keyVersion": "1",
"requestTime": <替换>,
"merchantNo": <替换>,
"appId": <替换>,
"data": {
"country": "MY",
"currency": "MYR",
"totalAmount":"50",
"userId": "20220622_00086",
"componentList":["APPLEPAY","CARD"]
}
}
response={
"msg": "",
"code": "APPLY_SUCCESS",
"data": {
"sessionKey": "bf2c47b085e24c299e45dd56fd751a70",
"clientKey": "bbd8d2639a7c4dfd8df7d005294390df"
}
}
1.2 渲染组件
- 前端示例
下载Demo示例,替换 clientKey 和 sessionKey 后,需要部署在带有ApplePay证书的域名打开可以看到效果。
- 前端集成步骤
(a) 在相关 HTML 页面上引入 CDN 包;
<script src="https://cdn.payermax.com/dropin/js/pmdropin.min.js"></script>
(b) 通过 div 标签嵌入一个 iframes;
<div class="frame-applepay">
<!-- form will be added here -->
</div>
(c) 初始化 PayerMax Frames;
// 初始化卡组件
const applePay = PMdropin.create('applepay', {
clientKey: "客户端公钥", // 在步骤1.1中获取到的 data.clientKey
sessionKey: "会话令牌", // 在骤1.1中获取到的 data.sessionKey
sandbox: true, // 默认是 false,即生产环境
theme: 'dark',// 主题,默认light
});
// 挂载实例
applePay.mount('.frame-applepay'); // 将挂载至匹配到的第一个 dom 元素上
// 组件加载完成时机
applePay.on('ready', () => {
// 移除自定义loading
})
(d) 监听 applePay 按钮点击,获取 paymentToken;
注意:
获取到 paymentToken
, 用于发起支付接口。
applePay.on('payButtonClick', (res) => {
applePay.emit('setDisabled', true) // 冻结表单,防止按钮重复点击
applePay.emit('canMakePayment')
.then(res => {
if (res.code === 'APPLY_SUCCESS') {
const paymentToken = res?.data?.paymentToken // 支付token,支付接口使用
// ❗️发起支付接口
// 商户自己请求后端接口进行下单,
// 商户自己用params构造请求参数,需要带上paymentToken
_postapi('orderAndPay',params).then(res =>{
const code = (res || {}).code
//商户将支付结果返回到前端
if (code == 'APPLY_SUCCESS') {
applepay.emit('paySuccess')//支付成功,ApplePay控件消失
} else {
applepay.emit('payFail')//支付失败,ApplePay控件消失
}
applePay.emit('setDisabled', false) // ❗️支付接口完成后解冻表单
}
})
.catch(err => {
applePay.emit('setDisabled', false) // 发生异常后解冻表单
})
})
(e) 发起支付,具体可查看1.3中的服务端发起支付。
1.3 商户后台下单
- 下单时机
请在前端回调 card.emit('canMakePayment') 后,当 response.code 为 'APPLY_SUCCESS' 时发起下单请求,此时可从 canMakePayment 方法获取到 paymentToken,用在后续下单接口入参。
- 下单步骤
(a) 户前端向商户后端发起下单,传入 canMakePayment 方法获取到的 paymentToken;
(b) 商户服务端生成订单号(outTradeNo)后向 PayerMax 服务端发起支付请求;
(c) 处理 PayerMax 响应结果。
- 响应处理
服务端下单会返回支付结果,处理完支付结果需要响应到前端,前端根据响应结果调用applepay.emit('paySuccess')或者applepay.emit('payFail')
- API 环境及地址
请求环境 | 请求地址 |
Test | https://pay-gate-uat.payermax.com/aggregate-pay/api/gateway/orderAndPay |
Prod | https://pay-gate.payermax.com/aggregate-pay/api/gateway/orderAndPay |
请求Header示例:
sign 字段的取值请参阅【配置与签名】。
{
'Content-Type': 'application/json;charset=utf-8',
'Accept': 'application/json',
'sign': <XXX>
};
请求Body示例:
下单详细字段请参阅接口参数。
{
"appId": "<替换>",
"version": "1.4",
"merchantNo": "<替换>",
"requestTime": "2024-06-05T10:46:01.694+08:00",
"keyVersion": "1",
"data": {
"totalAmount": 77.44,
"country": "HK",
"expireTime": "7200",
"paymentDetail": {
"paymentToken": "332e4cc1af1740aeafe9e7df82aeb5a1",
"buyerInfo": {
"clientIp": "59.82.59.92",
"userAgent": "Safari"
},
"sessionKey": "86409e2c04b44536a484caa5ce3ce0e9"
},
"frontCallbackUrl": "<替换>",
"subject": "<替换>",
"outTradeNo": "1003052024060510454400707",
"notifyUrl": "<替换>",
"currency": "HKD",
"userId": "3ff0495692d152be96d84dbc9352dc57",
"integrate": "Direct_Payment",//固定
"terminalType": "WEB"
}
}
2. 其他定制
前端接口详情请参阅【ApplePay前端接口】文档。