プロダクトAPI シングルウォレットとトランスファーウォレット
シングルウォレットとトランスファーウォレット
オペレーターのプレイヤー残高をカジノゲームAPIに接続する2種類のウォレットモデルの技術比較です。資金を誰が保持するのか、ベット中にどの呼び出しがネットワークを行き来するのか、障害をどう復旧するのか、オペレーター側で何を構築する必要があるのかを解説します。
比較一覧
| 項目 | シングルウォレット | トランスファーウォレット |
|---|---|---|
| 残高の保管 | 残高はオペレーターのデータベースにのみ存在します。プロバイダーはプレイヤーの資金を保持しません。 | プロバイダーが独立したゲーム残高を保持し、振替の呼び出しで資金を出し入れします。 |
| ベット中の呼び出し | ベットと配当のたびに、オペレーターへサーバー間コールバック(balance、debit、credit、rollback)が発生します。 | なし。ゲームはプロバイダー側の残高で進行し、呼び出しは振替の入出金時のみ発生します。 |
| 必要な可用性 | ウォレットのエンドポイントは、すべてのコールバックに通常数百ミリ秒以内で応答する必要があります。停止するとゲームが中断されます。 | 振替時のみ必要です。オペレーターのシステムが一時的にオフラインでも、ラウンドは継続します。 |
| 整合性モデル | オペレーターの元帳がリアルタイムの唯一の正となる情報源です。照合が必要なのは残高ではなく、ゲームラウンドのみです。 | 2つの元帳が一致するのは振替の境界時点のみで、振替単位の照合が必要です。 |
| 障害復旧 | タイムアウトは、取引IDをキーとしたべき等な再試行とrollback呼び出しで解決します。 | 振替は2段階(保留の後、成功または失敗)で、結果が不明な場合はステータス照会で確認します。 |
| 連携の工数 | 高め。べき等性と元帳を備えた低レイテンシのコールバックサービスを、自社で構築・運用する必要があります。 | 低め。呼び出すRESTエンドポイントは3~4個で、インバウンドトラフィックのセキュリティ確保やスケーリングは不要です。 |
| プレイヤー体験 | 残高は1つで、振替の手順は不要です。ボーナス、クロスプロダクトでのプレイ、リアルタイムの残高表示に適しています。 | プレイ前に入金し、プレイ後に出金します。わずかな遅延が生じ、プレイヤーがセッション途中で離脱すると残高が残るおそれがあります。 |
| 主な適合先 | 独自のウォレットやプラットフォームを持ち、資金とプロモーションを厳格に管理したいオペレーター。 | 早期のローンチを望む、またはリアルタイムのウォレットサービスを持たないオペレーター。 |
シングルウォレット(シームレス)
シングルウォレット(シームレス)モデルでは、オペレーターのシステムがそのままウォレットになります。プレイヤーがベットすると、SSG APIがオペレーターのコールバックエンドポイントを呼び出し、オペレーターは自社の元帳で残高を更新して、新しい残高を返します。資金がオペレーターのデータベースから出ることはありません。
呼び出しフロー
- 起動:オペレーターのバックエンドが、プレイヤーIDとセッショントークンを添えてSSGにゲームURLを要求します。
- ベット:ラウンドごとに、SSGが一意のtxIdを付けてdebitを呼び出します。オペレーターは残高を確認し、元帳に記録して、新しい残高を返します。
- 配当:同じラウンドについて、SSGが配当額(0の場合もあります)を付けてcreditを呼び出します。
- 障害:呼び出しがタイムアウトすると、SSGは同じtxIdで再試行し、再試行の上限を超えるとrollbackを送信します。
コールバックメソッド(例)
| メソッド | 目的 | 主要フィールド | べき等 |
|---|---|---|---|
balance | プレイヤーの現在の残高を返します。 | playerId, currency | はい(読み取り専用) |
debit | ベットの実行:金額を差し引きます。 | playerId, txId, roundId, gameId, amount, currency | txIdごと |
credit | 配当の精算:金額を加算します。 | playerId, txId, roundId, amount, currency | txIdごと |
rollback | エラー発生後に、以前のdebitまたはcreditを取り消します。 | txId, refTxId | txIdごと |
debitリクエストの例
{
"method": "debit",
"playerId": "p_839201",
"txId": "tx_20261007_000184",
"roundId": "r_77f3a1",
"gameId": "slots_fruit_01",
"currency": "MYR",
"amount": "2.50",
"ts": 1791338577,
"sign": "hex(HMAC-SHA256(secret, canonical))"
}レスポンスの例
{
"status": "OK",
"txId": "tx_20261007_000184",
"balance": "97.50",
"currency": "MYR"
}
// errors: INSUFFICIENT_FUNDS, PLAYER_NOT_FOUND,
// DUPLICATE_TX (return original result), INTERNAL_ERRORウォレットサービスが守るべきルール
- べき等性
- 同じtxIdのdebitまたはcreditが再度届いた場合は、元の結果を返し、資金を再度動かしてはいけません。txIdに一意インデックスを設定して担保してください。
- 元帳のアトミックな書き込み
- 残高の確認、元帳行の挿入、残高の更新を1つのデータベーストランザクションで行い、同時ベットによる残高超過を防ぎます。
- debitより先に届くrollback
- 元のdebitがタイムアウトした場合、未受信のtxIdに対するrollbackが届くことがあります。トゥームストーンを保存し、後から届く同じtxIdのdebitを拒否してください。
- レイテンシ目標
- ネットワーク遅延を含め、p99 を 500 ms 未満に抑えることを目標にしてください。コールバック経路はインデックス付き読み取り 1 回と書き込み 1 回に留め、レポート用クエリはこの経路に含めないでください。
- 金額の形式
- 金額は十進文字列または整数の最小通貨単位で扱ってください。浮動小数点数は使用せず、通貨がプレイヤーアカウントと一致しているか検証してください。
- ボーナスとフリースピン
- フリースピンは、金額 0 の debit の後に当選金の credit が続く形になります。台帳ではプロモーション残高と現金残高を分けて管理してください。
- セキュリティ
- 正規化したリクエストに対する HMAC-SHA256 署名を検証し、古いタイムスタンプは拒否してください。また、SSG の送信元 IP のみを許可し、TLS 1.2 以上を必須としてください。
- 照合
- SSG の日次ラウンドレポートと自社の台帳を roundId で突き合わせてください。差異は、コールバックの取りこぼしやロールバックが原因です。
トランスファーウォレット
トランスファーウォレット方式では、プロバイダーがプレイヤーごとにゲーム残高を保持します。オペレーターのバックエンドがプレイ前に資金を移し入れ、プレイ後に移し出します。プレイ中はオペレーターのシステムへのコールバックがないため、必要なのはアウトバウンドの REST 呼び出しだけです。
呼び出しフロー
- 入金:バックエンドが一意の txId と金額を指定して transferIn を呼び出します。結果は PENDING または SUCCESS です。
- プレイ:ゲームを起動します。すべてのベットと当選はプロバイダー側の残高のみを変更し、オペレーターへのコールバックはありません。
- 出金:プレイヤーが離脱したら全残高について transferOut を呼び出し、SUCCESS になった時点で自社の台帳に戻し入れます。
- 結果不明:移動の呼び出しがタイムアウトした場合は、他の処理を行う前に同じ txId で getTransferStatus を照会してください。
API メソッド(例)
| メソッド | 目的 | 主要フィールド | べき等 |
|---|---|---|---|
transferIn | オペレーターのウォレットからプレイヤーのゲーム残高へ資金を移します。 | playerId, txId, amount, currency | txIdごと |
transferOut | ゲーム残高からオペレーターのウォレットへ資金を戻します。 | playerId, txId, amount | all | txIdごと |
getBalance | プレイヤーのゲーム残高を取得します。 | playerId | はい(読み取り専用) |
getTransferStatus | txId に対して PENDING、SUCCESS、FAILED のいずれかを返します。 | txId | はい(読み取り専用) |
バックエンドが守るべきルール
- 1 つの取引意図に 1 つの txId
- 最初の呼び出しの前に txId を生成し、すべてのリトライで再利用してください。前回の取引の状態が分かるまでは、新しい txId を作成しないでください。
- まず自社台帳から引き落とす
- 入金では、SSG を呼び出す前に自社の台帳で金額を確保し、状態が確定した時点で確定または解放してください。
- 取り残された残高の回収
- ゲーム残高があるのにアクティブなセッションがないプレイヤーを検出し、出金処理を行うジョブを実行してください。セッション途中でブラウザを閉じたプレイヤーに対応できます。
- ベット要件とレポート
- ベットをリアルタイムで確認できないため、売上高、ボーナスの賭け条件、リスク上限は、コールバックではなく SSG から取得したラウンドレポートに基づいて算出してください。
- 照合
- すべての入金・出金を txId で SSG の記録と突き合わせ、タイムアウトを過ぎても PENDING のままの取引にはアラートを出してください。
- セキュリティ
- リクエストには HMAC-SHA256 で署名し、TLS 1.2 以上でのみ呼び出してください。API キーはシークレットストアに保管し、SSG を呼び出せるサーバーを制限してください。
障害シナリオ
| シナリオ | シングルウォレット | トランスファーウォレット |
|---|---|---|
| ネットワークタイムアウト | ベット中は、SSG が同じ txId でリトライし、上限に達すると rollback を送信します。オペレーター側はべき等性を確保する必要があります。 | 影響を受けるのは資金移動のみです。同じ txId で getTransferStatus を照会してから対処してください。 |
| オペレーターのシステム停止 | プレイヤーはラウンドを開始も継続もできません。進行中のラウンドはロールバックされます。 | プレイヤーは既存のゲーム残高でプレイを続けられます。新たな資金移動はブロックされます。 |
| 重複リクエスト | その txId に保存済みのレスポンスを返し、何も変更しません。 | その txId に保存済みの結果を返し、何も変更しません。 |
| ラウンド中にプレイヤーが切断 | ラウンドはプロバイダー側で正常に終了し、credit も通常どおり送信されます。 | ラウンドは終了し、資金は出金または回収ジョブが実行されるまでゲーム残高に残ります。 |
| 残高の不一致 | 多くはコールバックの取りこぼしやロールバックが原因です。roundId でラウンドレポートを照合すると見つかります。 | 多くは取り残された、または保留中の資金移動が原因です。txId で資金移動を照合すると見つかります。 |
どちらを選ぶべきか
シングルウォレットが適しているケース
- すでにリアルタイムのウォレットまたは台帳サービスを運用している。
- スポーツブック、カジノ、プロモーションで 1 つの残高を共通化したい。
- リスク管理、ボーナスの賭け条件、責任あるギャンブルの上限設定のために、リアルタイムのベットデータが必要。
- チームが、高可用性かつ低レイテンシのサービスを運用できる。
トランスファーウォレットが適しているケース
- 最小限の開発工数で素早くローンチしたい。
- リアルタイムのウォレットサービスがまだない。
- 公開コールバックを保護する必要のない、アウトバウンド呼び出しのみの構成を希望する。
- 残高が一時的に取り残されても許容でき、回収ジョブを運用できる。
多くのオペレーターは、まずトランスファーウォレットでローンチし、自社のウォレットサービスが整った段階でシングルウォレットへ移行しています。段階的な切り替え方法については、お問い合わせください。
連携チェックリスト
- 資金が動くすべての呼び出しに txId の一意インデックスとべき等なハンドラーを実装
- HMAC 署名の検証、タイムスタンプの許容範囲、IP 許可リスト
- 小数誤差の出ない金額処理と通貨の検証
- サンドボックスでのタイムアウト、リトライ、ロールバックのテスト(遅延リトライを含む)
- roundId(シングル)または txId(トランスファー)による日次照合ジョブ
- 監視とアラート:コールバックの遅延、エラー率、保留中の資金移動、取り残された残高
連携エンジニアに相談する
サンドボックスをエンジニアの方と一緒に確認し、御社のプラットフォームに合った方式の選定をお手伝いします。連携は 7 日以内の完了を保証します。
メールで問い合わせる Telegram で相談する プロダクト API に戻る
sales@ssggaming.com