# H5 自研猜拳接入接口

本文只记录独立自研猜拳 `rock/rps` 的 H5 接口。所有地址都有 `/api/v1` 前缀，所有接口都需要 `Authorization: Bearer <access_token>`。

成功响应统一格式：

```json
{
  "code": "OK",
  "message": "ok",
  "request_id": "req_xxx",
  "data": {}
}
```

时间字段都是 Unix epoch milliseconds。用户 ID 建议 H5 按字符串字段使用。

## 1. 获取游戏列表

地址：

```http
GET /api/v1/games
```

参数：

| 字段 | 位置 | 必填 | 说明 |
| --- | --- | --- | --- |
| `scene` | query | 否 | 场景，语音房传 `voice_room`。 |
| `room_id` | query | 否 | 房间 ID。 |

返回值：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `games` | array | 游戏列表。 |
| `games[].game_id` | string | 猜拳是 `rock`。 |
| `games[].name` | string | 游戏名称。 |
| `games[].launch_mode` | string | H5 打开方式。 |
| `games[].enabled` | bool | 是否可进入。 |
| `games[].maintenance` | bool | 是否维护中。 |
| `server_time_ms` | number | 服务端时间。 |

相关 IM：无。

## 2. 创建 H5 启动会话

地址：

```http
POST /api/v1/games/rock/launch
Content-Type: application/json
```

参数：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `scene` | string | 否 | 场景，语音房传 `voice_room`。 |
| `room_id` | string | 否 | 房间 ID。 |

返回值：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `session_id` | string | H5 启动会话 ID。 |
| `launch_url` | string | H5 页面地址。真实地址由后台配置，不在客户端拼。 |
| `expires_at_ms` | number | 启动会话过期时间。 |
| `orientation` | string | 页面方向。 |
| `safe_height` | number | 安全高度。 |
| `safeHeight` | number | 同 `safe_height`。 |
| `server_time_ms` | number | 服务端时间。 |

相关 IM：无。

## 3. 查询猜拳配置

地址：

```http
GET /api/v1/games/rps/config
```

参数：

| 字段 | 位置 | 必填 | 说明 |
| --- | --- | --- | --- |
| `game_id` | query | 否 | 固定是 `rock`，不传也按 `rock` 处理。 |

返回值：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `config.game_id` | string | 固定返回 `rock`。 |
| `config.status` | string | `active` 才能玩。 |
| `config.stake_options` | array | 可下注金币档位。 |
| `config.fee_bps` | number | 平台抽水，万分比。 |
| `config.pool_bps` | number | 奖池入池，万分比。 |
| `config.min_players` | number | 最少人数。 |
| `config.max_players` | number | 最多人数。 |
| `config.robot_enabled` | bool | 是否启用机器人补位。 |
| `config.robot_match_wait_ms` | number | 等待机器人补位时间。 |
| `config.pool_balance_coin` | number | 当前奖池余额。 |
| `server_time_ms` | number | 服务端时间。 |

`stake_options` 字段：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `stake_coin` | number | 下注金币。 |
| `enabled` | bool | 是否可选。 |
| `sort_order` | number | 排序。 |

相关 IM：无。

## 4. 快速匹配

地址：

```http
POST /api/v1/games/rps/match
Content-Type: application/json
```

参数：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `stake_coin` | number | 是 | 下注金币，必须是配置里的启用档位。 |
| `gesture` | string | 是 | 本人提前选择的手势：`rock`、`paper`、`scissors`。 |
| `rps_gesture` | string | 否 | 同 `gesture`，两个字段传一个即可。 |
| `game_id` | string | 否 | 固定是 `rock`。 |
| `room_id` | string | 否 | 房间 ID。 |

返回值：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `match` | object | 当前局详情，字段见“局详情字段”。 |
| `server_time_ms` | number | 服务端时间。 |

相关 IM：无。H5 可以轮询详情，也可以等后续接入 IM 后按 IM 刷新。

## 5. 创建等待局

地址：

```http
POST /api/v1/games/rps/matches
Content-Type: application/json
```

参数：

| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `stake_coin` | number | 是 | 下注金币。 |
| `gesture` | string | 是 | 本人提前选择的手势。 |
| `rps_gesture` | string | 否 | 同 `gesture`。 |
| `game_id` | string | 否 | 固定是 `rock`。 |
| `room_id` | string | 否 | 房间 ID。 |
| `min_players` | number | 否 | 最少人数，不传用配置。 |
| `max_players` | number | 否 | 最多人数，不传用配置。 |

返回值：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `match` | object | 当前局详情，字段见“局详情字段”。 |
| `server_time_ms` | number | 服务端时间。 |

相关 IM：无。

## 6. 加入等待局

地址：

```http
POST /api/v1/games/rps/matches/{match_id}/join
Content-Type: application/json
```

参数：

| 字段 | 位置 | 必填 | 说明 |
| --- | --- | --- | --- |
| `match_id` | path | 是 | 局 ID。 |
| `gesture` | body | 是 | 本人提前选择的手势。 |
| `rps_gesture` | body | 否 | 同 `gesture`。 |

