# 红包接口文档

## 接口列表

### 1. 发送红包

**接口地址**: `POST /redpacket/send_redpacket`

**接口描述**: 在群聊中发送红包，发送用户默认为群主

**请求参数**:

```json
{
    "groupID": "group123",        // 群ID（必填，string）
    "redPacketType": 1,           // 红包类型（必填，int32）：1-普通红包（平均分配），2-拼手气红包（随机分配）
    "totalAmount": 10000,         // 总金额（必填，int64，单位：分）
    "totalCount": 10,             // 总个数（必填，int32）
    "blessing": "恭喜发财"        // 祝福语（可选，string）
}
```

**参数说明**:
- `groupID`: 群ID，必须是已存在的群
- `redPacketType`: 红包类型
  - `1`: 普通红包，每个红包金额 = 总金额 / 总个数
  - `2`: 拼手气红包，金额随机分配
- `totalAmount`: 总金额，单位：分（例如：10000 = 100元）
- `totalCount`: 红包总个数，必须大于0
- `blessing`: 祝福语，可选

**响应参数**:

```json
{
    "errCode": 0,                 // 错误码，0表示成功
    "errMsg": "",                 // 错误信息
    "errDlt": "",                 // 错误详情
    "data": {
        "redPacketID": "rp_1234567890abcdef",  // 红包ID（string）
        "serverMsgID": "msg_1234567890abcdef", // 服务器消息ID（string）
        "clientMsgID": "client_1234567890",   // 客户端消息ID（string）
        "sendTime": 1704067200000              // 发送时间戳（int64，毫秒）
    }
}
```

**响应说明**:
- `redPacketID`: 红包唯一标识，用于后续领取、查询等操作
- `serverMsgID`: 服务器生成的消息ID
- `clientMsgID`: 客户端消息ID
- `sendTime`: 发送时间戳（毫秒）

**错误码**:
- `0`: 成功
- `1001`: 参数错误（金额、个数、类型等）
- `1002`: 群不存在
- `1003`: 群主不存在
- `1004`: 创建红包记录失败
- `1005`: 发送消息失败

**请求示例**:

```bash
curl -X POST http://localhost:10002/redpacket/send_redpacket \
  -H "Content-Type: application/json" \
  -H "token: your_token" \
  -d '{
    "groupID": "group123",
    "redPacketType": 1,
    "totalAmount": 10000,
    "totalCount": 10,
    "blessing": "恭喜发财"
  }'
```

**响应示例**:

```json
{
    "errCode": 0,
    "errMsg": "",
    "errDlt": "",
    "data": {
        "redPacketID": "rp_1234567890abcdef",
        "serverMsgID": "msg_1234567890abcdef",
        "clientMsgID": "client_1234567890",
        "sendTime": 1704067200000
    }
}
```

## 业务规则

1. **发送用户**: 自动使用群主作为发送用户，无需在请求中指定
2. **红包类型**:
   - 普通红包（type=1）: 每个红包金额 = 总金额 / 总个数（向下取整，最后一个红包包含余数）
   - 拼手气红包（type=2）: 金额随机分配，保证最后一个红包能领完剩余金额
3. **过期时间**: 红包默认24小时后过期
4. **红包状态**:
   - `0`: 进行中（可领取）
   - `1`: 已领完
   - `2`: 已过期
5. **消息类型**: 红包消息使用自定义消息类型 `110`（`constant.Custom`），通过 `description` 字段标识二级类型为 `"redpacket"`

## 数据库记录

发送红包时会自动创建以下数据库记录：

**red_packets 表**:
- 记录红包基本信息（金额、个数、类型等）
- 记录红包状态和剩余信息
- 记录过期时间

**消息记录**:
- 在群聊中发送一条红包消息
- 消息内容包含红包ID和基本信息
- 群成员可以看到红包消息

## 注意事项

1. 只支持群聊，不支持单聊
2. 发送用户固定为群主，不能指定其他用户
3. 红包金额单位是"分"，不是"元"
4. 红包个数必须大于0
5. 总金额必须大于0
6. 红包类型只能是1或2

### 2. 领取红包

**接口地址**: `POST /redpacket/receive`

**接口描述**: 领取红包，支持普通红包和拼手气红包

**请求参数**:

