Twilio 如何傳遞 Webhook

Twilio 的每個逾時與重試參數都可以設定,其他主要發送端都不允許。附 HMAC-SHA1 網址簽章與 Node 驗證程式。

傳遞行為

取自服務商自己的文件,最後檢查於 2026-08-06。服務商沒寫數字的地方,這張表也不填。

回應時限15 秒

可設定。rt 讀取逾時預設 15000ms(上限 15000),ct 連線預設 5000ms(上限 10000),tt 總時間預設 15000ms

檢查你的處理程式能否及時回應

重試可設定:rc 為 0 到 5,預設 1。rp 決定哪些失敗會重試
放棄服務商未公開
出處https://www.twilio.com/docs/usage/webhooks/webhooks-connection-overrides

簽章

用一個經測試套件證明可運作的驗證程式核對過,不是照文件抄來的。最後驗證於 2026-08-20。

演算法HMAC-SHA1
簽章內容full URL + form params sorted by key
編碼base64
標頭x-twilio-signature
容許時間差不強制

驗證簽章

要用原始請求主體(raw body),逐位元組原封不動,並在任何 JSON 解析之前取得。框架只要重新序列化 payload,這頁上的每一種機制就會立刻失效。

const crypto = require("node:crypto");

// base64(HMAC-SHA1(auth token, url + form params sorted by key, concatenated))
const sorted = Object.keys(req.body).sort();
const base = fullUrl + sorted.map((k) => k + req.body[k]).join("");
const expected = crypto
  .createHmac("sha1", authToken)
  .update(base)
  .digest("base64");
const received = Buffer.from(req.headers["x-twilio-signature"] ?? "");
const wanted = Buffer.from(expected);
// timingSafeEqual throws on a length mismatch, so check that first.
const valid =
  received.length === wanted.length && crypto.timingSafeEqual(received, wanted);

簽章涵蓋完整的公開網址,包含查詢字串。處理程式前面的 TLS 終止或會改寫路徑的代理伺服器,都會改變 Twilio 簽章時的網址,而這種不一致看起來跟偽造的請求一模一樣。

容易踩的坑

每個網址都能設定五個傳遞參數(連線逾時、讀取逾時、總時間、重試次數、重試政策),但幾乎每個人跑的都是預設值(總共 15 秒、重試 1 次)。旋鈕就在那裡,沒有人去轉。

延伸閱讀

AnyHook 架在接收 Twilio Webhook 的端點前面:大約 1 秒就回應,伺服器當機時依自己的排程重試,並讓每個事件都能重播。 換一個網址,程式碼不用動。

運作方式 →