跳至內文
使用文件
繁
English简体中文繁體中文
工作空間
指南API 參考API v1
指南

接收 Webhook 通知

在購買、續費或餘額變化時接收帶簽章的通知。

點選端點可編輯請求並查看回應。

建立訂閱

呼叫 POST/webhooks,傳入名稱、你的公開網路 HTTPS 地址、enabled: true 和所需的 event_types,併傳送已儲存的 Idempotency-Key。金鑰需要寫入存取權限及 webhooks:write。

安全儲存回傳的簽章金鑰。使用完整的 whsec_… 值,包括字首。普通訂閱讀取不會回傳金鑰。

事件 含義
fulfillment.updated 靜態資源或交付狀態變化
renewal.updated 續費狀態變化
dynamic.purchase.updated 流量購買狀態變化
refund.completed 退款完成
wallet.low_balance 錢包餘額降至你設定的閾值以下

餘額提醒還需傳入整數字串 wallet_low_balance_threshold_fen。訂閱只通知建立後的變化。

驗證簽章

保留原始請求體。使用簽章金鑰,對時間戳、一個句點和原始請求體位元組計算 HMAC-SHA256,再以恆定時間比較 X-Webhook-Signature。

以下 Node.js 函式接收 Buffer 型別的 rawBody 和 Headers 型別的 headers:

import { createHmac, timingSafeEqual } from 'node:crypto';

function verifyWebhook(rawBody, headers, secret) {
  const timestamp = headers.get('X-Webhook-Timestamp') ?? '';
  const signature = headers.get('X-Webhook-Signature') ?? '';
  if (!/^\d+$/.test(timestamp)) return false;
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
  if (!/^v1=[0-9a-f]{64}$/.test(signature)) return false;
  const expected = createHmac('sha256', secret)
    .update(timestamp + '.')
    .update(rawBody)
    .digest();
  const actual = Buffer.from(signature.slice(3), 'hex');
  return timingSafeEqual(expected, actual);
}

驗證通過後再解析 JSON。不要先解析再序列化請求體,否則簽章位元組會改變。

處理重複與重試

使用事件的 id 避免重複處理。通知可能重複或亂序;需要當前狀態時,請讀取對應的 API 資源。

安全儲存或處理通知後回傳 2xx。失敗通知每輪最多嘗試八次,間隔從 30 秒逐步增加至一小時。透過 GET/webhooks/{id}/deliveries 檢視記錄,透過 POST/webhooks/{id}/deliveries/{delivery}/retry 重試失敗的通知。

更換簽章金鑰

呼叫 POST/webhooks/{id}/rotate-secret 更換金鑰。傳送中的通知可能仍使用舊金鑰,請在接收端保留短暫的過渡時間。接收地址必須是使用 443 連接埠的公開網路 HTTPS 地址,且不能重定向。