hyapp-server/docs/flutter对接/进房接口Flutter对接.md
2026-07-03 10:43:34 +08:00

283 lines
8.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 进房接口 Flutter 对接
## 接口地址
```http
POST /api/v1/rooms/join
Authorization: Bearer <access_token>
Content-Type: application/json
```
新版本进房默认使用 `response_mode=lite``full` 仍保留给旧客户端兼容,不建议新 Flutter 首屏使用。
## 参数
Body
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `room_id` | string | 是 | 房间 ID。 |
| `command_id` | string | 是 | 本次进房命令 ID。同一次点击超时重试复用同一个值下一次重新进房换新值。 |
| `role` | string | 否 | 不传默认 `audience`。房主身份由服务端按房间 owner 判断,客户端不要靠传 `owner` 获取权限。 |
| `password` | string | 否 | 密码房传房间密码,非密码房不传或传空。 |
| `response_mode` | string | 是 | 新版固定传 `lite`。可选值:`lite` / `full`。 |
请求示例:
```json
{
"room_id": "lalu_abc123",
"command_id": "cmd_join_room_lalu_abc123_10001_1778000001000",
"role": "audience",
"password": "",
"response_mode": "lite"
}
```
也支持 query 参数:
```http
POST /api/v1/rooms/join?response_mode=lite
```
Flutter 建议放在 body 里,避免调用层漏拼 query。
## 返回值
统一外壳:
```json
{
"code": "OK",
"message": "ok",
"request_id": "req_xxx",
"data": {}
}
```
成功返回示例:
```json
{
"code": "OK",
"message": "ok",
"request_id": "req_xxx",
"data": {
"result": {
"applied": true,
"room_version": 8,
"server_time_ms": 1778000001123
},
"room": {
"room_id": "lalu_abc123",
"im_group_id": "lalu_abc123",
"room_short_id": "10001",
"title": "Live Room",
"cover_url": "https://cdn.example/room.png",
"background_url": "https://cdn.example/bg.png",
"description": "welcome",
"owner_user_id": "10001",
"mode": "voice",
"status": "active",
"chat_enabled": true,
"locked": false,
"heat": 88,
"online_count": 200,
"seat_count": 10,
"occupied_seat_count": 2,
"visible_region_id": 1001,
"version": 8
},
"viewer": {
"user_id": "10001",
"role": "audience",
"joined_at_ms": 1778000001000,
"last_seen_at_ms": 1778000001100
},
"seats": [
{
"seat_no": 1,
"user_id": "10002",
"locked": false,
"publish_state": "publishing",
"mic_session_id": "mic_10002",
"publish_deadline_ms": 1778000030000,
"mic_muted": false,
"seat_status": "publishing",
"mic_heartbeat_at_ms": 1778000000000,
"gift_value": 0
},
{
"seat_no": 2,
"locked": false,
"mic_muted": false,
"gift_value": 0
}
],
"profiles": [
{
"user_id": "10001",
"username": "host",
"avatar": "https://cdn.example/avatar.png",
"display_user_id": "10001"
},
{
"user_id": "10002",
"username": "speaker",
"avatar": "https://cdn.example/avatar2.png",
"display_user_id": "10002"
}
],
"im": {
"group_id": "lalu_abc123",
"need_join_group": true
},
"rtc": {
"need_token": true,
"available": true,
"token": {
"sdk_app_id": 1400000000,
"user_id": "10001",
"rtc_user_id": "10001",
"user_sig": "xxx",
"expire_at_ms": 1778007200000,
"room_id": "lalu_abc123",
"rtc_room_id": "lalu_abc123",
"rtc_room_id_type": "string",
"str_room_id": "lalu_abc123",
"app_scene": "voice_chat_room",
"role": "user"
}
},
"server_time_ms": 1778000001123
}
}
```
字段说明:
| 字段 | 说明 |
| --- | --- |
| `data.result.applied` | 本次进房是否真正写入。重复 `command_id` 重试可能为 `false`。 |
| `data.result.room_version` | 房间版本,用于客户端状态更新判断。 |
| `data.room.room_id` | 房间 ID。 |
| `data.room.im_group_id` | 腾讯 IM 房间群 ID。当前通常等于 `room_id`,客户端仍以返回值为准。 |
| `data.room.online_count` | 房间在线人数。`lite` 不返回在线用户明细,只返回人数。 |
| `data.room.seat_count` | 麦位总数。 |
| `data.room.occupied_seat_count` | 已占用麦位数。 |
| `data.viewer` | 当前登录用户在房间内的 presence。 |
| `data.viewer.role` | 当前用户房间角色,房主会由服务端返回 `owner`。 |
| `data.seats` | 首屏麦位状态。 |
| `data.seats[].user_id` | 麦上用户 ID空麦不返回该字段。 |
| `data.seats[].publish_state` | 麦上发流状态,常见值:`pending_publish` / `publishing`。 |
| `data.seats[].mic_session_id` | 麦位发流会话 ID。麦上心跳、发流确认需要使用它。 |
| `data.seats[].seat_status` | 麦位展示状态,常见值:`empty` / `locked` / `occupied` / `publishing` / `muted`。 |
| `data.profiles` | 首屏基础资料,只包含房主、当前用户、麦上用户。 |
| `data.profiles[].username` | 昵称。 |
| `data.profiles[].avatar` | 头像。 |
| `data.profiles[].display_user_id` | 展示 ID。 |
| `data.im.group_id` | Flutter 调腾讯 IM `joinGroup` 使用的群 ID。 |
| `data.im.need_join_group` | 为 `true` 时需要加入腾讯 IM 群。 |
| `data.rtc.available` | 是否拿到 RTC 票据。 |
| `data.rtc.token` | RTC 进房票据。`available=false` 时可能为空。 |
| `data.rtc.reason` | RTC 不可用原因。业务进房成功时RTC 不可用不代表进房失败。 |
| `data.server_time_ms` | 服务端时间UTC epoch milliseconds。 |
`lite` 不返回这些内容:
| 字段 | 说明 |
| --- | --- |
| `contribution_rank` | 贡献榜不在进房首屏主包返回。 |
| `profiles[].avatar_frame` | 头像框后置拉。 |
| `profiles[].profile_card` | 资料卡后置拉。 |
| `profiles[].vehicle` | 座驾后置拉。 |
| `profiles[].mic_seat_animation` | 麦位动画后置拉。 |
| `profiles[].badges` | 等级/成就徽章后置拉。 |
| `profiles[].vip` | VIP 展示后置拉。 |
## 相关 IM
进房成功后 Flutter 执行:
```text
1. POST /api/v1/rooms/joinbody 传 response_mode=lite
2. 如果 data.im.need_join_group=true调用腾讯 IM joinGroup(data.im.group_id)
3. joinGroup 成功或已在群内,都按进房 IM 成功处理
4. 页面开始房间 heartbeat
5. 如果 data.rtc.available=true用 data.rtc.token 进入 RTC
```
说明:
| 项 | 说明 |
| --- | --- |
| IM 登录 | 进房接口不返回 IM UserSig。Flutter 仍然通过 `GET /api/v1/im/usersig` 获取并登录腾讯 IM。 |
| IM 入群 | 必须先 `JoinRoom` 成功,再调腾讯 IM `joinGroup`。不要先入 IM 群。 |
| 入房广播 | 服务端会发 `RoomUserJoined` 房间事件。Flutter 按现有房间 IM 事件逻辑展示入房飘窗。 |
| 重复进房 | 用户重新打开房间页或重连时服务端仍会给展示用入房事件Flutter 正常展示即可。 |
| 入场座驾 | `lite` 进房不携带座驾快照。座驾、头像框、资料卡、麦位动画等展示资料在进房 UI 出来后异步补齐。 |
## 后置资料接口
进房首屏出来后,再按需要异步拉展示资料:
```http
GET /api/v1/users/room-display-profiles:batch?user_ids=10001,10002
Authorization: Bearer <access_token>
```
参数:
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `user_ids` | string | 是 | 逗号分隔的用户 ID。也支持多个 `user_id=10001&user_id=10002`。 |
返回值:
```json
{
"code": "OK",
"message": "ok",
"request_id": "req_xxx",
"data": {
"profiles": [
{
"user_id": "10001",
"username": "host",
"avatar": "https://cdn.example/avatar.png",
"display_user_id": "10001",
"avatar_frame": {},
"profile_card": {},
"vehicle": {},
"mic_seat_animation": {},
"badges": [],
"vip": {},
"level": {},
"level_badges": {},
"charm": 0
}
]
}
}
```
当前用户自己的装扮也可以后置拉:
```http
GET /api/v1/appearance
GET /api/v1/users/me/appearance
```
## 常见错误
| code | HTTP | 说明 |
| --- | --- | --- |
| `INVALID_JSON` | 400 | 请求体不是合法 JSON。 |
| `INVALID_ARGUMENT` | 400 | 参数错误,例如 `response_mode` 不是 `lite``full`。 |
| `UNAUTHORIZED` | 401 | 未登录或 token 无效。 |
| `PROFILE_REQUIRED` | 403 | 用户资料未补全。 |
| `PERMISSION_DENIED` | 403 | 密码错误、被踢/被禁等权限问题。 |
| `ROOM_CLOSED` | 409 | 房间已关闭;非房主不能进入。 |
| `NOT_FOUND` | 404 | 房间不存在。 |
| `UPSTREAM_ERROR` | 502 | 上游服务异常。 |