diff --git a/spec/ai-robot/openapi.provider.yaml b/spec/ai-robot/openapi.provider.yaml new file mode 100644 index 0000000..af75421 --- /dev/null +++ b/spec/ai-robot/openapi.provider.yaml @@ -0,0 +1,596 @@ +openapi: 3.0.3 +info: + title: Multi-Channel Customer Service API + description: | + 多渠道客服主框架对外提供的 API 契约。 + + 本文件定义主框架对外提供的能力(Provider): + - 渠道消息回调接口(微信、抖音、京东等) + - 人工客服工作台 REST API + - WebSocket 实时通信协议说明 + version: 1.0.0 + x-contract-level: L0 + x-consumer: "frontend, wechat-server, douyin-server, jd-server" + x-provider: "java-main-framework" + +servers: + - url: http://{host}:{port} + description: | + 服务地址占位符,根据环境替换: + - 开发环境: http://localhost:8080 + - 测试环境: http://ai-robot-test:8080 + - 生产环境: http://ai-robot:8080 + variables: + host: + default: localhost + description: 服务主机名 + port: + default: "8080" + description: 服务端口 + +tags: + - name: Channel Callback + description: 渠道消息回调接口 + - name: Session Management + description: 会话管理接口 + - name: WebSocket + description: WebSocket 实时通信 + +paths: + /wecom/callback: + get: + operationId: verifyWecomUrl + summary: 微信回调 URL 验证 + description: 企业微信回调 URL 验证接口 + tags: + - Channel Callback + parameters: + - name: msg_signature + in: query + required: true + schema: + type: string + - name: timestamp + in: query + required: true + schema: + type: string + - name: nonce + in: query + required: true + schema: + type: string + - name: echostr + in: query + required: true + schema: + type: string + responses: + '200': + description: 验证成功,返回解密后的 echostr + content: + text/plain: + schema: + type: string + '500': + description: 验证失败 + content: + text/plain: + schema: + type: string + example: error + + post: + operationId: handleWecomCallback + summary: 微信回调消息处理 + description: | + 企业微信回调消息处理入口。 + + 覆盖验收标准: + - AC-MCA-08: 根据渠道类型路由到对应的渠道适配器 + + 消息处理流程: + 1. 接收加密的 XML 消息 + 2. 解密并解析消息内容 + 3. 根据消息类型路由处理 + 4. 返回 success 确认 + tags: + - Channel Callback + x-requirements: + - AC-MCA-08 + parameters: + - name: msg_signature + in: query + required: false + schema: + type: string + description: 消息签名(用于验签) + - name: timestamp + in: query + required: false + schema: + type: string + description: 时间戳(用于防重放) + - name: nonce + in: query + required: false + schema: + type: string + description: 随机数(用于防重放) + requestBody: + required: true + content: + application/xml: + schema: + type: string + description: 加密的 XML 消息 + responses: + '200': + description: 处理成功 + content: + text/plain: + schema: + type: string + example: success + + /channel/{channelType}/callback: + post: + operationId: handleChannelCallback + summary: 通用渠道回调接口(预留) + description: | + 通用渠道消息回调接口,用于接入新渠道。 + + 当前为预留接口,后续实现抖音、京东等渠道时使用。 + + ### 鉴权/签名机制(各渠道实现时需补充) + 不同渠道需要不同的验签方式,建议通过以下方式传递: + + **方式一:Header 传递** + - `X-Signature`: 消息签名 + - `X-Timestamp`: 时间戳(防重放) + - `X-Nonce`: 随机数(防重放) + + **方式二:Query 参数传递** + - `signature`: 消息签名 + - `timestamp`: 时间戳 + - `nonce`: 随机数 + + **方式三:Body 内嵌** + - requestBody 中包含 `rawPayload` + `signature` 字段 + + 具体签名算法(HMAC-SHA256、RSA 等)由各渠道适配器实现时确定。 + tags: + - Channel Callback + parameters: + - name: channelType + in: path + required: true + schema: + type: string + enum: + - wechat + - douyin + - jd + description: 渠道类型 + - name: X-Signature + in: header + required: false + schema: + type: string + description: 消息签名(可选,具体由渠道决定) + - name: X-Timestamp + in: header + required: false + schema: + type: string + description: 时间戳(可选,用于防重放) + - name: X-Nonce + in: header + required: false + schema: + type: string + description: 随机数(可选,用于防重放) + requestBody: + required: true + content: + application/json: + schema: + type: object + description: 渠道消息体(格式由各渠道定义) + responses: + '200': + description: 处理成功 + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + + /api/sessions: + get: + operationId: getSessions + summary: 获取会话列表 + description: | + 获取客服工作台的会话列表。 + + 覆盖验收标准: + - AC-MCA-12: 支持按渠道类型筛选 + tags: + - Session Management + x-requirements: + - AC-MCA-12 + parameters: + - name: status + in: query + required: false + schema: + type: string + enum: + - ai + - pending + - manual + - closed + description: 会话状态筛选 + - name: csId + in: query + required: false + schema: + type: string + description: 客服ID筛选 + - name: channelType + in: query + required: false + schema: + type: string + enum: + - wechat + - douyin + - jd + description: 渠道类型筛选 + responses: + '200': + description: 成功 + content: + application/json: + schema: + $ref: '#/components/schemas/SessionListResponse' + + /api/sessions/{sessionId}: + get: + operationId: getSession + summary: 获取会话详情 + tags: + - Session Management + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + responses: + '200': + description: 成功 + content: + application/json: + schema: + $ref: '#/components/schemas/SessionResponse' + '404': + description: 会话不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + + /api/sessions/{sessionId}/history: + get: + operationId: getSessionHistory + summary: 获取会话消息历史 + tags: + - Session Management + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + responses: + '200': + description: 成功 + content: + application/json: + schema: + $ref: '#/components/schemas/MessageListResponse' + + /api/sessions/{sessionId}/accept: + post: + operationId: acceptSession + summary: 接入会话 + description: 客服接入待处理的会话 + tags: + - Session Management + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - csId + properties: + csId: + type: string + description: 客服ID + responses: + '200': + description: 接入成功 + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + '400': + description: 会话状态不正确 + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + '404': + description: 会话不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + + /api/sessions/{sessionId}/message: + post: + operationId: sendSessionMessage + summary: 发送消息 + description: 客服向会话发送消息 + tags: + - Session Management + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - content + properties: + content: + type: string + description: 消息内容 + msgType: + type: string + default: text + description: 消息类型 + responses: + '200': + description: 发送成功 + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + '400': + description: 会话状态不正确 + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + '404': + description: 会话不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + + /api/sessions/{sessionId}/close: + post: + operationId: closeSession + summary: 关闭会话 + tags: + - Session Management + parameters: + - name: sessionId + in: path + required: true + schema: + type: string + responses: + '200': + description: 关闭成功 + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + '404': + description: 会话不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/ApiResponse' + +components: + schemas: + ApiResponse: + type: object + required: + - code + - message + properties: + code: + type: integer + description: 响应码(0=成功,非0=失败) + message: + type: string + description: 响应消息 + data: + type: object + description: 响应数据(可选) + + SessionListResponse: + allOf: + - $ref: '#/components/schemas/ApiResponse' + - type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/SessionInfo' + + SessionResponse: + allOf: + - $ref: '#/components/schemas/ApiResponse' + - type: object + properties: + data: + $ref: '#/components/schemas/SessionInfo' + + SessionInfo: + type: object + properties: + sessionId: + type: string + description: 会话ID + customerId: + type: string + description: 客户ID + kfId: + type: string + description: 客服账号ID + channelType: + type: string + description: 渠道类型 + enum: + - wechat + - douyin + - jd + status: + type: string + description: 会话状态 + enum: + - ai + - pending + - manual + - closed + manualCsId: + type: string + description: 接待客服ID + lastMessage: + type: string + description: 最后一条消息 + lastMessageTime: + type: string + format: date-time + description: 最后消息时间 + messageCount: + type: integer + description: 消息数量 + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + + MessageListResponse: + allOf: + - $ref: '#/components/schemas/ApiResponse' + - type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/MessageInfo' + + MessageInfo: + type: object + properties: + msgId: + type: string + description: 消息ID + sessionId: + type: string + description: 会话ID + senderType: + type: string + description: 发送者类型 + enum: + - customer + - ai + - manual + senderId: + type: string + description: 发送者ID + content: + type: string + description: 消息内容 + msgType: + type: string + description: 消息类型 + createdAt: + type: string + format: date-time + +x-websocket: + path: /ws/cs/{csId} + description: | + ## WebSocket 实时通信协议 + + 客服工作台通过 WebSocket 接收实时消息推送。 + + 覆盖验收标准: + - AC-MCA-10: 会话状态为 MANUAL 时推送消息到人工客服工作台 + + ### 连接地址 + ``` + ws://{host}:{port}/ws/cs/{csId} + ``` + + ### 认证/鉴权方式 + - **路径参数**: `{csId}` 客服ID,用于标识连接身份 + - **可选增强**: 后续可增加 Token 验证(Query 参数或 Header) + - Query: `?token=xxx` + - Header: `Authorization: Bearer xxx` + + ### 客户端发送消息格式 + ```json + { + "type": "bind_session", + "sessionId": "会话ID" + } + ``` + + ### 服务端推送消息格式 + ```json + { + "type": "new_message", + "sessionId": "会话ID", + "data": { + "msgId": "消息ID", + "content": "消息内容", + "senderType": "customer", + "senderId": "客户ID", + "msgType": "text", + "createdAt": "2026-02-24T10:00:00" + } + } + ``` + + ### 推送事件类型 + | type | 说明 | + |------|------| + | new_message | 新消息通知 | + | new_pending_session | 新待接入会话 | + | session_accepted | 会话被接入 | + | session_closed | 会话已关闭 |