跳到内容
API 文档
Esc
切换打开⌘J预览

API v2 幂等、重试与错误处理

使用 order_code 安全重试创建订单,并按 HTTP 状态码和机器可读错误 code 处理冲突、限流与依赖故障。

Darkroom API v2 把同一商家的 order_code 作为创建订单的自然幂等键。客户端可以在网络超时后重试,但必须保持业务请求内容不变。

订单号怎么取:随机,别用连号

order_code 由你指定,Darkroom 原样保存,并会展示给顾客、写进通知。它除了做幂等键之外,还是顾客自助验证身份的因子之一:顾客凭「手机号 + 订单号」可以把微信绑到自己的顾客档案、在公众号里找到订单、找回密码。所以订单号必须不可预测

  • 建议至少 8 位随机字母数字,可以加固定前缀便于对账,例如 crm-20260727-K7Q2XM
  • ⛔ 不要用自增序号、日期加流水号、CRM 主键这类能推算出来的编号(如 20260904001)。知道某位顾客手机号的人,配合可预测的订单号,就能通过自助入口接管这位顾客的档案。
  • Darkroom 自动生成的订单号是 6 位随机大写字母数字,约 10 亿种组合;自助入口都有限流,同一来源每分钟只能试几十次,被猜中的概率接近零。这是民用行业的普遍做法,自定义连号会让这层保护失效。
  • 如果你的系统只能提供连号,把连号放在自己这边做关联(或写进 team_remark),把随机串作为 order_code 传给 Darkroom。

创建订单的三种结果

场景 HTTP idempotent_replay 客户端动作
第一次成功创建 201 false 保存返回的订单
相同 order_code、相同规范化内容 200 true 按成功处理,不创建重复订单
相同 order_code、不同规范化内容 409 停止自动重试,检查来源数据或使用正确的新编号

服务端会对验证后的业务字段做规范化再计算 hash,因此 JSON 的空格和 object key 顺序变化不会制造冲突;服务数组顺序、金额、日期、顾客字段等业务差异会参与判断。

安全重试规则

状态 是否自动重试 建议
网络超时、连接中断 使用相同的 order_code 和业务内容重新发送请求
429 rate_limit_exceeded 等到下一分钟窗口(Retry-After),加随机抖动
429 burst_limit_exceeded Retry-After 等待,默认约 1 秒,无需等待到下一分钟窗口
500 / 502 / 503 / 504 有限重试 指数退避,设重试上限
401 invalid_token 更新 token 后重试一次 token 可能已过期或被撤销;如果仍返回 401,请停止自动重试并检查凭据状态
400 / 403 / 404 / 422 修正请求、scope 或业务数据
409 order_code_conflict 人工或业务逻辑处理编号冲突

标准错误结构

{
  "error": {
    "code": "invalid_request",
    "message": "The request contains invalid fields.",
    "details": [
      {
        "field": "services.0.unit_price_amount",
        "reason": "must_be_non_negative_decimal_string"
      }
    ]
  },
  "request_id": "req_01K1A8M6WDQW8DM8QSCZ6N4G7Y"
}
HTTP 常见 error.code 含义
400 malformed_json, invalid_request body 不是合法 JSON 或基本格式错误
401 missing_token, invalid_token 缺少 Authorization: Bearer,或 token 已过期 / 被撤销
403 insufficient_scope, credential_disabled token 的 scope 不满足端点要求,或凭据已停用
404 order_not_found 当前 merchant tenant 中找不到订单
409 order_code_conflict 同编号被内容不同的订单占用
422 store_not_found, service_not_found, invalid_customer_mobile, coupon_invalid, prepayment_method_invalid 格式正确但业务数据不可接受
429 rate_limit_exceeded, burst_limit_exceeded 已达到分钟配额或秒级突发限制;两者采用不同的等待时间,见下节
503 api_temporarily_unavailable API gate、凭据服务或订单依赖暂不可用

错误 message 面向人阅读,集成逻辑只应依赖 HTTP status 与稳定的 error.codedetails 只在适用时出现。

/oauth/token 端点另有一组认证错误码(invalid_clientcredential_expiredinvalid_scopeunsupported_grant_type),见认证与访问令牌

分别处理分钟配额和秒级突发限制

阈值 性质 error.code Retry-After
分钟配额 20 req/min/key 限制每分钟的请求总量 rate_limit_exceeded 距下一分钟窗口的秒数
突发限制 2 req/s/key 限制短时间内的请求峰值 burst_limit_exceeded 1

收到 burst_limit_exceeded 时,应按 Retry-After 等待约 1 秒;收到 rate_limit_exceeded 时,应等待到下一分钟窗口。所有 2xx 和 429 响应均包含以下限流响应头,调用方可以据此调整请求速率:

RateLimit-Limit: 20
RateLimit-Remaining: 7
RateLimit-Reset: 34
Retry-After: 34          # 仅 429

分钟配额按凭据配置,默认值为 20 req/min/key。批量导入历史订单等场景可以申请调整,无需重新部署集成代码。/oauth/token 使用独立配额:10 req/min/client_id。

request_id 与日志

请保存每次调用返回的 request_id,并在服务端日志中关联外部订单号和 HTTP 状态码。日志中不得记录:

  • client_secret 或完整 access_token
  • 顾客姓名、手机号、Email、儿童资料或地址;
  • 完整 request / response body。

联系 Darkroom 支持团队时,请提供 request_id、发生时间、HTTP 状态码、error.code 和经过脱敏处理的 order_code 哈希值。