Appearance
WebSocket 连接与订阅
调用 /visitor/data/get 或 /agent/data/get 后,从响应的 setting.ws_address 与 setting.appkey 建立实时连接。
访客端订阅 /visitor/data/get 返回的 visitor.channel,不要自行拼接频道名。客服端订阅当前客服频道 agent-{agent_id};工作台还会使用商户全局频道接收状态变化。
HTTP 接口负责读取和写入业务数据;WebSocket 只负责服务端下行同步。发生断线时,应重新连接、重新订阅,再使用消息历史接口按 mid 补齐缺失记录。
连接参数来源
不要在前端硬编码 Socket 地址、应用 Key 或频道名。每次身份初始化后从接口响应读取:
| 端 | 地址与频道来源 | 必须订阅的频道 |
|---|---|---|
| 访客端 | /visitor/data/get 的 setting.ws_address、setting.appkey、visitor.channel | visitor.channel;Web 页面还监听 global-{bid} 的配置和客服状态变化。 |
| 客服端 | /agent/data/get 的实时配置与 agent.agent_id | agent-{agent_id};工作台还监听 global-{bid}。 |
系统 Web 页面使用 Pusher 协议兼容的 Socket 客户端。自定义前端应使用兼容客户端,并把 ws_address 解析为协议、主机和端口:
js
const socket = new Socket(setting.appkey, {
enabledTransports: ['ws', 'wss'],
encrypted: wsUrl.protocol === 'wss:',
wsHost: wsUrl.hostname,
wsPort: wsUrl.port || 80,
wssPort: wsUrl.port || 443
})
const channel = socket.subscribe(visitor.channel)
channel.on('pusher:subscription_succeeded', () => {
// 可在此确认订阅完成;不要把它当作消息数据已完全同步的保证
})当页面本身运行在 HTTPS 下,连接必须使用 wss://,否则浏览器会阻止不安全的 WebSocket 连接。
推荐客户端状态机
text
HTTP 初始化成功
↓
创建 Socket → 建立连接 → 订阅频道
↓ ↓
监听事件 ← subscription_succeeded
↓
连接中断 → 重新连接 → 重新订阅 → 按 mid 补拉消息| 状态 | 客户端处理 |
|---|---|
connecting | 保留现有消息和会话 UI;不要清空本地列表。 |
connected | 确认目标频道已订阅,允许接收增量事件。 |
| 断开或订阅失败 | 显示网络状态,可重试连接;不把本地未确认消息直接判定失败。 |
| 重连订阅成功 | 重新拉取当前消息历史或使用最后一个 mid 补齐,随后继续增量处理。 |
事件处理原则
- WebSocket 事件不替代 HTTP 响应:发送、撤回、转接等操作先以 HTTP 返回为准。
message.created可能在 HTTP 成功前后到达;使用mid去重,客户端临时消息可结合tmp_mid合并。- 不要假设事件严格有序。对同一对话的消息按服务端
mid排序。 - 收到未知会话、无法合并的事件或长时间断线后,重新读取对应数据,而不是在本地猜测完整对象。
- 前端不得通过 WebSocket 发送业务写入、商户密钥或内部推送参数。