跳到导航

Webhook 簽名驗證與冪等性

驗證原始 Webhook 主體,使用 HTTP 狀態碼進行確認,並可靠地處理重試和重複。

以 Markdown 格式查看

本頁依據 Agent Java SDK WEBHOOKS.md 提交 fa6c7b6 同步。此次僅更新文件,沒有發布包含預警輔助方法的新 SDK 製品。

四類事件共用一個商戶回呼 URL,依正文 event 分流。事件欄位與範例見 Webhook 事件與強平預警。

Webhook 標頭

標頭描述
X-Agent-TimestampUnix 時間戳(以秒為單位)。
X-Agent-Nonce隨機數。
X-Agent-SignatureHMAC-SHA256 十六進位簽章。
timestamp + nonce + rawBody

事件冪等性

去重必須在商戶與 environment 範圍內持久化,並與業務處理原子提交。不同 notificationId 的 FIRST / UPGRADE / REMINDER 是獨立通知,不可依使用者、輪次或 eventType 合併丟棄。空冪等鍵不能用於去重。SDK 只回傳輔助鍵,不儲存或處理業務資料。同一身份、不同正文應記錄為衝突,不能覆蓋已處理的正文。

簽名驗證及接收

使用商家API秘密計算timestamp + nonce + rawBody的HMAC-SHA256十六進位簽章。驗證原始接收的位元組;不要先格式化 JSON、重新命名欄位或重新序列化正文。

先驗簽,再校驗時間視窗(建議 ±300 秒)、商戶與環境,然後提取冪等身份並可靠處理。保留未知事件原值供排查,不能視為資金成功。驗證輔助方法本身不執行時間、歸屬或持久去重校驗。

處理完成或確認同正文重複後回傳 HTTP 2xx;失敗回傳非 2xx。預警發送端 HTTP 逾時為 5 秒,最多 8 次嘗試。重試保持已凍結的正文,僅簽章時間與隨機數更新。可靠接管後儘快回應;耗時業務可使用商戶自己的持久任務。

商家通知不依賴使用者的線上狀態。平台用戶推播僅在線上盡力推送,無線下重播;第一階段沒有通知收件匣。

成功響應並停止重試

資金回呼和強平預警只根據 HTTP 狀態碼 判斷本次投遞結果,不解析回應正文的 code、success、result 或 message,也不要求固定回傳 OK / success。

商家回應平台行為
HTTP 200–299,包括 200、202、204本次投遞成功;成功狀態持久化後,不再自動重發。
最終非 2xx 響應,包括 400、401、403、409、429、500 和 503投遞失敗重試遵循現有的退避策略;在嘗試限制之後,它被標記為 DEAD。 4xx 不會自動確認通知。
連線失敗或回應逾時,沒有可用的回應結果未確認並在失敗策略下重試。

回應正文可為空、文字或 JSON。範例 result 欄位僅供商戶閱讀,不是協定要求。202 Accepted 同樣會停止平台重試,因此必須先將通知可靠保存到商戶自己的持久任務佇列,不能只啟動記憶體非同步任務就確認成功。

成功響應範例

業務處理完成後,或通知已可靠地儲存至商家本身的待處理佇列:

HTTP/1.1 200 OK
Content-Type: application/json
{"result":"RECEIVED"}

當不需要響應體時:

HTTP/1.1 204 No Content

對於已經處理過且body相同的通知,跳過重複的業務處理,仍然返回2xx:

HTTP/1.1 200 OK
Content-Type: application/json
{"result":"DUPLICATE"}

失敗回應範例

例如資料庫暫時不可用,商戶尚未完成處理,也未可靠保存通知,應回傳非 2xx,讓平台後續重試:

HTTP/1.1 503 Service Unavailable
Content-Type: application/json
{"result":"FAILED","message":"temporary storage failure"}

拒絕無效簽名而不更新業務資料或成功的重複資料刪除記錄:

HTTP/1.1 401 Unauthorized
Content-Type: application/json
{"result":"INVALID_SIGNATURE"}

這些回應正文不影響重試判斷。不能期待回傳 401 或 409 就永久停止重試;需要排查簽章、通知內容或商戶設定。

錯誤範例:以下回應仍會被平台視為投遞成功,不會因 success:false 而觸發重試。

HTTP/1.1 200 OK
Content-Type: application/json
{"success":false,"code":500,"message":"processing failed"}

如果框架或統一例外處理預設將業務錯誤包裝成 HTTP 200,回呼入口須明確設定正確的 HTTP 失敗狀態。

可靠的確認和重複傳送

建議順序:驗證簽章並檢查時間/商家/環境→提取冪等性身分→處理事務中的業務資料和成功去重記錄,或可靠保存待處理任務→提交成功後回傳200/204。在成功寫入資料庫之前,不要返回 2xx 或將通知標記為已處理。

商戶處理成功後仍可能收到重複請求:回應可能在網路中遺失,或平台收到 2xx 後未能持久化 SUCCESS。HTTP 回呼不保證只投遞一次。必須在商戶與 environment 範圍內持久去重。資金使用 orderType:orderId:targetStatus,預警使用 liquidation.warning:notificationId。已處理的同正文通知回傳 2xx,避免重複入帳或提醒;同一身份、不同正文應記錄衝突並回傳非 2xx,不能覆蓋原記錄。

確認成功是指商家收到/處理了通知,而不是資金作業成功。以targetStatus=FAILED記錄有效資金通知後,也回2xx;訂單失敗並非拒絕通知確認的理由。

資金和環境邊界

原始合約轉帳 webhook 和 queryOrder 流程不會自動應用於資金。使用queryWalletTransfer和原始訂單環境確認資金操作。資金用途status;原始合約傳輸回應使用orderStatus。成功的 HTTP 回應或 code=0 本身並不能證明資金已轉移。

明確模擬合約轉移通知包括environment=SIMULATED。首先驗證原始主體,然後根據已儲存的本地業務訂單檢查使用者、金額、訂單身分和環境。

資金回收指南 · 環境指南