錯誤與重試
這個對接裡存在兩個彼此獨立的錯誤面,搞清楚你在除錯的是哪一個很重要:
- 運營商 API 錯誤——平台對你發起的呼叫(
launch、games、kick、rounds/replay、免費旋轉)所做的響應。 - 錢包回調錯誤——平台呼叫你的
POST /v1/wallet/transaction或GET /v1/wallet/balance時,如何解讀你的響應。
簽名與重放錯誤(雙向共用)
無論被校驗的一方是你(運營商 API)還是平台(錢包回調),這些規則都完全一致地適用——見簽名與身份驗證。
| Status | Meaning | Body |
|---|---|---|
401 | 簽名錯誤、缺失,或時間戳已過期 | 純文字:invalid signature——不是 JSON,因為這項檢查發生在請求到達任何處理程式之前 |
401 | 使用了已經用過的 nonce(重放) | JSON { "error": "replayed request" } |
400 | X-Nonce 缺失或過長 | JSON { "error": "invalid nonce" } |
運營商 API 狀態碼
運營商 API 參考裡的每個介面都共用這個結構。業務錯誤(遊戲不存在、貨幣不支援等)都是 JSON { "error": "<message>" }。
| Status | Meaning |
|---|---|
400 | 請求體無效,或某個值未通過校驗(不支援的 currency/language、缺少必填欄位) |
401 | 未能解析出運營商身份——見上方的簽名錯誤 |
403 | 啟動被風控攔截(玩家黑名單/自我排除)——見 POST /v1/operator/games/launch |
404 | 遊戲不存在,或存在但對你的運營商租戶不可見(這兩種情況刻意做成無法區分,避免被用來探測遊戲目錄);對回合回放而言,則是在你的租戶下找不到匹配的回合 |
429 | 超出你租戶的速率限制——見下方的速率限制 |
500 | 平台側的非預期失敗 |
速率限制
每個運營商 API 呼叫都按租戶做速率限制。超出限制會返回:
429
Retry-After: <seconds>json
{ "error": "rate limit exceeded" }請按 Retry-After 裡的秒數退避後再重試,而不要立即重試。如果你預期的流量需要比預設值更高的限額,請在生產環境觸發這個問題之前,聯繫你的對接窗口提高限額。
錢包回調:平台如何處理你的響應
這裡你不需要重試呼叫平台——是平台在呼叫你,並解讀你返回的任何內容:
| Your response | Platform's interpretation |
|---|---|
200,{ status: 'OK', balance } | 套用成功 |
200,{ status: 'DECLINED', balance } —— 僅限 BET | 正常的業務拒絕(例如餘額不足);不會重試 |
200,在 WIN/ROLLBACK/ADJUSTMENT 上返回 { status: 'DECLINED' } | 非法——這些類型不允許被拒絕;真正的失敗請改用非 200 狀態碼表達 |
任何非 200 的狀態碼 | 視為失敗。平台可能會用完全相同的 transactionId 重試——見冪等性 |
| 在你配置的逾時時間內沒有響應 | TIMED_OUT——之後會透過重試或核對機制解決,處理方式和非 200 一致 |
因為重試會複用完全相同的 transactionId,你的實現最重要的一件事就是用同一份快取的響應回答重複請求,而不是重新套用一次餘額變動——見錢包回調介面參考裡的冪等性。
冪等性與重試
每一次重試——無論是你發起的呼叫,還是平台呼叫你——都會複用完全相同的 transactionId(對免費旋轉而言,則是 requestRef/idempotencyKey)。正是這個共用 ID,讓雙方都能區分「同一次邏輯嘗試的重試」和「一次全新的嘗試」。接收重試的那一方負責依據它去重;任何一方都不會為同一次嘗試的重試發明一個新 ID。