SDK
Webhook 驗籤
瞭解如何使用 @stableops/webhook 在 Node.js、邊緣執行時和其他 JavaScript 環境中驗證 StableOps Webhook 簽名,正確保留原始請求體、讀取時間戳與簽名頭、限制重放視窗,並在金鑰輪換期間安全相容新舊簽名。
簽名內容
每次投遞攜帶三個 header:
X-Product-Signature: t=1780301011,v1=7b11b2c1…
X-Event-Id: evt_01JYA…
X-Delivery-Id: del_01JYA…簽名為 HMAC-SHA256(secret, "${timestamp}.${rawBody}"),hex 編碼。
5 分鐘時間窗防重放;簽名比較常量時間,避免計時側通道。
在 handler 中驗證
SDK 直接 re-export 驗籤函式,框架使用者不需要額外依賴:
import { verifySignature, SIGNATURE_HEADER } from '@stableops/api-sdk/webhooks'
export async function POST(req: Request) {
// 必須用 *原始* body 驗籤。不要先 JSON.parse 再 stringify,
// 即便對同一物件,key 順序也可能變化。
const rawBody = await req.text()
const result = verifySignature({
secrets: [process.env.STABLEOPS_WEBHOOK_SECRET!],
header: req.headers.get(SIGNATURE_HEADER.toLowerCase()) ?? undefined,
rawBody,
})
if (!result.ok) {
return new Response(JSON.stringify({ reason: result.reason }), {
status: 400,
})
}
const event = JSON.parse(rawBody)
// 業務邏輯,按 event.id 冪等
return new Response('ok')
}金鑰輪換
輪換介面立即返回新 secret,並保留舊 secret 24 小時。期間把兩條 secret 同時
傳給 verifySignature:
verifySignature({
secrets: [
process.env.STABLEOPS_WEBHOOK_SECRET!,
process.env.STABLEOPS_WEBHOOK_SECRET_PREVIOUS!,
],
header,
rawBody,
})失敗原因
verifySignature 返回判別聯合,ok: false 時讀取 reason:
| reason | 含義 |
|---|---|
missing_header | 缺失 X-Product-Signature |
invalid_format | header 不符合 t=…,v1=… |
timestamp_expired | 超出 5 分鐘視窗 |
bad_signature | HMAC 與任一 secret 都不匹配 |
重複 delivery
驗籤透過後,按 X-Event-Id(推薦)或自家業務鍵去重。平台的重試排程 +
網路重試,意味著 同一事件可能落多次。handler 必須冪等。
Edge / Serverless
verifySignature 使用 node:crypto 的 createHmac、timingSafeEqual 和 Buffer。
主流 edge 執行時都透過原生或相容層支援 node:crypto:Deno、Vercel 原生支援,
無需額外 polyfill;Cloudflare Workers 需在 wrangler.toml 中啟用 nodejs_compat
相容性標誌後即可使用。
這篇文件怎麼樣?
最後更新