1.优化接口/api/game/lobbyInit,新增赔率参数
This commit is contained in:
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\common\library\game\BetChips;
|
||||
use app\common\library\game\StreakWinReward;
|
||||
use app\common\library\game\ZiHuaDictionary;
|
||||
use app\common\model\BetOrder;
|
||||
use app\common\model\GameRecord;
|
||||
@@ -67,6 +68,7 @@ class Game extends MobileBase
|
||||
BetChips::lobbyChipsPayload()
|
||||
),
|
||||
'dictionary' => $items,
|
||||
'streak_win_reward' => StreakWinReward::lobbyPayload(),
|
||||
'user_snapshot' => [
|
||||
'coin' => $user->coin,
|
||||
'current_streak' => $user->current_streak ?? 0,
|
||||
|
||||
@@ -106,6 +106,25 @@ final class StreakWinReward
|
||||
return self::$cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* lobbyInit 用:连胜赔率档位(与后台「连胜奖励」、派彩公式一致)。
|
||||
*
|
||||
* @return array{rows: list<array{streak: int, odds_factor: int, is_jackpot: bool}>}
|
||||
*/
|
||||
public static function lobbyPayload(): array
|
||||
{
|
||||
$rows = [];
|
||||
foreach (self::loadRows() as $row) {
|
||||
$rows[] = [
|
||||
'streak' => (int) ($row['streak'] ?? 0),
|
||||
'odds_factor' => (int) ($row['odds_factor'] ?? 0),
|
||||
'is_jackpot' => ($row['is_jackpot'] ?? false) === true,
|
||||
];
|
||||
}
|
||||
|
||||
return ['rows' => $rows];
|
||||
}
|
||||
|
||||
/**
|
||||
* streak_at_bet 为下注时快照(0 表示尚未连胜);档位取 min(streak_at_bet+1, 10)。
|
||||
*/
|
||||
|
||||
@@ -235,6 +235,11 @@
|
||||
- `default_bet_chip_id`:int(含义:默认选中的筹码标识,来自 `game_config.default_bet_chip_id`,非法或指向无效档位时服务端回退为首个有效档)
|
||||
- `min_bet_per_number`:string(含义:单号码最小下注额,须 ≤ 所选筹码面额且受后台配置约束)
|
||||
- `max_bet_per_number`:string(含义:单号码最大下注额)
|
||||
- `streak_win_reward`:object(含义:连胜赔率配置,来自 `game_config.streak_win_reward`,与后台「连胜奖励」一致)
|
||||
- `rows`:array<object>(固定 1~10 档,按 `streak` 升序)
|
||||
- `streak`:int(连胜档位 1~10;下注时 `streak_at_bet=0` 适用档位 1,`streak_at_bet=n` 适用档位 `min(n+1, 10)`)
|
||||
- `odds_factor`:int(赔率乘数;中奖派彩 = 本笔 `total_amount` × `odds_factor`)
|
||||
- `is_jackpot`:bool(是否大奖档,触发 `jackpot.hit` 等流程)
|
||||
- `dictionary`:array<object>
|
||||
- `number`:int(1-36,含义:字花编号)
|
||||
- `name`:string(含义:字花名称)
|
||||
@@ -713,24 +718,38 @@
|
||||
|
||||
> 本版本已移除 webman/push 频道模式;H5 前端使用原生 WebSocket 直连,HTTP 轮询仅作为弱网兜底。
|
||||
|
||||
### 7.0 部署与连接前置条件(当前实现)
|
||||
|
||||
以下与代码 `app/process/GameWebSocketServer.php`、`config/process.php`、`app/common/library/admin/WebSocketConfigHelper.php` 一致,**文档此前未写明的条件**在此补齐:
|
||||
|
||||
- **独立进程**:需在运行环境中启动 Webman 自定义进程 **`gameWebSocketServer`**(见 `config/process.php`),默认监听 **`H5_WEBSOCKET_LISTEN`**(缺省为 `websocket://0.0.0.0:3131`)。未启动进程则客户端无法建连或立刻断线。
|
||||
- **连接 URL**:优先使用环境变量 **`H5_WEBSOCKET_URL`**(完整 `ws://` / `wss://` 地址,建议带路径,如 `.env-example` 所示)。未配置时,后台 **`GET /admin/test.GameCurrentStatus/wsConfig`**(及游戏实时页同类接口)会通过 `WebSocketConfigHelper` 按当前请求的 `Host` / `X-Forwarded-*` 推导 `ws(s)://{host}/ws/`,本地兜底 **`ws://127.0.0.1:3131/ws/`**。
|
||||
- **移动端配置缺口**:**`POST /api/game/lobbyInit` 当前不下发 WebSocket 地址**;H5 需与运维约定同一套 `H5_WEBSOCKET_URL`(打包进前端配置、远程配置中心等),与 HTTP API 基址可不同域。
|
||||
- **混合内容**:若 H5 页面为 **HTTPS**,浏览器要求 WebSocket 使用 **`wss://`**,否则会被拦截。
|
||||
- **事件投递依赖 Redis**:HTTP 侧业务通过 **`GameWebSocketEventBus`**(Redis 列表)将事件投递到 WebSocket 进程;Redis 不可用或队列异常时,**除 `admin.live.snapshot` 外**的广播类推送可能收不到。后台若订阅了 `admin.live.snapshot`,服务端有**每秒直连构建快照**的兜底,不依赖队列。
|
||||
- **鉴权(重要)**:**当前 `GameWebSocketServer` 在握手阶段不校验** URL Query 中的 `token` / `auth_token` / `user-token` 等;**任何人拿到地址即可建立连接**(与 §1 HTTP 接口必须 `auth-token` + `user-token` 不同)。Query 中上述参数为**预留/习惯写法**,便于后续若要在 `onWebSocketConnect` 中实现鉴权再与 HTTP 对齐;**文档中若写「未登录返回 1101」属规划口径,非现网行为**。
|
||||
- **订阅才有业务推送**:建连后仅会收到握手首帧(见下)及本连接已订阅主题的消息;不发送 `subscribe` 则收不到 `period.tick` 等(`admin.live.snapshot` 同上,需显式订阅)。
|
||||
|
||||
### 7.1 WebSocket 连接与消息
|
||||
|
||||
- **连接地址**:由服务端配置下发(后台测试页读取 `H5_WEBSOCKET_URL`)
|
||||
- **连接地址**:见 **§7.0**(环境变量 `H5_WEBSOCKET_URL` 或后台 `wsConfig` 返回的 `ws_url`)
|
||||
- **客户端**:浏览器原生 `WebSocket`(`ws://` / `wss://`)
|
||||
- **连接时携带参数(建议)**:
|
||||
- URL Query:`token`(用户登录态 user-token)、`auth_token`(接口鉴权)、`device_id`(设备标识)、`lang`(`zh/en`)
|
||||
- 示例:`wss://ws.example.com/ws?token=xxx&auth_token=xxx&device_id=ios_001&lang=zh`
|
||||
- **连接成功返回(服务端首帧建议)**:
|
||||
- **连接时携带参数(可选 / 预留)**:
|
||||
- URL Query 可带 `token`(与 HTTP 头 `user-token` 同义习惯)、`auth_token`(与 HTTP 头 `auth-token` 同义习惯)、`device_id`、`lang` 等,**当前服务端不解析、不校验**;若后续版本实现握手鉴权,以发布说明为准。
|
||||
- 示例(习惯写法):`wss://ws.example.com/ws?token=xxx&auth_token=xxx&device_id=ios_001&lang=zh`
|
||||
- **连接成功首帧(当前实现)**:
|
||||
- `event`:`ws.connected`
|
||||
- `connection_id`:连接唯一标识
|
||||
- `server_time`:服务器时间戳(秒)
|
||||
- `heartbeat_interval`:心跳间隔(秒)
|
||||
- **连接失败返回(建议)**:
|
||||
- `event`:`ws.error`
|
||||
- `code`:错误码(如 `1101` 未登录、`1103` 鉴权失败)
|
||||
- `message`:错误描述
|
||||
- `message`:固定文案 `WebSocket connected`(便于联调日志)
|
||||
- `connection_id`:连接唯一标识(进程内)
|
||||
- `server_time`:服务器时间戳(**秒**,int)
|
||||
- `heartbeat_interval`:建议心跳间隔(**秒**,当前实现固定为 `30`)
|
||||
- **连接后错误帧(当前实现,非 HTTP 业务码)**:
|
||||
- JSON 无法解析:`event`=`ws.error`,`message`=`Invalid JSON payload`(无 `code` 或与 HTTP `code` 不同体系)
|
||||
- 未知 `action`:`event`=`ws.error`,`message`=`Unsupported action`,并可能带 `received_action`
|
||||
- 进程级异常:`onError` 回包含 `event`=`ws.error`、`message`=`Server internal error` 及 Workerman 侧 `code`/`detail`(**非** §1.2 的 HTTP API `code` 段)
|
||||
- **建议消息**:
|
||||
- 心跳:`{"action":"ping"}`
|
||||
- 服务端对心跳的当前实现回包:`{"event":"pong","server_time":"YYYY-mm-dd HH:ii:ss"}`(**注意**:此处 `server_time` 为**本地时间字符串**,与业务推送帧里 `server_time` 常用**秒级 int** 不一致,客户端解析时请分支处理)
|
||||
- 订阅状态流:`{"action":"subscribe","topics":["period.tick","period.opened"]}`
|
||||
- 订阅资金流:`{"action":"subscribe","topics":["bet.accepted","wallet.changed"]}`
|
||||
- 订阅托管流:`{"action":"subscribe","topics":["auto.spin.progress","wallet.changed"]}`
|
||||
@@ -790,7 +809,7 @@
|
||||
1. `GET /api/v1/authToken?secret=xxx×tamp=xxx&device_id=xxx&signature=xxx` 获取 `auth-token`
|
||||
2. `POST /api/user/login` 登录(请求头带 `auth-token`)
|
||||
3. `POST /api/game/lobbyInit` 拉首页初始化(请求头带 `auth-token`)
|
||||
4. 建立 WebSocket(H5)连接,发送订阅消息监听状态流
|
||||
4. 取得 WebSocket 基址(**当前非 lobbyInit 下发**:与运维/打包配置中的 `H5_WEBSOCKET_URL` 或自建配置接口一致)后建立 WebSocket 连接,**立即发送 `subscribe`** 监听状态流(见 §7.0 / §7.1)
|
||||
5. 用户下注调用 `POST /api/game/placeBet`
|
||||
6. 下单后以 `placeBet.balance_after` 与 `wallet.changed` 同步余额
|
||||
7. 断线或页面回前台时,重连 WebSocket 并重新订阅主题回补实时状态
|
||||
|
||||
Reference in New Issue
Block a user