StableOps
概念

Webhooks

瞭解 StableOps Webhook 的事件模型、HMAC 簽名驗證、自動重試、併發限制、死信佇列與安全重放機制,並透過事件去重避免重複履約或重複記帳。掌握端點設定、金鑰輪換、投遞狀態與故障恢復方法,讓支付、訂閱和運維事件能夠可靠進入業務系統。

Webhook 讓你的應用在 StableOps 中發生事件(例如支付被檢測、確認、最終化)時即時收到通知。

總覽

不必輪詢 API 查支付狀態,事件發生時 StableOps 會直接 HTTP POST 到你的服務。好處:

  • 即時:到帳立刻知道。
  • 節省呼叫:不必持續輪詢。
  • 可靠投遞:失敗自動指數退避重試。
  • 可回放:所有投遞都有日誌,可在 dashboard 重放。

工作流

┌─────────────┐         ┌─────────────┐         ┌─────────────┐
│   區塊鏈     │────────▶│  StableOps  │────────▶│   你的應用   │
└─────────────┘         └─────────────┘         └─────────────┘
    支付發出                 檢測到事件              派發 Webhook
  1. 某個事件發生(例如鏈上檢測到支付)
  2. StableOps 建立一條 Webhook 投遞
  3. 向你的端點發 HTTP POST
  4. 你的服務處理後返回 200 OK
  5. 投遞失敗則指數退避重試

Webhook 事件

支付相關事件

payment_order.created

新訂單建立時傳送。

payment.detected

掃描器首次看到對應轉帳時傳送。掃描可能落後於鏈頭,此時不一定恰好是 0 確認。

動作:把 UI 切換到「支付已收到,確認中…」。

注意:此時不要履約,交易仍有可能被回滾。

payment.confirmed

支付獲得足夠鏈上確認時傳送。交易基本不可能回滾,但尚未達到鏈的 finality 保證。

動作:可以更新內部系統並通知使用者,但建議等待 payment.finalized 後再發貨。

payment.finalized

支付達到 finality、不再可回滾時傳送。

動作:可以安全履約。資金已經穩定。

這是推薦用來觸發履約的事件。

payment.expired

訂單超過過期時間仍未匹配到任何轉帳時傳送。

動作:把訂單標記為過期,引導使用者重新下單。

payment.reverted

已檢測到的支付被回滾時傳送。receipt 執行失敗,或區塊在重組後 block hash 不再與儲存的事件匹配。

動作:撤銷任何基於 payment.detected / payment.confirmed 做的樂觀處理。這也是 建議等 payment.finalized 再履約的原因。

payment_order.canceled

仍處於 created(尚未檢測到任何入帳)的訂單被呼叫 cancel 取消時傳送。

動作:把訂單標記為已取消,釋放任何為它預留的資源。

注意:雖然取消由使用者主動觸發、HTTP 回應已經返回結果,仍會回推此事件。這樣以 webhook 流為唯一事實源(event sourcing)的接入方不會漏掉這次終態流轉。不關心的接入方 可以直接忽略它。

完整 payload 結構請參見 Payment Events API 參考

商家訂閱事件

StableOps 也會為商戶管理的終端使用者訂閱和訂閱帳單推送事件。你可以用這些事件開通帳號、跟蹤續費、暫停逾期使用者,並對帳帳單支付結果。

事件觸發時機
end_user_subscription.created商家訂閱建立
end_user_subscription.activated首期帳單已支付,訂閱變為 active
end_user_subscription.renewed續費帳單已支付,帳期向前推進
end_user_subscription.canceled訂閱被立即取消
end_user_subscription.expired訂閱因期末取消或未付款而過期
end_user_subscription.past_due訂閱進入 past_due 狀態
end_user_invoice.open新的訂閱帳單已開出
end_user_invoice.paid訂閱帳單已支付
end_user_invoice.payment_failed訂閱帳單支付失敗
end_user_invoice.payment_late帳單已判為不可收回後又收到付款

訂閱帳單 Checkout 底層仍會建立付款單,因此你也可能收到該底層付款單的普通支付事件。訂閱狀態請以 end_user_invoice.*end_user_subscription.* 事件為準。

各事件完整 payload 結構請參見 Subscription Events API 參考

