产品动态
公告

组件 | 职责 |
客户端(发送方/接收方) | 发起发送红包/拆红包请求;渲染红包卡片 UI。 |
腾讯云 IM | 消息投递、状态更新、领取记录存储、领取通知推送。 |
红包系统 | 红包生命周期管理:创建、校验、拆开、金额计算。 |
支付系统 | 资金管理:扣款、转账、退款。 |
字段 | 类型 | 说明 |
BusinessID | String | 消息类型标识,红包消息固定为 "red_packet"。 |
packet_id | String | 发送方调用红包系统创建红包,支付系统扣款成功后,由红包系统生成唯一 packet_id ,红包系统通过 REST API 将它写入 IM 自定义消息的 customData,使消息与红包一一绑定。 |
money_amount | Number | 红包金额(一对一红包使用)。 |
best_wishes | String | 祝福语,例如"恭喜发财,大吉大利"。 |
cover | String | 红包封面图片 URL。 |
status | String | 红包状态: "Unopened"(未领取)/ "Opened"(已领取)/ "None left"(已领完)。 |
quantity | Number | (仅群红包) 红包个数。 |
total | Number | (仅群红包) 红包总金额。 |
random_amount | Boolean | (仅群红包) 是否为拼手气红包(随机金额)。 |
{"BusinessID": "red_packet","money_amount": 1.00,"best_wishes": "恭喜发财!","cover": "https://example.com/cover.png","status": "Unopened","packet_id": "rp_20260301_abc123"}
{"BusinessID": "red_packet","total": 2.00,"quantity": 3,"random_amount": true,"best_wishes": "新年快乐!","cover": "https://example.com/cover.png","status": "Unopened","packet_id": "rp_20260301_xyz789"}
Key | Value | 说明 |
{userID} | {金额},{时间戳} | 每条领取记录作为一个 KV 对存储 |
{"user_daniel": "1.40,1709312400","user_anson": "0.60,1709312580"}
MsgBody)。在红包场景中,用于更新红包卡片的 status 字段(例如从 "Unopened" 变为 "Opened" 或 "None left"),修改后所有客户端都能看到最新的红包状态。From_Account + To_Account + MsgKey 定位消息。GroupId + MsgSeq 定位消息。From_Account + To_Account + MsgKey 定位消息。GroupId + MsgSeq 定位消息。SupportMessageExtension 为 1。能力 | 用途(红包场景) | 单聊定位参数 | 群聊定位参数 |
消息变更 | 更新红包状态(Unopened → Opened → None left) | From_Account + To_Account + MsgKey | GroupId + MsgSeq |
消息扩展 | 存储红包领取记录(key=userID, value=金额,时间戳) | From_Account + To_Account + MsgKey | GroupId + MsgSeq |

packet_id。From_Account 设为发送方用户 ID)将红包作为自定义消息发送给接收方。这确保了扣款与消息发送的原子性,只有扣款成功才会发送红包消息 packet_id。// POST https://console.tim.qq.com/v4/openim/sendmsg{"SyncOtherMachine": 1,"From_Account": "sender_userid","To_Account": "receiver_userid","MsgRandom": 1287657,"MsgBody": [{"MsgType": "TIMCustomElem","MsgContent": {"Data": "{\\"BusinessID\\":\\"red_packet\\",\\"money_amount\\":1.00,\\"best_wishes\\":\\"恭喜发财!\\",\\"cover\\":\\"https://example.com/cover.png\\",\\"status\\":\\"Unopened\\",\\"packet_id\\":\\"rp_20260301_abc123\\"}"}}],"SupportMessageExtension": 1}


