Webhook 回调怎么设计:签名、重放保护与幂等

回调是对接的最后一公里。本文给出签名校验、重放保护、幂等消费与事件日志的结构化清单。

发布:2026-02-08 · 阅读 7 分钟 · 标签:Webhook / 回调 / 签名 / 幂等 / 重放保护

在虚拟商品自动发货体系里,Webhook 回调承担“交付结果确认”的角色:你把码发出去、把服务开通了,最终需要通过回调把结果交给对接方。 如果回调设计不严谨,最常见的后果是:重复处理、状态不一致、对账困难,甚至被恶意重放请求。

目录

1)回调的最小字段:事件、时间戳、签名

回调建议以“事件”为中心(event),而不是只传一个状态。因为同一订单可能出现多个事件:发货成功、回调成功、补发、退款等。 最小字段通常包括:

  • event_id:事件唯一 ID(用于幂等消费)
  • order_id:对接方订单号或平台订单号
  • event_type:例如 delivered / failed / refunded 等
  • timestamp:事件发生时间(用于重放保护)
  • signature:基于 body + timestamp 的 HMAC 签名

2)签名校验与重放保护:别只校验一个 token

只校验静态 token 的问题在于:一旦泄露,攻击者可以伪造回调。更稳的做法是: 使用 HMAC(如 SHA256)对请求体与时间戳做签名,并在接收端校验:

  • 签名是否正确(防伪造)
  • 时间戳是否在可接受窗口内(例如 5 分钟,防重放)
  • 是否已处理过相同 event_id(防重复消费)

3)幂等消费:重复回调是常态

回调的失败原因很多:对方网络抖动、接口超时、对方服务短暂不可用。你的系统会重试,同一个事件可能被推送多次。 因此接收端必须做到“重复回调不重复处理”。常见做法:

  • event_id 做幂等(最推荐)
  • 或以 order_id + event_type 做幂等(次优)
  • 幂等记录需有 TTL,避免无限增长

4)回调失败的重试策略:指数退避与死信

回调重试建议采用指数退避,并设置最大次数。超过阈值后进入“死信队列”(dead-letter),由人工或定时任务处理。 官网内容可以公开“重试原则”,但不必公开具体阈值。

指数退避

2s → 5s → 15s → 60s… 避免短时间集中重试放大故障。

最大次数

到达上限后转入死信,记录最后一次响应与错误码。

可追溯日志

回调次数、每次响应、时间线必须可查,才能支撑对账与争议处理。

如果你打算把官网作为长期知识库,Webhook 回调这类内容非常适合做主题聚合:既专业、又可复用,还能自然形成内部链接到“API 对接”与“对账口径”页面。

相关页面:自动发货履约 · API 对接 · 对账与结算 · FAQ