伺服端接入
@moose/provider-sdk 的 ProviderClient 是你後端需要的一切入口:session 校驗、餘額查詢和錢包交易提交。簽名、nonce、冪等重試都已經幫你處理好了。
安裝
由 moose-platform 直接以 npm 套件形式分發——你的對接窗口會提供存取方式。
建立客戶端
import { ProviderClient } from '@moose/provider-sdk'
const client = new ProviderClient({
baseUrl: 'https://platform.example.com',
tenantId: 'acme-studio',
secret: process.env.PLATFORM_SECRET!,
// retry: { maxAttempts: 5, baseDelayMs: 200 }, // 以上為預設值
})secret 是你租戶的 HMAC 簽名金鑰——見下方安全性。
典型的接入順序是:遊戲載入時呼叫一次 verifySession,需要展示或同步餘額時呼叫 getBalance,每局裡的每筆下注/派彩/回滾則用 submitTransaction。
校驗 session
在你的遊戲啟動時,校驗啟動 token 並讀取針對這個 (game, operator) 組合解析出的 Central Config(RTP 標籤 + 下注限額)。這裡的 sessionToken 就是你的瀏覽器客戶端從啟動 URL 讀出、再發給你後端的那個值——它如何到達,見取得 session token:
const session = await client.verifySession(sessionToken)
// {
// playerRef, gameId, operatorId, currency,
// config: { rtpProfile, minBetMinor, maxBetMinor } // maxBetMinor === 0 表示無上限
// }拿到 session 之後,你就可以用它查詢餘額,也可以直接提交交易。
查詢餘額
const { balance } = await client.getBalance(sessionToken)
// balance 為最小貨幣單位(分),和交易回應裡的 `balance` 結構一致只需要 session token 即可——playerRef 會在伺服端從 session 解析出來,因此這個介面永遠無法用來讀取其他廠商的玩家餘額。它不會移動任何資金:運營商的錢包仍是唯一的權威來源,這只是一次透傳查詢。
每筆 submitTransaction 回應本身就會返回交易後的餘額,所以對局進行中通常不需要另外查——適合在玩家第一次下注前展示餘額,或斷線重連後重新同步。DEMO session 返回的是記憶體中的試玩餘額,而不是查詢真實運營商。和 submitTransaction 不同,這個呼叫在平台側不做冪等追蹤——這是一次讀取操作,失敗了直接重試即可。完整狀態碼對照見錯誤碼與重試。
提交交易
const bet = await client.submitTransaction({
transactionId: crypto.randomUUID(),
sessionToken,
type: 'BET', // 'BET' | 'WIN' | 'ROLLBACK'
roundId,
roundComplete: false, // 該局最後一筆交易時為 true(僅對 BET/WIN 有意義)
playerRef: session.playerRef,
amount: 300, // 最小貨幣單位(分)—— 絕不用浮點數
currency: session.currency,
gameId: session.gameId,
})
if (bet.status === 'DECLINED') {
// 正常的業務結果(餘額不足,或超出配置的下注限額)—— 不是錯誤,不會重試。
}transactionId—— 由你自己生成(例如crypto.randomUUID())。對同一次邏輯嘗試的重試要原樣複用它;SDK 內部的自動重試已經會幫你複用了。ROLLBACK—— 把originalTransactionId設為要撤銷的那筆BET的transactionId。WIN—— 作為獨立於BET的另一筆交易提交,在兩者中結束該局的那筆上標記roundComplete: true。
什麼會重試,什麼不會
| 結果 | 行為 |
|---|---|
| 網路錯誤(DNS、連線被拒等) | 帶退避重試 |
HTTP 409(同一個 transactionId 已有請求在處理中) | 帶退避重試 |
HTTP 5xx(包括平台側判定為 TIMED_OUT 的情況) | 帶退避重試 |
| HTTP 400/401/403/404 | 立即以 PlatformApiError 丟擲,不重試——請求本身無效或未通過鑑權,重試沒有意義 |
| HTTP 429(超出限流) | 立即以 PlatformApiError 丟擲,SDK 不會重試。若平台有回傳 Retry-After 響應頭,會放在 PlatformApiError.retryAfter——請遵循這個值再自行重試,沒有的話再退回固定延遲 |
200 響應且 status: "DECLINED" | 正常返回,不是錯誤,不重試——BET 的一種業務結果 |
重試始終複用同一個 transactionId,匹配平台的冪等契約——你完全不需要自己實現這套邏輯。完整狀態碼參考見錯誤碼與重試。
入站回呼
有三件事是平台呼叫你的伺服端——session 撤銷和兩條免費旋轉路由——完全在這個 SDK 之外,因為這時候是你的伺服端接收呼叫,而不是發出呼叫。共用契約見平台 → 廠商回呼,各路由的完整細節見Session 撤銷回呼和免費旋轉回呼。
撤銷請求送達時,平台側的 session 其實已經被刪除了——這只是盡力而為的「立即通知」,不是權威來源。無論這個回呼有沒有送達,你自己下一次針對該 sessionToken 的 verifySession/submitTransaction 呼叫都已經會收到 401。若是瀏覽器端遊戲,請透過 @moose/game-client-sdk 的 notifySessionRevoked 把這個事件上報給 shell——見 game-client-sdk 參考。
單局回放
運營商可以請求一個連結來回放你遊戲的某一局。平台會把這個連結指向你的回放頁面——但只有當你完成兩件事之後這才會運作:與平台團隊為你的遊戲設定好回放頁面基礎網址,以及在 spin 時就把這一局的回放紀錄錄製下來(平台從頭到尾只看得到資金異動,從未看過你遊戲的視覺結果,如果你沒有自己錄製,平台也沒有東西可以拿來回放)。完整契約、verifyReplay 用法與範例見單局回放。
簽名
每個請求都用 HMAC-SHA256 對一段由方法、路徑、時間戳、nonce、主體組成的 canonical string 簽名,放入四個請求頭:X-Tenant-ID、X-Timestamp、X-Nonce、X-Signature。ProviderClient 會自動生成並發送這些頭——只有當你要實現 SDK 沒覆蓋的廠商端呼叫時才需要用到底層的 signRequest/generateNonce 匯出,若是實作上面提到的入站回呼則需要 verifyPlatformSignature。完整契約(含時鐘偏差、nonce 重複使用、金鑰輪替)見簽名與鑑權。
安全性
secret 是你租戶的 HMAC 簽名金鑰。必須只儲存在伺服端——絕不能發到瀏覽器。這個 SDK 是給你的後端(RGS)用的,不是給面向玩家的遊戲客戶端用的——那部分見取得 session token和生命週期上報。
除錯
遇到無法解釋的 401、呼叫在背後靜默重試——見除錯指南,內容涵蓋 onDebug、explainSignature,以及 PlatformApiError 的 hint/requestId;想在沒有完整平台環境的情況下跑整合測試,見用 createMockPlatform 測試。
完整參考
每個匯出型別和方法簽名詳見 @moose/provider-sdk 參考文件。