💡 一句話
玩家在大廳點一張卡,背後自動完成「建帳號 → 把餘額轉進那款遊戲 → 取一次性進場券 → 開遊戲」; 按返回時再自動把餘額全部轉回來。整個過程玩家不需要知道有幾個系統。
💬 這是一個 DEMO 站:不接金流、不接超商。玩家餘額的加減一律由後台人工操作, 而且每一筆都會寫進稽核紀錄。
🗺️ 三層圖
┌──────────────────────────────┐
玩家瀏覽器 ─────────▶ │ wolves_game_town │ 商戶門面(這個網站)
│ 玩家帳號 · 主錢包 · 遊戲牆 │ 對外開放
│ iframe · 商戶後台 │
└───────────┬──────────────────┘
│ MIS x-merchant-key(後端對後端)
▼
┌──────────────────────────────┐
│ wolves_game_hub │ 聚合層
│ 商戶 · 帳號命名空間 · 幣別 │ 🔒 不對外
│ 轉帳流水 · 對帳 · 遊戲目錄 │
└───────────┬──────────────────┘
│ GIS x-api-key(只有 hub 持有)
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
wolves_fortune_lotto SLOT 平台 魚機 / 百人 / 棋牌…
(彩票,已接) (規劃中) (規劃中)
▲
└──── iframe + 玩家的下注、開獎都直接連遊戲,不經過上面兩層
⚠️ 最容易誤會的一點:玩家在遊戲裡的下注與即時連線是 瀏覽器直接連遊戲平台的,完全不經過 town 與 hub。 那兩層一場遊戲只被呼叫三、四次(進場、轉帳、離場)。
📋 誰負責什麼
| 商戶門面 town | 聚合層 hub | 遊戲平台 game | |
|---|---|---|---|
| 玩家帳號 | ✅ 真正的玩家身分 | 帳號對映(加商戶前綴) | 平台側帳號(名字由 hub 給) |
| 錢包 | ✅ 主錢包,唯一真相 | ✗ 不持有餘額,只記流水 | 遊戲側錢包(轉進去才有錢) |
| 賠付 / RTP | ✗ | ✗ | ✅ 全歸遊戲 |
| 幣別換算 | 用商戶幣別 | ✅ 換算在這一層 | 只認得遊戲幣 |
| 遊戲目錄 | 快取 + 自己排序 | ✅ 唯一來源 | — |
| 注單明細 | 轉發顯示 | ✗ 不落地,現拉 | ✅ 只存在遊戲 |
| 對帳 | 自己的帳本 | ✅ 中立的第三方紀錄 | 自己的帳本 |
| 客服加減幣 | ✅ 在商戶後台 | ✗ | ✗ |
🎬 一次進場的全程
玩家點一張遊戲卡
│
│ town → hub → game
├─ ① 建帳號(冪等,已經有就用既有的)
├─ ② 把玩家主錢包的餘額全額轉入那款遊戲所屬的平台
├─ ③ 取一次性進場券(5 分鐘、用一次即失效)
└─▶ 在站內 iframe 打開遊戲,玩家開始玩
│
│ ← 這段時間 town 與 hub 完全沒有參與
│
玩家按「返回大廳」
├─ ④ 查玩家在那個平台還剩多少
├─ ⑤ 全額轉回主錢包
└─▶ 回到大廳,餘額同步
玩家直接關掉瀏覽器怎麼辦?
錢會暫時留在遊戲那邊。後端有一個回收工作會定期把「太久沒動靜」的場次撈出來, 把餘額收回主錢包 —— 所以玩家的錢不會不見,下次登入就看得到。
🔴 一個玩家同時只能在一款遊戲裡。要換遊戲會先把上一款的餘額收回來 —— 否則自動轉帳會互相打架,錢被分散在好幾個平台。
🧩 為什麼要有中間這層
只有一個商戶、一款遊戲的時候,hub 看起來像多餘的一層。它存在有三個具體理由:
| # | 理由 | 沒有它會怎樣 |
|---|---|---|
| 1 | 帳號命名空間隔離 | 🔴 遊戲側的帳號名是全平台唯一的。兩個商戶各有一個 test001 就撞號 ——
而且要補救得去每一款遊戲的資料庫改帳號名。這是唯一一個「晚做會非常痛」的點,所以一開始就做。 |
| 2 | API 金鑰託管 | 沒有 hub 就得把每一款遊戲的金鑰發給每一個商戶:無法單獨撤銷、無法限額, 一個商戶外洩就全部遊戲受害。 |
| 3 | 中立的對帳 | 進出金額記在商戶自己那邊,等於「自己報自己的帳」。放在中間層才有第三方紀錄。 |
順帶的好處
- 吸收各平台的差異:每個自研平台的 API 長得不一樣(有的走 POST + JSON、有的走 GET + 簽章), 差異全部關在 hub 的轉接器裡,商戶只看到一組介面。
- 商戶不用懂遊戲:接一組 API 就有全部遊戲;之後平台加新遊戲,商戶零改動。
- 新增一個商戶=在 hub 開一組憑證,遊戲那邊完全不用動。
💱 幣別怎麼換(不是匯率)
設計目標很明確:讓幣別對遊戲的影響是零。遊戲那邊永遠只看到一種東西(遊戲幣), 不需要幣別欄位、不需要為了不同幣別多開機器或多套資料庫。換算全部發生在 hub。
| 幣別 | 換算 | 最小帶入單位 |
|---|---|---|
| USD / EUR / AUD | 1 元 = 1000 遊戲幣 | 0.01 |
| CNY / PHP / HKD / MYR | 1 元 = 100 遊戲幣 | 0.1 |
| TWD / THB / JPY / INR | 1 元 = 10 遊戲幣 | 1 |
| KRW / MMK | 1 元 = 1 遊戲幣 | 1 |
| IDR / VND | 10 元 = 1 遊戲幣 | 10 |
🔴 除不盡的零頭不會消失。轉回來時無條件捨去到整數, 剩下的餘額留在遊戲那邊,下次進場它還在 —— 不進位(那會憑空生錢)、也不捨去(那會吃掉玩家的錢)。
比 MMK 更小的幣別(IDR / VND)沒辦法用 1:1,所以改用「最小帶入單位」處理: 一次至少要帶 10 元進遊戲。這樣比把比例硬湊成 1 誠實得多 —— 後者會讓這些幣別憑空貴十倍。
要接一個新幣別,就是在 hub 加一列設定,不用改任何程式碼。
🧾 注單為什麼不存在 hub
分界線是「帳同構、單不同構」:
- 帳(錢的移動)跨平台長得一模一樣,只有金額與方向 → hub 存得起、也對得起帳。
- 單(注單 / 局 / 開獎明細)每款結構完全不同 —— 彩票是門與賠率、拉霸是盤面與線、魚機是砲台與魚種。hub 要存就得為每款做一套資料表, 等於把遊戲邏輯搬進中間層。
所以細單一律用單號回遊戲現拉,不在中間層留副本 —— 遊戲那邊本來就有自己的稽核機制,再存一份只會製造「兩份可能不一致的真相」。
🔐 關於錢的三條紅線
- 帳本只增不改:每一筆加減都留一列,永不修改、永不刪除。 隨時可以驗「餘額 = 帳本總和」。
- 重送不會重複記帳:每筆轉帳有唯一流水號,網路超時重送同一筆, 結果只會記一次。
- 🔴 結果未知時不猜:呼叫遊戲逾時而不知道成功與否, 系統會把它標成「待查明」而不是自動回沖,交由對帳查明。 寧可卡住一筆,也不要猜錯方向。
📈 容量與部署
因為玩家的遊戲流量不經過前兩層,會被人數壓垮的永遠是遊戲平台本身。 商戶門面與聚合層都很輕,可以跟其中一台遊戲共處。
| 元件 | 對外 | 說明 |
|---|---|---|
| 商戶門面 town | 是 | 玩家入口,需要網域與 HTTPS |
| 聚合層 hub | 否 | 🔒 只綁本機。所有遊戲的金鑰都在它身上,不對外就少一整個攻擊面 |
| 遊戲平台 | 是 | 玩家的 iframe 直接連它,各自獨立擴充 |
⚠️ 關閉服務的順序:門面 → 聚合層 → 遊戲(跟啟動相反)。 先關中間層的話,正在進行的轉帳會變成「結果未知」,得走對帳處理。