Table of Contents
5.13 系统消息【代码实现完成,待登录态联调】
说明:系统消息按当前 Token 的 current_identity 隔离读取。当前身份为 fan 时查询 receiver_identity=fan 且 receiver_id=当前 tieup_user.id 的消息;当前身份为 artist 时查询 receiver_identity=artist 且 receiver_id=当前账号对应 tieup_artist.id 的消息。business_type 只表示用于筛选和未读统计的粗分类,具体通知场景由 title、content 展示;需要交互的消息由稳定的 source_type 和 payload 描述,客户端不得依赖标题文字判断操作类型。
融云实时通知使用 SYSTEM 会话和自定义消息类型 Tieup:SysMsg,不使用 RC:TxtMsg、图片或视频等内置消息类型。iOS、Android 必须注册 Tieup:SysMsg;content.extra 是 JSON 字符串,需要再次反序列化。融云 SDK 外层 SYSTEM 会话的 targetId 是系统发送方融云用户 ID,不是业务群 ID;普通系统消息不提供群聊跳转上下文。
SYSTEM 离线通知同时提交独立的 pushData JSON 字符串。iOS、Android 收到厂商离线推送后从通知载荷的 appData 取得该字符串并再次反序列化;Android 也可通过融云 PushNotificationMessage#getPushData() 获取。pushData.notificationType=system 后必须继续根据 sourceType 和 payload 跳转业务页面,不得根据通知标题、正文或 SDK 外层 targetId 判断。
融云原始消息内容示例:
{
"objectName": "Tieup:SysMsg",
"content": {
"content": "福利可兑换:您已满足福利兑换条件",
"extra": "{\"message_id\":90001,\"business_type\":\"benefit\",\"message_category\":\"fan\",\"link_id\":30001,\"source_type\":\"benefit_redeemable\",\"source_no\":\"BF202607130001\",\"conversationType\":0,\"targetId\":\"\",\"channelId\":\"\",\"payload\":{\"artist_id\":20001,\"artist_name\":\"示例艺人\",\"benefit_title\":\"签名照\"}}"
}
}
content.extra 反序列化结果:
{
"message_id": 90001,
"business_type": "benefit",
"message_category": "fan",
"link_id": 30001,
"source_type": "benefit_redeemable",
"source_no": "BF202607130001",
"conversationType": 0,
"targetId": "",
"channelId": "",
"payload": {
"artist_id": 20001,
"artist_name": "示例艺人",
"benefit_title": "签名照"
}
}
自定义系统消息字段:
| 字段 | 类型 | 说明 |
|---|---|---|
content.content |
string | 推送展示文本,由标题和正文摘要组成 |
content.extra |
string | JSON 字符串,反序列化后得到业务路由数据 |
message_id |
integer | 本地系统消息 ID |
business_type |
string | 系统消息粗分类,用于列表筛选和未读统计;完整取值见 5.13.1 粗分类表 |
message_category |
string | 消息分类:artist 或 fan |
link_id |
integer/null | 关联业务主记录 ID |
source_type |
string | 稳定的系统消息场景分类;完整取值、接收端和触发时机见 5.13.1 场景分类表 |
source_no |
string | 业务来源编号 |
conversationType |
integer | 普通系统消息固定为 0,表示没有群聊跳转上下文 |
targetId |
string | 普通系统消息固定为空字符串 |
channelId |
string | 普通系统消息固定为空字符串 |
payload |
object | 对应系统消息的业务扩展数据 |
SYSTEM 离线通知 pushData 反序列化完整示例:
{
"schemaVersion": 1,
"notificationType": "system",
"messageType": "system",
"conversationType": 0,
"messageId": 90001,
"businessType": "benefit",
"sourceType": "benefit_redeemable",
"sourceNo": "BF202607130001",
"linkId": 30001,
"payload": {
"artist_id": 20001,
"artist_name": "示例艺人",
"benefit_title": "签名照"
}
}
SYSTEM pushData 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
schemaVersion |
integer | 跳转协议版本,当前固定为 1 |
notificationType |
string | 固定为 system |
messageType |
string | 固定为 system,与聊天内容类型区分 |
conversationType |
integer | 固定为 0,表示不直接使用融云群聊定位 |
messageId |
integer | 本地系统消息 ID |
businessType |
string | 系统消息粗分类,取值与列表响应的 business_type 一致 |
sourceType |
string | 稳定的系统消息场景分类,是系统消息页面跳转的主要判断字段;完整取值见 5.13.1 场景分类表 |
sourceNo |
string | 业务来源编号 |
linkId |
integer/null | 关联业务主记录 ID |
payload |
object | 业务跳转所需的最小扩展数据,不包含 Token、手机号等敏感信息 |
5.13.1 我的系统消息列表
GET /tieup/api/v1/me/system-messages
鉴权:需要 Authorization: Bearer <access_token>。
查询参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
page |
integer | 否 | 页码,默认 1 |
page_size |
integer | 否 | 每页数量,默认 20,最大 100 |
business_type |
string | 否 | 当前身份的粗分类;不传或传 all 表示全部,非法值或跨身份分类返回参数错误 |
read_status |
integer | 否 | 阅读状态:1=未读,2=已读 |
type 与 business_type 返回相同的粗分类值,type_label 返回对应中文名称。粗分类仅用于列表筛选、未读统计和分栏展示;source_type 才是稳定的具体场景分类。查询参数中的 all 只表示不限制粗分类,不会出现在 type、business_type 或 type_label 响应字段中。
business_type 粗分类:
| 使用端 | business_type |
type_label |
分类说明 | 当前包含的 source_type |
|---|---|---|---|---|
| 粉丝端 | subscription |
订阅 | 订阅开通、续费、到期和自动续费状态 | subscription_success、subscription_renewed、subscription_expiring、subscription_expired、subscription_canceled、subscription_auto_renew_closed、subscription_renew_failed |
| 粉丝端 | consume |
消费 | 提问、追问、视频通话消费及退款结果 | question_paid、follow_up_paid、video_call_paid、consume_refund |
| 粉丝端 | benefit |
福利 | 福利可兑换、提交兑换和发放结果 | benefit_redeemable、benefit_redemption_submitted、benefit_fulfilled;另有尚未接入触发入口的 benefit_outcome 模板 |
| 粉丝端 | call |
通话 | 视频通话预约、提醒、完成和其他终态 | video_call_booked、video_call_reminder、video_call_completed、video_call_outcome |
| 粉丝端 | feedback |
反馈 | 提问处理结果、客服反馈、入驻审核、内容审核和通话违规 | question_answered、question_rejected、customer_feedback_handled、customer_feedback_closed、artist_application_approved、artist_application_rejected、tieup_audit、video_call |
| 粉丝端 | system |
系统 | 后台公告和经纪公司绑定邀请 | admin_push、artist_agency_bind_invite |
| 艺人端 | income |
收益 | 订阅、回答和视频通话收益 | income_subscription、income_question、income_video_call |
| 艺人端 | fan |
粉丝 | 新粉丝关注 | artist_followed |
| 艺人端 | question |
提问 | 收到粉丝提问或追问 | question_received、follow_up_received |
| 艺人端 | call |
通话 | 收到预约、开始提醒、完成和其他终态 | video_call_received、video_call_reminder、video_call_completed、video_call_outcome |
| 艺人端 | benefit |
福利 | 收到待发放的福利兑换申请 | benefit_redemption_pending |
| 艺人端 | feedback |
反馈 | 客服反馈、内容审核和通话违规反馈 | customer_feedback_handled、customer_feedback_closed、tieup_audit、video_call |
| 艺人端 | system |
系统 | 后台公告和经纪公司绑定邀请 | admin_push、artist_agency_bind_invite |
注意:视频通话退款结果只向粉丝端写入 business_type=consume、source_type=consume_refund 的消息;艺人端只保留 source_type=video_call_outcome 的通话状态更新,避免同一爽约结果重复通知。其他关联艺人的退款业务仍按各自既有规则通知。
source_type 场景分类:
| 接收端 | business_type |
source_type |
场景名称 | 触发时机或当前状态 |
|---|---|---|---|---|
| 粉丝端 | subscription |
subscription_success |
订阅成功 | 新订阅权益成功发放后;现有超级群 Tieup:Subscribe 消息继续保留 |
| 粉丝端 | subscription |
subscription_renewed |
续费成功 | 续费权益成功发放后;现有超级群 Tieup:Subscribe 消息继续保留 |
| 粉丝端 | subscription |
subscription_expiring |
订阅即将到期 | 到达后台配置的提前通知天数后,每个订阅周期提醒一次;配置为 0 时关闭 |
| 粉丝端 | subscription |
subscription_expired |
订阅已到期 | 订阅生命周期任务或支付渠道状态处理将订阅推进为到期后 |
| 粉丝端 | subscription |
subscription_canceled |
订阅已取消 | 退款或撤销处理将订阅推进为取消后 |
| 粉丝端 | subscription |
subscription_auto_renew_closed |
自动续费已关闭 | Apple 自动续费关闭通知处理成功后,当前权益继续有效至原到期时间 |
| 粉丝端 | subscription |
subscription_renew_failed |
自动续费失败 | Apple 自动续费失败通知处理成功后 |
| 粉丝端 | consume |
question_paid |
提问支付成功 | 提问记录创建和糖果扣减在事务中成功后 |
| 粉丝端 | consume |
follow_up_paid |
追问支付成功 | 追问记录创建和糖果扣减在事务中成功后 |
| 艺人端 | question |
question_received |
收到新提问 | 粉丝提问记录创建和糖果扣减成功后 |
| 艺人端 | question |
follow_up_received |
收到新追问 | 粉丝追问记录创建和糖果扣减成功后 |
| 粉丝端 | feedback |
question_answered |
提问已回答 | 艺人提交回答并完成业务状态更新后 |
| 粉丝端 | feedback |
question_rejected |
提问已拒绝并退款 | 艺人拒绝提问且糖果退款完成后 |
| 粉丝端、艺人端 | feedback |
customer_feedback_handled |
反馈已处理 | 后台回复粉丝或艺人反馈并将状态更新为 3=已处理 后;经纪公司和未知身份不通知 |
| 粉丝端、艺人端 | feedback |
customer_feedback_closed |
反馈已关闭 | 后台填写关闭原因并将粉丝或艺人反馈更新为 4=已关闭 后;经纪公司和未知身份不通知 |
| 粉丝端 | consume |
video_call_paid |
视频通话支付成功 | 视频通话订单扣减糖果成功后 |
| 粉丝端 | call |
video_call_booked |
预约成功 | 视频通话预约创建成功后 |
| 艺人端 | call |
video_call_received |
收到新通话预约 | 粉丝视频通话预约创建成功后 |
| 粉丝端、艺人端 | call |
video_call_reminder |
通话即将开始 | 到达后台配置的提前提醒分钟数;配置为 0 时关闭提醒 |
| 粉丝端、艺人端 | call |
video_call_completed |
通话已完成 | 视频通话正常完成并写入实际时长后 |
| 粉丝端、艺人端 | call |
video_call_outcome |
通话状态更新 | 爽约、取消、退款等通话终态确定后 |
| 粉丝端;非视频通话业务可按既有规则通知艺人端 | consume |
consume_refund |
退款状态更新 | 退款最终成功、失败或关闭后;处理中不发送最终结果消息。视频通话退款不向艺人端发送该消息,艺人端只保留通话状态更新 |
| 粉丝端 | benefit |
benefit_redeemable |
福利可兑换 | 上架福利首次满足兑换条件、仍有库存且尚未兑换时;同一粉丝和福利只提醒一次 |
| 粉丝端 | benefit |
benefit_redemption_submitted |
兑换申请已提交 | 粉丝成功提交福利兑换申请后 |
| 艺人端 | benefit |
benefit_redemption_pending |
收到待发放福利 | 粉丝成功提交福利兑换申请后 |
| 粉丝端 | benefit |
benefit_fulfilled |
福利已发放 | 艺人完成福利发放并成功更新兑换状态后 |
| 未固定 | benefit |
benefit_outcome |
福利状态更新 | 代码已定义消息模板,但当前未发现业务调用入口;客户端不应假设该场景必然下发 |
| 艺人端 | income |
income_subscription |
订阅收益产生 | 订阅业务完成并成功创建收入记录后;待经纪公司结算时正文明确为待结算收入 |
| 艺人端 | income |
income_question |
回答收益产生 | 提问或追问回答业务完成并成功创建收入记录后 |
| 艺人端 | income |
income_video_call |
视频通话收益产生 | 视频通话业务完成并成功创建收入记录后 |
| 艺人端 | fan |
artist_followed |
新粉丝关注 | 粉丝从未关注变为关注后;同一粉丝和艺人按最近成功写入时间滚动一小时限频 |
| 粉丝端 | feedback |
artist_application_approved |
艺人入驻审核通过 | 后台审核通过艺人入驻申请后,固定通知申请人的粉丝身份 |
| 粉丝端 | feedback |
artist_application_rejected |
艺人入驻审核未通过 | 后台驳回艺人入驻申请后,固定通知申请人的粉丝身份 |
| 粉丝端、艺人端 | system |
admin_push |
后台系统公告 | 后台创建系统推送批次后,按目标范围异步写入接收人的系统消息 |
| 粉丝端、艺人端 | system |
artist_agency_bind_invite |
经纪公司绑定邀请 | 经纪公司向未绑定公司的用户发起邀请后;无艺人档案时归粉丝端,已有艺人档案时归艺人端 |
| 粉丝端、艺人端 | feedback |
tieup_audit |
内容审核通知 | 人工审核拒绝用户或艺人提交的内容后;接收端按内容提交方身份确定 |
| 粉丝端、艺人端 | feedback |
video_call |
视频通话违规中断 | 视频审核判定违规并强制结束通话后;通过 payload.action=force_leave_video_call 识别该场景 |
以上 33 个值是当前代码定义或当前写入入口使用的系统消息场景契约。客户端应使用 source_type 与 payload 共同决定页面跳转和交互;标题、正文和 tag_label 仅用于展示,不是稳定的业务判断字段。历史数据库中可能存在迁移前旧值,不作为当前接口支持枚举。
所有业务系统消息先写入 tieup_system_message,再投递异步队列调用融云。队列或融云失败不回滚订阅、扣款、福利、通话等业务结果;服务端每分钟扫描 notify_status in (0,2) 且未超过最大尝试次数的消息重新投递。notify_status=1 只表示融云服务端已成功接收发送请求,厂商通知是否最终展示仍受客户端注册、厂商配置和用户系统通知权限影响。
响应字段:
| 字段 | 类型 | 说明 |
|---|---|---|
items[].id |
integer | 系统消息 ID |
items[].title |
string | 消息标题,例如订阅成功、续费成功、提问已支付、追问已支付、福利可兑换、兑换申请已提交 |
items[].content |
string | 消息内容 |
items[].created_at |
string/null | 消息创建时间 |
items[].type |
string | 系统消息粗分类,等同 tieup_system_message.business_type;完整取值见本节粗分类表 |
items[].business_type |
string | 系统消息粗分类,与 type 完全相同;用于筛选、未读统计和分栏展示 |
items[].type_label |
string | 消息类型展示文案 |
items[].message_category |
string | 消息分类:artist=艺人消息,fan=粉丝消息 |
items[].tag_label |
string | 右侧标签文案 |
items[].read_status |
integer | 阅读状态:1=未读,2=已读 |
items[].read_at |
string/null | 阅读时间 |
items[].link_id |
integer/null | 关联业务主记录 ID,用于 APP 跳转或业务处理 |
items[].source_type |
string | 稳定的系统消息场景分类;完整取值、接收端和触发时机见本节场景分类表 |
items[].source_no |
string | 业务来源编号 |
items[].payload |
object | 业务扩展数据;具体字段由 source_type 决定,不包含敏感明文 |
pagination.page |
integer | 当前页码 |
pagination.page_size |
integer | 每页数量 |
pagination.total |
integer | 总条数 |
pagination.next_cursor |
string/null | 游标分页预留字段,当前返回 null |
当 items[].source_type=customer_feedback_handled 或 customer_feedback_closed 时,link_id 为 tieup_feedback.id,source_no 固定为 feedback:{feedback_id}。粉丝反馈归属粉丝端,艺人反馈归属提交时的艺人端;客户端点击消息后必须按 payload.action=view_feedback_detail 和 payload.feedback_id 打开“我的反馈”详情。消息正文取实际回复或关闭原因的前 30 个字符,超过时追加 ...,完整内容以反馈详情接口的 handle_result 为准。
| 字段 | 类型 | 说明 |
|---|---|---|
items[].payload.feedback_id |
integer | 反馈 ID,与 items[].link_id 相同 |
items[].payload.feedback_type |
integer | 反馈类型:1=功能建议,2=问题反馈,3=内容反馈,4=投诉,5=其他 |
items[].payload.handle_status |
integer | 通知产生后的终态:3=已处理,4=已关闭 |
items[].payload.action |
string | 固定为 view_feedback_detail,表示打开当前身份的反馈详情 |
回复并处理后的完整消息项示例:
{
"id": 90003,
"title": "反馈处理通知",
"content": "您反馈的登录问题已经处理完成,请重新登录后查看,如仍有问题请...",
"created_at": "2026-08-04 15:30:00",
"type": "feedback",
"business_type": "feedback",
"type_label": "反馈",
"message_category": "fan",
"tag_label": "反馈",
"read_status": 1,
"read_at": null,
"link_id": 88,
"source_type": "customer_feedback_handled",
"source_no": "feedback:88",
"payload": {
"feedback_id": 88,
"feedback_type": 2,
"handle_status": 3,
"action": "view_feedback_detail"
}
}
关闭反馈后的完整消息项示例:
{
"id": 90004,
"title": "反馈关闭通知",
"content": "该问题缺少必要的设备信息,本次反馈已关闭",
"created_at": "2026-08-04 15:35:00",
"type": "feedback",
"business_type": "feedback",
"type_label": "反馈",
"message_category": "artist",
"tag_label": "反馈",
"read_status": 1,
"read_at": null,
"link_id": 89,
"source_type": "customer_feedback_closed",
"source_no": "feedback:89",
"payload": {
"feedback_id": 89,
"feedback_type": 4,
"handle_status": 4,
"action": "view_feedback_detail"
}
}
当 items[].source_type=artist_agency_bind_invite 时,items[].payload 包含以下字段。邀请状态从邀请主记录实时读取,不使用消息创建时的状态快照,因此用户同意、拒绝或邀请过期后,再次查询列表和详情均返回最新状态。
| 字段 | 类型 | 说明 |
|---|---|---|
items[].payload.invite_no |
string | 经纪公司绑定邀请编号,与 items[].source_no 相同 |
items[].payload.agency_company_id |
integer | 发起邀请的经纪公司 ID |
items[].payload.agency_company_name |
string | 发起邀请时的经纪公司名称快照 |
items[].payload.target_user_id |
integer | 被邀请 APP 用户 ID |
items[].payload.target_artist_id |
integer/null | 被邀请艺人档案 ID;普通用户尚未创建艺人档案时为空 |
items[].payload.target_identity |
string | 邀请消息接收身份:fan=粉丝端,artist=艺人端 |
items[].payload.action_required |
boolean | 是否仍需用户处理;仅 invite_status=pending 时为 true,其他状态为 false |
items[].payload.priority |
string | 操作优先级;待处理时为 urgent,其他状态为 normal |
items[].payload.invite_status |
string | 邀请状态:pending=待处理、accepted=已同意、rejected=已拒绝、expired=已过期、cancelled=已取消 |
经纪公司绑定邀请完整消息项示例(待处理状态):
{
"id": 90001,
"title": "经纪公司绑定邀请",
"content": "星河娱乐邀请您成为旗下艺人,请确认是否同意。",
"created_at": "2026-07-15 10:00:00",
"type": "system",
"business_type": "system",
"type_label": "系统",
"message_category": "artist",
"tag_label": "艺人",
"read_status": 1,
"read_at": null,
"link_id": 70001,
"source_type": "artist_agency_bind_invite",
"source_no": "ABI202607150001",
"payload": {
"invite_no": "ABI202607150001",
"agency_company_id": 1001,
"agency_company_name": "星河娱乐",
"target_user_id": 10001,
"target_artist_id": 20001,
"target_identity": "artist",
"action_required": true,
"priority": "urgent",
"invite_status": "pending"
}
}
艺人入驻审核结果消息使用 link_id = tieup_artist_application.id,点击后统一跳转入驻申请详情。客户端必须按 source_type 和 payload.application_id 路由,不得根据标题文字判断审核结果。完整消息项示例:
{
"id": 90002,
"title": "艺人入驻审核未通过",
"content": "您的艺人入驻申请未通过审核:资料不完整,请补充相关经历",
"created_at": "2026-07-27 16:30:00",
"type": "feedback",
"business_type": "feedback",
"type_label": "反馈",
"message_category": "fan",
"tag_label": "反馈",
"read_status": 1,
"read_at": null,
"link_id": 88,
"source_type": "artist_application_rejected",
"source_no": "application:88",
"payload": {
"application_id": 88,
"application_status": 3,
"artist_type": null,
"artist_id": null,
"agency_company_id": null,
"audit_remark": "资料不完整,请补充相关经历",
"action_required": false,
"priority": "normal"
}
}
响应示例:
{
"code": 200,
"message": "成功",
"data": {
"items": [
{
"id": 90001,
"title": "经纪公司绑定邀请",
"content": "星河娱乐邀请您成为旗下艺人,请确认是否同意。",
"created_at": "2026-07-15 10:00:00",
"type": "system",
"business_type": "system",
"type_label": "系统",
"message_category": "artist",
"tag_label": "艺人",
"read_status": 1,
"read_at": null,
"link_id": 70001,
"source_type": "artist_agency_bind_invite",
"source_no": "ABI202607150001",
"payload": {
"invite_no": "ABI202607150001",
"agency_company_id": 1001,
"agency_company_name": "星河娱乐",
"target_user_id": 10001,
"target_artist_id": 20001,
"target_identity": "artist",
"action_required": true,
"priority": "urgent",
"invite_status": "pending"
}
}
],
"pagination": {
"page": 1,
"page_size": 20,
"total": 1,
"next_cursor": null
}
}
}
5.13.2 我的系统消息详情
GET /tieup/api/v1/me/system-messages/90001
鉴权:需要 Authorization: Bearer <access_token>。
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
message_id |
integer | 是 | 系统消息 ID |
响应字段:同 5.13.1 items[] 单条结构。
响应示例:
{
"code": 200,
"message": "成功",
"data": {
"id": 90001,
"title": "经纪公司绑定邀请",
"content": "星河娱乐邀请您成为旗下艺人,请确认是否同意。",
"created_at": "2026-07-15 10:00:00",
"type": "system",
"business_type": "system",
"type_label": "系统",
"message_category": "fan",
"tag_label": "艺人",
"read_status": 2,
"read_at": "2026-07-15 10:30:00",
"link_id": 70001,
"source_type": "artist_agency_bind_invite",
"source_no": "ABI202607150001",
"payload": {
"invite_no": "ABI202607150001",
"agency_company_id": 1001,
"agency_company_name": "星河娱乐",
"target_user_id": 10001,
"target_artist_id": null,
"target_identity": "fan",
"action_required": false,
"priority": "normal",
"invite_status": "rejected"
}
}
}
5.13.3 批量标记系统消息已读
PATCH /tieup/api/v1/me/system-messages/read
鉴权:需要 Authorization: Bearer <access_token>。
请求体二选一。按单一分类将当前分类全部标记已读:
{
"type": "subscription"
}
按系统消息 ID 将指定的一条或多条消息标记已读:
{
"sys_message_ids": [90001, 90002]
}
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
type |
string | 条件必填 | 当前身份的单一系统消息粗分类;枚举与 5.13.1 列表接口的 business_type 一致,不支持 all;与 sys_message_ids 必须且只能传一个 |
sys_message_ids |
array | 条件必填 | 系统消息 ID 数组,最少 1 条、最多 100 条,ID 不允许重复;与 type 必须且只能传一个 |
sys_message_ids[] |
integer | 条件必填 | 正整数系统消息 ID |
粉丝端支持 subscription、consume、benefit、call、feedback、system;艺人端支持 income、fan、question、call、benefit、feedback、system。空值、all、非法值或当前身份不支持的分类均返回 422。
业务规则:
-
type模式只更新当前 Token 身份、当前接收人下该粗分类的全部未读系统消息。 -
sys_message_ids模式只更新当前 Token 身份、当前接收人拥有且 ID 命中的未读系统消息;不存在、属于其他用户或其他身份、已经已读的 ID 不更新,也不计入read_count。 - 两种模式都使用单次批量更新并保持幂等;重复提交时已读消息不会再次计数。
响应字段:
| 字段 | 类型 | 说明 |
|---|---|---|
read_count |
integer | 本次实际从未读更新为已读的系统消息数量;重复提交时不会重复计数 |
响应示例:
{
"code": 200,
"message": "成功",
"data": {
"read_count": 2
}
}
5.13.4 我的系统消息未读数
GET /tieup/api/v1/me/system-messages/unread-count
鉴权:需要 Authorization: Bearer <access_token>。
粉丝端响应字段固定为 all_count、subscription_count、consume_count、benefit_count、call_count、feedback_count、system_count、fan_message_unread_count、pending_count;艺人端固定为 all_count、income_count、fan_count、question_count、call_count、benefit_count、feedback_count、system_count、pending_count。所有计数字段均为非负整数。all_count 仅表示当前身份全部未读系统消息数,其他系统消息字段是对应粗分类未读数;fan_message_unread_count 和 pending_count 均不计入 all_count。
pending_count 为福利待发放数量:艺人端统计当前艺人全部历史福利兑换记录中 tieup_benefit_redemption.status = 1 的记录,福利下架或删除后仍计入;粉丝端当前无艺人待办,固定返回 0。
粉丝聊天未读统计口径:fan_message_unread_count 汇总当前粉丝历史订阅过的所有艺人发送的未读聊天消息。艺人定向消息必须发送成功、未撤回、接收粉丝为当前用户且尚未读;艺人普通群发消息必须发送成功、未撤回,且当前粉丝没有 MySQL 已读回执或 Redis 实时已读记录。两类消息的发送时间都必须落在当前粉丝对同一艺人的任一订阅有效区间内,已过期订阅不会抹去有效期内仍未读的历史消息;订阅断档期间、粉丝发给艺人、发送失败、已撤回或已被当前粉丝身份删除的消息均不统计。渠道关闭艺人群发已读能力时,与粉丝聊天列表保持一致,只统计艺人定向未读消息,不统计普通群发。
粉丝端完整响应示例:
{
"code": 200,
"message": "成功",
"data": {
"all_count": 12,
"subscription_count": 3,
"consume_count": 2,
"benefit_count": 2,
"call_count": 2,
"feedback_count": 1,
"system_count": 2,
"fan_message_unread_count": 8,
"pending_count": 0
}
}
响应字段:
| 字段 | 类型 | 返回身份 | 说明 |
|---|---|---|---|
data.all_count |
integer | 粉丝、艺人 | 当前身份未读系统消息总数,不包含 fan_message_unread_count |
data.subscription_count |
integer | 粉丝 | 订阅类未读系统消息数 |
data.consume_count |
integer | 粉丝 | 消费类未读系统消息数 |
data.income_count |
integer | 艺人 | 收益类未读系统消息数 |
data.fan_count |
integer | 艺人 | 粉丝类未读系统消息数 |
data.question_count |
integer | 艺人 | 提问类未读系统消息数 |
data.call_count |
integer | 粉丝、艺人 | 通话类未读系统消息数 |
data.benefit_count |
integer | 粉丝、艺人 | 福利类未读系统消息数 |
data.feedback_count |
integer | 粉丝、艺人 | 反馈类未读系统消息数 |
data.system_count |
integer | 粉丝、艺人 | 系统类未读系统消息数 |
data.fan_message_unread_count |
integer | 仅粉丝 | 当前粉丝订阅艺人的未读聊天消息总数,统计口径见本节说明;艺人身份不返回 |
data.pending_count |
integer | 粉丝、艺人 | 待发放福利数量;艺人统计兑换状态 status=1 的全部历史福利兑换记录,粉丝端固定为 0;不计入 all_count |
艺人端完整响应示例:
{
"code": 200,
"message": "成功",
"data": {
"all_count": 14,
"income_count": 3,
"fan_count": 2,
"question_count": 2,
"call_count": 2,
"benefit_count": 1,
"feedback_count": 1,
"system_count": 3,
"pending_count": 2
}
}
5.13.5 粉丝系统消息摘要
GET /tieup/api/v1/me/system-messages/summary
鉴权:需要 Authorization: Bearer <access_token>,且当前 Token 的 current_identity 必须为 fan。艺人身份调用返回 403,接口不会跨身份读取同一账号的粉丝消息。接口不接收查询参数或请求体。
统计口径:仅统计 receiver_identity=fan 且 receiver_id=当前 tieup_user.id 的系统消息。unread_count 统计 read_status=1 的消息,total_count 统计包括已读和未读在内的全部消息,latest_message_at 取全部消息中最大的 created_at,不受阅读状态影响。
完整响应示例:
{
"code": 200,
"message": "成功",
"data": {
"unread_count": 3,
"total_count": 12,
"latest_message_at": "2026-07-20 15:30:00"
}
}
响应字段:
| 字段 | 类型 | 说明 |
|---|---|---|
code |
integer | 业务状态码,成功为 200 |
message |
string | 响应说明,成功为 成功 |
data |
object | 粉丝系统消息摘要 |
data.unread_count |
integer | 当前粉丝未读系统消息数量 |
data.total_count |
integer | 当前粉丝系统消息历史总数,包括已读和未读 |
data.latest_message_at |
string/null | 最后一条系统消息的创建时间,格式为 Y-m-d H:i:s;无消息时为 null |
无系统消息时完整响应示例:
{
"code": 200,
"message": "成功",
"data": {
"unread_count": 0,
"total_count": 0,
"latest_message_at": null
}
}
5.13.6 同意经纪公司绑定邀请
PATCH /tieup/api/v1/me/agency-bind-invites/ABI202607150001/accept
鉴权:需要 Authorization: Bearer <access_token>,粉丝和艺人身份均可调用。请求体为空,服务端按邀请的 target_user_id 校验当前账号;同一结果重复提交幂等返回当前状态。
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
invite_no |
string | 是 | 经纪公司绑定邀请编号 |
响应字段:
| 字段 | 类型 | 说明 |
|---|---|---|
invite_no |
string | 邀请编号 |
agency_company_id |
integer | 邀请经纪公司 ID |
artist_created |
boolean | 本次同意操作是否自动创建了艺人档案 |
artist_id |
integer/null | 艺人档案 ID;拒绝普通用户邀请时可能为空 |
invite_status |
string | 邀请状态:pending、accepted、rejected、expired、cancelled |
handled_at |
string/null | 邀请处理时间 |
完整响应示例:
{
"code": 200,
"message": "成功",
"data": {
"invite_no": "ABI202607150001",
"agency_company_id": 1001,
"artist_created": true,
"artist_id": 20001,
"invite_status": "accepted",
"handled_at": "2026-07-15 10:30:00"
}
}
5.13.7 拒绝经纪公司绑定邀请
PATCH /tieup/api/v1/me/agency-bind-invites/ABI202607150001/reject
鉴权、权限与幂等规则同 5.13.6。拒绝只更新邀请状态,不建立经纪公司绑定。
路径参数和响应字段同 5.13.6。
完整响应示例:
{
"code": 200,
"message": "成功",
"data": {
"invite_no": "ABI202607150001",
"agency_company_id": 1001,
"artist_created": false,
"artist_id": null,
"invite_status": "rejected",
"handled_at": "2026-07-15 10:30:00"
}
}
经纪公司绑定邀请消息通过 business_type=system 归入系统分类,通过 source_type=artist_agency_bind_invite 区分交互场景。普通用户在邀请创建时收到粉丝端消息,已有艺人收到艺人端消息;消息归属创建后不迁移。服务端动态返回 payload.action_required、payload.priority、payload.invite_status、payload.target_identity 和公司信息,客户端不得根据标题判断操作类型;其中 payload.invite_status 是同意、拒绝及其他终态的唯一状态字段,不在消息项顶层重复返回。
普通用户同意邀请后,服务端直接创建经纪公司艺人档案并绑定邀请公司,无需平台审核;艺名取粉丝昵称,头像由前端使用默认展示,手机号取当前账号手机号。响应中的 artist_created=true 表示本次自动建档,当前粉丝 Token 仍可继续使用,需要进入艺人端时调用现有身份切换接口获取艺人身份 Token。已有艺人同意时 artist_created=false,只更新经纪公司绑定。
业务规则:
- 列表、详情、已读和未读数都只作用于当前 Token 的
current_identity,不会混合粉丝端和艺人端消息。 - 当前身份为
artist时,服务端会校验当前账号tieup_user.is_idol = 1且存在tieup_artist档案,否则返回无权限错误。 - 详情和已读接口都限制只能操作当前身份自己的消息,不能跨用户或跨身份读取、标记。
- 已读接口幂等:重复提交同一批消息不会报错,已读消息不会重复计入
read_count。 -
type与business_type均返回粗分类,APP 可优先展示type_label;具体通知场景使用标题和正文展示。 - 同一用户只能有一条待处理绑定邀请;已拒绝、已过期或已取消后允许重新邀请,已经绑定经纪公司的艺人禁止再次邀请。
测试状态:已完成代码实现和 PHP 语法检查,待登录态和真实系统消息数据联调。