12 KiB
12 KiB
红包消息结构文档
客户端收到的推送消息结构
完整消息结构 (MsgData)
客户端通过WebSocket或HTTP拉取收到的红包消息,消息结构如下:
{
"clientMsgID": "client_1234567890abcdef", // 客户端消息ID(string)
"serverMsgID": "msg_1234567890abcdef", // 服务器消息ID(string)
"sendID": "user_owner123", // 发送者ID(群主ID)(string)
"recvID": "", // 接收者ID(群消息为空)(string)
"groupID": "group123", // 群ID(string)
"senderPlatformID": 0, // 发送者平台ID(int32,0表示系统)
"senderNickname": "群主昵称", // 发送者昵称(string)
"senderFaceURL": "https://...", // 发送者头像URL(string)
"sessionType": 3, // 会话类型(int32):3-群聊
"msgFrom": 200, // 消息来源(int32):200-系统消息
"contentType": 110, // 消息类型(int32):110-自定义消息
"content": "{\"data\":\"{\\\"redPacketID\\\":\\\"rp_123\\\",\\\"redPacketType\\\":1,\\\"blessing\\\":\\\"恭喜发财\\\"}\",\"description\":\"redpacket\",\"extension\":\"\"}", // 消息内容(JSON字符串,自定义消息格式)
"seq": 123456, // 消息序号(int64)
"sendTime": 1704067200000, // 发送时间戳(int64,毫秒)
"createTime": 1704067200000, // 创建时间戳(int64,毫秒)
"status": 2, // 消息状态(int32):2-发送成功
"isRead": false, // 是否已读(bool)
"options": { // 消息选项(map[string]bool)
"history": true, // 是否保存历史
"persistent": true, // 是否持久化
"offlinePush": true, // 是否离线推送
"unreadCount": true, // 是否计入未读数
"conversationUpdate": true, // 是否更新会话
"senderSync": true // 是否同步给发送者
},
"offlinePushInfo": { // 离线推送信息(可选)
"title": "[HONGBAO]", // 推送标题
"desc": "[HONGBAO]", // 推送描述
"ex": "", // 扩展字段
"iosPushSound": "", // iOS推送声音
"iosBadgeCount": false // iOS角标计数
},
"atUserIDList": [], // @用户列表(string[])
"attachedInfo": "", // 附加信息(string)
"ex": "" // 扩展字段(string)
}
Content字段解析
content 字段是一个JSON字符串,需要先解析为 CustomElem 结构(自定义消息格式),然后从 data 字段中解析出 RedPacketElem 结构:
CustomElem 结构(自定义消息外层结构)
{
"data": "{\"redPacketID\":\"rp_123\",\"redPacketType\":1,\"blessing\":\"恭喜发财\",\"isReceived\":false,\"receiveInfo\":null}", // 红包数据的JSON字符串(string,必填)
"description": "redpacket", // 二级类型标识(string):"redpacket"表示红包消息
"extension": "" // 扩展字段(string,可选)
}
RedPacketElem 结构(从data字段中解析)
{
"redPacketID": "rp_1234567890abcdef", // 红包ID(string,必填)
"redPacketType": 1, // 红包类型(int32,必填):1-普通红包,2-拼手气红包
"blessing": "恭喜发财", // 祝福语(string,可选)
"isReceived": false, // 当前用户是否已领取(bool,服务器填充)
"receiveInfo": null // 领取信息(RedPacketReceiveInfo,仅拼手气红包且已领取时返回)
}
RedPacketReceiveInfo 结构(领取信息)
{
"amount": 1000, // 领取金额(int64,单位:分)
"receiveTime": 1704067200000, // 领取时间戳(int64,毫秒)
"isLucky": false // 是否为手气最佳(bool,仅拼手气红包有效)
}
字段说明
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
redPacketID |
string | 是 | 红包唯一标识,用于后续领取、查询等操作(总金额、总个数等信息可通过红包ID查询获取) |
redPacketType |
int32 | 是 | 红包类型:1-普通红包(平均分配),2-拼手气红包(随机分配) |
blessing |
string | 否 | 祝福语 |
isReceived |
bool | 是 | 当前用户是否已领取(服务器根据用户ID自动填充) |
receiveInfo |
RedPacketReceiveInfo | 否 | 领取信息,仅当 isReceived=true 且 redPacketType=2(拼手气红包)时返回 |
receiveInfo 字段说明
| 字段名 | 类型 | 说明 |
|---|---|---|
amount |
int64 | 领取金额,单位:分 |
receiveTime |
int64 | 领取时间戳,毫秒 |
isLucky |
bool | 是否为手气最佳(仅拼手气红包有效) |
消息类型常量
- ContentType:
110(constant.Custom- 自定义消息) - 二级类型标识:
"redpacket"(存储在CustomElem.description字段中) - SessionType:
3(constant.ReadGroupChatType- 群聊) - MsgFrom:
200(constant.SysMsgType- 系统消息)
客户端解析示例
JavaScript/TypeScript
interface RedPacketReceiveInfo {
amount: number; // 领取金额(分)
receiveTime: number; // 领取时间戳(毫秒)
isLucky: boolean; // 是否为手气最佳
}
interface RedPacketElem {
redPacketID: string;
redPacketType: number; // 1-普通红包,2-拼手气红包
blessing?: string;
isReceived: boolean; // 当前用户是否已领取
receiveInfo?: RedPacketReceiveInfo; // 领取信息(仅拼手气红包且已领取时返回)
}
interface CustomElem {
data: string; // 红包数据的JSON字符串
description: string; // 二级类型标识:"redpacket"
extension?: string; // 扩展字段
}
interface RedPacketMessage {
clientMsgID: string;
serverMsgID: string;
sendID: string;
groupID: string;
contentType: number; // 110 (自定义消息)
content: string; // CustomElem的JSON字符串
sendTime: number;
// ... 其他字段
}
// 解析消息
function parseRedPacketMessage(msg: RedPacketMessage): RedPacketElem | null {
// 检查是否为自定义消息类型
if (msg.contentType !== 110) {
return null;
}
try {
// 先解析自定义消息结构
const customElem: CustomElem = JSON.parse(msg.content);
// 检查二级类型是否为红包
if (customElem.description !== "redpacket") {
return null;
}
// 从data字段中解析红包数据
const redPacketElem: RedPacketElem = JSON.parse(customElem.data);
return redPacketElem;
} catch (e) {
console.error('Failed to parse red packet content:', e);
return null;
}
}
Go
type RedPacketReceiveInfo struct {
Amount int64 `json:"amount"` // 领取金额(分)
ReceiveTime int64 `json:"receiveTime"` // 领取时间戳(毫秒)
IsLucky bool `json:"isLucky"` // 是否为手气最佳
}
type RedPacketElem struct {
RedPacketID string `json:"redPacketID"`
RedPacketType int32 `json:"redPacketType"`
TotalAmount int64 `json:"totalAmount"`
TotalCount int32 `json:"totalCount"`
Blessing string `json:"blessing"`
IsReceived bool `json:"isReceived"` // 当前用户是否已领取
ReceiveInfo *RedPacketReceiveInfo `json:"receiveInfo,omitempty"` // 领取信息(仅拼手气红包且已领取时返回)
}
type CustomElem struct {
Data string `json:"data"` // 红包数据的JSON字符串
Description string `json:"description"` // 二级类型标识:"redpacket"
Extension string `json:"extension"` // 扩展字段
}
func ParseRedPacketContent(content []byte) (*RedPacketElem, error) {
// 先解析自定义消息结构
var customElem CustomElem
if err := json.Unmarshal(content, &customElem); err != nil {
return nil, err
}
// 检查二级类型是否为红包
if customElem.Description != "redpacket" {
return nil, fmt.Errorf("not a red packet message")
}
// 从data字段中解析红包数据
var redPacketElem RedPacketElem
if err := json.Unmarshal([]byte(customElem.Data), &redPacketElem); err != nil {
return nil, err
}
return &redPacketElem, nil
}
完整消息示例
{
"clientMsgID": "client_1704067200000_abc123",
"serverMsgID": "msg_1704067200000_def456",
"sendID": "user_owner123",
"recvID": "",
"groupID": "group123",
"senderPlatformID": 0,
"senderNickname": "群主",
"senderFaceURL": "https://example.com/avatar.jpg",
"sessionType": 3,
"msgFrom": 200,
"contentType": 110,
"content": "{\"data\":\"{\\\"redPacketID\\\":\\\"rp_1234567890abcdef\\\",\\\"redPacketType\\\":1,\\\"blessing\\\":\\\"恭喜发财\\\",\\\"isReceived\\\":false,\\\"receiveInfo\\\":null}\",\"description\":\"redpacket\",\"extension\":\"\"}",
"seq": 123456,
"sendTime": 1704067200000,
"createTime": 1704067200000,
"status": 2,
"isRead": false,
"options": {
"history": true,
"persistent": true,
"offlinePush": true,
"unreadCount": true,
"conversationUpdate": true,
"senderSync": true
},
"offlinePushInfo": {
"title": "[HONGBAO]",
"desc": "[HONGBAO]"
},
"atUserIDList": [],
"attachedInfo": "",
"ex": ""
}
消息选项说明
| 选项名 | 说明 |
|---|---|
history |
是否保存到历史记录 |
persistent |
是否持久化存储 |
offlinePush |
是否离线推送 |
unreadCount |
是否计入未读数 |
conversationUpdate |
是否更新会话 |
senderSync |
是否同步给发送者 |
注意事项
- Content字段: 是JSON字符串,需要先解析为
CustomElem结构,然后从data字段中解析RedPacketElem - 消息类型: 使用自定义消息类型(
contentType = 110),通过description字段标识二级类型为"redpacket" - 二级类型扩展: 未来可以扩展其他自定义消息类型,只需在
description字段中使用不同的标识(如"wallet"、"coupon"等) - 金额单位:
receiveInfo.amount单位是"分",不是"元" - 总金额和总个数: 不在消息中传递,客户端可通过
redPacketID调用查询接口获取详细信息 - 红包类型:
1= 普通红包(平均分配)2= 拼手气红包(随机分配)
- 发送者: 固定为群主,
sendID为群主ID - 消息来源:
msgFrom = 200表示系统消息 - 会话类型:
sessionType = 3表示群聊 - 领取状态:
isReceived字段由服务器根据当前用户ID自动填充,客户端无需设置 - 领取信息:
receiveInfo仅在以下情况返回:isReceived = true(用户已领取)redPacketType = 2(拼手气红包)- 普通红包(
redPacketType = 1)即使已领取也不会返回receiveInfo
- 客户端存储: 客户端收到消息后,应将
isReceived和receiveInfo存储到本地,用于UI展示 - 兼容性: 使用标准自定义消息类型,无需修改客户端SDK,只需在客户端添加红包消息的解析逻辑