Webhook 规范
了解 Tracksuite 在 Webhook 中发送的事件和运单字段,以及如何用签名密钥验证请求。
请求体是一个 JSON 数组,一次可以包含多条运单更新。每条更新用 event 表示发生了什么,这个名字由运单当前的 status 决定。对应关系见下表。status 与 statusLabel 的含义见运单状态。
每条更新都有 eventId、eventTime 和 data。同一条更新被重试时,eventId 不变,接收端用它去掉重复。data 是这条运单当时的内容:运单号 trackingNumber、状态 status、承运商细分状态 statusTrack、运单编号 routerId、当前摘要 summary、轨迹 detail。承运商返回了错误对象时,data 里还会多一个 error。
Webhook 签名
Section titled “Webhook 签名”Tracksuite 发出的每个 Webhook 都带有计算好的数字签名。你的服务器可以用它确认请求来自 Tracksuite。没有签名密钥的第三方或恶意请求无法通过校验。签名使用 SHA256 对原始请求体计算 HMAC,结果是十六进制字符串,放在请求头 X-Tracky-Signature 里。
签名验证的工作原理
Section titled “签名验证的工作原理”步骤 1:获取 Webhook 密钥
Section titled “步骤 1:获取 Webhook 密钥”登录 Tracksuite 管理门户,打开 设置 → API 与 Webhook,复制签名密钥。接收地址和签名密钥都有值之后,Tracksuite 才会开始投递。
步骤 2:使用 SHA256 计算 HMAC
Section titled “步骤 2:使用 SHA256 计算 HMAC”用签名密钥对收到的原始请求体做 HMAC-SHA256,输出十六进制字符串。计算时必须用这一段原始字符串。不要先解析 JSON 再重新序列化,也不要对 X-Tracky-Timestamp 计算,否则签名会对不上。
步骤 3:验证签名
Section titled “步骤 3:验证签名”取出请求头 X-Tracky-Signature,和上面算出的结果比较。下面这个函数先计算,再比较。返回 false,或请求头缺失时,返回 401,拒绝这次请求。验证通过后,先在 5 秒内返回 2xx,再处理较慢的业务。
import { createHmac, timingSafeEqual } from 'node:crypto'
function verifySignature(rawBody: string, signature: string): boolean { const expected = createHmac('sha256', WEBHOOK_SECRET).update(rawBody).digest('hex')
if (expected.length !== signature.length) { return false }
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature))}