开始集成
环境准备
在开始前,请您确保已完成 设置测试环境 步骤以便继续。
环境信息如下:
| 测试环境 | https://pay-gate-uat.checus.com/aggregate-pay/api/gateway/<PATH> |
| 正式环境 | https://pay-gate-hk-prod.checus.com/aggregate-pay/api/gateway/<PATH> |
交互流程

关键接口
| 关联交互时序 | 调用方向 | 接口类型 | 接口名称/方法 |
|---|---|---|---|
| 1.3 获取前置组件初始化信息 | 商户 -> Checus | 后端接口 | /applyDropinSession |
| 1.6 创建并挂载Checus组件 | 商户客户端 -> Checus前置组件JS SDK | 前端接口 | PMdropin.create |
| 1.6 创建并挂载Checus组件 | 商户客户端 -> Checus前置组件JS SDK | 前端接口 | PMdropin.mount |
| 1.6 创建并挂载Checus组件 | 商户客户端 -> Checus前置组件JS SDK | 前端接口 | PMdropin.on |
| 2.2 获取paymentToken | 商户客户端 -> Checus前置组件JS SDK | 前端接口 | PMdropin.emit |
| 3.4 创建支付,调用前置组件下单接口 | 商户 -> Checus | 后端接口 | /orderAndPay |
| 4.1 支付结果异步通知 | Checus -> 商户 | 后端接口 | /collectResultNotifyUrl |
| 5.1 查询支付交易 | 商户 -> Checus | 后端接口 | /orderQuery |
卡类支付集成步骤
1. 创建支付会话
调用 前置组件初始化API ,发起POST请求以创建支付。
从返回值获取 clientKey 和 sessionKey,用于前端组件初始化。
{
'Content-Type': 'application/json;charset=utf-8',
'Accept': 'application/json',
'sign': <参考:https://docs-v2.checus.com/doc-center/developer/config-settings.html>
};
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"
}
}2. 渲染组件
您可下载 Demo示例,替换
clientKey和sessionKey后可以本地打开看到效果。
- 引入 JS 组件js
<script src="https://dropin.checus.com/dropin/js/pmdropin.min.js"></script> - 添加挂载容器js
<div class="frame-card"> <!-- form will be added here --> </div> - 初始化组件js
// 初始化卡组件 const card = PMdropin.create('card', { clientKey: "客户端公钥", // 在步骤1中获取到的 data.clientKey sessionKey: "会话令牌", // 在步骤1中获取到的 data.sessionKey sandbox: false, // 默认是 false,即生产环境 hideSaveCard: false, //是否隐藏保存卡信息选项,默认是false展示 hideCardBrands: false, //是否隐藏左上角卡品牌的Logo,默认是false展示 }); // 挂载实例 card.mount('.frame-card'); // 将挂载至匹配到的第一个dom元素上 // 组件加载完成时机 card.on('ready', () => { // 移除自定义loading }) - 监听表单状态(可选)
状态变更时将实时回调,可以由此决定支付按钮是否可点击。
card.on('form-check', (res) => {
// res.isFormValid 为表单状态 false/true
// true 表示表单校验通过,可尝试支付;false 表示校验未通过,无法点击支付按钮
console.log('[dropin][form-check]:', res)
})- 获取支付 token 并发起下单
调用支付接口前务必检查是否可支付;可支付时,将获取到 paymentToken, 用于发起支付接口。
card.emit('setDisabled', true) // 点击支付按钮后冻结表单,防止重复提交支付过程
card.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') {
//支付成功,展示支付结果
} else {
//支付失败,展示支付结果
}
}
card.emit('setDisabled', false) // ❗️支付接口完成后解冻表单
}
})
.catch(err => {
card.emit('setDisabled', false) // 发生异常后解冻表单
})3. 商户后台下单
发起时机
当 canMakePayment 返回 APPLY_SUCCESS 后,从中获取 paymentToken,由商户服务端调用 /orderAndPay 接口完成下单。
请求流程
商户前端将
paymentToken传至商户后端;商户服务端生成唯一
outTradeNo,向 Checus 发起支付请求;若返回
redirectUrl且status=PENDING,前端需跳转该 URL 进行认证(如 3DS);其他情况下直接返回支付结果。
下单详细字段请参与 前置组件支付接口。
json{ 'Content-Type': 'application/json;charset=utf-8', 'Accept': 'application/json', 'sign': <XXX> }; { "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": "Chrome" }, "sessionKey": "86409e2c04b44536a484caa5ce3ce0e9" }, "frontCallbackUrl": <替换>, "subject": "GoGeal PTE. LTD.", "outTradeNo": <商户订单号,需唯一>, "notifyUrl": <替换>, "currency": "HKD", "userId": "3ff0495692d152be96d84dbc9352dc57", "integrate": "Direct_Payment", "terminalType": "WEB" } }
卡类前端接口
API 使用说明
前置组件提供了标准的 API 接口供前端调用,核心方法通过 PMdropin.API 调用。
| 方法 | 描述 | 说明 |
|---|---|---|
create | 初始化组件 | 详见 1.1 |
mount | 挂载组件至页面 | 详见 1.2 |
on | 监听组件事件 | 详见 1.3 |
emit | 触发组件方法 | 详见 1.4 |
1. create — 初始化组件
const card = PMdropin.create('card', options);ComponentName:当前支持'card'(卡支付)options参数如下:
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| clientKey | string | ✅ | - | 客户端公钥 |
| sessionKey | string | ✅ | - | 会话令牌 |
| sandbox | boolean | ❌ | false | 是否启用沙盒环境 |
| language | string | ❌ | 'en' | 显示语言 |
| theme | string | ❌ | 'light' | 默认主题 |
| customLocalization | object | ❌ | - | 自定义语言包 |
| customTheme | object | ❌ | - | 自定义样式 |
| grayscale | string | ❌ | '0' | 页面灰度(0-1) |
| isRtl | boolean | ❌ | false | 从右至左布局支持 |
| hideSaveCard | boolean | ❌ | false | 是否隐藏“保存卡”选项 |
| hideCardBrands | boolean | ❌ | false | 是否隐藏卡组织 Logo |
| hideCardHolderName | boolean | ❌ | false | 是否隐藏姓名输入框 |
| saveCardChecked | boolean | ❌ | true | “保存卡”默认是否勾选 |
| ignoreUserCheckedCache | boolean | ❌ | false | 忽略用户勾选缓存 |
2. mount — 挂载组件
card.mount('#card-frame'); // 挂载到指定 DOM 节点支持使用 id 或 class 选择器。
3. on — 监听组件事件
card.on('ready', () => {
// 组件加载完成
});
card.on('form-check', (res) => {
if (res.isFormValid) {
// 表单校验通过,可启用支付按钮
}
});| 事件名 | 说明 |
|---|---|
ready | 组件加载完成 |
form-check | 实时返回表单是否校验通过(res.isFormValid = true/false) |
4. emit — 调用组件方法
常用事件
| 方法 | 参数 | 说明 |
|---|---|---|
canMakePayment | - | 校验表单并获取 paymentToken |
setDisabled | boolean | 启用/禁用表单交互 |
switchLanguage | string | 切换语言 |
switchTheme | string | 切换主题 |
addLocalization | object | 添加自定义语言包 |
addTheme | object | 添加自定义主题 |
setRtl | boolean | 启用 RTL 布局 |
setGrayscale | string | 设置页面灰度(0-1) |
4.1 canMakePayment — 校验表单并获取 paymentToken
card.emit('canMakePayment')
.then(res => {
if (res.code === 'APPLY_SUCCESS') {
const paymentToken = res.data.paymentToken;
// 使用 token 发起后端支付
}
})
.catch(err => {
console.error('支付失败:', err);
});返回结构
// 成功
{
code: 'APPLY_SUCCESS',
data: {
paymentToken: 'xxx'
},
msg: ''
}
// 失败
{
code: 'FORM_INVALID', // 或 UNKNOWN_ISSUE
msg: 'Invalid params: cvv'
}| 返回码 | 说明 |
|---|---|
APPLY_SUCCESS | 成功获取 paymentToken |
FORM_INVALID | 表单未通过校验 |
UNKNOWN_ISSUE | 其他异常错误 |
4.2 emit.switchLanguage
参阅 定制化
4.3 emit.switchTheme
参阅定制化
4.4 emit.addLocalization
参阅定制化
4.5 emit.addTheme
参阅定制化
4.6 emit.setDisabled
- 设置组件可用状态
- 类型
Boolean - 默认:
false
// 不可编辑状态
PMdropin.emit('setDisabled', true)
// 可编辑状态
PMdropin.emit('setDisabled', false)4.7 emit.setRtl
- 设置组件从右到左布局
- 类型:
Boolean - 默认:
false
// 从右到左布局
PMdropin.emit('setRtl', true)
// 从左到右布局
PMdropin.emit('setRtl', false)4.8 emit.setGrayscale
- 设置组件页面灰度
- 类型:
String - 默认:
0
// 设置 0 - 1 灰度值
PMdropin.emit('setGrayscale', '1')更多配置请参考 卡类定制化
// 设置表单为不可编辑状态
card.emit('setDisabled', true);
// 切换语言
card.emit('switchLanguage', 'zh-CN');
// 启用右至左布局
card.emit('setRtl', true);
// 设置页面灰度为 100%
card.emit('setGrayscale', '1');卡类定制化
通过定制语言和主题样式,您可以更好地适配自身网站的 UI 和用户体验。
1. 语言本地化
1.1 使用预置语言
支持设置 language 参数快速切换语言:
PMdropin.create('card', {
clientKey: '',
sessionKey: '',
language: 'zh' // zh: 中文, en: 英文(默认)
});也可通过如下方式动态切换:
PMdropin.emit('switchLanguage', 'zh');1.2 自定义语言
如预置语言不满足需求,可通过 customLocalization 添加自定义字段:
PMdropin.create('card', {
clientKey: '',
sessionKey: '',
customLocalization: {
// 添加中文示例
'zh': {
loading: '加载中',
loadingFailed: '加载失败',
refresh: '刷新',
confirm: '确定',
cancel: '取消',
removeCard: '移除卡',
removeCardTip: '确定移除当前选中卡吗?',
addNewCard: '使用新卡',
useSavedCard: '使用已存卡',
cardnum: '银行卡号',
cardnumHint: 'XXXX XXXX XXXX XXXX',
cardnumErrTip: '卡号不正确',
cardbinErrTip: {
// {cardOrg} 变量字段,无需翻译
CARD_NOT_SUPPORT: '不支持{cardOrg},请检查卡号或者更换其他卡重试',
// {cardType} 变量字段,无需翻译
CARD_INVALID: '不支持{cardType}的卡类型',
CARD_NO_INVALID: '请确认卡号输入是否正确',
},
expdate: '过期日期',
expdateHint: '月/年',
expdateErrTip: '过期日期不正确',
cvv: 'CVV/CVC',
cvvHint: '123',
cvvErrTip: 'CVV/CVC 格式不正确',
name: '持卡人姓名',
nameHint: 'XX XX',
nameErrTip: '姓名格式不正确',
saveCardInfoTip: '为下次支付保存信息',
// 以下为新增多语言字段
// 本地卡额外采集要素
buyerEmail: '邮箱',
buyerEmailHint: '',
buyerEmailErrTip: '格式错误,请复核',
buyerFullName: '姓名',
buyerFullNameHint: '',
buyerFullNameErrTip: '格式错误,请复核',
buyerFirstName: '名',
buyerFirstNameHint: '',
buyerFirstNameErrTip: '格式错误,请复核',
buyerLastName: '姓',
buyerLastNameHint: '',
buyerLastNameErrTip: '格式错误,请复核',
// 秘鲁 Document(ID)
dni: 'DNI',
dniHint: '',
dniErrTip: '格式错误,请复核',
// 阿根廷 Document(ID)
dni_cuit: 'DNI/CUIT',
dni_cuitHint: '',
dni_cuitErrTip: '格式错误,请复核',
// 南非 Document(ID)
idCard: 'ID',
idCardHint: '',
idCardErrTip: '格式错误,请复核',
// 哥伦比亚 Document(ID)
cc: 'CC',
ccHint: '',
ccErrTip: '格式错误,请复核',
// 墨西哥 Document(ID)
curp: 'CURP',
curpHint: '',
curpErrTip: '格式错误,请复核',
// 巴西 Document(ID)
cpf: 'CPF',
cpfHint: '',
cpfErrTip: '格式错误,请复核',
// 智利/巴拉圭/乌拉圭 Document(ID)
ci: 'CI',
ciHint: '',
ciErrTip: '格式错误,请复核',
buyerPhoneNo: '手机号码',
buyerPhoneNoHint: '',
buyerPhoneNoErrTip: '格式错误,请复核',
buyerPhoneNoRegion: '手机区号',
buyerPhoneNoRegionHint: '',
buyerPhoneNoRegionErrTip: '格式错误,请复核',
}
},
...
});动态添加方式:
PMdropin.emit('addLocalization', {
'zh': {
// 参数如上所示
}
});2. 主题样式
2.1 使用预置主题
支持 light(默认)与 dark 两种主题:
PMdropin.create('card', {
clientKey: '',
sessionKey: '',
theme: 'dark'
});动态切换:
PMdropin.emit('switchTheme', 'dark');2.2 自定义主题
可通过 customTheme 自定义 CSS 变量覆盖主题样式:
PMdropin.create('card', {
clientKey: '',
sessionKey: '',
customTheme: [
{
name: 'red',
base: 'light',
style: `:root {
--color-primary: #e60000;
--bg-primary: #fff;
--border-radius-primary: 8px;
// ... 其他样式
}`
}
]
});也可通过动态添加:
PMdropin.emit('addTheme', [{ name: 'red', base: 'light', style: '...' }]);