返回值：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `match` | object | 当前局详情，字段见“局详情字段”。 |
| `server_time_ms` | number | 服务端时间。 |

相关 IM：无。

## 7. 查询局详情

地址：

```http
GET /api/v1/games/rps/matches/{match_id}
```

参数：

| 字段 | 位置 | 必填 | 说明 |
| --- | --- | --- | --- |
| `match_id` | path | 是 | 局 ID。 |

返回值：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `match` | object | 当前局详情，字段见“局详情字段”。 |
| `server_time_ms` | number | 服务端时间。 |

相关 IM：无。

## 8. 揭晓并结算

地址：

```http
POST /api/v1/games/rps/matches/{match_id}/roll
Content-Type: application/json
```

参数：

| 字段 | 位置 | 必填 | 说明 |
| --- | --- | --- | --- |
| `match_id` | path | 是 | 局 ID。 |
| `gesture` | body | 否 | 可以不传；如果传，必须等于创建或加入时的预选手势。 |
| `rps_gesture` | body | 否 | 同 `gesture`。 |

返回值：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `match` | object | 已结算局详情。 |
| `server_time_ms` | number | 服务端时间。 |

说明：猜拳不会随机出拳。服务端用双方提前选择的 `gesture` 比输赢，然后扣款、派奖和更新余额。

相关 IM：无。

## 9. 取消等待局

地址：

```http
POST /api/v1/games/rps/matches/{match_id}/cancel
```

参数：

| 字段 | 位置 | 必填 | 说明 |
| --- | --- | --- | --- |
| `match_id` | path | 是 | 局 ID。 |

返回值：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `match` | object | 取消后的局详情。 |
| `server_time_ms` | number | 服务端时间。 |

相关 IM：无。

## 10. 局详情字段

`match` 字段：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `match_id` | string | 局 ID。 |
| `game_id` | string | 固定是 `rock`。 |
| `room_id` | string | 房间 ID。 |
| `region_id` | number | 用户区域 ID。 |
| `min_players` | number | 最少人数。 |
| `max_players` | number | 最多人数。 |
| `current_players` | number | 当前人数。 |
| `stake_coin` | number | 本局下注金币。 |
| `round_no` | number | 当前轮次。 |
| `status` | string | `created`、`ready`、`settled`、`canceled`。 |
| `phase` | string | `waiting`、`countdown`、`settled`、`canceled`。 |
| `phase_deadline_ms` | number | 当前阶段截止时间。 |
| `result` | string | 当前用户视角结果：`win`、`lose`、`draw`。 |
| `participants` | array | 参与者列表。 |
| `join_deadline_ms` | number | 等待加入截止时间。 |
| `ready_at_ms` | number | 匹配完成时间。 |
| `settled_at_ms` | number | 结算时间。 |
| `canceled_at_ms` | number | 取消时间。 |
| `fee_bps` | number | 平台抽水。 |
| `pool_bps` | number | 奖池入池。 |
| `match_mode` | string | `human` 或 `robot`。 |
| `forced_result` | string | 机器人奖池不足时的强制结果。 |
| `pool_delta_coin` | number | 本局奖池变化。 |

`participants` 字段：

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `user_id` | string | 用户 ID，H5 优先用这个字段。 |
| `user_id_number` | number | 用户 ID 数字值。 |
| `seat_no` | number | 座位号。 |
| `status` | string | `joined`、`settled`、`canceled`。 |
| `stake_coin` | number | 下注金币。 |
| `gesture` | string | 预选手势。 |
| `rps_gesture` | string | 同 `gesture`。 |
| `result` | string | `win`、`lose`、`draw`。 |
| `payout_coin` | number | 派彩金币。 |
| `balance_after` | number | 结算后余额。 |
| `joined_at_ms` | number | 加入时间。 |
| `updated_at_ms` | number | 更新时间。 |
| `participant_type` | string | `user` 或 `robot`。 |
| `is_robot` | bool | 是否机器人。 |
| `user.display_user_id` | string | 展示 ID。 |
| `user.nickname` | string | 昵称。 |
| `user.avatar` | string | 头像。 |
| `avatar_frame` | object | 头像框资源。 |

## 11. H5 推荐流程

1. App 调 `GET /api/v1/games`，看到 `game_id=rock` 后展示入口。
2. App 调 `POST /api/v1/games/rock/launch` 打开 H5。
3. H5 调 `GET /api/v1/games/rps/config` 展示下注档位。
4. 用户先选择 `rock`、`paper` 或 `scissors`。
5. H5 调 `POST /api/v1/games/rps/match` 快速匹配。
6. 返回 `phase=countdown` 后，H5 用 `phase_deadline_ms` 做倒计时。
7. 倒计时结束后，H5 调 `POST /api/v1/games/rps/matches/{match_id}/roll` 揭晓并结算。
8. H5 读返回的 `participants[].gesture/result/payout_coin/balance_after` 展示结果。

相关 IM：当前独立猜拳没有 IM。H5 用 HTTP 返回和详情轮询刷新。
