XD-OP-04 · DOC

错误码与排障

排障先看 `code`,不要按 message 猜。本篇按 HTTP 状态与错误码分组,给出触发条件、正确处理动作与不能做的事(例如 409 先查单、422 不重试)。

小豆支付开放平台是面向已有自有系统的商家的支付接入服务:通过服务器对服务器的接口,把支付宝与微信收款接进商家自己的系统,并以签名事件通知回传支付状态;资金由持牌支付公司收付结算。个人也能申请:主体类型选「个人」,身份证 + 本人银行卡即可完成商户进件。央行持牌机构清算,安全可靠的个人和企业支付接口。

1. 错误信封

失败响应永不使用 2xx,信封以三字段为准(另有两个码带 details:403 OPEN_API_SOURCE_IP_REJECTED 的平台边缘腿带 details.reason,422 OPEN_API_LIMIT_EXCEEDED 带触发面枚举——见下表对应行):

{ "code": "OPEN_API_BODY_INVALID", "message": "…可读说明…", "requestId": "018f2c1e-8b21-7c3a-9f10-2b7c9a1d4e55" }

message 是给人看的,判错请只认 code;排障请记录 requestId(向平台反馈时提供它最快)。

码空间是封闭的:平台侧的内部故障(含支付机构链的内部异常)在到达你之前会被中性化——一律投影为本表内的 503 OPEN_API_GUARD_UNAVAILABLE,不会把内部码或内部原文透出。若你确实收到本表之外的 code(说明该口径被破),请按 503 语义处置并带 requestId 与 code 原文走官网反馈渠道;不要据此判断业务结果,更不要换单号重下单。

2. 错误码总表

codeHTTP含义与处置
OPEN_API_HEADER_INVALID400签名头缺失/重复/形态非法(含 Content-Type 不是 application/json)。检查六头是否成组、格式是否合规——各头的长度与字符集是硬约束,见表后的 API 参考 · 请求头。
OPEN_API_SIGNATURE_INVALID401验签失败或应用/密钥解析失败(中性,不区分原因)。核对规范串、时间窗、nonce 唯一性,并把 X-XD-App-Id 与门户凭证页逐字符核对——大写 I 与数字 1、大写 O 与数字 0 外观相近,手抄极易混淆(appId 只要有一位错,六个签名头再正确也一样中性 401;建议用凭证页复制按钮取值)。
OPEN_API_SOURCE_IP_REJECTED403来源 IP 判定失败。两条腿处置不同:① 平台边缘腿——信封带 details.reason(七种取值见 安全红线 · 请求来源),加白名单无效,请带 requestId 与出口 IP 走官网反馈;② 应用白名单腿——信封只有三字段,把该出口 IP 加进门户白名单(含灾备出口);你已自助关闭来源校验时不会出现这条腿。两条腿都不回显平台观测到的地址。
OPEN_API_RISK_FROZEN403应用被风控冻结:新增下单/支付尝试被拒;存量订单查询、关闭、退款与结算读回不受影响。
OPEN_API_APP_SUSPENDED403应用被暂停:商家 API 全部不可用。实际拿到的是 401——应用状态非 ACTIVE 时,密钥解析在鉴权阶段就中性失败(不区分「应用不存在」与「应用被暂停」,防枚举),这个 403 只在极窄的竞态窗口(鉴权通过后状态才变更)才可能返回。存量订单的查询/关单/退款同样打不通,转平台人工通道。
OPEN_API_APP_REVOKED403应用被吊销(永久终态):商家 API 全部不可用,退款仅保留平台人工通道。同上,实际拿到的是 401。
OPEN_API_MERCHANT_INACTIVE403商家准入状态非 ACTIVE:新增下单/支付尝试被拒;存量订单不受影响。
OPEN_API_BODY_INVALID400请求体不是合法 JSON,或形状/枚举/边界违规(含未知字段)。
OPEN_API_PAYLOAD_TOO_LARGE413请求体超过流式硬上限。精简 attach/description。
OPEN_API_REPLAY409nonce 重放命中。每次请求用新的 nonce。
OPEN_API_REQUEST_ID_CONFLICT409同 requestId 绑定了不同请求体。重试必须复用同一请求体。
OPEN_API_IDEMPOTENCY_CONFLICT409同 outTradeNo/outRefundNo 绑定了不同业务摘要。先查单,不要换号重试。
OPEN_API_RESOURCE_NOT_FOUND404资源不存在(查无/跨应用/跨商家/引用畸形统一中性)。
OPEN_API_STATE_INVALID409状态机非法迁移或终态冲突(例如对已成功订单再次关单)。
OPEN_API_CLOSE_NOT_COMPLETED409关单未完成:支付机构未完成本次关单,订单仍可能处于可支付状态(平台不会把订单本地判死)。稍后重试关单,或等订单到期自动关闭(到期后不可支付)。可重试,但不要紧循环。
OPEN_API_CHANNEL_UNAVAILABLE422通道存在但链路未放行(闸门关闭或前置未齐)。可预期的正常拒绝,不要重试刷量。
OPEN_API_CHANNEL_UNSUPPORTED422通道不受支持(预留词表位)。
OPEN_API_SCOPE_CHANNEL_MISMATCH422申报交易形态与通道绑定不符(含越界/双申报缺省/空申报)。
OPEN_API_LIMIT_EXCEEDED422限额越界。信封带触发面:订单/尝试腿=details.scopes(数组);退款累计腿=details.scope 单值 REFUND_CUMULATIVE + outRefundNo——枚举与处置见 费率与限额。限额值不在任何页面展示:先关掉不再支付的在途订单;需要调整走官网反馈渠道(附 requestId)。
OPEN_API_RATE_LIMITED429频率限流越界。按响应头的窗口信息退避重试,不要紧循环。
OPEN_API_PROVIDER_REJECTED502支付机构拒绝本次请求(平台不向外暴露内部原因)。此类失败不要原样无限重试,先核对业务参数。
OPEN_API_GUARD_UNAVAILABLE503平台运行时守卫不可用(fail-closed)。这是「安全地拒绝」而不是「未处理」:按退避重试,不要改换路径绕过。

