Skip to content

錯誤碼與重試

每個廠商可呼叫的端點都共用同一套錯誤形狀和重試契約。ProviderClient 對它發出的每一個呼叫,都已經實作了下表「SDK 行為」那一欄——本頁是完整參考,適合在你除錯一個被丟出的錯誤、要實作 SDK 沒覆蓋的呼叫,或想圍繞 isRetryableStatus 寫自己的重試邏輯時查閱。

狀態碼參考

狀態碼意義響應體SDK 行為
200status: "DECLINED"BET 的正常業務結果(餘額不足、超出下注限額)JSON TransactionResponse正常返回——不是錯誤,不會重試
400請求主體無效(校驗失敗),或請求與其引用的 session 不符(playerRef/gameId/currency 不一致)JSON { "error": "..." }PlatformApiError 丟擲,不重試
400(nonce)X-Nonce 缺失或過長JSON { "error": "invalid nonce" }PlatformApiError 丟擲,不重試
401(簽名)簽名錯誤、缺失,或時間戳過期純文字invalid signaturePlatformApiError 丟擲,不重試
401(重放)一個已經被使用過的 nonceJSON { "error": "replayed request" }PlatformApiError 丟擲,不重試
401(身份)未能解析出廠商身份,或 session token 無效/已過期JSON { "error": "..." }PlatformApiError 丟擲,不重試
403該 session 屬於和本次請求簽名者不同的廠商JSON { "error": "..." }PlatformApiError 丟擲,不重試
404沒有匹配的路由——檢查 baseUrl 和路徑JSON { "error": "..." }PlatformApiError 丟擲,不重試
409同一個 transactionId 已有請求在處理中JSON { "error": "..." }帶退避重試,複用同一個 transactionId
429超出限流(按租戶)JSON { "error": "rate limit exceeded" },附 Retry-After 響應頭(秒數)PlatformApiError 丟擲,不會自動重試——請自行遵循 retryAfter
500平台側可重試的失敗(包含判定為 TIMED_OUT 的情況)JSON { "error": "..." }帶退避重試
503遊戲或運營商轉接器未配置JSON { "error": "..." }帶退避重試——見下方提示

除了上面純文字的 401 之外,其他每一種錯誤響應都共用 { "error": "<訊息>" } 這個結構。

503 會被重試,儘管它通常不是暫時性問題

isRetryableStatus 把任何 >= 500 的狀態碼都視為值得重試,包括 503。實務上,這個介面回傳 503 幾乎都代表平台這一側的遊戲/運營商配置有問題(某個轉接器還沒接好),而不是一時的抖動——所以如果 submitTransaction 呼叫在連續多次 503 後耗盡所有重試次數,這是提示你去檢查接入配置,而不是懷疑網路問題。

PlatformApiError

對上面每一個不可重試的響應(400/401/403/404/429),以及重試耗盡後的 409/5xx丟擲:

ts
class PlatformApiError extends Error {
  status: number
  body: string          // 原始響應體
  requestId?: string    // 對應平台的 X-Request-Id 響應頭
  retryAfter?: string   // 若存在,對應 Retry-After 響應頭
  hint?: string         // 一句話指出最可能的原因
}

requestId 是交給平台支援最有用的單一資訊——讓對方能直接在伺服端日誌裡找到這個確切的請求,而不需要你描述時間點或請求內容。hint 是針對該狀態碼最可能原因的一句話提示,並非窮盡診斷。範例見除錯

RequestTimeoutError

當單次請求嘗試超過 timeoutMs(預設 15000)時丟擲。這是網路層級的失敗,不是 PlatformApiError——因為根本沒有收到任何 HTTP 響應——所以會像其他網路錯誤一樣被重試。只有當所有嘗試(含全部重試)都逾時後,呼叫方才會收到這個錯誤。

ts
class RequestTimeoutError extends Error {
  timeoutMs: number
  hint: string
}

isRetryableStatus

ts
function isRetryableStatus(status: number): boolean
// 409 和任何 >= 500 為 true
// 其他一律為 false,包括 429

匯出給需要圍繞 SDK 沒覆蓋的呼叫自建重試邏輯的呼叫方使用。這正是 ProviderClient 內部使用的判斷邏輯——網路錯誤(DNS 失敗、連線被拒等)永遠視為可重試,與這個函式無關,因為它根本沒有產生一個可供檢查的 HTTP 狀態碼。

冪等性與重試

重試永遠複用同一個 transactionId(針對錢包呼叫)——這是平台用來分辨「同一次邏輯嘗試的重試」和「一次全新嘗試」的方式。透過 ProviderClient 發出的呼叫完全不需要你自己實現這套邏輯;如果你是手動簽名發送請求,也要用同樣的方式在自己的重試中複用同一個 ID。

免費旋轉回呼(由平台呼叫、且平台不會重試)用的是不同的冪等鍵——requestRef/externalRef,因為需要重試的一方換成了平台,而它並不會這麼做。完整契約見免費旋轉回呼