331 lines
11 KiB
Markdown
331 lines
11 KiB
Markdown
# 幸运礼物 Flutter 对接
|
||
|
||
本文只保留 App 对接需要的信息:地址、参数、返回值、IM 字段。服务端实现细节看 [幸运礼物实现文档](../幸运礼物实现文档.md),礼物面板通用字段看 [礼物 Tab Flutter 对接](礼物TabFlutter对接.md)。
|
||
|
||
## 1. 送礼前检查
|
||
|
||
地址:
|
||
|
||
```http
|
||
POST /api/v1/activities/lucky-gifts/check
|
||
Authorization: Bearer <access_token>
|
||
X-App-Code: lalu
|
||
Content-Type: application/json
|
||
```
|
||
|
||
请求参数:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `room_id` | string | 是 | 当前房间 ID。 |
|
||
| `gift_id` | string | 是 | 礼物 ID。 |
|
||
| `pool_id` | string | 是 | 幸运礼物奖池 ID,例如 `lucky`、`super_lucky` 或后台配置值。 |
|
||
|
||
请求示例:
|
||
|
||
```json
|
||
{
|
||
"room_id": "lalu_room_001",
|
||
"gift_id": "rose",
|
||
"pool_id": "super_lucky"
|
||
}
|
||
```
|
||
|
||
返回值:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `enabled` | bool | 是否可参与幸运礼物抽奖。 |
|
||
| `reason` | string | 不可参与原因;可为空。 |
|
||
| `room_id` | string | 房间 ID。 |
|
||
| `gift_id` | string | 礼物 ID。 |
|
||
| `pool_id` | string | 奖池 ID。 |
|
||
| `gift_price` | int64 | 当前规则参考礼物价格,只展示用,扣费以后端送礼结果为准。 |
|
||
| `rule_version` | int64 | 命中的幸运礼物规则版本。 |
|
||
| `target_rtp_ppm` | int64 | 目标 RTP,ppm 口径;`950000` 表示 95%。 |
|
||
| `experience_pool` | string | 当前用户体验池,例如 `novice`、`normal`、`advanced`。 |
|
||
|
||
返回示例:
|
||
|
||
```json
|
||
{
|
||
"code": "OK",
|
||
"message": "ok",
|
||
"request_id": "req_abc",
|
||
"data": {
|
||
"enabled": true,
|
||
"reason": "",
|
||
"room_id": "lalu_room_001",
|
||
"gift_id": "rose",
|
||
"pool_id": "super_lucky",
|
||
"gift_price": 100,
|
||
"rule_version": 12,
|
||
"target_rtp_ppm": 950000,
|
||
"experience_pool": "novice"
|
||
}
|
||
}
|
||
```
|
||
|
||
## 2. 发送幸运礼物
|
||
|
||
地址:
|
||
|
||
```http
|
||
POST /api/v1/rooms/gift/send
|
||
Authorization: Bearer <access_token>
|
||
X-App-Code: lalu
|
||
Content-Type: application/json
|
||
```
|
||
|
||
请求参数:
|
||
|
||
| 字段 | 类型 | 必填 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `room_id` | string | 是 | 当前房间 ID。 |
|
||
| `command_id` | string | 是 | 本次送礼幂等键;同一次重试必须复用。 |
|
||
| `target_type` | string | 否 | 当前固定传 `user`;为空后端按 `user`。 |
|
||
| `target_user_ids` | int64[] | 是 | 收礼用户列表;当前只传 1 个用户。 |
|
||
| `target_user_id` | int64 | 否 | 旧单目标兼容字段,新代码优先用 `target_user_ids`。 |
|
||
| `gift_id` | string | 是 | 礼物 ID。 |
|
||
| `gift_count` | int32 | 是 | 礼物数量,必须大于 0;批量送礼会聚合返回一次中奖结果。 |
|
||
| `pool_id` | string | 是 | 幸运礼物奖池 ID;普通礼物不传。 |
|
||
|
||
请求示例:
|
||
|
||
```json
|
||
{
|
||
"room_id": "lalu_room_001",
|
||
"command_id": "gift_1779259000000_10001_rose_01",
|
||
"target_type": "user",
|
||
"target_user_ids": [10002],
|
||
"gift_id": "rose",
|
||
"gift_count": 9,
|
||
"pool_id": "super_lucky"
|
||
}
|
||
```
|
||
|
||
返回值:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `result.applied` | bool | 本次命令是否实际落地;重复提交同一 `command_id` 可能为 `false`。 |
|
||
| `result.room_version` | int64 | 房间版本。 |
|
||
| `result.server_time_ms` | int64 | 服务端时间。 |
|
||
| `billing_receipt_id` | string | 送礼扣费回执。 |
|
||
| `room_heat` | int64 | 送礼后的房间热度。 |
|
||
| `gift_rank` | array | 当前房间礼物榜。 |
|
||
| `room` | object | 房间快照。 |
|
||
| `rocket` | object | 房间火箭状态。 |
|
||
| `lucky_gift` | object | 幸运礼物抽奖结果;普通礼物可为空。 |
|
||
|
||
`lucky_gift` 返回字段:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `enabled` | bool | 本次是否触发幸运礼物。 |
|
||
| `draw_id` | string | 聚合抽奖 ID。 |
|
||
| `command_id` | string | 本次送礼命令 ID。 |
|
||
| `pool_id` | string | 奖池 ID。 |
|
||
| `gift_id` | string | 礼物 ID。 |
|
||
| `rule_version` | int64 | 规则版本。 |
|
||
| `experience_pool` | string | 用户体验池。 |
|
||
| `selected_tier_id` | string | 命中奖档 ID。 |
|
||
| `multiplier_ppm` | int64 | 倍率 ppm;`2000000` 表示 2x。 |
|
||
| `base_reward_coins` | int64 | 基础奖池返奖金币。 |
|
||
| `room_atmosphere_reward_coins` | int64 | 房间气氛池返奖金币。 |
|
||
| `activity_subsidy_coins` | int64 | 活动补贴返奖金币。 |
|
||
| `effective_reward_coins` | int64 | 实际中奖金币;0 表示未中奖。 |
|
||
| `reward_status` | string | `granted` 已入账;`pending`/`granting` 到账处理中;`failed` 需要人工处理。 |
|
||
| `stage_feedback` | bool | 是否有阶段反馈表现。 |
|
||
| `high_multiplier` | bool | 是否高倍率中奖。 |
|
||
| `created_at_ms` | int64 | 抽奖创建时间。 |
|
||
| `wallet_transaction_id` | string | 返奖钱包交易 ID;已入账时有值。 |
|
||
| `coin_balance_after` | int64 | 返奖入账后的 COIN 可用余额。 |
|
||
|
||
返回示例:
|
||
|
||
```json
|
||
{
|
||
"code": "OK",
|
||
"message": "ok",
|
||
"request_id": "req_abc",
|
||
"data": {
|
||
"result": {
|
||
"applied": true,
|
||
"room_version": 14,
|
||
"server_time_ms": 1779259000000
|
||
},
|
||
"billing_receipt_id": "receipt-lucky",
|
||
"room_heat": 123456,
|
||
"gift_rank": [],
|
||
"room": {},
|
||
"rocket": {},
|
||
"lucky_gift": {
|
||
"enabled": true,
|
||
"draw_id": "lucky_draw_test",
|
||
"command_id": "gift_1779259000000_10001_rose_01",
|
||
"pool_id": "super_lucky",
|
||
"gift_id": "rose",
|
||
"rule_version": 12,
|
||
"experience_pool": "novice",
|
||
"selected_tier_id": "novice_2x",
|
||
"multiplier_ppm": 2000000,
|
||
"base_reward_coins": 1800,
|
||
"room_atmosphere_reward_coins": 0,
|
||
"activity_subsidy_coins": 0,
|
||
"effective_reward_coins": 1800,
|
||
"reward_status": "granted",
|
||
"stage_feedback": false,
|
||
"high_multiplier": false,
|
||
"created_at_ms": 1779259000000,
|
||
"wallet_transaction_id": "wallet_tx_lucky",
|
||
"coin_balance_after": 8800
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
客户端处理:
|
||
|
||
- `reward_status=granted` 且 `effective_reward_coins > 0`:立即展示中奖,并用 `coin_balance_after` 覆盖本地金币余额。
|
||
- `reward_status=pending` 或 `granting`:展示“到账处理中”,不要本地加金币,不要生成新 `command_id` 重发。
|
||
- `effective_reward_coins=0`:未中奖,只展示普通送礼表现。
|
||
- 同一用户同一房间连续发送幸运礼物时,客户端需要本地排队;重试必须复用原 `command_id`。
|
||
|
||
## 3. IM 字段
|
||
|
||
### 3.1 送礼房间 IM
|
||
|
||
用途:房间内播放普通送礼动效、同步热度和礼物榜。幸运礼物也会先产生这条送礼 IM。
|
||
|
||
| 字段 | 值 |
|
||
| --- | --- |
|
||
| `MsgContent.Desc` | `room_gift_sent` |
|
||
| `Data.event_type` | `room_gift_sent` |
|
||
|
||
`Data` 核心字段:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `event_id` | string | 房间事件 ID,用于去重。 |
|
||
| `room_id` | string | 房间 ID。 |
|
||
| `room_version` | int64 | 房间版本。 |
|
||
| `occurred_at_ms` | int64 | 事件发生时间。 |
|
||
| `actor_user_id` | string/int64 | 送礼用户 ID。 |
|
||
| `target_user_id` | string/int64 | 收礼用户 ID。 |
|
||
| `gift_value` | int64 | 本次送礼房间价值/热度口径。 |
|
||
| `room_heat` | int64 | 送礼后的房间热度。 |
|
||
| `attributes.gift_id` | string | 礼物 ID。 |
|
||
| `attributes.pool_id` | string | 幸运礼物奖池 ID;普通礼物可为空。 |
|
||
| `attributes.gift_count` | string | 礼物数量,字符串格式。 |
|
||
| `attributes.billing_receipt_id` | string | 钱包扣费回执。 |
|
||
| `attributes.coin_spent` | string | 本次实际消耗金币,字符串格式。 |
|
||
| `attributes.gift_point_added` | string | 主播礼物积分增量,字符串格式。 |
|
||
| `attributes.price_version` | string | 价格版本。 |
|
||
|
||
示例:
|
||
|
||
```json
|
||
{
|
||
"event_type": "room_gift_sent",
|
||
"event_id": "room_event_xxx",
|
||
"room_id": "lalu_room_001",
|
||
"room_version": 14,
|
||
"occurred_at_ms": 1779259000000,
|
||
"actor_user_id": "10001",
|
||
"target_user_id": "10002",
|
||
"gift_value": 900,
|
||
"room_heat": 123456,
|
||
"attributes": {
|
||
"gift_id": "rose",
|
||
"pool_id": "super_lucky",
|
||
"gift_count": "9",
|
||
"billing_receipt_id": "receipt-lucky",
|
||
"coin_spent": "900",
|
||
"gift_point_added": "900",
|
||
"price_version": "v1"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.2 幸运礼物开奖 IM
|
||
|
||
用途:房间公屏展示幸运礼物中奖结果、其他用户同步中奖表现。当前用户自己的余额以 HTTP 返回的 `coin_balance_after` 为准,不等这条 IM。
|
||
|
||
| 字段 | 值 |
|
||
| --- | --- |
|
||
| `MsgContent.Desc` | `lucky_gift_drawn` |
|
||
| `Data.event_type` | `lucky_gift_drawn` |
|
||
|
||
`Data` 核心字段:
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| --- | --- | --- |
|
||
| `event_id` | string | 开奖事件 ID,用于去重。 |
|
||
| `app_code` | string | App Code。 |
|
||
| `draw_id` | string | 聚合抽奖 ID。 |
|
||
| `command_id` | string | 送礼命令 ID。 |
|
||
| `pool_id` | string | 奖池 ID。 |
|
||
| `room_id` | string | 房间 ID。 |
|
||
| `gift_id` | string | 礼物 ID。 |
|
||
| `gift_count` | int32 | 礼物数量。 |
|
||
| `user_id` | int64 | 中奖用户 ID。 |
|
||
| `sender_user_id` | int64 | 送礼用户 ID。 |
|
||
| `target_user_id` | int64 | 收礼用户 ID。 |
|
||
| `visible_region_id` | int64 | 展示区域 ID。 |
|
||
| `coin_spent` | int64 | 本次送礼消耗金币。 |
|
||
| `rule_version` | int64 | 规则版本。 |
|
||
| `experience_pool` | string | 用户体验池。 |
|
||
| `selected_tier_id` | string | 命中奖档 ID。 |
|
||
| `multiplier_ppm` | int64 | 命中倍率 ppm。 |
|
||
| `base_reward_coins` | int64 | 基础奖池返奖金币。 |
|
||
| `room_atmosphere_reward_coins` | int64 | 房间气氛池返奖金币。 |
|
||
| `activity_subsidy_coins` | int64 | 活动补贴返奖金币。 |
|
||
| `effective_reward_coins` | int64 | 实际中奖金币。 |
|
||
| `stage_feedback` | bool | 是否有阶段反馈表现。 |
|
||
| `high_multiplier` | bool | 是否高倍率中奖。 |
|
||
| `created_at_ms` | int64 | 抽奖创建时间。 |
|
||
|
||
示例:
|
||
|
||
```json
|
||
{
|
||
"event_type": "lucky_gift_drawn",
|
||
"event_id": "lucky_gift_drawn:lucky_draw_test",
|
||
"app_code": "lalu",
|
||
"draw_id": "lucky_draw_test",
|
||
"command_id": "gift_1779259000000_10001_rose_01",
|
||
"pool_id": "super_lucky",
|
||
"room_id": "lalu_room_001",
|
||
"gift_id": "rose",
|
||
"gift_count": 9,
|
||
"user_id": 10001,
|
||
"sender_user_id": 10001,
|
||
"target_user_id": 10002,
|
||
"visible_region_id": 688,
|
||
"coin_spent": 900,
|
||
"rule_version": 12,
|
||
"experience_pool": "novice",
|
||
"selected_tier_id": "novice_2x",
|
||
"multiplier_ppm": 2000000,
|
||
"base_reward_coins": 1800,
|
||
"room_atmosphere_reward_coins": 0,
|
||
"activity_subsidy_coins": 0,
|
||
"effective_reward_coins": 1800,
|
||
"stage_feedback": false,
|
||
"high_multiplier": false,
|
||
"created_at_ms": 1779259000000
|
||
}
|
||
```
|
||
|
||
## 4. 状态处理
|
||
|
||
| 场景 | App 处理 |
|
||
| --- | --- |
|
||
| `lucky_gift` 为空 | 当普通礼物处理。 |
|
||
| `effective_reward_coins=0` | 未中奖,不更新中奖余额。 |
|
||
| `reward_status=granted` | 已入账;用 `coin_balance_after` 更新余额。 |
|
||
| `reward_status=pending` / `granting` | 到账处理中;等待钱包通知、刷新余额或后端补偿。 |
|
||
| `reward_status=failed` | 展示异常状态,记录 `request_id/draw_id/command_id` 方便排查。 |
|
||
| HTTP 超时 | 保留原 `command_id` 重试,不生成新命令。 |
|