```json
{
    "redPacketID": "rp_1234567890abcdef"  // 红包ID（必填，string）
}
```

**参数说明**:
- `redPacketID`: 红包ID，从发送红包接口的响应中获取

**响应参数**:

```json
{
    "errCode": 0,                 // 错误码，0表示成功
    "errMsg": "",                 // 错误信息
    "errDlt": "",                 // 错误详情
    "data": {
        "redPacketID": "rp_1234567890abcdef",  // 红包ID（string）
        "amount": 1000,                        // 领取金额（int64，单位：分）
        "isLucky": false                       // 是否为手气最佳（bool，仅拼手气红包有效）
    }
}
```

**响应说明**:
- `redPacketID`: 红包ID
- `amount`: 领取到的金额，单位：分
- `isLucky`: 是否为手气最佳，仅拼手气红包有效
  - `true`: 是手气最佳（领取金额最大）
  - `false`: 不是手气最佳

**错误码**:
- `0`: 成功
- `1001`: 参数错误（红包ID为空）
- `1004`: 红包不存在（RecordNotFoundError）
- `1801`: 红包已被领完（RedPacketFinishedError）
- `1802`: 红包已过期（RedPacketExpiredError）
- `1803`: 用户已领取过该红包（RedPacketAlreadyReceivedError）
- `500`: 服务器内部错误（Redis队列操作失败等）

**请求示例**:

```bash
curl -X POST http://localhost:10002/redpacket/receive \
  -H "Content-Type: application/json" \
  -H "token: your_token" \
  -d '{
    "redPacketID": "rp_1234567890abcdef"
  }'
```

**响应示例**:

```json
{
    "errCode": 0,
    "errMsg": "",
    "errDlt": "",
    "data": {
        "redPacketID": "rp_1234567890abcdef",
        "amount": 1000,
        "isLucky": false
    }
}
```

**业务规则**:

1. **领取限制**:
   - 每个用户只能领取一次
   - 红包必须处于"进行中"状态
   - 红包不能已过期
   - 红包不能已被领完

2. **金额分配**:
   - **普通红包（type=1）**: 金额 = 剩余金额 / 剩余个数（向下取整，最后一个包含余数）
   - **拼手气红包（type=2）**: 从Redis队列中获取预分配的随机金额

3. **手气最佳判断**:
   - 仅拼手气红包有效
   - 领取金额最大的用户被标记为手气最佳
   - 如果有多个相同最大金额，第一个领取的会被标记为手气最佳

4. **消息更新**:
   - 领取红包后，客户端下次拉取消息时会自动看到已领取状态
   - 消息同步时会动态填充领取信息（`IsReceived` 和 `ReceiveInfo`）

5. **原子操作**:
   - 领取操作是原子的，确保并发安全
   - 使用数据库事务保证数据一致性

### 3. 查询红包列表（后台管理接口）

**接口地址**: `POST /redpacket/get_redpackets_by_group`

**接口描述**: 根据群ID查询红包列表，支持查询所有红包或指定群的红包

**请求参数**:

```json
{
    "groupID": "group123",        // 群ID（选填，string），不填或为空则查询所有红包
    "pagination": {
        "pageNumber": 1,          // 页码（选填，int32），从1开始，默认1
        "showNumber": 20           // 每页数量（选填，int32），默认20
    }
}
```

**参数说明**:
- `groupID`: 群ID，选填
  - 如果为空或不传，则查询所有红包
  - 如果指定群ID，则只查询该群的红包
- `pagination`: 分页参数，选填
  - `pageNumber`: 页码，从1开始，默认1
  - `showNumber`: 每页数量，默认20

**响应参数**:

```json
{
    "errCode": 0,
    "errMsg": "",
    "errDlt": "",
    "data": {
        "total": 100,              // 总数（int64）
        "redPackets": [            // 红包列表（array）
            {
                "redPacketID": "rp_1234567890abcdef",  // 红包ID（string）
                "sendUserID": "user123",               // 发送者ID（string）
                "groupID": "group123",                 // 群ID（string）
                "groupName": "测试群",                  // 群名称（string）
                "redPacketType": 1,                    // 红包类型（int32）：1-普通红包，2-拼手气红包
                "totalAmount": 10000,                  // 总金额（int64，单位：分）
                "totalCount": 10,                      // 总个数（int32）
                "remainAmount": 5000,                  // 剩余金额（int64，单位：分）
                "remainCount": 5,                      // 剩余个数（int32）
                "blessing": "恭喜发财",                // 祝福语（string）
                "status": 0,                           // 状态（int32）：0-进行中，1-已领完，2-已过期
                "expireTime": 1704153600000,           // 过期时间戳（int64，毫秒）
                "createTime": 1704067200000             // 创建时间戳（int64，毫秒）
            }
        ]
    }
}
```

