Skip to content

@moosehq/provider-sdk 參考

完整講解見伺服端接入指南

ProviderClient

ts
new ProviderClient(options: ProviderClientOptions)
選項型別說明
baseUrlstring平台基礎 URL,不帶結尾斜槓
tenantIdstring你的廠商租戶 ID
secretstringHMAC 金鑰——只存在於伺服端
retryPartial<RetryOptions>預設為 { maxAttempts: 5, baseDelayMs: 200 }
timeoutMsnumber單次嘗試的請求逾時時間。逾時的嘗試會被中止,並像其他網路錯誤一樣被重試。預設為 15000
now() => Date可注入的時鐘,用於測試
onDebug(event: DebugEvent) => void選用診斷鉤子,預設關閉——見除錯指南
fetchtypeof fetch可注入的 fetch 實作——搭配 createMockPlatform 可做離線測試。預設為全域 fetch
ts
type RetryOptions = {
  maxAttempts: number // 總嘗試次數,包含第一次——不是重試次數
  baseDelayMs: number  // 第一次重試前的延遲;之後每次重試翻倍
  sleep?: (ms: number) => Promise<void> // 可注入,用於測試;預設是基於 setTimeout 的真實等待
}

退避演算法是指數退避:baseDelayMs * 2^(attempt-1)

方法

  • verifySession(sessionToken: string): Promise<VerifySessionResponse>
  • submitTransaction(req: TransactionRequest): Promise<TransactionResponse>
  • getBalance(sessionToken: string): Promise<BalanceResponse> —— 按需查詢玩家目前餘額,不會移動任何資金。見 POST /v1/wallet/balance
  • verifyReplay(replayToken: string): Promise<VerifyReplayResponse> —— 將運營商的回放連結(網址中的 ?replay= token)解析回它所指向的那一局。見單局回放

注意這裡沒有 submitBehavior——機器人偵測遙測是由瀏覽器透過 @moosehq/game-client-sdk/behavior-reporterBehaviorReporter 直接送出的,完全不經過這個 SDK。見機器人偵測訊號

型別

欄位層級語義(限制條件、校驗規則、metadata 的用途)見資料模型與列舉;這一節是確切的 TypeScript 型別宣告。

ts
type TransactionType = 'BET' | 'WIN' | 'ROLLBACK'
type ResponseStatus = 'OK' | 'DECLINED'

type TransactionRequest = {
  transactionId: string
  sessionToken: string
  type: TransactionType
  roundId: string
  roundComplete: boolean
  originalTransactionId?: string // type === 'ROLLBACK' 時必填
  playerRef: string
  amount: number // 最小貨幣單位
  currency: string // ISO-4217,大寫,3 個字母(例如 "USD")
  gameId: string
}

type TransactionResponse = { status: ResponseStatus; balance: number }

type VerifySessionConfig = {
  rtpProfile: string
  minBetMinor: number
  maxBetMinor: number
  language: string // BCP-47 語言標籤(例如 "en"、"zh-TW")——運營商在啟動時要求的語言,若未要求則為 "",此時請回退到你自己的預設語言(例如 "en")
}
type VerifySessionResponse = {
  playerRef: string
  gameId: string
  operatorId: string
  currency: string
  config: VerifySessionConfig
}

type BalanceResponse = { balance: number } // 最小貨幣單位

type VerifyReplayResponse = {
  roundId: string // 用這個去查你自己的 ReplayStore —— 見單局回放
  gameId: string
  playerRef: string
  currency: string
  language: string // 這一局原本進行時使用的 BCP-47 語言標籤,若未設定則為 ""——回退規則與 VerifySessionConfig.language 相同
}

錯誤

PlatformApiError —— 對不可重試的 HTTP 響應(400/401/403/404/429)丟擲;有 status: numberbody: string(原始響應體),另外還有 requestId?: string(平台的 X-Request-Id 響應頭,若存在——把這個交給平台支援用於伺服端日誌關聯)、retryAfter?: stringRetry-After 響應頭,若存在——特別是在 429 時,SDK 不會自動重試這個狀態)、以及 hint?: string(一句話指出該狀態最可能的原因,例如 401 的 hint 會列出常見的簽名錯誤)。不會暴露其他響應頭。 isRetryableStatus(status) —— SDK 自身判斷"是否值得重試"的方法(只有 409 和任何 >= 500 才是 true——429 不會被自動重試),匯出給需要自定義重試邏輯的呼叫方使用。 RequestTimeoutError —— 當一次請求嘗試超過 timeoutMs 時丟擲;有 timeoutMs: numberhint: string。它被當作網路層級的錯誤處理,會像其他網路錯誤一樣被重試,所以只有當所有嘗試(含全部重試)都逾時後,呼叫方才會收到這個錯誤。

完整狀態碼參考,包含以上這些類別所依據的主表,見錯誤碼與重試

底層簽名原語

signRequest / generateNonce —— ProviderClient 內部使用,同時也匯出給需要簽名 SDK 未覆蓋的廠商端請求的呼叫方。explainSignature 計算方式與 signRequest 相同,但同時返回它所雜湊的原始 canonical string,用於診斷無法解釋的 401——見除錯指南。完整 canonical string 契約見簽名與鑑權

ts
type SignRequestInput = {
  method: string
  path: string     // 僅 URL 路徑——不含協定/主機/查詢字串
  tenantId: string
  secret: string
  body: string      // 實際將傳送的請求主體位元組
  now: Date
  nonce: string     // 來自 generateNonce()——每次簽名請求必須唯一
}

type SignedHeaders = {
  'X-Tenant-ID': string
  'X-Timestamp': string
  'X-Nonce': string
  'X-Signature': string
}

type SignatureExplanation = {
  canonicalString: string // 被雜湊的原始位元組
  timestamp: string
  signature: string
  headers: SignedHeaders
}

function signRequest(input: SignRequestInput): SignedHeaders
function explainSignature(input: SignRequestInput): SignatureExplanation
function generateNonce(): string // 16 個隨機位元組,轉十六進位制

除錯

DebugEvent —— onDebug 收到的內容;一個以 phase 區分的聯合型別:

ts
type DebugEvent =
  | { phase: 'request'; method: string; path: string; tenantId: string; transactionId?: string; attempt: number }
  | { phase: 'response'; method: string; path: string; status: number; attempt: number; latencyMs: number; requestId?: string; clockSkewMs?: number }
  | { phase: 'retry'; method: string; path: string; attempt: number; reason: 'network' | 'timeout' | 'conflict-409' | 'server-5xx'; delayMs: number }

onDebugexplainSignaturePlatformApiErrorhint/requestId 的完整走查,見除錯指南

離線模擬平台

createMockPlatform(options: MockPlatformOptions): MockPlatform —— 平台錢包/RGS 端點的可簽名記憶體模擬實作,用於不需要網路的整合測試。完整範例見用 createMockPlatform 測試

ts
type MockPlatformOptions = { secret: string; tenantId: string; now?: () => Date }

type MockSession = {
  sessionToken: string
  playerRef: string
  gameId: string
  operatorId: string
  currency: string
  config: VerifySessionConfig
  balanceMinor: number
}

type MockPlatform = {
  fetch: typeof fetch // 作為 ProviderClientOptions.fetch 傳入
  registerSession(session: MockSession): void
  registerReplay(replayToken: string, resolved: VerifyReplayResponse): void
  getBalance(sessionToken: string): number | undefined
}