PM Dropin 错误码参考
本文档面向对接商户,说明接入 PM Dropin 支付组件时,在各调用入口 / 时序阶段可能收到的code及其含义,以及应该如何处理。本文档不区分错误码是由 SDK 前端产生还是服务端返回
商户只需要关注:我在哪个入口、哪个阶段、收到什么 code、它意味着什么。
0. 总览
0.1 如何阅读本文档
组件 API 只有两类入口:
| 入口 | 形式 | 携带code | 对应章节 |
| 订阅事件 | instance.on('load' /'form-check' /'payButtonClick' / ...) | 仅 load 带 code, 其余为状态/通知 | §1、§2.2 等 |
| 触发动作 | instance.emit('canMakePayment' / ...),返回 Promise | resolve = 成功; reject = 失败,err.code为错误码 | §2.3、§3、 §4 |
四类支付组件统一按以下时序阶段展开描述:
初始化(ready → load)→ 用户交互(卡表单 form-check / 系统支付按钮 payButtonClick)→ 支付请求(emit('canMakePayment'))→ 商户下单收尾 (Apple Pay 需 paySuccess / payFail)。
0.2 统一约定
| 约定 | 说明 |
| 成功码 | 事件入口成功为 SUCCESS ; emit('canMakePayment') 成功为 APPLY_SUCCESS (二者含义相同,出现位置不同) |
| 失败响应 | 统一为 { code, msg, displayMsg? } : code 见各章表格; msg 为英文机器文案(或服务端返回文案); displayMsg 为双语 { en, ar } 可直接展示的文案(目前主要在卡组件出现) |
| code 透传 | 服务端受理阶段返回的错误码会原样透传给商户,SDK 不做翻译;本文档无法穷举,通用处理见附录 B |
组件 type | load 事件返回 type : card / applepay / googlepay / userinfocollect ,可用于区分组件 |
0.3 完整流程(以 Apple Pay 为例,最完整链路)
const applePay = PMdropin.create('applepay', options)
applePay.on('load', (res) => { res.code === 'SUCCESS' /* 才挂载/启用组件 */ })
applePay.on('payButtonClick', () => { /* 用户点击系统按钮 → 发起支付 */ })
// 阶段①:拉起 Apple Pay 系统弹层 → 用户授权 → SDK 完成商户验证与取 token
applePay.emit('canMakePayment', payload)
.then(res => {
// 阶段②:成功 —— res.code === 'APPLY_SUCCESS',拿 res.data.paymentToken
const paymentToken = res.data.paymentToken
// 阶段③:商户调用自己的下单/支付接口(demo 中的 orderAndPay)
return postOrderAndPay({ paymentToken }) // 商户自有后端接口
})
.then(orderRes => {
if (orderRes.code === 'APPLY_SUCCESS') applePay.emit('paySuccess') // 通知组件支付成功,完成系统弹层
else applePay.emit('payFail')
})
.catch(err => { /* err.code / err.msg 见 §3 */ applePay.emit('payFail') })1. 通用:组件初始化加载 instance.on('load')
创建组件后 SDK 会拉取组件初始化配置,完成后通过 load 事件告知结果(四种组件同构,仅 type 不同):
const card = PMdropin.create('card', options)
card.on('load', (data) => {
if (data.code === 'SUCCESS') {
// 加载成功,可挂载并启用支付组件
} else {
// 加载失败,见下表
}
})| code | msg(默认值) | 描述 | 范围 |
|---|---|---|---|
SUCCESS | 空 | 初始化成功。组件可正常使用 | 全部 |
DROPIN_INIT_FAIL | Failed to initialize '{type}' Dropin! | 初始化阶段:组件创建后未能在规定时间内完成初始化(多为 create 配置、密钥/环境参数问题)。建议检查 create 参数后刷新重试 | 全部 |
DROPIN_INIT_ACTIONS_FAIL | Failed to register '{type}' Dropin actions! | 初始化阶段:组件内部动作注册失败或等待初始化超时。建议刷新重试 | 全部 |
DROPIN_INIT_GOOGLEPAY_FAIL | Failed to init 'googlePay' button! | 初始化阶段:Google Pay 按钮初始化失败——通常是 Google Pay JS 加载失败,或当前设备/浏览器不支持(HTTPS、系统版本、地区限制)。建议检查页面协议是否为 HTTPS、设备是否支持 | 仅 googlepay |
HTTP_ERR | An error occurred with the http request! | 初始化阶段:拉取初始化配置的请求发生网络层错误。建议检查网络后重试 | 全部 |
<HTTP 状态码> | statusText | 初始化阶段:服务端返回了错误 HTTP 状态(如 403 / 500)。code 即为状态码数字 | 全部 |
<后端业务码> | 服务端 msg | 初始化阶段:初始化配置请求被服务端拒绝(如参数/密钥/商户状态异常)。按服务端 msg 处理,必要时联系技术支持 | 全部 |
同一页面创建多个组件时,各组件会分别触发各自的 load,请分别监听。
2. Card(卡支付)
2.1 卡组件时序
load(成功) → 用户填写卡信息 → on('form-check') 实时反馈校验状态
→ 点击支付 → emit('canMakePayment')
├─ 本地表单校验(见 2.2)
├─ 服务端受理(见 2.3)
└─ 网络/超时(见 2.2)2.2 表单校验阶段(on('form-check') 与 canMakePayment 本地校验)
form-check事件:用户输入过程中实时触发,负载为表单校验状态(不含 code),结构示例: { isFormValid, invalidReason, displayMsg, fieldStatus: { cardnum, expdate, cvv, name } }。
商户可监听它控制"支付"按钮的可点击状态:isFormValid === true 才允许发起支付。
emit('canMakePayment')被本地校验拦截时(表单无效直接 reject,不会请求服务端):
| code | msg(默认值) | 描述 | 范围 |
|---|---|---|---|
FORM_INVALID | 见描述 | 提交支付时表单校验未通过:卡号/有效期/CVV/姓名缺失或格式错误(msg 给出具体原因,如 No selected card),或推荐卡模式下未选中卡。displayMsg 为字段双语文案。让用户修正后重试 | card |
REQUEST_TIMEOUT | error.message 或 Unknown | 支付请求超时(默认 15 秒未收到回执)。可提示稍后重试 | card |
UNKNOWN_ISSUE | Failed to register '{type}' Dropin actions! | 未知/内部异常:请求网络错误或 SDK 内部未预期异常。建议重试,仍失败联系技术支持 | card |
2.3 服务端受理阶段(emit('canMakePayment') 的 Promise 结果)
表单校验通过后,SDK 将卡信息提交服务端受理:
card.emit('canMakePayment', payload)
.then(res => { /* 成功 */ })
.catch(err => { /* err.code / err.msg / err.displayMsg */ })| code | msg(默认值) | 描述 | 范围 |
|---|---|---|---|
APPLY_SUCCESS | 服务端返回 | 受理成功。 res 内含服务端返回的数据(如支付 token 等),可继续商户侧下单流程 | card |
PARAMETER_INVALID | 服务端 msg | 服务端参数校验失败:提交的数据非法(卡信息不完整等)。按 msg 修正后重试 | card |
SAVE_CARD_INFO_ERROR | 服务端 msg | 保存卡信息失败(服务端写入异常)。稍后重试,仍失败联系技术支持 | card |
FORM_INVALID | 服务端 msg | 服务端判定表单字段非法(与 2.2 同名,但发生在服务端校验)。引导用户核对卡信息 | card |
NO_SELECTED_CARD | 服务端 msg | 未选择要使用的卡(推荐卡场景)。请用户先选卡 | card |
USER_INFO_NOT_COMPLETE | 服务端 msg | 附加的用户信息采集未完成:需要先引导用户在 userinfocollect 组件完成必填信息(如部分市场要求的收件人/证件信息),再重新支付 | card |
REQUEST_TIMEOUT | 服务端 msg | 服务端处理超时。可提示稍后重试 | card |
UNKNOWN_ISSUE | 服务端 msg | 服务端返回的未知错误 | card |
| 其它后端码 | 服务端 msg | 服务端自定义错误码: SDK 不识别时原样透传,同时 displayMsg 固定为通用兜底文案 ERROR ( Something went wrong, please try again. )。通用处理见附录 B | card |
关于displayMsg:卡组件的失败响应会附带 displayMsg({ en, ar }双语),可直接按用户语言展示;
其中 FORM_INVALID 场景的 displayMsg 是字段名映射结构,需要拼接提示(如 Field not valid: Card number)。
2.4 其它动作(无 code)
setDisabled / getFormValid / switchTheme / focus 等动作返回布尔值或表单状态,不含错误码;
switchTheme 等失败时其 Promise 会 reject 但无业务 code 含义。
3. Apple Pay
3.1 Apple Pay 时序(注意收尾动作)
load(成功) → 用户点击系统支付按钮 → on('payButtonClick') → 商户 emit('canMakePayment')
→ 弹出 Apple Pay 系统弹层 → 用户授权
→ SDK 内部:商户验证(applePaySession)→ 取 token(retrievePaymentToken)
→ resolve(res: APPLY_SUCCESS + data.paymentToken) 或 reject(err)
→ 商户拿 paymentToken 调自己的下单接口
→ 下单成功 emit('paySuccess') / 下单失败 emit('payFail') ← 决定系统弹层的完成/失败展示重要:
Apple Pay 弹层的最终收尾由商户控制。canMakePayment resolve 后请务必先完成商户侧下单/支付,再调用 paySuccess;不要在下单成功前调用 paySuccess。
3.2 参数拦截 / 本地校验阶段
以下 code 在调用 canMakePayment 后立即(弹层弹出前)返回:
| code | msg(默认值) | 描述 | 范围 |
|---|---|---|---|
REPEAT_REQUEST | The request is repeated | 重复请求:上一次支付流程尚未结束(弹层未关闭/未回执)时再次发起。请等待上次回调后再调用 | applepay |
AMOUNT_INVALID | Amount is incorrect. | 金额格式非法:传入的 totalAmount 不是合法金额(需为整数或至多 2 位小数的数字)。修正参数后重试 | applepay |
MIT_PARAMS_VALIDATION_ERROR | 聚合英文错误文本 | 代扣(MIT/订阅)参数校验失败:支付参数携带订阅计划(subscriptionPlan)或 mitManagementUrl 时校验未通过。msg 为聚合的错误描述(如 subject is required),按附录 C 对照修正后重试 | applepay |
3.3 用户授权 / 服务端受理阶段(弹层内)
| code | msg(默认值) | 描述 | 范围 |
|---|---|---|---|
APPLY_SUCCESS | 服务端返回 | 授权受理成功。 res.data.paymentToken 为支付凭证,进入商户下单流程 | applepay |
APPLE_PAY_SESSION_ERROR | error 信息 | 商户验证失败: SDK 向服务端换取商户验证(applePaySession)时网络异常/失败,Apple Pay 弹层中断。可提示重试 | applepay |
RETRIEVE_PAYMENT_TOKEN_ERROR | error 信息 | 取 token 失败:获取支付凭证(retrievePaymentToken)时网络异常/失败。可提示重试 | applepay |
| 其它后端码 | 服务端 msg | 服务端在商户验证 / 取 token 阶段返回的业务错误码原样透传(如余额/额度/风控类拒绝)。通用处理见附录 B | applepay |
3.4 用户行为与内部异常
| code | msg(默认值) | 描述 | 范围 |
|---|---|---|---|
APPLE_PAY_CANCEL | applepay canceled | 用户主动取消:用户在系统弹层点了取消。不是错误,无需报错提示,重新引导支付即可 | applepay |
APPLEPAY_INTERNAL_ERROR | error.message | SDK 内部异常:创建 Apple Pay 会话失败(多为环境不支持、配置缺失)。检查设备/环境与配置后重试 | applepay |
4. Google Pay
4.1 时序
load(成功) → 用户点击 Google Pay 系统按钮 → on('payButtonClick') → 商户 emit('canMakePayment')
→ 弹出 Google Pay 系统弹层 → 用户选卡授权
→ SDK 内部:取 token(retrievePaymentToken)→ 3DS/风控(apply3DS)
→ resolve(res: APPLY_SUCCESS + data.paymentToken) 或 reject(err)
→ 商户拿 paymentToken 调自己的下单接口(无系统弹层需要收尾)4.2 参数拦截 / 本地校验阶段
| code | msg(默认值) | 描述 | 范围 |
|---|---|---|---|
REPEAT_REQUEST | The request is repeated | 重复请求:上一次支付流程未结束时再次发起。等待上次回调后再调用 | googlepay |
AMOUNT_INVALID | Amount is incorrect. | 金额格式非法: totalAmount 不是整数或至多 2 位小数的数字。修正参数后重试 | googlepay |
MIT_PARAMS_VALIDATION_ERROR | 聚合英文错误文本 | 代扣(MIT/订阅)参数校验失败。 msg 为聚合错误描述,按附录 C 修正后重试 | googlepay |
4.3 用户授权 / 服务端受理阶段
| code | msg(默认值) | 描述 | 范围 |
|---|---|---|---|
APPLY_SUCCESS | 服务端返回 | 授权受理成功。 res.data.paymentToken 为支付凭证,进入商户下单流程 | googlepay |
CANCELED | Google 返回 | 用户主动取消: Google Pay 系统弹层被关闭(Google Pay 原生的 statusCode,SDK 原样透传)。非错误,重新引导支付即可 | googlepay |
其它 Google 原生 statusCode | Google 返回 | Google Pay JS 返回的其它状态(如参数错误类,由 Google 定义),SDK 原样透传。可按 Google Pay 官方文档对照处理 | googlepay |
| 其它后端码 | 服务端 msg | 服务端在取 token / 3DS 阶段返回的业务错误码原样透传。通用处理见附录 B | googlepay |
no_paymentToken | no paymentToken | SDK 内部兜底: 服务端响应中缺少支付凭证。正常情况不应出现,出现请联系技术支持并附请求信息 | googlepay |
| 异常 | 缺少参数 | SDK 内部兜底: 内部调用参数缺失。正常情况不应出现 | googlepay |
5. userinfocollect(用户信息采集)
组件加载错误与 §1 完全一致(load 事件,type = 'userinfocollect')。
form-check 事件负载为采集表单状态({ isValid, invalidFields, needCollect, formData }),不含 code:商户可据此判断用户是否已填完必填信息、是否需要展示采集表单。
该组件自身无支付业务错误码。若商户在卡支付时收到 USER_INFO_NOT_COMPLETE(见 §2.3),即表示采集信息未完成,请先引导用户完成采集后再支付。
6. 附录
附录 A:code 速查索引表
| code | 出现入口 | 阶段 | 支付方式 | 一句话含义 |
|---|---|---|---|---|
SUCCESS | on('load') | 初始化 | 全部 | 组件加载成功 |
APPLY_SUCCESS | emit('canMakePayment') resolve | 支付受理 | card / applepay / googlepay | 支付受理成功,拿到 paymentToken 可下单 |
DROPIN_INIT_FAIL / DROPIN_INIT_ACTIONS_FAIL | on('load') | 初始化 | 全部 | 组件初始化失败 |
DROPIN_INIT_GOOGLEPAY_FAIL | on('load') | 初始化 | googlepay | Google Pay 按钮初始化失败/环境不支持 |
HTTP_ERR / HTTP 状态码 | on('load') | 初始化 | 全部 | 拉取初始化配置网络/服务端错误 |
REQUEST_TIMEOUT | emit('canMakePayment') reject | 支付 | card(服务端亦可能返回) | 超时 |
FORM_INVALID | emit('canMakePayment') reject | 表单校验 | card | 卡表单无效(本地或服务端判定) |
NO_SELECTED_CARD | emit('canMakePayment') reject | 表单校验 | card | 推荐卡未选中 |
PARAMETER_INVALID | emit('canMakePayment') reject | 服务端受理 | card | 服务端参数校验失败 |
SAVE_CARD_INFO_ERROR | emit('canMakePayment') reject | 服务端受理 | card | 保存卡信息失败 |
USER_INFO_NOT_COMPLETE | emit('canMakePayment') reject | 服务端受理 | card | 用户附加信息采集未完成 |
UNKNOWN_ISSUE | on('load') / canMakePayment reject | 各阶段 | card | 未知错误(本地或服务端) |
AMOUNT_INVALID | emit('canMakePayment') reject | 参数校验 | applepay / googlepay | 金额格式非法 |
MIT_PARAMS_VALIDATION_ERROR | emit('canMakePayment') reject | 参数校验 | applepay / googlepay | MIT/订阅参数校验失败 |
REPEAT_REQUEST | emit('canMakePayment') reject | 请求拦截 | applepay / googlepay | 上一次支付流程未结束时重复请求 |
APPLE_PAY_SESSION_ERROR | emit('canMakePayment') reject | 弹层内商户验证 | applepay | 换取商户验证失败 |
RETRIEVE_PAYMENT_TOKEN_ERROR | emit('canMakePayment') reject | 弹层内取 token | applepay | 取支付凭证失败 |
APPLE_PAY_CANCEL / CANCELED | emit('canMakePayment') reject | 用户交互 | applepay / googlepay | 用户取消(非错误) |
APPLEPAY_INTERNAL_ERROR | emit('canMakePayment') reject | 内部 | applepay | 创建支付会话内部异常 |
附录 B:未列出的服务端错误码,怎么处理?
收到不在本手册表格内的 code 时:
先看 msg:它是服务端返回的错误描述(多为英文),是最直接的定位信息;卡组件还可看 displayMsg(双语文案)直接展示给用户。
判断来源阶段:
来自 on('load') → 初始化配置被拒绝(密钥/商户状态/参数问题);
来自 emit('canMakePayment') reject → 支付受理被服务端拒绝(常见为余额不足、卡被拒、风控拦截、银行侧拒绝等)。
- 处理建议:
把收到的 code + msg 原样透传/记录(不要自行改文案);
向用户展示服务端文案或通用失败提示,不要对同一笔交易自动重试(可能造成重复扣款),引导用户重新发起;
联系技术支持时请提供:商户号、时间、支付组件类型、收到的 code/msg、请求流水(requestId)。
附录 C:MIT / 订阅参数校验(MIT_PARAMS_VALIDATION_ERROR)错误文本解读
失败时 msg 会返回一条或多条(; 连接)的英文描述,对照下表修正 canMakePayment 入参:
| msg 片段 | 含义 | 正确取值示例 |
|---|---|---|
The mitManagementUrl is invalid | mitManagementUrl 缺失或不是 http(s):// 开头的链接 | 必须以 http(s):// 开头 |
subject is required | 订阅标题缺失 | subscriptionPlan.subject 为字符串 |
totalPeriods must be greater than or equal to 1 | 总期数 < 1 或非整数 | subscriptionPlan.totalPeriods ≥ 1 |
periodUnit must be one of D, W, M, Y | 扣款周期单位非法 | subscriptionPlan.periodRule.periodUnit ∈ D/W/M/Y |
periodCount must be greater than or equal to 1 | 每期扣款间隔非法 | periodRule.periodCount ≥ 1 |
amount must be greater than or equal to 0 | 每期金额非法 | periodAmount.amount ≥ 0 |
currency must be equal to XXX | 订阅币种与当前订单币种不一致 | periodAmount.currency 等须等于订单 currencyCode |
currency must be a 3-character string | 币种不是 3 位字符串 | 如 USD、SAR |
firstPeriodStartDate must be in the future | 首期开始日期是过去时间 | 需为未来的 RFC3339 时间(如 2026-10-01T00:00:00+08:00) |
xxx must be of type xxx | 字段类型错误 | 按提示传入对应类型 |
xxx is required / Invalid subscriptionPlan: ... | 嵌套对象(如 trialConfig)缺失或内部字段错误 | 按提示补全嵌套字段 |