**响应说明**:
- `total`: 符合条件的红包总数
- `redPackets`: 红包列表，按创建时间倒序排列
- 每个红包包含完整的信息：ID、发送者、群ID、群名称、类型、金额、个数、剩余信息、状态等
- `groupName`: 群名称，通过批量查询群信息获取，如果群不存在或查询失败则为空字符串

**错误码**:
- `0`: 成功
- `1001`: 参数错误
- `500`: 服务器内部错误

**请求示例**:

```bash
# 查询所有红包
curl -X POST http://localhost:10002/redpacket/get_redpackets_by_group \
  -H "Content-Type: application/json" \
  -H "token: your_token" \
  -d '{
    "pagination": {
      "pageNumber": 1,
      "showNumber": 20
    }
  }'

# 查询指定群的红包
curl -X POST http://localhost:10002/redpacket/get_redpackets_by_group \
  -H "Content-Type: application/json" \
  -H "token: your_token" \
  -d '{
    "groupID": "group123",
    "pagination": {
      "pageNumber": 1,
      "showNumber": 20
    }
  }'
```

**响应示例**:

```json
{
    "errCode": 0,
    "errMsg": "",
    "errDlt": "",
    "data": {
        "total": 100,
        "redPackets": [
            {
                "redPacketID": "rp_1234567890abcdef",
                "sendUserID": "user123",
                "groupID": "group123",
                "groupName": "测试群",
                "redPacketType": 1,
                "totalAmount": 10000,
                "totalCount": 10,
                "remainAmount": 5000,
                "remainCount": 5,
                "blessing": "恭喜发财",
                "status": 0,
                "expireTime": 1704153600000,
                "createTime": 1704067200000
            }
        ]
    }
}
```

### 4. 查询红包领取情况（后台管理接口）

**接口地址**: `POST /redpacket/get_receive_info`

**接口描述**: 查询指定红包的领取情况，包括所有领取记录和详细信息

**请求参数**:

```json
{
    "redPacketID": "rp_1234567890abcdef"  // 红包ID（必填，string）
}
```

**参数说明**:
- `redPacketID`: 红包ID，必填

**响应参数**:

```json
{
    "errCode": 0,
    "errMsg": "",
    "errDlt": "",
    "data": {
        "redPacketID": "rp_1234567890abcdef",  // 红包ID（string）
        "totalAmount": 10000,                  // 总金额（int64，单位：分）
        "totalCount": 10,                      // 总个数（int32）
        "remainAmount": 5000,                  // 剩余金额（int64，单位：分）
        "remainCount": 5,                      // 剩余个数（int32）
        "status": 0,                           // 状态（int32）：0-进行中，1-已领完，2-已过期
        "receives": [                          // 领取记录列表（array）
            {
                "receiveID": "rec_1234567890",  // 领取记录ID（string）
                "receiveUserID": "user456",     // 领取者ID（string）
                "amount": 1000,                 // 领取金额（int64，单位：分）
                "receiveTime": 1704070800000,   // 领取时间戳（int64，毫秒）
                "isLucky": false                // 是否为手气最佳（bool，仅拼手气红包有效）
            }
        ]
    }
}
```

**响应说明**:
- `redPacketID`: 红包ID
- `totalAmount`: 红包总金额
- `totalCount`: 红包总个数
- `remainAmount`: 剩余金额
- `remainCount`: 剩余个数
- `status`: 红包状态
- `receives`: 领取记录列表，按领取时间正序排列
  - `receiveID`: 领取记录ID
  - `receiveUserID`: 领取者用户ID
  - `amount`: 领取的金额
  - `receiveTime`: 领取时间戳
  - `isLucky`: 是否为手气最佳（仅拼手气红包有效）

**错误码**:
- `0`: 成功
- `1001`: 参数错误（红包ID为空）
- `1004`: 红包不存在
- `500`: 服务器内部错误