運維與 Agent 事件

除支付事件外,StableOps 還會在以下場景推送事件。在控制台裡它們構成運維事件訂閱分組。一個開關覆蓋全部,與支付事件分組相互獨立:

事件觸發時機
address.pool.low某條鏈的可用收款地址池低於水位線
agent.action.requestedAgent 發起一個需要審批的寫操作
agent.action.approved待審批的 Agent 操作被批准
agent.action.executed已批准的 Agent 操作完成執行

各事件完整 payload 結構請參見 Operational Events API 參考

接入 Webhook

1. 建立端點

在 StableOps dashboard:

  1. 進入 Webhooks(左側導覽欄)
  2. Add Endpoint
  3. 填入你的 Webhook URL(生產環境建議使用 HTTPS)
  4. 勾選訂閱的事件型別
  5. 儲存 Webhook secret

secret 欄位只在建立與 rotate 時返回一次,Dashboard 不會再展示,請安全儲存。 呼叫 rotate-secret 後,舊 secret 仍保留 24 小時與新 secret 同時有效,便於 你平滑地把驗籤 key 切換到新值,不會丟投遞。

2. 驗證簽名

始終驗證簽名,確保請求來自 StableOps。

import { SIGNATURE_HEADER, verifySignature } from '@stableops/api-sdk/webhooks'

const result = verifySignature({
  secrets: [webhookSecret],
  header: request.headers.get(SIGNATURE_HEADER) ?? undefined,
  rawBody,
})

if (!result.ok) {
  console.error('Invalid signature:', result.reason)
  // 拒絕請求
}

投遞、重試與死信

成功判定

任何 2xx 回應都算成功。其它狀態碼、網路錯誤、或者超過 10 秒 沒返回,都按 失敗處理。

重試退避

失敗後按下表延遲重排,第 6 次仍失敗轉入 DLQ(dead letter queue):

第幾次間隔
130 秒
260 秒
35 分鐘
430 分鐘
52 小時
6+DLQ

投遞記錄欄位

webhook-deliveries 上你能查到的關鍵欄位:

欄位說明
attemptsHTTP 已嘗試的次數
response_status最近一次下游返回的狀態碼
response_duration_ms最近一次耗時
error_message最近一次失敗的簡短原因
next_retry_at下次重試時間;進入終態時為 null
statuspending / succeeded / failed / dead_letter

Replay

三個重放介面(endpoint replay、單條 delivery replay、批次 replay dead letters) 都是建立一條 delivery 記錄進行投遞,原審計日誌保持不變。Dashboard 的 "replay" 按鈕就是呼叫這些介面。

最佳實踐

1. 始終驗證簽名

拒絕任何不帶有效 X-Product-Signature 的請求。不驗籤的話,只要別人知道你的端點 URL 就能偽造事件。

2. 儘快返回 200

驗籤並記錄 X-Event-Id 後立即返回 200。履約、通知、帳本更新等耗時操作應非同步處理,否則投遞超時會觸發無謂的重試。

3. 按 X-Event-Id 冪等處理

在變更自身狀態前先記錄 X-Event-Id。網路重試和平台重放可能多次投遞同一事件,重複執行必須安全。

4. 驗籤必須用 raw body

簽名計算的是收到的原始位元組,任何 JSON 解析或重新序列化都會改變 body 內容、破壞簽名。務必在驗簽完成後才解析 JSON。

5. 處理全部相關事件型別

訂閱並妥善處理你可能收到的每種事件,包括 payment.revertedpayment.expired,以及 end_user_invoice.paid / end_user_subscription.renewed 等訂閱事件。未處理的事件雖然也算投遞成功,但你的訂單和訂閱狀態會逐漸失準。

6. 詳盡記錄日誌

記錄每次投遞的 X-Event-IdX-Delivery-Id、事件型別以及你的處理結果。完善的日誌是排查漏單或重複履約最快的手段。

7. 監控投遞健康度

定期檢查投遞日誌,留意 faileddead_letter 數量上升的端點。對過去一小時未返回 2xx 的端點設定告警,問題修復後用 replay 介面清空死信佇列。

下一步

這篇文件怎麼樣?

最後更新

本頁內容