3. 排障决策树

请求失败
├─ 400 → 六头形态(含每头长度/字符集)?→ 否:按 API 参考的请求头表补全
│        └ 是:Content-Type 是 application/json 吗?→ 否:写请求必须带它
│        └ 是:请求体有 schema 外字段、非法 JSON 或重复键?→ 去掉未知字段/修 JSON
├─ 401 → `X-XD-App-Id` 与门户凭证页逐字符一致(大写 `I` 与数字 `1`、大写 `O` 与数字 `0`
│        外观相近,建议用复制按钮取值)?→ 否:修正 appId 后重试(单字符错同样中性 401)
│        └ 是:规范串与实现逐字节对齐?→ 否:用[安全红线 · 响应验签](./09-security-redlines.md)的规范串定义重写拼串
│        └ 是:服务器时间是否准(NTP)?nonce 是否复用?kid 是否已轮换?**应用是否仍是
│            ACTIVE**(被暂停/吊销的表现在这一档,不报 403)?旧 kid 只在**你已申请开启的
│            限时宽限窗**内可用——默认不并行,轮换即原子切换(见[凭证与密钥管理](./12-credential-key-management.md))
├─ 403 → 来源校验开启且出口在白名单内?→ 否:门户加白 / 开回校验
│        └ 是:应用/商家状态(风控冻结/商家准入失效)→ 按上表处置
├─ 404 → 是否用了别的应用的订单号?查询接口对跨应用/跨商家统一中性 404
├─ 409 → 先查单。幂等冲突=同号异内容;状态机冲突=动作与当前状态不符
├─ 413 → 精简请求体
├─ 422 → 通道链路未放行 / 申报不符 / 限额越界(三者 code 不同,按 code 分派)
├─ 429 → 退避重试(指数退避 + 上限),复用 requestId
├─ 502 → 支付机构拒绝:核对业务参数与订单状态,先查单再决定是否重试
├─ 503 → 平台守卫不可用(平台侧内部故障也中性投影到这一档):退避重试;
│        不要据它判断业务结果、不要切换通道或改走非公开路径绕过
└─ 总表外的 code(不应出现)→ 按 503 语义处置并反馈

4. 三个高频误区

  1. 把 403 当成「签名不对」:签名错是 401;403 一律是来源或状态问题。
  2. 把 422 CHANNEL_UNAVAILABLE 当故障重试:它是产品口径的正常拒绝,重试不会变成功。
  3. 409 之后换 outTradeNo 重下单:会造成两笔真实订单。正确动作是查单。

5. 反馈给平台时请带上

requestId(响应头 X-XD-Request-Id 或错误信封里的 requestId)、发生时间(含时区)、outTradeNo、错误 code。注意:来源 IP 拒绝(403)、请求体门卫拒绝(400/413)与六头形态非法(400)这三类都不回头(X-XD-Request-Id),这类反馈请附上错误体里的 requestId 或请求时间与出口 IP;若信封里的 requestId 是空串(平台签名密钥不可用时的 503),以响应头为准。 不要把私钥、完整签名材料或买家个人信息贴进反馈。

6. 错误码镜像(机器校验,勿手改)

<!-- xd-contract-mirror:error-catalog -->

{
  "errorCodes": {
    "OPEN_API_HEADER_INVALID": 400,
    "OPEN_API_SIGNATURE_INVALID": 401,
    "OPEN_API_SOURCE_IP_REJECTED": 403,
    "OPEN_API_RISK_FROZEN": 403,
    "OPEN_API_APP_SUSPENDED": 403,
    "OPEN_API_APP_REVOKED": 403,
    "OPEN_API_MERCHANT_INACTIVE": 403,
    "OPEN_API_PAYLOAD_TOO_LARGE": 413,
    "OPEN_API_BODY_INVALID": 400,
    "OPEN_API_REPLAY": 409,
    "OPEN_API_REQUEST_ID_CONFLICT": 409,
    "OPEN_API_IDEMPOTENCY_CONFLICT": 409,
    "OPEN_API_RESOURCE_NOT_FOUND": 404,
    "OPEN_API_CHANNEL_UNAVAILABLE": 422,
    "OPEN_API_CHANNEL_UNSUPPORTED": 422,
    "OPEN_API_SCOPE_CHANNEL_MISMATCH": 422,
    "OPEN_API_STATE_INVALID": 409,
    "OPEN_API_LIMIT_EXCEEDED": 422,
    "OPEN_API_RATE_LIMITED": 429,
    "OPEN_API_PROVIDER_REJECTED": 502,
    "OPEN_API_CLOSE_NOT_COMPLETED": 409,
    "OPEN_API_GUARD_UNAVAILABLE": 503
  }
}

<!-- /xd-contract-mirror:error-catalog -->

内容源:open-platform/docs/04-errors-and-troubleshooting.md · 最后更新 2026-10-16 下载本文 .md 在 GitHub 查看