WebSocket 接口文档
-
端点信息
-
URL: ws.cuzservice.vip
- 协议: WebSocket(支持 JSON 消息)。
- 认证: 要求 JWT token,通过以下方式传递:
- HTTP 头:Authorization: Bearer
(建议方式) - WebSocket 子协议:Sec-WebSocket-Protocol:
- URL 参数:?token=
- 空闲检测: 服务器配置了 60 秒空闲检测(IdleStateHandler),客户端需定期发送心跳以保持连接。
- 心跳机制
为保持 WebSocket 连接活跃,客户端需发送心跳消息,服务器会响应以确认连接状态。
- 客户端发送:
json
json
{
"type": "UP_HEARTBEAT",
"data": {
"timestamp": long // 客户端时间戳(毫秒)
}
}
- 服务器响应:
json
json
{
"type": "DOWN_HEARTBEAT",
"data": {
"timestamp": long // 服务器时间戳(毫秒)
}
}
-
频率建议: 每 30 秒发送一次心跳,最大间隔不超过 60 秒以避免连接被服务器关闭。
-
超时处理: 如果 60 秒内未收到客户端消息(包括心跳),服务器将关闭连接。
-
认证机制
-
认证方式: 客户端在建立 WebSocket 连接时需提供有效的 JWT token。
-
Token 获取:
-
从登录接口获取 JWT token(具体接口由 TokenProvider 实现)。
-
Token 验证:
-
服务器通过 TokenProvider 验证 token 签名。
- 检查 Redis 中是否存在对应的 loginKey(由 TokenProvider.loginKey(token) 生成)。
-
提取 token 中的 userId(Snowflake ID,Long 类型,表示坐席或临时用户)。
-
失败处理:
-
如果 token 缺失、无效或 Redis 中不存在,服务器返回错误消息并关闭连接:
json
json { "error": "未授权" // 或 "缺少 token", "无效 token", "Token 已过期或无效", "无效身份" } -
消息格式
所有 WebSocket 消息均为 JSON 格式,结构如下:
json
{
"type": "string",
"data": object
}
- 字段说明:
- type: 消息类型,枚举值见 WebSocketMessageType(如 UP_SEND_MESSAGE, DOWN_NEW_MESSAGE)。
- data: 消息内容,具体结构取决于 type。
支持的消息类型
| 方向 | 类型 | 描述 |
|---|---|---|
| 上行 | UP_AUTH | 授权请求 |
| 上行 | UP_SEND_MESSAGE | 发送聊天消息 |
| 上行 | UP_MARK_READ | 标记会话消息为已读 |
| 上行 | UP_HEARTBEAT | 心跳消息 |
| 下行 | DOWN_AUTH | 授权响应 |
| 下行 | DOWN_NEW_MESSAGE | 新消息通知 |
| 下行 | DOWN_MESSAGE_SENT | 消息发送成功确认 |
| 下行 | DOWN_MARK_READ | 标记已读通知 |
| 下行 | DOWN_HEARTBEAT | 心跳响应 |
| 下行 | DOWN_NEW_SESSION | 新会话通知(会话转移) |
| 下行 | DOWN_ERROR | 错误响应 |
UP_MARK_READ:消息进入可视区域:当用户滚动聊天窗口,消息出现在屏幕可视区域内时,可能会被标记为已读。这种方式常见于移动端或Web端聊天应用。
- 消息类型详情
5.1 上行消息
客户端调用示例
客户端需在连接建立后立即发送 UP_AUTH 消息:
json
{
"type": "UP_AUTH",
"data": {
"token": "eyJhbGciOiJIUzUxMiJ9..."
}
}
服务端响应(成功):
json
{
"type": "DOWN_AUTH",
"data": {
"success": true,
"message": "认证成功"
}
}
服务端响应(失败):
json
{
"type": "DOWN_AUTH",
"data": {
"success": false,
"message": "无效 token"
}
}
UP_SEND_MESSAGE(发送消息)
-
描述: 客户端发送聊天消息到指定会话。
-
请求格式:
json
json
{
"type": "UP_SEND_MESSAGE",
"data": {
"sessionId": long, // 会话 ID
"content": string, // 消息内容
"lang":string
}
}
-
响应:
-
成功:DOWN_MESSAGE_SENT(确认消息已发送)。
- 失败:DOWN_ERROR(如会话不存在或用户无权限)。
UP_MARK_READ(标记已读)
-
描述: 客户端标记指定会话的消息为已读。
-
请求格式:
json
json
{
"type": "UP_MARK_READ",
"data": {
"sessionId": long // 会话 ID
}
}
-
响应:
-
成功:DOWN_MARK_READ(通知会话参与者)。
- 失败:DOWN_ERROR(如会话不存在或用户无权限)。
UP_HEARTBEAT(心跳)
-
描述: 客户端发送心跳以保持连接。
-
请求格式:
json
json
{
"type": "UP_HEARTBEAT",
"data": {
"timestamp": long // 客户端时间戳(毫秒)
}
}
-
响应:
-
成功:DOWN_HEARTBEAT。
- 失败:DOWN_ERROR。
5.2 下行消息
DOWN_NEW_MESSAGE(新消息通知)
-
描述: 通知接收者有新消息。
-
格式:
json
json
{
"type": "DOWN_NEW_MESSAGE",
"data": {
"chat": {
"id": long, // 消息 ID
"sessionId": long, // 会话 ID
"senderId": long, // 发送者 ID
"receiverId": long, // 接收者 ID
"content": string, // 消息内容
"sendTime": long, // 发送时间(毫秒)
"isRead": boolean, // 是否已读
"chatType": integer // 消息类型(1: 会员-客服, 2: 临时用户-客服)
},
"sessionId": long, // 会话 ID
"unreadCount": integer // 该会话的未读消息数
}
}
DOWN_MESSAGE_SENT(消息发送成功)
-
描述: 确认客户端发送的消息已保存。
-
格式:
json
json
{
"type": "DOWN_MESSAGE_SENT",
"data": {
"chatId": long, // 消息 ID
"sessionId": long, // 会话 ID
"sendTime": long // 发送时间(毫秒)
}
}
DOWN_MARK_READ(标记已读通知)
-
描述: 通知会话参与者消息已标记为已读。
-
格式:
json
json
{
"type": "DOWN_MARK_READ",
"data": {
"sessionId": long // 会话 ID
}
}
DOWN_HEARTBEAT(心跳响应)
-
描述: 服务器响应客户端心跳。
-
格式:
json
json
{
"type": "DOWN_HEARTBEAT",
"data": {
"timestamp": long // 服务器时间戳(毫秒)
}
}
DOWN_QUERY_UNREAD(未读消息数查询结果)
-
描述: 返回用户所有会话的未读消息数。
-
格式:
json
json
{
"type": "DOWN_QUERY_UNREAD",
"data": [
{
"sessionId": long, // 会话 ID
"unreadCount": integer // 未读消息数
}
// ... 更多会话
]
}
DOWN_NEW_SESSION(新会话通知)
-
描述: 通知用户有新的会话(新临时客户进入及转接)。
-
格式:
json
json
{
"type": "DOWN_NEW_SESSION",
"data": {
"session": {
"id": long, // 会话 ID
"userId": long, // 用户 ID(坐席)
"tempUserId": long, // 临时用户 ID
"status": integer // 会话状态(1: 活跃)
// 其他会话字段
}
}
}
DOWN_ERROR(错误响应)
-
描述: 返回错误信息。
-
格式:
json
json
{
"type": "DOWN_ERROR",
"data": {
"code": string, // 错误码(如 "UNAUTHORIZED", "SESSION_NOT_FOUND")
"message": string // 错误描述
}
}
- 错误码
| 错误码 | 描述 |
|---|---|
| UNAUTHORIZED | 未认证或用户无权限 |
| SESSION_NOT_FOUND | 会话不存在或已关闭 |
| INVALID_TYPE | 未知的消息类型 |
| INVALID_RECIPIENT | 接收者未指定 |
| PROCESS_ERROR | 处理消息失败 |
| SERVER_ERROR | 服务器内部错误 |
-
使用示例
7.1 建立连接
javascript
const ws = new WebSocket('ws://<your-server>:8081/ws', ['<jwt-token>']);
// 或者使用 URL 参数
// const ws = new WebSocket('ws://<your-server>:8081/ws?token=<jwt-token>');
ws.onopen = () => {
console.log('Connected');
// 启动心跳
setInterval(() => {
ws.send(JSON.stringify({
type: 'UP_HEARTBEAT',
data: { timestamp: Date.now() }
}));
}, 30000);
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log('Received:', msg);
};
ws.onclose = () => console.log('Disconnected');
7.2 发送消息
json
{
"type": "UP_SEND_MESSAGE",
"data": {
"sessionId": 123,
"content": "Hello, how can I help you?"
}
}
7.3 标记已读
json
{
"type": "UP_MARK_READ",
"data": {
"sessionId": 123
}
}
7.4 查询未读消息数
json
{
"type": "UP_QUERY_UNREAD",
"data": {}
}
-
注意事项
-
认证要求: 确保提供有效的 JWT token,否则连接将被拒绝。
- 心跳频率: 每 30 秒发送一次心跳,最大间隔不超过 60 秒。
- 会话状态: 仅活跃会话(status=1)支持消息发送和标记已读。
- 未读消息数: UP_QUERY_UNREAD 返回所有相关会话的未读消息数,需检查 sessionId。