如何實現無縫的 Webhook 系統?以點數儲值與自動分發為例
在現代的 SaaS 服務體驗中,「即時性」是決定使用者滿意度的關鍵。想像一下,當客戶因為急需轉檔而刷卡購買了服務點數,卻還要等待系統每五分鐘「整理一次訂單」才能拿到點數,這短短的幾分鐘絕對會引發客戶的焦慮與客訴。
為了實現「付款完成的 1 秒內點數入帳」,我們不能依賴傳統的輪詢(Polling)機制,而必須建構一套高可用性的 Webhook(網路呼叫)系統。這篇文章將以 Flozium 雲端處理平台 的點數分發機制為例,解析如何設計無縫的 Webhook 架構。
輪詢 (Polling) 的致命傷
早期的電商系統在處理第三方支付時,常常採用「輪詢」:也就是伺服器每隔一段時間(例如每分鐘)主動去向金流公司(如 Stripe)詢問:「請問訂單 #12345 付款成功了嗎?」
- 資源浪費: 99% 的詢問都是無效的,徒增雙方伺服器的負載。
- 延遲極高: 就算每 10 秒問一次,使用者最長還是得等上 10 秒。
Webhook 的運作邏輯:不要打給我,我會打給你
Webhook 的概念恰好相反。我們在自己的伺服器上開放一個特定的 API 端點(Endpoint),並把這個網址登記給金流公司。
當使用者的信用卡被成功扣款(Authorized & Captured)的那一瞬間,金流公司的伺服器會「主動」發送一個 HTTP POST 請求到我們的端點,並附上訂單的詳細 JSON 資料。這就像是金流公司在付款成功的當下,立刻打了一通電話通知我們的系統。
實戰架構:Flozium 的點數自動分發流水線
在建置 app.flozium.com 的點數預付費系統時,我們設計了以下的工作流來確保 Webhook 處理的絕對安全與即時:
步驟一:接收與驗證 (Signature Verification)
Webhook 的端點是公開的,任何人都可以對它發送 POST 請求。如果有人偽造了一個「付款成功」的請求,不就能無限刷點數了嗎? 因此,金流平台在發送 Webhook 時,會用一把只有雙方知道的密鑰(Secret Key)對內容進行加密簽章(Signature)。我們的端點收到請求的第一件事,就是用同樣的演算法驗證簽章。如果簽章不符,立刻丟棄該請求,防堵駭客的重播攻擊(Replay Attack)。
步驟二:防重複處理 (Idempotency)
網路環境是不穩定的。有時候金流平台發了 Webhook,但沒收到我們的成功回覆,它可能會在幾分鐘後「再發一次」。
為了解決這個問題,我們的資料庫在處理點數發放時,必須具備「冪等性 (Idempotency)」。我們會將金流端傳來的唯一 event_id 存入資料庫。每次收到 Webhook,先檢查這個 event_id 是否已經處理過。如果是,就直接回傳 200 OK,絕不重複發放點數。
步驟三:異步分發與狀態更新
驗證無誤後,我們不能在同一個 Request 裡面去執行冗長的資料庫寫入。我們會將「發放點數給 User A」這個任務丟進訊息佇列(Message Queue,如 Redis),然後立刻回覆金流端 200 Success。
背景的 Worker 節點會在一秒內從佇列中取出任務,將「處理點數 (CRD)」增加到使用者的帳戶中,並透過 WebSocket 即時更新前端 Dashboard 的點數餘額畫面。
結語
一個穩定的 Webhook 系統是串接現代微服務的微血管。它不僅用於金流儲值,也能用於影音處理完成的通知、API 狀態的同步。在設計架構時,將「安全性驗證」與「異步處理」做好,才能真正打造出讓使用者感到「絲滑無縫」的高端 SaaS 體驗。