Appearance
客户不在 APP 时的消息推送
客户问完就退出 APP 了,客服十分钟后才回。要让他收到系统推送,需要你的服务端参与。
这件事为什么要你参与
给 APP 发系统推送需要推送证书:iOS 的 APNs 证书、Android 各家厂商的推送通道。这些都在你手里,合从没有,也不应该有。
所以分工是:合从负责报信,你负责推送。客户离线期间客服发了新消息,合从把这条消息的信息发到你指定的地址,你的服务端查到这位客户的推送 token,用你自己的推送通道发出去。
和未读红点的分工
推送要你的服务端参与,SDK 内置的未读消息与红点不用:客户回到 APP 时 SDK 查一次未读数,你把数字画在自己的客服入口上就行。
| 什么时候触达客户 | 要你做什么 | |
|---|---|---|
| 系统推送 | 客户完全退出 APP 也能收到 | 服务端接回调 + 用你自己的推送通道发 |
| 未读红点 | 客户下次打开 APP 时看到 | 在入口上画一个数字 |
两件事是互补的:红点管「客户回来了」,推送管「客户没回来」。这一页的推送链路要拉服务端同事一起做,先只接红点也成立 —— 客户重新打开 APP 就能看到有新回复,做法见未读消息与红点。
配置回调地址
在工作台的 App 渠道详情页,左侧选择 离线消息通知,填写你的服务端接收地址。
密钥可以不填。填了之后合从会对报文签名,你的服务端可以据此确认这条请求确实来自合从,见下面的验真。
什么时候会收到
三个条件同时成立时,合从发出一次请求:
- 这位客户已经离开会话 —— 退出 APP、切到后台、或者关掉了客服页面
- 发消息的是人工客服
- 消息不是内部备注
机器人的回复、自动回复、场景消息都不会触发。客户还在 APP 里看着聊天页时也不会。
自己嵌容器的话,前后台联动必须接
客户切到后台时 SDK 会主动断开连接,合从据此在一秒内判定他已离开。这一步依赖 APP 的前后台事件。
用 SDK 提供的整页界面时,这件事已经内置。把聊天嵌进自己页面的话,你必须转发宿主的前后台回调,否则合从会一直认为客户在线,离线推送一条都不会发,工作台里这位客户的在线状态也会长亮。做法见把聊天嵌进自己的页面。
你会收到什么
一个 POST 请求,Content-Type: application/json,报文结构:
json
{
"event": "offline_message",
"tenantId": "…",
"channelId": "…",
"dialogId": "…",
"customerId": "…",
"anonymousId": "…",
"externalUserId": "…",
"agentNickname": "小美",
"message": {
"id": "…",
"contentType": "text",
"text": "您的订单已经发出了",
"createdAt": 1755500000000
},
"ts": 1755500000100
}| 字段 | 说明 |
|---|---|
anonymousId | 合从给这台设备的稳定标识,客户没登录时靠它认人 |
externalUserId | 你通过 identify 传的会员 ID,客户登录过才有值 |
agentNickname | 客服的对外昵称,可以直接写进推送文案 |
message.contentType | 消息类型,text 之外还有图片、视频、语音等 |
message.text | 文本内容,只给前 500 个字符。非文本消息这里是 null,按 contentType 出兜底文案(例如「[图片]」) |
message.createdAt | 消息时间,毫秒时间戳 |
anonymousId 和 externalUserId 两个都会给,不是二选一。客户登录过的话两个同时有值。
怎么找到该推给谁
你的服务端要能从报文里的身份找到设备的推送 token,分两种情况:
客户登录过:用 externalUserId,那就是你自己的会员 ID,直接查你的库。
客户没登录:只能用 anonymousId。这个值要提前存下来 —— 在 APP 里监听 onAnonymousIdChanged 回调,拿到值之后连同这台设备的推送 token 一起报给你的服务端:
kotlin
// Android
HecongChat.onAnonymousIdChanged = { anonymousId ->
reportToMyServer(anonymousId, myPushToken)
}不要用你自己生成的设备 ID 去对照
anonymousId 由合从维护,可能和你在配置里传的 deviceId 不同。以回调里给到的值为准。
验证请求确实来自合从
配了密钥的话,请求头里会带一个签名:
X-Hecong-Signature: sha256=<十六进制签名>签名是用你填的密钥对请求体原始字符串做 HMAC-SHA256。你的服务端用同样的方法算一遍,比对一致再处理。
用解析后的对象重新序列化再算签名会对不上,要用原始的请求体字节。
送达与失败
只发一次,不重试。 手机推送本身不承诺百分之百送达,为报信建重试机制的收益有限。
你的服务端返回什么状态码都算送到了,包括 4xx。合从不消费响应内容。连续失败 5 次(超时、连不上、5xx)之后,这个渠道的报信会暂停 5 分钟再恢复,避免地址配错时持续空打。
所以你的服务端要做到:快速返回,把推送逻辑丢进自己的队列异步处理,不要在这个请求里同步等推送结果。
怎么自测
工作台里没有测试发送按钮,验证要走一遍真实链路:
- 真机打开 APP,进客服页面发一条消息,让对话建立起来
- 把 APP 切到后台或直接杀掉进程
- 在工作台里用人工客服身份回一条消息
- 看你的服务端有没有收到回调
收不到的话,先对照什么时候会收到的三个条件,再看接入问题排查。
用机器人回复、或者客户还开着客服页面,都不会触发。
下一步
- 未读消息与红点 —— APP 开着时的提醒
- 把聊天嵌进自己的页面 —— 前后台联动的接法