CirculeID

Webhooks

有意思的是投递失败时会发生什么

签名、重试、顺序与幂等性,构成了全部约定。只处理正常路径的集成不算做完,它根本还没开始。

投递
至少一次
已签名
对原始请求体计算
重试
指数退避

Definition

护照的 Webhook 如何运作?

当护照、事件或凭证发生变化时,CirculeID 会向您的端点推送一次带签名的回调。投递保证为至少一次并采用指数退避,因此处理程序必须校验签名、把重复的投递标识视为空操作,并在执行动作前通过 API 回读当前状态。

Treat a payload as a notification, not as the record. That single habit removes the entire class of bug where a delayed retry overwrites newer data with older data.

事件

您可以订阅什么

按资源分组。订阅要精准 —— 一个接收自己并不处理之事件的端点,就是一个没人会去排查其故障的端点。
Webhook 事件类型及各自所示意的含义
EventFires whenTypical handler
passport.createdA passport is issued against an identifierPrint or encode the data carrier
passport.updatedThe record changes materiallyRe-read state; refresh a cached storefront view
event.recordedAn EPCIS event is appended to an objectAdvance an internal workflow
credential.issuedA supplier signs a claim against your productClear the compliance gap for that field
credential.revokedAn issuer withdraws a claimRe-open the gap; review anything that relied on it
passport.gap_detectedA delegated act change leaves a field unmetRaise it to the compliance owner

验证

先验证,再解析

请对原始请求体计算签名 —— 而不是对重新序列化后的对象,那样不会匹配。凡超出时间戳容差的请求一律拒绝。
Node.js
import { createHmac, timingSafeEqual } from 'node:crypto';

export function verify(rawBody, header, secret) {
  const [ts, signature] = parseHeader(header);

  // Reject replays before doing any work.
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;

  const expected = createHmac('sha256', secret)
    .update(`${ts}.${rawBody}`)   // raw body, exactly as received
    .digest();

  // Constant-time: a fast reject leaks the signature one byte at a time.
  return timingSafeEqual(Buffer.from(signature, 'hex'), expected);
}

合同

平台保证什么

  • 已签名的负载

    以每个端点独立的密钥对原始请求体计算的 HMAC,外加时间戳。

  • 至少一次投递

    对于会重试的系统而言,这是诚实的保证。处理程序必须是幂等的。

  • 指数退避

    在较长时间窗内重试,因此短暂的中断不会给您造成任何损失。

  • 每份载荷都带版本

    若某次投递描述的是您已经越过的版本,请直接忽略。

  • 可见的失败日志

    投递失败会被列出并可重放,而不是被悄悄丢弃。

  • 精确限定的订阅

    按事件类型分别订阅,让每个端点只接收自己会处理的内容。

答疑

常见问题

我如何确认某个 Webhook 确实来自 CirculeID?

每一次投递都带有对原始请求体的签名以及时间戳。请在解析之前用端点密钥校验签名,并拒绝时间戳超出容差窗口的投递。一个信任未经校验负载的端点,就是任何人都能向其投递的端点。

投递是否有序?

按对象尽力保证顺序 —— 但请不要依赖它。重试与网络状况都可能让较早的事件晚于较新的事件到达。每个负载都带有它所反映的对象版本,因此处理程序应当忽略描述已越过版本的投递,而不是假定到达顺序。

如果我的端点宕机了会怎样?

投递会在较长的时间窗内以指数退避方式重试,失败日志在您的账户中可见,而不是悄无声息。时间窗到期后,该次投递被标记为失败;但底层变更仍可通过 API 查询,因此 Webhook 故障造成的是延迟,而非数据丢失。

同一条事件会被投递两次吗?

会的,而且您应当默认它会发生。至少投递一次,是任何具备重试机制的系统所能给出的诚实保证。每次投递都带有稳定的标识符,因此正确的处理程序会记录该标识符,并把重复视为空操作——这也让重放失败时间窗变得安全。

Webhook 的负载可以当作完整记录来信任吗?

请把载荷当作通知,而不是事实来源。它告诉您有内容发生了变化,并提供足够的信息让您判断是否需要关注;若要据此行动,请通过 API 回读当前状态。这样一来,过期或乱序的投递就无法把旧数据写入您的系统。

Next step

先把第一个指向测试端点

先在沙箱中订阅,故意让您的端点出错,观察重试与重放行为,然后再在生产中依赖它。

Index