OnepageSDK(下单并支付)
# 接入流程
# 1. 获取 sdkAccessToken 接口
商户后端系统通过获取 sdkAccessToken 接口 得到JS-SDK访问凭证(token),该凭证用于前端JS-SDK的初始化调用。
# 2. 引入Javascript-SDK
复制以下代码,通过CDN地址引入 PingPongCheckout Javascript-SDK
<script type="module" src="https://payssr-cdn.pingpongx.com/production-fra/acquirer-checkout-onepage/sandbox/pp-checkout.js"></script>
<script type="module" src="https://payssr-cdn.pingpongx.com/production-fra/acquirer-checkout-onepage/pp-checkout.js"></script>
<script type="module" src="https://acquirer-cdn.pingpongx.com/acquirer/checkout-onepage/production-sg/pp-checkout.js"></script>
<script type="module" src="https://acquirer-cdn.pingpongx.com/acquirer/checkout-onepage/production-us/pp-checkout.js"></script>
// Make sure to add code blocks to your code group
# 3. 初始化收银台
将 pp-checkout 标签插入 html body 中
<pp-checkout locale="en"></pp-checkout>
调用 PingPong.Checkout.create 完成初始化
# 入参
| 字段 | 类型 | 必填 | 描述 | 备注 |
|---|---|---|---|---|
| amount | String | M | 交易金额 | 该交易仅用于收银台展示,后续金额变更需调用 updateCheckoutHook 函数进行更新 |
| currency | String | M | 交易币种 | |
| tradeCountry | String | M | 用于指定pingpong收银台国家 | 后续国家变更需调用 updateCheckoutHook 函数进行更新 |
| sdkAccessToken | String | M | JS-SDK访问凭证 | |
| originalPay | Boolean | O | 控制是否使用默认的 PingPong 支付按钮 | 默认为true,若将其设置为false,则表示不使用内置支付按钮。 此时,需要在页面内自定义支付按钮点击事件中调用 PingPong.Checkout.pay.run() 方法来触发支付流程。 |
| paymentMethods | String[] | O | 指定支付方式列表,内嵌收银台会根据指定的支付方式进行展示 | 传入的支付方式将与该accId下配置的支付方式进行交集运算。支付方式的展示顺序将根据传入数组的顺序进行排列。 |
| useTabMode | Boolean | O | 控制是否展示支付方式选项框 | 默认为true,当设置为false时,如果商户仅有卡支付配置,将不展示选项框,直接显示支付表单。适用于简化用户体验的场景。 |
| goods | Array | O | 商品列表 | 同下单接口的 goods 参数,包含 description、imgUrl、name、number、sku、unitPrice、virtualProduct 等字段 |
| bizType | String | C | ApplePay 绑卡业务参数 | ApplePay 交易必传 固定值: CodeGrant |
| recurringInfoDTO | Object | C | 配置 Recurring 付款 | ApplePay 交易必传 |
| recurringPaymentStartDate | Date | C | 首次付款日期 | eg: "2024-06-01 00:00:00" |
| recurringPaymentIntervalUnit | String | C | 表示年、月、日、时等日历单位的类型 | enum: year/month/day/hour/minute eg: "month" |
| recurringPaymentIntervalCount | String | C | 构成总支付间隔的间隔单位数 | eg: "6" |
| recurringPaymentEndDate | Date | C | 最后付款日期 | eg: "2024-12-01 00:00:00" |
PingPong.Checkout.create({
amount: '1.08',
currency: 'USD',
tradeCountry: 'US',
originalPay: true,
useTabMode: false,
sdkAccessToken: sdkAccessToken,
paymentMethods: ['VISA', 'Klarna'],
goods: [{
description: 'short legs',
imgUrl: 'http://pic.bizhi360.com/bpic/30/5230.jpg',
name: '한국어/English',
number: '1',
sku: '20230524001',
unitPrice: '1',
virtualProduct: 'N'
}],
// 如果需走 ApplePay 支付, 需额外传入以下参数
bizType: 'CodeGrant',
recurringInfoDTO:{
recurringPaymentStartDate: "2024-06-01 00:00:00",
recurringPaymentIntervalUnit: "month",
recurringPaymentIntervalCount: "6",
recurringPaymentEndDate: "2024-12-01 00:00:00"
},
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Make sure to add code blocks to your code group
# 自定义支付按钮(可选)
用户可以自定义按钮,通过点击事件去绑定 pingpong 的支付功能。
// 初始化参数中 originalPay 为 false 时, 需自定义支付按钮点击事件
document.querySelector('#pay').onclick = function () {
PingPong.Checkout.pay.run()
}
2
3
4
// Make sure to add code blocks to your code group
# 事件监听(可选)
SDK 支持监听初始化过程中的 ready 和 error 事件,方便外部进行状态管理和错误处理。
// 监听初始化成功事件
document.querySelector('pp-checkout').addEventListener('ready', (e) => {
console.log('SDK初始化成功');
// 可以在此处执行初始化完成后的逻辑
});
// 监听初始化失败事件
document.querySelector('pp-checkout').addEventListener('error', (e) => {
console.log('SDK初始化失败', e.detail);
// 可以在此处执行错误处理逻辑,如显示错误提示、重试等
});
2
3
4
5
6
7
8
9
10
11
// Make sure to add code blocks to your code group
事件说明:
- ready: 当 SDK 初始化成功时触发,表示收银台已准备就绪
- error: 当 SDK 初始化失败时触发,事件详情包含在 e.detail 中
# 4. 修改金额、国家和商品
在使用全局变量前,请确保Javascript-SDK 加载完成。
# updateCheckoutHook(可选)
updateCheckoutHook 用来更新收银台要素。
# ts 类型
PingPong.Checkout.updateCheckoutHook: ({amount?: string, tradeCountry?: string, goods?: Goods[]}) => void
// Make sure to add code blocks to your code group
使用场景:
- 当用户选择优惠券后,调用该Hook,传入最新的金额,PP 内嵌收银台会显示最新金额
PingPong.Checkout.updateCheckoutHook({ amount: newAmount });
- 当用户选择Country后,调用该Hook,传入最新的Country 二字码,PP 内嵌收银台会根据新的Country渲染支付方式列表
PingPong.Checkout.updateCheckoutHook({ tradeCountry: newCountry });
- 当商品信息变更时,调用该Hook,传入最新的 goods,PP 内嵌收银台会显示最新的商品信息
PingPong.Checkout.updateCheckoutHook({ goods: newGoods });
# 5. 下单前检验
# beforeCheckoutHook(可选)
type:
(() => void) | (() => Promise<void>)
// Make sure to add code blocks to your code group
beforeCheckoutHook 用来设置发起支付请求前的钩子函数。
当你在用户点击支付按钮,发起支付请求前,需要执行你自己的业务逻辑,如:上报埋点、检查库存等,可以设置该钩子函数。
该函数可以返回一个Promise,后续的支付流程会等待该 Promise 状态变为 Fulfilled 后才会继续执行。如果你想在 Promise 状态为 Rejected 或者异步结果不满足你的业务条件时,可以抛出异常,SDK在捕获到异常后中断支付流程。
PingPong.Checkout.beforeCheckoutHook = async ({payMethod}) => {
return fetch('/api/requestInventory').then(res => {
const { inventoryQuantity } = res;
if(inventoryQuantity < MIN_QUANTITY) {
throw new Error('库存不足,需中断交易')
}
}).catch((error) => {
throw new Error('接口异常,需中断交易')
})
};
2
3
4
5
6
7
8
9
10
11
12
// Make sure to add code blocks to your code group
# ts 类型
PingPong.Checkout.beforeCheckoutHook: (params: {payMethod?: string}) => string | Promise<string>
// Make sure to add code blocks to your code group
# 6. 下单
点击支付按钮后,调用下单接口支付去完成支付
# 7. 错误处理
# checkoutFailedHook(可选)
type:
(() => void) | (() => Promise<void>)
// Make sure to add code blocks to your code group
checkoutFailedHook 接收以下参数:
(code: string, message: string) => void | Promise<void>;
// code: string - 错误码
// message: string - 错误消息
2
3
4
// Make sure to add code blocks to your code group
checkoutFailedHook 用来自定义错误逻辑
当用户支付失败时,PingPong 默认会弹窗提示用户失败原因。如果你想自定义弹窗 UI 或文本,可以设置该钩子函数。
该函数可以返回一个 Promise。如果返回 Promise,后续的流程会等待该 Promise 状态变为 Fulfilled 后才继续执行
PingPong.Checkout.checkoutFailedHook = (code: string, message: string) => {
notification.open({
message: 'Error title',
description: `${code}: ${message}`
})
};
2
3
4
5
6
// Make sure to add code blocks to your code group
# 使用示例:
<body>
<div class="checkout">
<!-- billing 表单 -->
<form action="/billing"></form>
<!-- PingPong 内嵌收银台 -->
<pp-checkout locale="en"></pp-checkout>
<!-- shipping 表单 -->
<form action="/shipping"></form>
</div>
<div class="pay">
<!-- 优惠券码 -->
<div class="gift-card"></div>
<!-- 自定义支付按钮 -->
<button id="customPay">Pay Now</button>
</div>
<!-- 加载 PingPong JS-SDK -->
<script src="https://pay-cdn.pingpongx.com/production-fra/static/
pp-checkout-one-page/sandbox/pp-checkout.js"></script>
<script>
// 3. 初始化
const createCheckout = async () => {
PingPong.Checkout.create({
amount: '1.08',
currency: 'USD',
tradeCountry: 'US',
originalPay: false,
sdkAccessToken
})
}
// 定义hook
const createCheckoutHook = () => {
// 5. 定义 beforeCheckoutHook
PingPong.Checkout.beforeCheckoutHook = async ({payMethod}) => this.prePay();
// 7. 定义 checkoutFailedHook
PingPong.Checkout.checkoutFailedHook = (code, message) => {
notification.open({
message: 'Error title',
description: `${code}: ${message}`
})
};
// 4 监听 country、amount
amountEle.addEventListener('input', function() {
const newAmount = event.target.value;
PingPong.Checkout.updateCheckoutHook({amount: newAmount})
});
countryEle.addEventListener('change', function() {
const newCountry = event.target.value;
PingPong.Checkout.updateCheckoutHook({tradeCountry: newCountry})
});
// 初始化参数中 originalPay 为 false 时, 需自定义支付按钮点击事件
document.querySelector('#pay').onclick = function () {
PingPong.Checkout.pay.run()
}
}
window.onload = function() {
createCheckout();
createCheckoutHook();
};
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Make sure to add code blocks to your code group
# 常见问题
# Q1: 为什么我的结账流程无法启动,系统提示 beforeCheckoutHook 相关错误?
A: 当系统提示 "The beforeCheckoutHook is not defined or is not a function" 时,表明您的 one-page sdk 配置中缺少有效的 beforeCheckoutHook 函数。请确保在配置中正确定义此函数,它是启动结账流程的必要条件。
# Q2: 我已定义 beforeCheckoutHook 函数,但仍收到 token 相关错误,如何解决?
A: 错误 "Invalid or missing token returned by beforeCheckoutHook" 表明您的 beforeCheckoutHook 函数未返回有效的 token。请确保该函数返回一个非空字符串类型的 token,这是支付处理的必要凭证。
# Q3: 创建支付时,系统提示 amount 参数错误,应如何处理?
A: 当系统显示 "Invalid or missing amount: must be a non-empty string" 时,表明您提供的 amount 参数不符合要求。请确保 amount 参数是非空字符串类型,例如 "10.99"。
# Q4: 如何确保我使用的货币代码有效?
A: 系统支持特定的货币代码列表。如果收到 "Invalid or missing currency" 错误,请检查您提供的货币代码是否在支持列表中。常用的代码包括 "USD"、"EUR"、"CNY" 等。完整列表请参考 API 文档。
# Q5: sdkAccessToken 验证失败的原因是什么?
A: 错误 "Invalid or missing sdkAccessToken" 表明您提供的 sdkAccessToken 无效或缺失。请确保提供一个有效的、非空字符串类型的 sdkAccessToken,这是身份验证的关键凭证。
# Q6: 配置 paymentMethods 时需要注意什么?
A: 如果您选择配置 paymentMethods 参数,必须确保它是数组类型。若收到 "Invalid paymentMethods: must be an array or undefined" 错误,请检查您提供的值是否为数组,或考虑完全移除此参数以使用默认支付方式。
# Q7: 如何确保 one-page sdk 配置的正确性?
A: 建议在实施前全面测试您的配置。特别注意:
- beforeCheckoutHook 函数必须正确定义并返回有效 token
- 所有必需参数(amount、currency、sdkAccessToken)必须符合类型要求
- 可选参数如 paymentMethods 必须符合预期格式
# Q8: 支付流程中断时如何快速排查问题?
A: 请检查控制台错误信息,它通常会精确指出问题所在。根据错误信息对照本 FAQ 进行相应调整。如果问题持续,请确保您使用的是最新版本的 SDK,并查阅完整的技术文档。
