バランスと財布:マルチウォレットアーキテクチャ
1)マルチウォレットの理由と目標
1つの「balance=number」エントリは、iGamingの現実をカバーしていません。リアルマネー(現金)、ボーナスファンド、賭けプール、フリースピン、コンピュータポイント、時々通貨ウォレット(EUR/USD/BRL)。
アーキテクチャの目的は次のとおりです:- お金の正確さ(二重記入項目、auditability)。
- 書き込みポリシー(例えば、最初のボーナス/ベーガー、次に現金)。
- 速度(p95 API ≤ 250-400ミリ秒、リアルタイムでのベット/決済)。
- 安全性とコンプライアンス(KYC/AML、責任あるプレイ制限、レギュレータ)。
- スケール:ピーク→数万の操作/秒、数十億の投稿/月。
2)データモデル: 「元帳+サブウォレット」
最小限のエンティティ
アカウント:プレーヤー/ブランド/市場。
表の例(簡略化)
SQL
--二重参入のための貸借対照表の記述(ビジネスを含む)
アカウント(ID、 owner_user_id、種類、通貨、ステータス、……)
--投稿(二重エントリ、ビジネス取引への参照)
 (ID、 、 、 、通貨、カテゴリー、 、 )
--保有(準備金)
ホールド(ID、 account_id、 amount_minor、通貨、理由、expires_at、状態、operation_id、 created_at)
--ライトオフポリシー(優先順位)
spend_policies (id、 market、 wallet_priority jsonb、 updated_at)
--クロス為替レートfx_rates (ccy_from、 ccy_to、レート、精度、valid_from)ルール:真実はトランザクションジャーナル('ledger_entries')にあります。現在のバランスは、集計(実体化されたスナップショット)またはジャーナルから計算されます(高価ですが、trueのみ)。
3)財布の種類とその動作
4)書き込みポリシーと優先順位
資金源のアルゴリズムを明確に形式化する: 例(スロット/カジノ):1.まず、(賭けが有効な場合)WAGERから書き込みます。
2.その後、ボーナスから疲れるまで。
3.残りはCASHのものです。
例(スポーツ):1.最初の現金(レギュレーター/税)。
2.その後、ボーナス(フリーベット)、WAGERに翻訳。
「policy decision」をPostingsに属性として保存して、サポートと監査が「なぜ彼らがそれを書いたのか」を確認するようにします。
5)お金と業務のライフサイクル
デポジット(入金)
1.'POST/wallet/deposit'→保留中のエントリ(PSPソーセージの受信トレイ)を作成します。
2.Webhook PSP (HMAC署名、'operation_id'によるidempotency)→credit CASH、 category='DEPOSIT'。
3.wallet_updatedイベントを公開します。
レート(Rate)
1.'POST/bet/place'→ソースアカウント(CASH/BONUS/WAGER)にホールド(予約)を作成します。
2.レートを確認すると、ホールド→デビットソースの転送、プロバイダのサービス「決済」アカウントのクレジットが→。
3.キャンセル時-リリースホールド。
決済(結果)
ゲイン:プロバイダーの「決済」口座のデビット→クレジットキャッシュまたはポリシーWAGER→ボーナス→現金。
損失:プロバイダの「費用」をトランザクション→プレイヤーへのクレジットなしで閉じます。
1.KYC/AMLチェック、責任あるプレイ制限。
2.引き出し金額を保持します。
3.PSP→最終口座CASH→クレジットアカウント「支払い」の成功。
4.PSP→リリースホールドに失敗しました。
6) Idempotenceと正確に一度「意味内」
どこでも'operation_id' (UUID/enhanced ULID)と一意のインデックスを持つ。再リクエスト→過去の取引のステータス。
PSP/ゲームプロバイダのwebhooks: 'event_id+signature'で重複排除された受信トレイブルテーブル。処理-idempotent worker (Outboxパターン)。
クライアントのHTTP上のIdempotency-Key;ストアTTL ≥ 24-72時間。
7)予約および保有
ホールドは書き込みオフではなく、利用可能なバランスの「フリーズ」です。
ルール:- ホールド寿命:秒→分(レート)または時間(出力)。
- ホールドは部分的または完全に消滅することができます(部分的な解決)。
- 期限切れの場合-自動リリースとイベント。
- 'hold_id' ↔ 'bet_id/withaw_id'の関係を保持します。
8)通貨、FX、丸め
金額-マイナーユニット(セント)、タイプ-整数。
円形になる銀行(への円形の半分)またはT&C。
FX: 'CASH (EUR)' ↔ 'CASH (USD)'財布を分割することをお勧めします。別の操作として変換:- "デビットEUR、クレジットFX_EURUSD'および"デビットFX_EURUSD、クレジットUSD"-監査に透明。
- 紛争で自動的にコースに「到達」することは禁止されています。すべてのルールはFXポリシーにあります。
9)責任あるプレーと制限
デポジット/ベット/ロス/セッション制限(曜日/週/月)、クーリングオフ、自己除外。
ホールド/デビット前の事前チェックとして実装。
故障ログ-別の監査ログで、サポートとレギュレータが使用できます。
10)財布の周りの詐欺防止信号
デバイスクラスター/ASN、頻繁な小さな預金→大きな引き出し、洗濯パターン。
BIN/country/deviceによる'deposit/within'の速度制限。
受信者のブロックリスト(ウォレット/IBAN)、 「mules」のリスト。
ウォレットイベント→スコアリング機能ストア(ログイン/デポジット/レート)。
11)一貫性とパフォーマンス
真のキャッシュとキャッシュ
真実は台帳にあります。「get balance」 APIでは、実体化されたスナップショット('user_id+wallet_type→balance_minor、 version')を保持します。
書き込み:データベース内のトランザクション→キャッシュを無効にします。
「重い」フロー(ライブ)では、引き出し/大きな賭けが適切である前に、ショートTTL 1-5 s+必須の真実チェック。
スケーリング(Scalding)
sharding by 'user_id' (module/ranking)、 CASHとBONUSの別々のシャードプール。
ホットキー(VIP/bots)-'user_id'による結合要求。
非同期集計(バックグラウンドで「投稿」→「スナップショット更新」を作成します)。
12) API契約(擬似)
バランスをとる
http: http
GET/v1/wallets?タイプ=現金、ボーナス
→200{「ウォレット」:[
{「type「:「CASH「、「currency「:「EUR「、「available」: 12050」、 hold」: 500」、 version」: 1942}、 {「type「:「BONUS「、「currency「:「EUR「、「available」: 3000」、 wager_req」: 15000}}
]}ベット(ホールド付き)
http: http
POST/v1/ベット/場所
{"bet_id": "b_123"、 "amount': 500、" currency":"EUR"、"source_policy":"casino_default'、 "idempotency_key":"ik_abc"}
→201 {「status「:「HOLD「、「hold_id「:」h_789」、」 expires_in」: 30}決済について
http: http
POST/v1/bets/settle
{"bet_id": "b_123"、 "result':" WIN"、"payout":1250}
→200{「ステータス「:「決済「、」現金_デルタ」:+1250}http: http
POST/v1/出金
{"withdraw_id": "w_456"、 "amount': 10000、" currency":"EUR"、"method': "sepa"、 "idempotency_key":"ik_def"}
→202 {「state「:「PENDING「、「next_check_sec「:2、 「status_url」: 」/v1/出金/w_456」}13)投稿例(ダブルエントリー)
デポジット€100 (PSP手数料€1、コミス。アカウント-別途)
デビット:PSP_Settlements (EUR) 10000
クレジット:ユーザー。現金(EUR) 10000
デビット:ユーザー。現金(EUR) 100(手数料シフト)
クレジット:PSP_Fees (EUR) 100ベット€5からボーナス(WAGERに転送)
デビット:ユーザー。ボーナス(EUR) 500
クレジット:ユーザー。WAGER (EUR) 500(賭けに移動)
デビット:ユーザー。WAGER (EUR) 500
クレジット:プロバイダー。決済(EUR) 500(税抜)€12を獲得します。5→現金で
デビット:プロバイダー。決済(EUR) 1250
クレジット:ユーザー。現金(EUR) 1250ホールドライオフ(HOLDサービスアカウントによる実現)
デビット:ユーザー。現金(EUR) 500
クレジット:ユーザー。HOLD (EUR) 500 (holdによって作成)
--セトルで
デビット:ユーザー。HOLD (EUR) 500
クレジット:プロバイダー。決済(EUR) 500
--キャンセルについて
デビット:ユーザー。HOLD (EUR) 500
クレジット:ユーザー。現金(EUR) 50014)監査、不変性および承諾
ログのWORM/immunity (オブジェクトストレージ/WALアーカイブ)。
アクセスメタログ:制限を読み取り/変更した人、手動で調整を行った人(「調整投稿」でのみ正当化)。
GDPR/規制当局:5〜10年間の取引の保管(管轄)、プレーヤーの決済の透明性(write-ofs/wagerの履歴)。
15)欠陥の許容およびDR
複数のAZ必須;DR-region for wallet:ゾーン内の同期レプリケーション、非同期-地域;PITRが有効になっています。
スタンバイプロモート-チェックリストによる手動のみ(スプリットブレインを除く)。
毎週のリストアチェック(テストリストア)、制御レポートの量の調整。
16)ウォレットの可視性
SLI: 'deposit_success_ratio'、 'withdraw_success_ratio'、 'bet_hold_latency_p95'、 'settlement_latency_p95'。
Тех: 'ledger_postings_rate'、 'db_connections_saturation'、 'queue_lag_seconds'、 'hold_expired_rate'。
アラート:PSPの成功は市場で低下し、'hold_expired_rate'の成長、ゲームプロバイダは同期しない(確認なし>N min)。
17)テストおよび品質管理
PSP/ゲームプロバイダ (webhook/signatures)との契約テスト。
資産ベースのマネーのテスト:各ポスティングのデビットの合計==クレジットの合計。
Fuzz/chaos: PSP/プロバイダの遅延、webhookの繰り返し、ネットワークフラップ。
ロード:バーストベット(60-120秒)、ソーク(4-8 h)、コントロール'queue_lag'とp99。
18)生産準備チェックリスト
- ダブルレジャーエントリ、'operation_id'でポスティングを介してすべての操作。
- 支出ポリシーと優先順位をクリアします(投稿に保持されます)。
- TTL/部分決済/有効期限、ベット/引き出しとの通信を保持します。
- 受信トレイ/アウトボックス、HMAC webhooks、すべての国境でのidempotency。
- 個人の現金/ボーナス/賭け/FS/ポイントウォレット;通貨単位で分割します。
- FXおよびマイナーな丸め;変換-別の操作。
- ホールド/デビットに対する責任あるプレイ制限;失敗の監査。
- Read cache(短いTTL)+required truth check before critical actions。
- PITR/backups/DRスクリプト;マニュアルプロモート、定期的なDR演習。
- ダッシュボード/アラートSLI+テクニカル;WORMログとアクセスログ。
- ロード/カオステスト;PSP/プロバイダとの和解レポート。
履歴書のサマリー
マルチウォレットアーキテクチャは「多くのバランス番号」ではなく、二重エントリー、支出ポリシー、予約、監査とプレーヤーのための透明なトレイルを備えた金融システムです。ログに真実を保ち、ホールドとidempotenceを使用し、別の財布と通貨を使用し、和解とDRRを自動化します。このようにして、財布はUXの高速化、お金の正確性、ピーク負荷や規制のチェックに耐性があります。