**请求示例**:

```bash
curl -X POST http://localhost:10002/redpacket/get_receive_info \
  -H "Content-Type: application/json" \
  -H "token: your_token" \
  -d '{
    "redPacketID": "rp_1234567890abcdef"
  }'
```

**响应示例**:

```json
{
    "errCode": 0,
    "errMsg": "",
    "errDlt": "",
    "data": {
        "redPacketID": "rp_1234567890abcdef",
        "totalAmount": 10000,
        "totalCount": 10,
        "remainAmount": 5000,
        "remainCount": 5,
        "status": 0,
        "receives": [
            {
                "receiveID": "rec_1234567890",
                "receiveUserID": "user456",
                "amount": 1000,
                "receiveTime": 1704070800000,
                "isLucky": false
            },
            {
                "receiveID": "rec_1234567891",
                "receiveUserID": "user789",
                "amount": 2000,
                "receiveTime": 1704071400000,
                "isLucky": true
            }
        ]
    }
}
```

### 5. 暂停红包（后台管理接口）

**接口地址**: `POST /redpacket/pause`

**接口描述**: 暂停红包，清空Redis队列，使红包无法继续被领取（仅对拼手气红包有效）

**请求参数**:

```json
{
    "redPacketID": "rp_1234567890abcdef"  // 红包ID（必填，string）
}
```

**参数说明**:
- `redPacketID`: 红包ID，必填

**响应参数**:

```json
{
    "errCode": 0,
    "errMsg": "",
    "errDlt": "",
    "data": {
        "redPacketID": "rp_1234567890abcdef"  // 红包ID（string）
    }
}
```

**响应说明**:
- `redPacketID`: 红包ID

**错误码**:
- `0`: 成功
- `1001`: 参数错误（红包ID为空）
- `1004`: 红包不存在
- `500`: 服务器内部错误（Redis操作失败等）

**请求示例**:

```bash
curl -X POST http://localhost:10002/redpacket/pause \
  -H "Content-Type: application/json" \
  -H "token: your_token" \
  -d '{
    "redPacketID": "rp_1234567890abcdef"
  }'
```

**响应示例**:

```json
{
    "errCode": 0,
    "errMsg": "",
    "errDlt": "",
    "data": {
        "redPacketID": "rp_1234567890abcdef"
    }
}
```

**业务规则**:

1. **暂停操作**:
   - 清空该红包在Redis中的队列（`redpacket:queue:{redPacketID}`）
   - 清空后，后续领取请求会因队列为空而失败（返回 `1801: red packet has been finished`）
   - 已领取的记录不受影响，只是无法继续领取

2. **红包类型**:
   - **拼手气红包（type=2）**: 会清空Redis队列
   - **普通红包（type=1）**: 没有Redis队列，直接返回成功

3. **注意事项**:
   - 暂停操作不可逆，清空后的Redis队列无法恢复
   - 暂停后，红包状态不会自动更新，但实际已无法领取
   - 建议在暂停后手动更新红包状态为"已领完"或"已过期"

## 接口汇总

| 接口路径 | 方法 | 描述 | 类型 |
|---------|------|------|------|
| `/redpacket/send_redpacket` | POST | 发送红包 | 用户接口 |
| `/redpacket/receive` | POST | 领取红包 | 用户接口 |
| `/redpacket/get_redpackets_by_group` | POST | 查询红包列表 | 后台管理接口 |
| `/redpacket/get_receive_info` | POST | 查询红包领取情况 | 后台管理接口 |
| `/redpacket/pause` | POST | 暂停红包 | 后台管理接口 |

## 错误码汇总

| 错误码 | 说明 | 适用接口 |
|--------|------|----------|
| `0` | 成功 | 所有接口 |
| `1001` | 参数错误 | 所有接口 |
| `1004` | 记录不存在 | 领取、查询、暂停接口 |
| `1801` | 红包已被领完 | 领取接口 |
| `1802` | 红包已过期 | 领取接口 |
| `1803` | 用户已领取过该红包 | 领取接口 |
| `500` | 服务器内部错误 | 所有接口 |

## 客户端消息结构

客户端收到的红包消息结构请参考：[红包消息结构文档](./redpacket-message-structure.md)