userID,value = 金额,时间戳。status 从 "Unopened" 更新为 "Opened"。{"From_Account": "sender_userid","To_Account": "receiver_userid","MsgKey": "msg_key_from_send_response","MsgBody": [{"MsgType": "TIMCustomElem","MsgContent": {"Data": "{\\"BusinessID\\":\\"red_packet\\",\\"money_amount\\":1.00,\\"best_wishes\\":\\"恭喜发财!\\",\\"cover\\":\\"https://example.com/cover.png\\",\\"status\\":\\"Opened\\",\\"packet_id\\":\\"rp_20260301_abc123\\"}"}}]}
{"From_Account": "sender_userid","To_Account": "receiver_userid","MsgKey": "msg_key_from_send_response","OperateType": 1,"ExtensionList": [{"Key": "user_anson","Value": "0.60,1709312580"}]}



From_Account 设为发送方用户 ID)将红包作为自定义消息发送至群组。GroupId 设为目标群组 ID,payload 增加 quantity、total、random_amount 字段。请求示例如下:// POST https://console.tim.qq.com/v4/group_open_http_svc/send_group_msg{"GroupId": "group_id","From_Account": "sender_userid","Random": 1287657,"MsgBody": [{"MsgType": "TIMCustomElem","MsgContent": {"Data": "{\\"BusinessID\\":\\"red_packet\\",\\"total\\":2.00,\\"quantity\\":3,\\"random_amount\\":true,\\"best_wishes\\":\\"新年快乐!\\",\\"cover\\":\\"https://example.com/cover.png\\",\\"status\\":\\"Unopened\\",\\"packet_id\\":\\"rp_20260301_xyz789\\"}"}}],"SupportMessageExtension": 1}
status 更新为 "None left"。GroupId + MsgSeq。状态流转包含 "None left"。status 更新为 "None left":{"GroupId": "group_id","MsgSeq": 67890,"MsgBody": [{"MsgType": "TIMCustomElem","MsgContent": {"Data": "{\\"BusinessID\\":\\"red_packet\\",\\"total\\":2.00,\\"quantity\\":3,\\"random_amount\\":true,\\"best_wishes\\":\\"新年快乐!\\",\\"cover\\":\\"https://example.com/cover.png\\",\\"status\\":\\"None left\\",\\"packet_id\\":\\"rp_20260301_xyz789\\"}"}}]}
{"GroupId": "group_id","MsgSeq": 67890,"OperateType": 1,"ExtensionList": [{"Key": "user_harvy","Value": "1.90,1709312400"},{"Key": "user_anson","Value": "0.10,1709312580"}]}

userID。客户端获取到扩展数据中的 userID 列表后,需要调用批量拉取群成员资料接口来获取每位领取人的头像、昵称等展示信息。faceUrl)、昵称(nickName)等资料,用于渲染领取列表 UI。
quantity 个)。"Unopened"(未领取)→ "Opened"(部分领取)→ "None left"(已领完)。接口 | 调用时机 | 说明 |
扣款接口(Deduction API) | 发红包 | 从发送方余额扣款到资金管理账户。 |
转账接口(Transfer API) | 拆红包 | 从资金管理账户转账到领取方账户。 |
退款接口(Refund API) | 到期退款(24小时) | 未领取金额从资金管理账户退回发送方。 |
资金流水接口(Fund Flow API) | 查询/审计 | 查询交易记录,用于对账。 |


类别 | 项目 | 说明 |
通用规则 | 24 小时过期退款 | 红包发出后 24 小时内未被领取的金额,将自动退回发送方账户。 |
| 一人一次 | 每位用户只能领取同一个红包一次,系统需在拆红包前做校验。 |
| 状态一致性 | 通过消息修改接口保持红包状态在所有客户端的同步。 |
群红包专项 | 最大领取人数 | 群红包最多支持 300 人领取(受消息扩展数据容量限制)。 |
| 并发领取 | 红包系统必须安全处理并发拆红包请求,建议使用分布式锁或原子操作,防止超发。 |
| 随机金额算法 | 拼手气模式下,需确保公平性并保证每个红包有最低金额。常用方案为"二倍均值"算法。 |
| 手气最佳 | 领取金额最高者在详情页标注"手气最佳"标签。 |
异常处理 | 扣款失败 | 不创建红包、不发送消息,提示发送方余额不足。 |
| 转账失败 | 重试转账操作。若持续失败,标记为待人工对账,不更新消息状态。 |
| 消息修改失败 | 使用指数退避策略重试。红包状态可能短暂不一致,但资金已完成处理。 |
| 拆红包网络超时 | 采用幂等设计 —— 同一 packet_id + userid 的拆红包请求应返回相同结果。 |
安全实践 | 服务端校验 | 所有红包操作(发送、拆开、查询)必须在服务端校验,不能信任客户端提交的金额。 |
| 幂等性设计 | 使用 packet_id + userid 作为拆红包操作的幂等键。 |
| 限频控制 | 对拆红包请求实施限频策略,防止恶意刷取。 |
| 审计日志 | 记录所有支付操作(扣款、转账、退款)的日志,用于对账和争议处理。 |
文档反馈