yh 1 dzień temu
rodzic
commit
a41ce71d45

+ 746 - 0
docs/小红书店铺消息收发接入细则.md

@@ -0,0 +1,746 @@
+# 小红书店铺消息收发接入细则
+
+## 一、平台概述
+
+### 1.1 平台定位
+
+小红书开放平台(open.xiaohongshu.com)面向第三方开发者提供电商、内容、广告等 API 能力。店铺客户消息收发功能基于小红书的**私信系统**和**蒲公英客服系统**实现。
+
+小红书商家与消费者的沟通主要通过**私信**完成,商家可在专业号后台或客服工作台处理消费者咨询。作为第三方 SaaS 平台,我们通过小红书开放平台的**私信消息推送**和**私信发送 API** 实现消息收发。
+
+### 1.2 核心概念
+
+| 概念 | 说明 |
+|------|------|
+| 专业号 | 小红书商家账号类型,具备电商经营能力 |
+| 蒲公英 | 小红书商家客服工作台 |
+| 私信 | 用户之间的即时消息,商家通过私信与消费者沟通 |
+| app_id / app_secret | 应用凭证 |
+| access_token | 访问令牌 |
+| open_id | 用户在小红书体系的唯一标识 |
+| conversation_id | 私信会话 ID |
+| message_id | 消息 ID |
+| red_id | 小红书用户 ID |
+
+### 1.3 消息收发链路总览
+
+```
+买家发私信 → 小红书私信服务 → HTTP 回调推送(签名验证)→ 我们的回调接口
+                                                           ↓
+                                                     验签 + 标准化
+                                                           ↓
+                                                     MQ → 业务处理
+                                                           ↓
+                                                   AI 生成回复内容
+                                                           ↓
+                             调用私信发送 API ← ─ ─ ─ ─ ─ ─ ─ ┘
+                                   ↓
+                             小红书私信服务 → 买家收到回复
+```
+
+---
+
+## 二、前置准备
+
+### 2.1 注册与认证
+
+1. **注册小红书开放平台账号**
+   - 访问 https://open.xiaohongshu.com
+   - 使用企业手机号注册
+   - 完成企业实名认证
+
+2. **创建应用**
+   - 进入控制台 → 应用管理 → 创建应用
+   - 选择应用类型:
+     - **自研应用**:商家自用
+     - **三方应用**(推荐):SaaS 服务商,可服务多个商家
+   - 填写应用名称、描述、回调地址
+   - 获取 `app_id` 和 `app_secret`
+
+3. **申请权限**
+   - 在应用详情页申请所需权限
+   - 部分权限需要审核通过后才能使用
+
+### 2.2 权限申请
+
+| 权限 | 权限标识 | 说明 | 是否必须 |
+|------|---------|------|---------|
+| 私信消息接收 | `im_message_receive` | 接收私信消息推送 | ✅ 必须 |
+| 私信消息发送 | `im_message_send` | 向用户发送私信 | ✅ 必须 |
+| 用户信息 | `user_info` | 获取用户基本信息 | 推荐 |
+| 笔记信息 | `note_info` | 获取笔记信息 | 可选 |
+| 商品信息 | `product_info` | 获取商品信息 | 推荐 |
+| 订单信息 | `order_info` | 获取订单信息 | 推荐 |
+
+### 2.3 商家授权
+
+商家需要授权我们的应用访问其店铺数据,流程与抖音类似。
+
+---
+
+## 三、OAuth2.0 授权详解
+
+### 3.1 授权流程
+
+```
+┌────────┐     ┌──────────┐     ┌──────────────┐     ┌──────────┐
+│  商家   │     │ 我们系统  │     │小红书开放平台 │     │ 我们系统  │
+│ 浏览器  │     │ 前端     │     │ 授权服务     │     │ 后端     │
+└───┬────┘     └────┬─────┘     └──────┬───────┘     └────┬─────┘
+    │               │                  │                   │
+    │ 点击"授权店铺" │                  │                   │
+    │──────────────→│                  │                   │
+    │               │ 构造授权URL       │                   │
+    │               │─────────────────→│                   │
+    │  跳转授权页面  │                  │                   │
+    │──────────────────────────────────→│                   │
+    │  商家扫码/登录  │                  │                   │
+    │──────────────────────────────────→│                   │
+    │  商家同意授权   │                  │                   │
+    │──────────────────────────────────→│                   │
+    │               │                  │ 回调带code        │
+    │               │                  │──────────────────→│
+    │               │                  │                   │ 用code换token
+    │               │                  │                   │─────────→
+    │               │                  │                   │←─────────
+    │               │                  │                   │ 保存token
+    │               │ 授权成功通知      │                   │
+    │←──────────────│←─────────────────────────────────────│
+```
+
+### 3.2 授权 URL 构造
+
+```
+https://open.xiaohongshu.com/oauth/authorize?app_id={app_id}&redirect_uri={redirect_uri}&response_type=code&state={state}&scope={scope}
+```
+
+| 参数 | 必须 | 说明 |
+|------|------|------|
+| `app_id` | 是 | 应用 app_id |
+| `redirect_uri` | 是 | 授权回调地址,需与开放平台配置一致 |
+| `response_type` | 是 | 固定值 `code` |
+| `state` | 否 | 自定义参数,回调时原样返回 |
+| `scope` | 否 | 请求的权限范围,多个用逗号分隔 |
+
+### 3.3 获取 access_token
+
+**接口地址**:`POST https://open.xiaohongshu.com/oauth/token`
+
+**请求参数**:
+
+| 参数 | 类型 | 必须 | 说明 |
+|------|------|------|------|
+| `app_id` | String | 是 | 应用 app_id |
+| `app_secret` | String | 是 | 应用 app_secret |
+| `grant_type` | String | 是 | `authorization_code`(首次)或 `refresh_token`(刷新) |
+| `code` | String | 是 | 授权回调获取的 code(首次获取时必传) |
+| `redirect_uri` | String | 是 | 回调地址(需与授权时一致) |
+| `refresh_token` | String | 否 | 刷新令牌(刷新时必传) |
+
+**请求示例**:
+
+```
+POST /oauth/token HTTP/1.1
+Host: open.xiaohongshu.com
+Content-Type: application/x-www-form-urlencoded
+
+app_id=xxx&app_secret=xxx&grant_type=authorization_code&code=xxx&redirect_uri=https://your-domain.com/callback
+```
+
+**响应示例**:
+
+```json
+{
+  "code": 0,
+  "data": {
+    "access_token": "xxx",
+    "expires_in": 172800,
+    "refresh_token": "xxx",
+    "refresh_expires_in": 2592000,
+    "open_id": "xxx",
+    "scope": "im_message_receive,im_message_send,user_info"
+  },
+  "msg": "success"
+}
+```
+
+### 3.4 Token 刷新策略
+
+| 项目 | 说明 |
+|------|------|
+| access_token 有效期 | **48 小时**(比抖音/快手长) |
+| refresh_token 有效期 | 30 天 |
+| 刷新时机 | access_token 过期前 2 小时自动刷新 |
+| 刷新方式 | 使用 `grant_type=refresh_token` 调用 token 接口 |
+| 失败处理 | 标记店铺授权过期,通知商家重新授权 |
+
+### 3.5 Token 存储
+
+```sql
+-- 在 platform_shop 表中存储
+access_token    VARCHAR(512)  -- AES-256 加密存储
+refresh_token   VARCHAR(512)  -- AES-256 加密存储
+token_expire_time DATETIME    -- access_token 过期时间
+```
+
+---
+
+## 四、消息推送接入
+
+### 4.1 配置推送地址
+
+1. 登录小红书开放平台控制台
+2. 进入应用管理 → 消息推送
+3. 配置推送地址:`https://your-domain.com/api/chat/callback/xiaohongshu`
+4. 配置消息加密 Key(用于消息体加密/解密)
+5. 配置消息验证 Token(用于签名验证)
+6. 平台会发送验证请求,验证通过后启用推送
+
+### 4.2 订阅消息类型
+
+在控制台的消息订阅页面,订阅以下消息:
+
+| 消息名称 | event_type | 说明 | 是否必须 |
+|---------|-----------|------|---------|
+| 私信消息 | `im_message` | 用户发送私信 | ✅ 必须 |
+| 私信会话事件 | `im_conversation` | 会话创建/关闭 | ✅ 必须 |
+| 用户关注事件 | `user_follow` | 用户关注专业号 | 可选 |
+| 订单事件 | `order_status` | 订单状态变更 | 可选 |
+| 商品事件 | `product_status` | 商品状态变更 | 可选 |
+
+### 4.3 私信消息推送(event_type=im_message)
+
+**触发场景**:用户向商家专业号发送私信时推送
+
+**消息体结构**:
+
+```json
+{
+  "event_type": "im_message",
+  "event_id": "evt_xxx",
+  "timestamp": 1703560445000,
+  "data": {
+    "conversation_id": "conv_xxx",
+    "message_id": "msg_xxx",
+    "msg_type": "text",
+    "content": "你好,请问这个商品还有吗?",
+    "sender_open_id": "user_open_id_xxx",
+    "receiver_open_id": "merchant_open_id_xxx",
+    "create_time": 1703560445000,
+    "extra": "{}"
+  }
+}
+```
+
+**字段详解**:
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `event_type` | String | 事件类型,私信消息固定为 `im_message` |
+| `event_id` | String | 事件 ID,用于幂等去重 |
+| `timestamp` | Int64 | 事件时间(毫秒时间戳) |
+| `data.conversation_id` | String | 会话 ID |
+| `data.message_id` | String | 消息 ID |
+| `data.msg_type` | String | 消息类型:`text`、`image`、`video`、`card` |
+| `data.content` | String | 消息内容 |
+| `data.sender_open_id` | String | 发送者 openId |
+| `data.receiver_open_id` | String | 接收者 openId(商家) |
+| `data.create_time` | Int64 | 消息时间(毫秒时间戳) |
+| `data.extra` | String | 扩展信息 JSON |
+
+### 4.4 私信会话事件(event_type=im_conversation)
+
+**触发场景**:会话创建、关闭等事件
+
+**消息体结构**:
+
+```json
+{
+  "event_type": "im_conversation",
+  "event_id": "evt_xxx",
+  "timestamp": 1703560445000,
+  "data": {
+    "conversation_id": "conv_xxx",
+    "action": "create",
+    "user_open_id": "user_open_id_xxx",
+    "merchant_open_id": "merchant_open_id_xxx",
+    "create_time": 1703560445000
+  }
+}
+```
+
+**action 类型**:
+
+| action | 说明 |
+|--------|------|
+| `create` | 新会话创建 |
+| `close` | 会话关闭 |
+| `user_read` | 用户已读 |
+| `merchant_read` | 商家已读 |
+
+### 4.5 消息类型详解
+
+#### 文本消息
+
+```json
+{
+  "msg_type": "text",
+  "content": "你好,请问这个商品还有吗?"
+}
+```
+
+#### 图片消息
+
+```json
+{
+  "msg_type": "image",
+  "content": "https://xxx.com/image.jpg",
+  "extra": "{\"width\":800,\"height\":600,\"file_size\":102400}"
+}
+```
+
+#### 视频消息
+
+```json
+{
+  "msg_type": "video",
+  "content": "https://xxx.com/video.mp4",
+  "extra": "{\"duration\":30,\"cover_url\":\"https://xxx.com/cover.jpg\"}"
+}
+```
+
+#### 卡片消息
+
+```json
+{
+  "msg_type": "card",
+  "content": "",
+  "extra": "{\"card_type\":\"product\",\"card_id\":\"product_123\",\"title\":\"商品名称\",\"image_url\":\"https://xxx.com/product.jpg\",\"price\":\"99.00\"}"
+}
+```
+
+---
+
+## 五、消息发送
+
+### 5.1 私信发送 API
+
+**接口地址**:`POST https://open.xiaohongshu.com/api/im/message/send`
+
+**请求头**:
+
+```
+Content-Type: application/json
+Authorization: Bearer {access_token}
+```
+
+**请求参数**:
+
+| 参数 | 类型 | 必须 | 说明 |
+|------|------|------|------|
+| `receiver_open_id` | String | 是 | 接收者 openId(用户) |
+| `msg_type` | String | 是 | 消息类型:`text`、`image` |
+| `content` | String | 是 | 消息内容 |
+| `extra` | String | 否 | 扩展信息 JSON |
+
+### 5.2 发送文本消息
+
+**请求示例**:
+
+```json
+{
+  "receiver_open_id": "user_open_id_xxx",
+  "msg_type": "text",
+  "content": "您好,商品还有库存,可以直接下单哦~"
+}
+```
+
+**响应示例**:
+
+```json
+{
+  "code": 0,
+  "data": {
+    "message_id": "msg_xxx",
+    "create_time": 1703560500000
+  },
+  "msg": "success"
+}
+```
+
+### 5.3 发送图片消息
+
+**请求示例**:
+
+```json
+{
+  "receiver_open_id": "user_open_id_xxx",
+  "msg_type": "image",
+  "content": "https://xxx.com/product.jpg",
+  "extra": "{\"width\":800,\"height\":600}"
+}
+```
+
+**图片要求**:
+
+| 规范项 | 要求 |
+|--------|------|
+| 格式 | JPG/PNG |
+| 大小 | 不超过 10MB |
+| 尺寸 | 建议不超过 4096×4096px |
+| URL | 必须为 HTTPS |
+
+### 5.4 其他消息管理接口
+
+| 接口 | 方法 | 说明 |
+|------|------|------|
+| `/api/im/conversation/list` | GET | 获取会话列表 |
+| `/api/im/conversation/detail` | GET | 获取会话详情 |
+| `/api/im/message/list` | GET | 获取历史消息 |
+| `/api/im/message/read` | POST | 标记消息已读 |
+| `/api/im/conversation/close` | POST | 关闭会话 |
+
+---
+
+## 六、消息推送验签
+
+### 6.1 验签流程
+
+小红书开放平台在推送消息时,通过请求头携带签名信息:
+
+| 请求头 | 说明 |
+|--------|------|
+| `X-Signature` | 消息签名值 |
+| `X-Timestamp` | 时间戳 |
+| `X-Nonce` | 随机字符串 |
+
+### 6.2 HMAC-SHA256 签名验证
+
+```
+签名原文 = timestamp + nonce + request_body
+签名结果 = HMAC-SHA256(callback_token, 签名原文)
+```
+
+**Java 验签示例**:
+
+```java
+public boolean verifySign(HttpServletRequest request, String body) {
+    String signature = request.getHeader("X-Signature");
+    String timestamp = request.getHeader("X-Timestamp");
+    String nonce = request.getHeader("X-Nonce");
+
+    String signSource = timestamp + nonce + body;
+    Mac mac = Mac.getInstance("HmacSHA256");
+    mac.init(new SecretKeySpec(callbackToken.getBytes(), "HmacSHA256"));
+    String calculatedSign = Hex.encodeHexString(mac.doFinal(signSource.getBytes()));
+
+    return calculatedSign.equalsIgnoreCase(signature);
+}
+```
+
+### 6.3 时间戳验证
+
+为防止重放攻击,需验证时间戳:
+
+```java
+long timestamp = Long.parseLong(request.getHeader("X-Timestamp"));
+long currentTime = System.currentTimeMillis();
+if (Math.abs(currentTime - timestamp) > 5 * 60 * 1000) {
+    return false;
+}
+```
+
+### 6.4 消息体加密(可选)
+
+小红书开放平台支持消息体加密传输:
+
+- 在控制台配置消息加密 Key
+- 推送的消息体会使用 AES 加密
+- 需要解密后才能获取明文
+
+**解密方式**:
+
+```
+1. Base64 解码密文
+2. 使用配置的 EncodingAESKey 进行 AES 解密
+3. AES Key = Base64(EncodingAESKey + "=")
+4. AES 模式 = CBC
+5. 填充方式 = PKCS7Padding
+6. IV = AES Key 的前 16 字节
+```
+
+**Java 解密示例**:
+
+```java
+public String decrypt(String cipherText, String encodingAESKey) throws Exception {
+    byte[] keyBytes = Base64.getDecoder().decode(encodingAESKey + "=");
+    byte[] ivBytes = new byte[16];
+    System.arraycopy(keyBytes, 0, ivBytes, 0, 16);
+
+    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
+    IvParameterSpec iv = new IvParameterSpec(ivBytes);
+
+    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
+    cipher.init(Cipher.DECRYPT_MODE, key, iv);
+
+    byte[] decoded = Base64.getDecoder().decode(cipherText);
+    byte[] decrypted = cipher.doFinal(decoded);
+    return new String(decrypted, StandardCharsets.UTF_8);
+}
+```
+
+---
+
+## 七、回调接口实现
+
+### 7.1 接口定义
+
+```
+POST /api/chat/callback/xiaohongshu
+Content-Type: application/json
+```
+
+### 7.2 处理流程
+
+```
+1. 读取 request body
+2. 从 header 获取 X-Signature、X-Timestamp、X-Nonce
+3. 验证签名
+4. 验证时间戳(防重放)
+5. 如启用加密,解密消息体
+6. 解析 event_type 判断消息类型
+7. event_type=im_message:私信消息 → 转换为统一消息模型 → 发送 MQ
+8. event_type=im_conversation:会话事件 → 处理会话生命周期
+9. 立即返回成功响应
+```
+
+### 7.3 Java 实现示例
+
+```java
+@RestController
+@RequestMapping("/api/chat/callback/xiaohongshu")
+public class XiaohongshuCallbackController {
+
+    @Autowired
+    private XiaohongshuAdapter xiaohongshuAdapter;
+    @Autowired
+    private MessageProducer messageProducer;
+
+    @PostMapping
+    public Map<String, Object> callback(
+            HttpServletRequest request,
+            @RequestBody String body) {
+
+        if (!xiaohongshuAdapter.verifySignature(request, body)) {
+            return Map.of("code", -1, "msg", "sign verify failed");
+        }
+
+        try {
+            String decrypted = body;
+            if (xiaohongshuAdapter.isEncrypted(body)) {
+                decrypted = xiaohongshuAdapter.decrypt(body);
+            }
+
+            JSONObject msg = JSON.parseObject(decrypted);
+            String eventType = msg.getString("event_type");
+
+            if ("im_message".equals(eventType)) {
+                UnifiedMessage unified = xiaohongshuAdapter.normalize(decrypted);
+                messageProducer.sendReceiveMessage(unified);
+            } else if ("im_conversation".equals(eventType)) {
+                handleConversationEvent(msg);
+            }
+        } catch (Exception e) {
+            log.error("处理小红书回调异常", e);
+        }
+
+        return Map.of("code", 0, "msg", "success");
+    }
+}
+```
+
+### 7.4 响应要求
+
+| 要求 | 说明 |
+|------|------|
+| HTTP 状态码 | 200 |
+| 响应体 | `{"code":0,"msg":"success"}` |
+| 响应时效 | **2 秒内** |
+
+---
+
+## 八、消息标准化映射
+
+### 8.1 小红书消息 → 统一消息模型
+
+| 小红书字段 | 统一消息字段 | 转换规则 |
+|-----------|-------------|---------|
+| `event_type=im_message` | `platform` | 固定值 `xiaohongshu` |
+| `data.conversation_id` | `conversationId` | 直接映射 |
+| `data.message_id` | `msgId` | 直接映射 |
+| `data.msg_type` | `msgType` | `text`→`text`, `image`→`image`, `video`→`video`, `card`→`card` |
+| `data.content` | `content` | 直接映射 |
+| `data.extra` | `extra` | 解析为 Map |
+| `data.sender_open_id` | `senderId` | 直接映射 |
+| `data.receiver_open_id` | `receiverId` | 直接映射 |
+| `data.create_time` | `createTime` | 毫秒时间戳直接映射 |
+
+### 8.2 统一消息 → 小红书发送请求
+
+| 统一消息字段 | 小红书发送字段 | 转换规则 |
+|-------------|-------------|---------|
+| `conversationId` | `receiver_open_id` | 从会话记录中获取用户 openId |
+| `msgType` | `msg_type` | 直接映射 |
+| `content` | `content` | 直接映射 |
+| `extra` | `extra` | 转为 JSON 字符串 |
+
+---
+
+## 九、小红书私信特殊规则
+
+### 9.1 私信准入条件
+
+小红书对商家私信有严格的准入要求:
+
+| 条件 | 说明 |
+|------|------|
+| 账号类型 | 必须为专业号 |
+| 认证状态 | 需完成企业认证 |
+| 信用分 | 专业号信用分达标 |
+| 行业限制 | 部分行业不允许私信营销 |
+
+### 9.2 私信发送限制
+
+| 限制项 | 规则 |
+|--------|------|
+| 主动私信 | 用户关注商家后,商家可主动私信 |
+| 被动回复 | 用户发私信后,48 小时内可回复 |
+| 日发送量 | 根据专业号等级不同,每日发送上限不同 |
+| 频率限制 | 同一用户 24 小时内最多发送 N 条(按等级) |
+| 敏感词 | 小红书有严格的敏感词过滤机制 |
+
+### 9.3 私信场景
+
+| 场景 | 说明 | 限制 |
+|------|------|------|
+| 售前咨询 | 用户主动咨询商品 | 48 小时内回复 |
+| 售后服务 | 订单/物流/退换货咨询 | 48 小时内回复 |
+| 营销触达 | 主动向关注用户推送 | 用户需关注,有日频限制 |
+| 活动通知 | 促销/上新通知 | 用户需关注,有日频限制 |
+
+### 9.4 私信风控
+
+小红书对私信有严格的风控机制:
+
+| 风控项 | 说明 |
+|--------|------|
+| 敏感词过滤 | 涉及违规词汇的消息会被拦截 |
+| 频率限制 | 超过发送频率会被限流 |
+| 投诉机制 | 用户可投诉骚扰消息 |
+| 违规处罚 | 违规可能导致私信功能被封禁 |
+| 内容审核 | 部分消息可能进入人工审核 |
+
+---
+
+## 十、蒲公英客服工作台
+
+### 10.1 客服工作台入口
+
+| 入口 | 地址 |
+|------|------|
+| 网页版 | https://pgy.xiaohongshu.com |
+| 移动端 | 小红书商家版 App |
+
+### 10.2 客服能力
+
+| 能力 | 说明 |
+|------|------|
+| 消息收发 | 文本、图片、表情、商品卡片 |
+| 会话管理 | 待处理、进行中、已结束 |
+| 快捷回复 | 团队话术、个人话术 |
+| 客服状态 | 在线、忙碌、离线 |
+| 分流策略 | 按技能组、按负载均衡 |
+| 数据统计 | 客服绩效、响应时效 |
+| 智能助手 | AI 辅助回复建议 |
+
+### 10.3 客服管理
+
+- 客服人员:从专业号团队成员中添加
+- 客服分组:按技能组分配
+- 排班管理:设置客服工作时间
+- 自动回复:设置欢迎语、离线自动回复
+
+---
+
+## 十一、限流与频率控制
+
+### 11.1 API 限流
+
+| 接口 | 限流规则 |
+|------|---------|
+| 私信发送 API | 按应用配置,默认 QPS 5 |
+| 会话列表 API | 按应用配置 |
+| Token 接口 | 每分钟最多 30 次 |
+
+### 11.2 私信发送限制
+
+| 限制项 | 规则 |
+|--------|------|
+| 被动回复时效 | 48 小时 |
+| 主动私信 | 用户需关注商家 |
+| 日发送上限 | 按专业号等级,通常 100-500 条/日 |
+| 同用户频率 | 24 小时内限制条数 |
+| 图片大小 | 不超过 10MB |
+
+### 11.3 推送重试机制
+
+| 规则 | 说明 |
+|------|------|
+| 超时时间 | 2 秒 |
+| 重试次数 | 最多 3 次 |
+| 重试间隔 | 递增间隔 |
+| 幂等要求 | 同一 event_id 可能推送多次 |
+
+---
+
+## 十二、常见问题与注意事项
+
+### 12.1 常见问题
+
+| 问题 | 原因 | 解决方案 |
+|------|------|---------|
+| 推送地址验证失败 | 返回格式不对 | 确保返回 `{"code":0,"msg":"success"}` |
+| 验签不通过 | 签名算法或 Token 错误 | 检查 callback_token,确认 HMAC-SHA256 计算 |
+| 消息发送失败 | Token 过期或权限不足 | 刷新 Token,检查是否申请了私信发送权限 |
+| 私信被拦截 | 触发风控 | 检查消息内容是否包含敏感词,降低发送频率 |
+| 收不到推送 | 未订阅消息类型 | 在控制台检查消息订阅状态 |
+| 消息解密失败 | EncodingAESKey 配置错误 | 检查 Key 配置,确认 AES 解密参数 |
+| 主动私信失败 | 用户未关注 | 仅对关注用户可主动私信 |
+
+### 12.2 注意事项
+
+1. **专业号要求**:商家必须为认证的专业号才能使用私信功能
+2. **私信风控严格**:小红书对私信内容审核严格,需注意敏感词和发送频率
+3. **48 小时回复窗口**:用户发消息后 48 小时内可回复,超时需用户再次发起
+4. **主动私信限制**:只能向关注用户主动发送,且有日频限制
+5. **回调响应时效**:必须在 2 秒内返回,否则判定推送失败
+6. **消息加密**:建议启用消息体加密,提高安全性
+7. **时间戳验证**:验证推送时间戳,防止重放攻击
+8. **Token 安全**:access_token 和 refresh_token 必须加密存储
+9. **图片 URL**:必须为 HTTPS,否则发送失败
+10. **内容合规**:严格遵守小红书社区规范,避免违规内容
+
+---
+
+## 十三、参考文档
+
+| 文档 | 地址 |
+|------|------|
+| 小红书开放平台首页 | https://open.xiaohongshu.com |
+| OAuth2.0 授权文档 | https://open.xiaohongshu.com/document/oauth |
+| 私信消息推送文档 | https://open.xiaohongshu.com/document/im |
+| 私信发送 API | https://open.xiaohongshu.com/document/api/im/message/send |
+| 蒲公英客服工作台 | https://pgy.xiaohongshu.com |
+| 专业号管理 | https://pro.xiaohongshu.com |
+| 小红书社区规范 | https://www.xiaohongshu.com/protocols |
+| 开放平台 API 列表 | https://open.xiaohongshu.com/document/api |

+ 621 - 0
docs/快手店铺消息收发接入细则.md

@@ -0,0 +1,621 @@
+# 快手店铺消息收发接入细则
+
+## 一、平台概述
+
+### 1.1 双平台架构
+
+快手电商消息收发涉及**两个开放平台**,需要分别对接:
+
+| 平台 | 域名 | 用途 |
+|------|------|------|
+| **快手电商开放平台** | open.kwaixiaodian.com | 电商业务 API(商品、订单、物流等)+ 消息推送 |
+| **快手开放平台** | open.kuaishou.com | 小程序客服消息 + 私信三方客服 API |
+
+**核心要点**:
+- 电商店铺的**订单消息、退款消息**等业务消息走电商开放平台(open.kwaixiaodian.com)
+- **客户私信/客服消息**走快手开放平台(open.kuaishou.com)的私信三方客服接口
+- 两个平台的应用创建、授权、Token 体系是独立的
+
+### 1.2 核心概念
+
+| 概念 | 说明 |
+|------|------|
+| app_key / app_secret | 应用凭证,两个平台各自独立 |
+| access_token | 访问令牌,通过 OAuth2.0 获取 |
+| open_id | 用户在快手体系的唯一标识 |
+| kwai_item_id | 快手商品 ID |
+| shop_id | 快手店铺 ID |
+| kpn | 业务标识,当前固定填 `KUAISHOU` |
+| sub_biz | 子业务标识,如 `KSIM_TO_ADIM`(通用行业) |
+| scene | 消息发送场景标识 |
+
+### 1.3 消息收发链路总览
+
+```
+买家发消息 → 快手消息服务 → HTTP 回调推送(AES加密)→ 我们的回调接口
+                                                          ↓
+                                                    验签 + AES解密 + 标准化
+                                                          ↓
+                                                    MQ → 业务处理
+                                                          ↓
+                                                  AI 生成回复内容
+                                                          ↓
+                          调用私信三方客服 API ← ─ ─ ─ ─ ─ ─ ┘
+                                ↓
+                          快手消息服务 → 买家收到回复
+```
+
+---
+
+## 二、前置准备
+
+### 2.1 注册与认证
+
+#### 电商开放平台
+
+1. 访问 https://open.kwaixiaodian.com
+2. 注册开发者账号,完成企业认证
+3. 选择应用类型:
+   - **自用型应用**:商家自己创建,仅供自己店铺使用
+   - **第三方应用**:SaaS 服务商创建,在服务市场售卖(推荐)
+
+#### 快手开放平台
+
+1. 访问 https://open.kuaishou.com
+2. 注册开发者账号,完成企业认证
+3. 创建应用,申请「私信消息发送」权限
+
+### 2.2 权限申请
+
+#### 电商开放平台权限
+
+| 权限 | 说明 | 是否必须 |
+|------|------|---------|
+| 客服管理 | 发送客服信息/订单/商品卡片 | ✅ 必须 |
+| 订单管理 | 查看/管理订单 | 推荐 |
+| 商品管理 | 管理商品信息 | 推荐 |
+| 消息推送 | 接收订单/退款等业务消息推送 | 推荐 |
+
+#### 快手开放平台权限
+
+| 权限 | 说明 | 是否必须 |
+|------|------|---------|
+| 私信消息发送 | 向用户发送私信 | ✅ 必须 |
+| 客服消息能力 | 小程序客服消息收发 | ✅ 必须 |
+| 用户信息 | 获取用户基本信息 | 推荐 |
+
+### 2.3 商家授权
+
+与抖音类似,需要引导商家完成 OAuth2.0 授权。
+
+---
+
+## 三、OAuth2.0 授权详解
+
+### 3.1 电商开放平台授权
+
+**授权 URL**:
+
+```
+https://open.kwaixiaodian.com/oauth/authorize?app_key={app_key}&redirect_uri={redirect_uri}&response_type=code&state={state}
+```
+
+**Token 接口**:
+
+```
+POST https://open.kwaixiaodian.com/oauth2/access_token
+```
+
+**请求参数**:
+
+| 参数 | 类型 | 必须 | 说明 |
+|------|------|------|------|
+| `app_key` | String | 是 | 应用 app_key |
+| `app_secret` | String | 是 | 应用 app_secret |
+| `grant_type` | String | 是 | `authorization_code` 或 `refresh_token` |
+| `code` | String | 是 | 授权回调获取的 code |
+
+**响应示例**:
+
+```json
+{
+  "result": 1,
+  "error_msg": "SUCCESS",
+  "data": {
+    "access_token": "xxx",
+    "expires_in": 86400,
+    "refresh_token": "xxx",
+    "refresh_expires_in": 2592000,
+    "open_id": "xxx"
+  }
+}
+```
+
+### 3.2 快手开放平台授权
+
+**授权 URL**:
+
+```
+https://open.kuaishou.com/oauth2/authorize?app_id={app_id}&redirect_uri={redirect_uri}&response_type=code&scope=user_info&state={state}
+```
+
+**Token 接口**:
+
+```
+POST https://open.kuaishou.com/oauth2/access_token
+```
+
+### 3.3 Token 管理
+
+| 项目 | 电商开放平台 | 快手开放平台 |
+|------|-------------|-------------|
+| access_token 有效期 | 24 小时 | 24 小时 |
+| refresh_token 有效期 | 30 天 | 30 天 |
+| 刷新策略 | 过期前 1 小时自动刷新 | 同左 |
+| 存储方式 | AES-256 加密存储 | AES-256 加密存储 |
+
+---
+
+## 四、消息推送接入
+
+### 4.1 电商开放平台消息推送
+
+#### 配置推送地址
+
+1. 登录电商开放平台控制台
+2. 进入应用管理 → 消息推送配置
+3. 填写推送地址:`https://your-domain.com/api/chat/callback/kuaishou`
+4. 验证地址可用性
+
+#### 消息加密
+
+快手推送的消息使用 **AES 加密**,需要解密后才能获取明文:
+
+```
+解密步骤:
+1. 对推送的密文进行 Base64 解码
+2. 使用 app_secret 的前 32 字节作为 AES Key
+3. 使用 app_secret 的前 16 字节作为 AES IV
+4. 采用 AES/CBC/PKCS5Padding 模式解密
+5. 得到明文 JSON
+```
+
+**Java 解密示例**:
+
+```java
+public String decrypt(String cipherText, String appSecret) throws Exception {
+    byte[] secretBytes = appSecret.getBytes(StandardCharsets.UTF_8);
+    byte[] keyBytes = new byte[32];
+    byte[] ivBytes = new byte[16];
+    System.arraycopy(secretBytes, 0, keyBytes, 0, Math.min(secretBytes.length, 32));
+    System.arraycopy(secretBytes, 0, ivBytes, 0, Math.min(secretBytes.length, 16));
+
+    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
+    IvParameterSpec iv = new IvParameterSpec(ivBytes);
+
+    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+    cipher.init(Cipher.DECRYPT_MODE, key, iv);
+
+    byte[] decoded = Base64.getDecoder().decode(cipherText);
+    byte[] decrypted = cipher.doFinal(decoded);
+    return new String(decrypted, StandardCharsets.UTF_8);
+}
+```
+
+#### 消息体结构(解密后)
+
+```json
+{
+  "biz_type": "im_message",
+  "data": {
+    "conversation_id": "conv_xxx",
+    "msg_id": "msg_xxx",
+    "msg_type": "text",
+    "content": "{\"text\":\"你好,请问这个商品还有吗?\"}",
+    "from_open_id": "user_open_id_xxx",
+    "to_open_id": "merchant_open_id_xxx",
+    "create_time": 1703560445000,
+    "shop_id": 123456
+  }
+}
+```
+
+#### 支持的消息类型
+
+| biz_type | 说明 |
+|----------|------|
+| `im_message` | 客服消息 |
+| `order_status_change` | 订单状态变更 |
+| `refund_status_change` | 退款状态变更 |
+| `item_status_change` | 商品状态变更 |
+
+### 4.2 快手开放平台消息推送
+
+快手开放平台(open.kuaishou.com)的小程序客服消息通过 Webhook 推送:
+
+1. 在快手开放平台控制台配置 Webhook 回调地址
+2. 订阅相关事件(如 `im_receive_msg` 接收私信消息)
+3. 平台通过 HTTP POST 推送事件通知
+
+---
+
+## 五、消息发送
+
+### 5.1 私信三方客服 API
+
+**接口地址**:`POST https://open.kuaishou.com/openapi/message/send`
+
+**请求头**:
+
+```
+Content-Type: application/json
+access_token: {access_token}
+```
+
+**系统参数(URL Query)**:
+
+| 参数 | 类型 | 必须 | 说明 |
+|------|------|------|------|
+| `appkey` | String | 是 | 应用 app_key |
+| `timestamp` | Number | 是 | 请求时间戳(毫秒) |
+| `access_token` | String | 是 | 访问令牌 |
+| `version` | Number | 是 | API 版本号,当前为 `1` |
+| `sign` | String | 是 | 签名 |
+| `signMethod` | String | 是 | 签名算法:`HMAC_SHA256` 或 `MD5` |
+
+**Body 请求参数**:
+
+| 参数 | 类型 | 必须 | 说明 |
+|------|------|------|------|
+| `request_id` | String | 是 | 唯一请求 ID(UUID) |
+| `open_id` | String | 是 | B 端商家对应的 openId |
+| `app_id` | String | 是 | 快手开平注册的应用唯一标识 |
+| `kpn` | String | 是 | 业务标识,固定填 `KUAISHOU` |
+| `sub_biz` | String | 是 | 子业务标识,通用行业填 `KSIM_TO_ADIM` |
+| `scene` | String | 是 | 发送场景(见下表) |
+| `target_open_id` | String | 是 | 目标客户 openId |
+| `msg_type` | String | 是 | 消息类型:`text`、`image`、`interactive` |
+| `content` | String | 是 | 消息内容 JSON |
+
+**scene 场景值**:
+
+| scene | 说明 | 限制 |
+|-------|------|------|
+| `im_reply_msg` | 回复私信消息 | 48 小时内,用户发消息后可回复 |
+| `im_enter_direct_msg` | 用户进入私信会话页 | 30 秒内回复,每条 webhook 最多 3 条消息 |
+| `im_potential_customer_msg` | 潜客主动触达 | 10 日内有互动的用户,每日额度有限 |
+| `im_authorize_message` | 主动私信持续触达 | 用户需授权,每日 1 次 |
+
+### 5.2 发送文本消息
+
+**请求示例**:
+
+```json
+{
+  "request_id": "1a2a1d1c-3942-427c-bee9-d651c5762c51",
+  "open_id": "5b748d9adcd4d76cc0656638eb95b7ae",
+  "app_id": "123456",
+  "kpn": "KUAISHOU",
+  "sub_biz": "KSIM_TO_ADIM",
+  "scene": "im_reply_msg",
+  "target_open_id": "customer_open_id_xxx",
+  "msg_type": "text",
+  "content": "{\"text\":\"您好,商品还有库存,可以直接下单哦~\"}"
+}
+```
+
+### 5.3 发送图片消息
+
+**请求示例**:
+
+```json
+{
+  "request_id": "uuid-xxx",
+  "open_id": "5b748d9adcd4d76cc0656638eb95b7ae",
+  "app_id": "123456",
+  "kpn": "KUAISHOU",
+  "sub_biz": "KSIM_TO_ADIM",
+  "scene": "im_reply_msg",
+  "target_open_id": "customer_open_id_xxx",
+  "msg_type": "image",
+  "content": "{\"image_url\":\"https://xxx.com/product.jpg\"}"
+}
+```
+
+### 5.4 发送卡片消息(交互式消息)
+
+**请求示例**:
+
+```json
+{
+  "request_id": "uuid-xxx",
+  "open_id": "5b748d9adcd4d76cc0656638eb95b7ae",
+  "app_id": "123456",
+  "kpn": "KUAISHOU",
+  "sub_biz": "KSIM_TO_ADIM",
+  "scene": "im_reply_msg",
+  "target_open_id": "customer_open_id_xxx",
+  "msg_type": "interactive",
+  "content": "{\"title\":\"优惠通知\",\"desc\":\"点击领取专属福利\",\"image_url\":\"https://example.com/card.jpg\",\"buttons\":[{\"text\":\"立即领取\",\"action\":\"open_url\",\"params\":{\"url\":\"https://activity.example.com\"}}]}"
+}
+```
+
+**卡片设计规范**:
+
+| 规范项 | 要求 |
+|--------|------|
+| 图片尺寸 | 建议 750×1334px |
+| 文件格式 | PNG/JPG,大小不超过 2MB |
+| 按钮限制 | 最多 3 个交互按钮 |
+| 标题 | 不超过 20 字 |
+| 描述 | 不超过 50 字 |
+
+### 5.5 潜客主动触达
+
+快手支持对潜客(10 日内有互动行为的用户)主动发送消息:
+
+**潜客列表查询接口**:
+
+```
+POST https://open.kuaishou.com/openapi/kuailiao/potentialUsersPage?access_token={token}&app_id={app_id}
+```
+
+**请求参数**:
+
+| 参数 | 类型 | 必须 | 说明 |
+|------|------|------|------|
+| `request_id` | String | 是 | 唯一请求 ID |
+| `open_id` | String | 是 | B 端商家 openId |
+| `app_id` | String | 是 | 应用 ID |
+| `kpn` | String | 是 | 固定 `KUAISHOU` |
+| `sub_biz` | String | 是 | `KSIM_TO_ADIM` |
+
+**潜客消息发送**:scene 填写 `im_potential_customer_msg`
+
+**限制**:
+- 单 appid QPS 10
+- 每日主动沟通额度有限
+- 只能对 10 日内有互动的用户发送
+
+---
+
+## 六、签名算法
+
+### 6.1 API 请求签名
+
+快手电商开放平台的 API 请求需要签名验证:
+
+**签名步骤**:
+
+1. 将除 `sign` 外的所有系统参数和业务参数按字母排序
+2. 用 `&` 连接:`app_key=xxx&method=xxx&param=xxx&timestamp=xxx&version=1`
+3. 拼接 `app_secret`:`排序后的字符串 + app_secret`
+4. 计算签名
+
+**HMAC-SHA256 签名**(推荐):
+
+```java
+public String sign(SortedMap<String, String> params, String appSecret) {
+    StringBuilder sb = new StringBuilder();
+    for (Map.Entry<String, String> entry : params.entrySet()) {
+        sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
+    }
+    sb.deleteCharAt(sb.length() - 1);
+
+    Mac mac = Mac.getInstance("HmacSHA256");
+    mac.init(new SecretKeySpec(appSecret.getBytes(), "HmacSHA256"));
+    return Hex.encodeHexString(mac.doFinal(sb.toString().getBytes()));
+}
+```
+
+**MD5 签名**:
+
+```java
+public String signMd5(SortedMap<String, String> params, String appSecret) {
+    StringBuilder sb = new StringBuilder();
+    for (Map.Entry<String, String> entry : params.entrySet()) {
+        sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
+    }
+    sb.append(appSecret);
+    return DigestUtils.md5Hex(sb.toString());
+}
+```
+
+### 6.2 消息推送验签
+
+快手推送消息时,通过请求头或参数携带签名信息,验证方式与 API 签名类似。
+
+---
+
+## 七、回调接口实现
+
+### 7.1 接口定义
+
+```
+POST /api/chat/callback/kuaishou
+Content-Type: application/json
+```
+
+### 7.2 处理流程
+
+```
+1. 读取 request body
+2. 验证签名
+3. 解密消息体(AES 解密)
+4. 解析 biz_type 判断消息类型
+5. biz_type=im_message:客服消息 → 转换为统一消息模型 → 发送 MQ
+6. 其他 biz_type:业务消息 → 按类型处理
+7. 立即返回成功响应
+```
+
+### 7.3 Java 实现示例
+
+```java
+@RestController
+@RequestMapping("/api/chat/callback/kuaishou")
+public class KuaishouCallbackController {
+
+    @Autowired
+    private KuaishouAdapter kuaishouAdapter;
+    @Autowired
+    private MessageProducer messageProducer;
+
+    @PostMapping
+    public Map<String, Object> callback(
+            HttpServletRequest request,
+            @RequestBody String body) {
+
+        if (!kuaishouAdapter.verifySignature(request, body)) {
+            return Map.of("result", -1, "error_msg", "sign verify failed");
+        }
+
+        try {
+            String decrypted = kuaishouAdapter.decrypt(body);
+            JSONObject msg = JSON.parseObject(decrypted);
+            String bizType = msg.getString("biz_type");
+
+            if ("im_message".equals(bizType)) {
+                UnifiedMessage unified = kuaishouAdapter.normalize(decrypted);
+                messageProducer.sendReceiveMessage(unified);
+            } else {
+                handleBusinessMessage(bizType, msg);
+            }
+        } catch (Exception e) {
+            log.error("处理快手回调异常", e);
+        }
+
+        return Map.of("result", 1, "error_msg", "SUCCESS");
+    }
+}
+```
+
+### 7.4 响应要求
+
+| 要求 | 说明 |
+|------|------|
+| HTTP 状态码 | 200 |
+| 响应体 | `{"result":1,"error_msg":"SUCCESS"}` |
+| 响应时效 | **2 秒内** |
+
+---
+
+## 八、消息标准化映射
+
+### 8.1 快手消息 → 统一消息模型
+
+| 快手字段 | 统一消息字段 | 转换规则 |
+|---------|-------------|---------|
+| `biz_type=im_message` | `platform` | 固定值 `kuaishou` |
+| `data.shop_id` | `shopId` | 直接映射 |
+| `data.conversation_id` | `conversationId` | 直接映射 |
+| `data.msg_id` | `msgId` | 直接映射 |
+| `data.msg_type` | `msgType` | `text`→`text`, `image`→`image` |
+| `data.content` | `content` | 解析 JSON 提取 text 字段 |
+| `data.from_open_id` | `senderId` | 直接映射 |
+| `data.create_time` | `createTime` | 毫秒时间戳直接映射 |
+
+### 8.2 统一消息 → 快手发送请求
+
+| 统一消息字段 | 快手发送字段 | 转换规则 |
+|-------------|-------------|---------|
+| `conversationId` | `target_open_id` | 从会话记录中获取客户 openId |
+| `msgType` | `msg_type` | 直接映射 |
+| `content` | `content` | 包装为 JSON |
+| `shopId` | `open_id` | 从店铺绑定记录获取商家 openId |
+
+---
+
+## 九、客服工作台
+
+### 9.1 快手客服工作台入口
+
+| 入口 | 地址 |
+|------|------|
+| 网页版 | https://s.kwaixiaodian.com |
+| PC 客户端 | 快手小店客服客户端 |
+
+### 9.2 客服能力
+
+| 能力 | 说明 |
+|------|------|
+| 消息收发 | 文本、图片、表情 |
+| 会话管理 | 转单、待处理、关单 |
+| 快捷话术 | 团队话术、个人话术 |
+| 客服状态 | 在线、忙碌、下班 |
+| 分流策略 | 就近分流、负载分流、离线分流、不分流 |
+| 数据统计 | 实时数据、绩效数据 |
+| 敏感词 | 店铺维度禁用词设置 |
+
+### 9.3 客服成员管理
+
+- 新增客服:从小程序项目成员中添加
+- 客服昵称:可自定义
+- 客服头像:默认使用小程序头像
+
+---
+
+## 十、限流与频率控制
+
+### 10.1 API 限流
+
+| 接口 | 限流规则 |
+|------|---------|
+| 私信三方客服 API | 单 appid QPS 10 |
+| 潜客列表查询 | 单 appid QPS 10 |
+| 电商开放平台 API | 按应用权限配置 |
+
+### 10.2 消息发送限制
+
+| 场景 | 限制 |
+|------|------|
+| 回复私信(im_reply_msg) | 48 小时内,用户发消息后可回复 |
+| 进私问候(im_enter_direct_msg) | 30 秒内,每条 webhook 最多 3 条,每日最多 3 条 webhook |
+| 潜客触达(im_potential_customer_msg) | 10 日内有互动,每日额度有限 |
+| 主动私信(im_authorize_message) | 用户授权后每日 1 次,最多 5000 个用户 |
+
+### 10.3 推送重试机制
+
+| 规则 | 说明 |
+|------|------|
+| 超时时间 | 2 秒 |
+| 重试次数 | 最多 3 次 |
+| 幂等要求 | 同一 msg_id 可能推送多次 |
+
+---
+
+## 十一、常见问题与注意事项
+
+### 11.1 常见问题
+
+| 问题 | 原因 | 解决方案 |
+|------|------|---------|
+| 消息解密失败 | AES Key/IV 配置错误 | 使用 app_secret 前 32 字节做 Key,前 16 字节做 IV |
+| 签名验证失败 | 参数排序或拼接错误 | 严格按照字母序排列,注意 body 不参与排序 |
+| 发送消息返回限流 | QPS 超限 | 控制发送频率,做排队限流 |
+| Token 过期 | 超过 24 小时 | 自动刷新,过期前 1 小时刷新 |
+| 潜客消息发送失败 | 用户 10 日内无互动 | 仅对近期有互动的用户发送 |
+
+### 11.2 注意事项
+
+1. **双平台独立管理**:电商开放平台和快手开放平台的应用、Token 体系独立,需分别管理
+2. **AES 解密**:推送消息必须先解密才能处理,注意 Key 和 IV 的取法
+3. **签名算法**:推荐使用 HMAC-SHA256,比 MD5 更安全
+4. **scene 场景值**:不同场景有不同的限制,需根据实际场景选择
+5. **潜客功能**:需要白名单申请,联系快手运营开通
+6. **回调响应**:必须在 2 秒内返回,否则判定推送失败
+7. **消息回复时效**:48 小时内可回复,超时无法主动联系
+
+---
+
+## 十二、参考文档
+
+| 文档 | 地址 |
+|------|------|
+| 快手电商开放平台 | https://open.kwaixiaodian.com |
+| 快手开放平台 | https://open.kuaishou.com |
+| 快手客服消息能力 | https://open.kuaishou.com/docs/develop/functionAccessGuide/customerService.html |
+| 快手消息服务文档 | https://open.kwaixiaodian.com/docs/dev?pageSign=120a69028f0e9ea69145644317ae8bcd1614263915925 |
+| 私信三方客服接口 | https://open.kuaishou.com/openapi/message/send |
+| 潜客列表查询接口 | https://open.kuaishou.com/openapi/kuailiao/potentialUsersPage |
+| 快手客服工作台 | https://s.kwaixiaodian.com |
+| Java SDK 示例 | https://open.kwaixiaodian.com/docs/api (各接口页面有 Java 示例) |

+ 655 - 0
docs/抖音抖店消息收发接入细则.md

@@ -0,0 +1,655 @@
+# 抖音(抖店)店铺消息收发接入细则
+
+## 一、平台概述
+
+### 1.1 平台定位
+
+抖店开放平台(op.jinritemai.com)是字节跳动旗下的电商开放平台,面向电商商家和第三方开发者提供商品、订单、物流、客服等全链路 API 能力。
+
+店铺客户消息收发功能基于**飞鸽客服系统**实现。飞鸽是抖店的 IM 客服系统,商家通过飞鸽处理消费者咨询。作为第三方 SaaS 平台,我们通过抖店开放平台的**飞鸽消息推送**和**三方客服 API** 实现消息收发。
+
+### 1.2 核心概念
+
+| 概念 | 说明 |
+|------|------|
+| 飞鸽 | 抖店的 IM 客服系统,处理消费者咨询 |
+| 飞鸽消息推送 | 平台将飞鸽会话消息通过 HTTP 回调推送给开发者 |
+| 三方客服 API | 允许第三方系统以客服身份接入飞鸽,收发消息 |
+| 飞鸽插件 | 可嵌入飞鸽右侧工作台的自研应用插件 |
+| app_key / app_secret | 应用的唯一标识和密钥 |
+| shop_id | 抖店店铺 ID |
+| doudian_open_id | 用户在抖店体系的 Open ID |
+| conversation_id | 飞鸽会话 ID |
+| pigeon_cid | 飞鸽客服 ID |
+
+### 1.3 消息收发链路总览
+
+```
+买家发消息 → 抖店飞鸽系统 → HTTP 回调推送 → 我们的回调接口
+                                                    ↓
+                                              验签 + 标准化
+                                                    ↓
+                                              MQ → 业务处理
+                                                    ↓
+                                            AI 生成回复内容
+                                                    ↓
+                              调用三方客服 API ← ─ ─ ─ ─ ┘
+                                    ↓
+                              抖店飞鸽系统 → 买家收到回复
+```
+
+---
+
+## 二、前置准备
+
+### 2.1 注册与认证
+
+1. **注册抖店开放平台账号**
+   - 访问 https://op.jinritemai.com
+   - 使用企业手机号注册
+   - 完成企业实名认证(营业执照、法人信息等)
+
+2. **选择应用类型**
+   - **第三方应用**(推荐):SaaS 平台作为服务商,可服务多个商家店铺
+   - **自用型应用**:仅服务自有店铺
+
+3. **创建应用**
+   - 进入控制台 → 应用管理 → 创建应用
+   - 填写应用名称、描述、回调地址等
+   - 获取 `app_key` 和 `app_secret`
+
+### 2.2 权限申请
+
+需要在开放平台控制台申请以下权限:
+
+| 权限 | 权限标识 | 说明 | 是否必须 |
+|------|---------|------|---------|
+| 飞鸽消息 | `pigeon` | 接收飞鸽会话消息推送 | ✅ 必须 |
+| 发送消息 | `pigeon/sendMessage` | 以客服身份发送消息 | ✅ 必须 |
+| 会话管理 | `pigeon/conversation` | 获取会话列表、结束会话等 | ✅ 必须 |
+| 店铺信息 | `shop/info` | 获取店铺基本信息 | 推荐 |
+| 订单信息 | `order/info` | 获取订单信息(用于客服上下文) | 推荐 |
+| 商品信息 | `product/info` | 获取商品信息(用于商品卡片) | 推荐 |
+
+### 2.3 商家授权
+
+商家需要授权我们的应用访问其店铺数据:
+
+1. 构造授权 URL,引导商家跳转
+2. 商家在抖店授权页同意授权
+3. 平台回调带 `code` 到我们的回调地址
+4. 用 `code` 换取 `access_token`
+
+---
+
+## 三、OAuth2.0 授权详解
+
+### 3.1 授权流程
+
+```
+┌────────┐     ┌──────────┐     ┌──────────────┐     ┌──────────┐
+│  商家   │     │ 我们系统  │     │ 抖店开放平台  │     │ 我们系统  │
+│ 浏览器  │     │ 前端     │     │ 授权服务     │     │ 后端     │
+└───┬────┘     └────┬─────┘     └──────┬───────┘     └────┬─────┘
+    │               │                  │                   │
+    │ 点击"授权店铺" │                  │                   │
+    │──────────────→│                  │                   │
+    │               │ 构造授权URL       │                   │
+    │               │─────────────────→│                   │
+    │  跳转授权页面  │                  │                   │
+    │──────────────────────────────────→│                   │
+    │  商家同意授权   │                  │                   │
+    │──────────────────────────────────→│                   │
+    │               │                  │ 回调带code        │
+    │               │                  │──────────────────→│
+    │               │                  │                   │ 用code换token
+    │               │                  │                   │─────────→
+    │               │                  │                   │←─────────
+    │               │                  │                   │ 保存token
+    │               │ 授权成功通知      │                   │
+    │←──────────────│←─────────────────────────────────────│
+    │               │                  │                   │
+```
+
+### 3.2 授权 URL 构造
+
+```
+https://openapi-fxg.jinritemai.com/oauth/authorize?app_key={app_key}&redirect_uri={redirect_uri}&response_type=code&state={state}
+```
+
+| 参数 | 必须 | 说明 |
+|------|------|------|
+| `app_key` | 是 | 应用 app_key |
+| `redirect_uri` | 是 | 授权回调地址,需与开放平台配置一致 |
+| `response_type` | 是 | 固定值 `code` |
+| `state` | 否 | 自定义参数,回调时原样返回,用于防 CSRF |
+
+### 3.3 获取 access_token
+
+**接口地址**:`POST https://openapi-fxg.jinritemai.com/oauth/token`
+
+**请求参数**:
+
+| 参数 | 类型 | 必须 | 说明 |
+|------|------|------|------|
+| `app_key` | String | 是 | 应用 app_key |
+| `app_secret` | String | 是 | 应用 app_secret |
+| `grant_type` | String | 是 | `authorization_code`(首次获取)或 `refresh_token`(刷新) |
+| `code` | String | 是 | 授权回调获取的 code(首次获取时必传) |
+| `refresh_token` | String | 否 | 刷新令牌(刷新时必传) |
+
+**响应示例**:
+
+```json
+{
+  "code": 10000,
+  "data": {
+    "access_token": "act.xxx",
+    "expires_in": 86400,
+    "refresh_token": "rft.xxx",
+    "refresh_expires_in": 2592000,
+    "open_id": "xxx",
+    "scope": "pigeon,shop,order"
+  },
+  "message": "success"
+}
+```
+
+### 3.4 Token 刷新策略
+
+| 项目 | 说明 |
+|------|------|
+| access_token 有效期 | 24 小时 |
+| refresh_token 有效期 | 30 天 |
+| 刷新时机 | access_token 过期前 1 小时自动刷新 |
+| 刷新方式 | 使用 `grant_type=refresh_token` 调用 token 接口 |
+| 失败处理 | 标记店铺授权过期,通知商家重新授权 |
+
+### 3.5 Token 存储
+
+```sql
+-- 在 platform_shop 表中存储
+access_token    VARCHAR(512)  -- AES-256 加密存储
+refresh_token   VARCHAR(512)  -- AES-256 加密存储
+token_expire_time DATETIME    -- access_token 过期时间
+```
+
+---
+
+## 四、消息推送接入
+
+### 4.1 配置推送地址
+
+1. 登录抖店开放平台控制台
+2. 进入应用管理 → 消息推送
+3. 配置推送地址:`https://your-domain.com/api/chat/callback/douyin`
+4. 平台会发送测试消息验证地址可用性
+5. 必须返回 `{"code":0,"msg":"success"}` 才能启用推送
+
+### 4.2 订阅消息类型
+
+在控制台的消息订阅页面,订阅以下消息:
+
+| 消息名称 | tag 值 | 说明 | 是否必须 |
+|---------|--------|------|---------|
+| 飞鸽会话消息 | `143` | 客服实时会话消息 | ✅ 必须 |
+| 飞鸽会话事件 | `144` | 会话创建/结束/转接等事件 | ✅ 必须 |
+| 售后消息 | `200`-`210` | 售后申请/审核等 | 可选 |
+| 订单消息 | `100`-`110` | 订单状态变更 | 可选 |
+
+### 4.3 飞鸽会话消息(tag=143)
+
+**触发场景**:客服实时会话中有新消息时推送
+
+**消息体结构**:
+
+```json
+[
+  {
+    "tag": "143",
+    "msgId": "0443477XXXXXXX48874::xxx:1618990587:6837374XXXXXXX89128",
+    "data": {
+      "conversation_id": 7316734919177160000,
+      "content": "你好,请问这个商品还有吗?",
+      "extra": "{}",
+      "server_msg_id": 1786312592802848,
+      "sender_role": "Buyer",
+      "customer_hint": "提示信息",
+      "type": "text",
+      "create_time": 1703560445,
+      "card_type": "",
+      "data_id": "",
+      "foot_text": "",
+      "doudian_open_id": "xxxxxx",
+      "aid": "1128",
+      "shop_id": 77977,
+      "pigeon_cid": "72123232377977"
+    }
+  }
+]
+```
+
+**字段详解**:
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `tag` | String | 消息种类,飞鸽会话消息固定为 `"143"` |
+| `msgId` | String | 消息记录 ID,用于幂等去重 |
+| `data.conversation_id` | Int64 | 会话 ID,回复消息时需要此字段 |
+| `data.content` | String | 消息内容 |
+| `data.extra` | String | 消息扩展信息(JSON),图片消息含图片 URL |
+| `data.server_msg_id` | Int64 | 服务端消息 ID,回复时引用 |
+| `data.sender_role` | String | 发送方角色:`Buyer`(买家)、`System`、`Robot`、`CurrentServer`(当前客服) |
+| `data.type` | String | 消息类型:`text`(文本)、`image`(图片)、`card`(卡片) 等 |
+| `data.create_time` | Int64 | 消息时间(秒级时间戳) |
+| `data.card_type` | String | 卡片类型(当 type=card 时) |
+| `data.data_id` | String | 卡片携带的业务 ID |
+| `data.doudian_open_id` | String | 用户 Open ID |
+| `data.shop_id` | Int64 | 店铺 ID |
+| `data.pigeon_cid` | String | 客服 ID |
+
+### 4.4 飞鸽会话事件(tag=144)
+
+**触发场景**:会话创建、结束、转接等事件
+
+**关键事件类型**:
+
+| 事件 | 说明 |
+|------|------|
+| 会话创建 | 新客户进线,创建新会话 |
+| 会话结束 | 会话关闭 |
+| 会话转接 | 会话从一个客服转给另一个客服 |
+| 客服上线 | 客服上线 |
+| 客服下线 | 客服下线 |
+
+### 4.5 消息类型详解
+
+#### 文本消息
+
+```json
+{
+  "type": "text",
+  "content": "你好,请问这个商品还有吗?"
+}
+```
+
+#### 图片消息
+
+```json
+{
+  "type": "image",
+  "content": "",
+  "extra": "{\"image_url\":\"https://xxx.com/image.jpg\",\"width\":800,\"height\":600}"
+}
+```
+
+#### 卡片消息
+
+```json
+{
+  "type": "card",
+  "card_type": "order_create_care",
+  "data_id": "2112212121",
+  "content": "",
+  "foot_text": "此消息由系统发送"
+}
+```
+
+常见卡片类型:
+
+| card_type | 说明 |
+|-----------|------|
+| `order_create_care` | 订单关怀卡片 |
+| `product_recommend` | 商品推荐卡片 |
+| `invite_order` | 邀请下单卡片 |
+| `urge_pay` | 催付卡片 |
+
+---
+
+## 五、消息发送
+
+### 5.1 三方客服 API 概述
+
+通过三方客服 API,我们的系统以客服身份在飞鸽中收发消息。需要先获取客服身份的 access_token。
+
+**API 基础信息**:
+
+| 项目 | 说明 |
+|------|------|
+| 基础 URL | `https://openapi-fxg.jinritemai.com` |
+| 协议 | HTTPS |
+| 认证 | access_token 放在请求头或参数中 |
+| 响应格式 | JSON |
+
+### 5.2 发送文本消息
+
+**接口地址**:`POST /pigeon/sendMessage`
+
+**请求头**:
+
+```
+Content-Type: application/json
+access-token: {access_token}
+```
+
+**请求参数**:
+
+| 参数 | 类型 | 必须 | 说明 |
+|------|------|------|------|
+| `conversation_id` | Int64 | 是 | 会话 ID |
+| `msg_type` | String | 是 | 消息类型:`text` |
+| `content` | String | 是 | 消息内容 JSON |
+| `shop_id` | String | 是 | 店铺 ID |
+
+**请求示例**:
+
+```json
+{
+  "conversation_id": 7316734919177160000,
+  "msg_type": "text",
+  "content": "{\"text\":\"您好,商品还有库存,可以直接下单哦~\"}",
+  "shop_id": "77977"
+}
+```
+
+**响应示例**:
+
+```json
+{
+  "code": 10000,
+  "data": {
+    "msg_id": "1786312592802849",
+    "create_time": 1703560500
+  },
+  "message": "success"
+}
+```
+
+### 5.3 发送图片消息
+
+**请求示例**:
+
+```json
+{
+  "conversation_id": 7316734919177160000,
+  "msg_type": "image",
+  "content": "{\"image_url\":\"https://xxx.com/product.jpg\"}",
+  "shop_id": "77977"
+}
+```
+
+### 5.4 发送商品卡片
+
+**请求示例**:
+
+```json
+{
+  "conversation_id": 7316734919177160000,
+  "msg_type": "card",
+  "content": "{\"card_type\":\"product_recommend\",\"product_id\":\"123456\"}",
+  "shop_id": "77977"
+}
+```
+
+### 5.5 其他会话管理接口
+
+| 接口 | 方法 | 说明 |
+|------|------|------|
+| `/pigeon/getConversationList` | GET | 获取会话列表 |
+| `/pigeon/endConversation` | POST | 结束会话 |
+| `/pigeon/transferConversation` | POST | 转接会话 |
+| `/pigeon/getCustomerInfo` | GET | 获取客户信息 |
+| `/pigeon/setMessageRead` | POST | 设置消息已读 |
+
+---
+
+## 六、消息推送验签
+
+### 6.1 验签流程
+
+抖店开放平台在推送消息时,会在 HTTP 请求头中携带签名信息:
+
+| 请求头 | 说明 |
+|--------|------|
+| `event-sign` | 消息签名值 |
+| `app-id` | 应用 app_key |
+
+### 6.2 MD5 签名验证
+
+```
+签名原文 = app_id + request_body + app_secret
+签名结果 = MD5(签名原文)
+```
+
+**Java 验签示例**:
+
+```java
+public boolean verifySign(HttpServletRequest request, String body) {
+    String eventSign = request.getHeader("event-sign");
+    String appId = request.getHeader("app-id");
+    String signSource = appId + body + appSecret;
+    String calculatedSign = DigestUtils.md5Hex(signSource);
+    return calculatedSign.equalsIgnoreCase(eventSign);
+}
+```
+
+### 6.3 HMAC-SHA256 签名验证
+
+```
+签名原文 = app_id + request_body + app_secret
+签名结果 = HMAC-SHA256(app_secret, 签名原文)
+```
+
+**Java 验签示例**:
+
+```java
+public boolean verifySignHmac(HttpServletRequest request, String body) {
+    String eventSign = request.getHeader("event-sign");
+    String appId = request.getHeader("app-id");
+    String signSource = appId + body + appSecret;
+    Mac mac = Mac.getInstance("HmacSHA256");
+    mac.init(new SecretKeySpec(appSecret.getBytes(), "HmacSHA256"));
+    String calculatedSign = Hex.encodeHexString(mac.doFinal(signSource.getBytes()));
+    return calculatedSign.equalsIgnoreCase(eventSign);
+}
+```
+
+---
+
+## 七、回调接口实现
+
+### 7.1 接口定义
+
+```
+POST /api/chat/callback/douyin
+Content-Type: application/json
+```
+
+### 7.2 处理流程
+
+```
+1. 读取 request body
+2. 从 header 获取 event-sign 和 app-id
+3. 验证签名
+4. 解析消息体(JSON 数组)
+5. 遍历消息列表:
+   a. 根据 tag 判断消息类型
+   b. tag=143:飞鸽会话消息 → 转换为统一消息模型 → 发送 MQ
+   c. tag=144:飞鸽会话事件 → 处理会话生命周期事件
+6. 立即返回 {"code":0,"msg":"success"}
+```
+
+### 7.3 Java 实现示例
+
+```java
+@RestController
+@RequestMapping("/api/chat/callback/douyin")
+public class DouyinCallbackController {
+
+    @Autowired
+    private DouyinAdapter douyinAdapter;
+    @Autowired
+    private MessageProducer messageProducer;
+
+    @PostMapping
+    public Map<String, Object> callback(
+            HttpServletRequest request,
+            @RequestBody String body) {
+
+        if (!douyinAdapter.verifySignature(request, body)) {
+            return Map.of("code", -1, "msg", "sign verify failed");
+        }
+
+        try {
+            JSONArray messages = JSON.parseArray(body);
+            for (int i = 0; i < messages.size(); i++) {
+                JSONObject msg = messages.getJSONObject(i);
+                String tag = msg.getString("tag");
+
+                if ("143".equals(tag)) {
+                    UnifiedMessage unified = douyinAdapter.normalize(body, i);
+                    messageProducer.sendReceiveMessage(unified);
+                } else if ("144".equals(tag)) {
+                    handleConversationEvent(msg);
+                }
+            }
+        } catch (Exception e) {
+            log.error("处理抖音回调异常", e);
+        }
+
+        return Map.of("code", 0, "msg", "success");
+    }
+}
+```
+
+### 7.4 响应要求
+
+| 要求 | 说明 |
+|------|------|
+| HTTP 状态码 | 200 |
+| 响应体 | `{"code":0,"msg":"success"}` |
+| 响应时效 | **2 秒内**,超时平台判定推送失败会重推 |
+| code 值 | 不能传负数 |
+
+---
+
+## 八、消息标准化映射
+
+### 8.1 抖音消息 → 统一消息模型
+
+| 抖音字段 | 统一消息字段 | 转换规则 |
+|---------|-------------|---------|
+| `tag=143` | `platform` | 固定值 `douyin` |
+| `data.shop_id` | `shopId` | 直接映射 |
+| `data.conversation_id` | `conversationId` | 转为字符串 |
+| `data.server_msg_id` | `msgId` | 转为字符串 |
+| `data.type` | `msgType` | `text`→`text`, `image`→`image`, `card`→`card` |
+| `data.content` | `content` | 直接映射 |
+| `data.extra` | `extra` | 解析为 Map |
+| `data.sender_role` | `senderType` | `Buyer`→`customer`, 其他→`system` |
+| `data.doudian_open_id` | `senderId` | 直接映射 |
+| `data.create_time` | `createTime` | 秒级时间戳转毫秒 |
+
+### 8.2 统一消息 → 抖音发送请求
+
+| 统一消息字段 | 抖音发送字段 | 转换规则 |
+|-------------|-------------|---------|
+| `conversationId` | `conversation_id` | 转为 Int64 |
+| `msgType` | `msg_type` | 直接映射 |
+| `content` | `content` | 包装为 JSON |
+| `shopId` | `shop_id` | 直接映射 |
+
+---
+
+## 九、飞鸽插件接入(可选增强)
+
+### 9.1 插件概述
+
+飞鸽右侧工作台支持嵌入自研插件,可在客服工作台直接展示 AI 回复建议、客户画像等信息。
+
+### 9.2 插件类型
+
+| 类型 | 说明 |
+|------|------|
+| 客服工具 | 售后处理、工单等 |
+| 商品工具 | 商品管理 |
+| 订单工具 | 订单管理 |
+| 营销工具 | 精准营销 |
+| **机器人** | **AI 智能回复(我们的目标类型)** |
+
+### 9.3 插件接入流程
+
+1. 商家入驻抖店开放平台
+2. 商家后台申请类目权限(商家后台系统)
+3. 创建自用型应用
+4. 申请开通飞鸽插件权限(联系平台运营开白名单)
+5. 开发插件(前端页面,宽度 410px)
+6. 在开放平台插件管理中上传插件
+7. 在飞鸽应用管理中开启插件
+
+### 9.4 插件页面规范
+
+| 规范项 | 要求 |
+|--------|------|
+| 宽度 | 410px |
+| 高度 | 无限制 |
+| 运行环境 | 飞鸽桌面端内嵌 WebView |
+| 通信 | 通过 postMessage 与飞鸽主界面通信 |
+
+---
+
+## 十、限流与频率控制
+
+### 10.1 平台限流
+
+| 接口 | 限流规则 |
+|------|---------|
+| 消息推送 | 平台主动推送,无频率限制 |
+| 发送消息 API | 按店铺限流,具体限制参考应用权限 |
+| Token 接口 | 每分钟最多 50 次 |
+
+### 10.2 推送重试机制
+
+| 规则 | 说明 |
+|------|------|
+| 超时时间 | 2 秒 |
+| 重试次数 | 最多重推 3 次 |
+| 重试间隔 | 递增间隔 |
+| 幂等要求 | 同一 msgId 可能推送多次,需做幂等 |
+
+---
+
+## 十一、常见问题与注意事项
+
+### 11.1 常见问题
+
+| 问题 | 原因 | 解决方案 |
+|------|------|---------|
+| 推送地址验证失败 | 返回格式不对 | 确保返回 `{"code":0,"msg":"success"}` |
+| 验签不通过 | 签名算法或密钥错误 | 检查 app_secret,确认使用 MD5 还是 HMAC-SHA256 |
+| 消息发送失败 | Token 过期或权限不足 | 刷新 Token,检查是否申请了飞鸽消息权限 |
+| 收不到推送 | 未订阅消息类型 | 在控制台检查消息订阅状态 |
+| 同一消息收到多次 | 平台重推 | 基于 msgId 做幂等处理 |
+
+### 11.2 注意事项
+
+1. **回调接口必须在 2 秒内返回**,否则平台判定推送失败
+2. **消息回复时效为 48 小时**,超时无法回复
+3. **敏感词过滤**:抖音对客服消息有敏感词检测,违规消息会被拦截
+4. **消息格式**:content 字段为 JSON 字符串,需要二次解析
+5. **店铺隔离**:一个第三方应用可服务多个店铺,通过 shop_id 区分
+6. **Token 安全**:access_token 和 refresh_token 必须加密存储
+
+---
+
+## 十二、参考文档
+
+| 文档 | 地址 |
+|------|------|
+| 抖店开放平台首页 | https://op.jinritemai.com |
+| 消息推送接入指南 | https://op.jinritemai.com/docs/guide-docs/10/99 |
+| 飞鸽会话消息推送 | https://op.jinritemai.com/docs/message-docs/1456/6015 |
+| 三方客服 API | https://op.jinritemai.com/docs/api-docs/61/1880 |
+| 飞鸽插件开发指南 | https://school.jinritemai.com/doudian/web/article/108125 |
+| SPI 网关接入文档 | https://bytedance.larkoffice.com/docx/BPMYdiQ6woCoI4xsQNVc1zIMnmc |
+| 飞鸽客服后台 | https://im.jinritemai.com/pc_seller_v2/main/workspace |

+ 966 - 0
docs/电商平台店铺消息收发功能技术方案.md

@@ -0,0 +1,966 @@
+# 电商平台店铺客户消息收发功能 — 技术方案
+
+## 一、项目概述
+
+### 1.1 目标
+
+作为 SaaS 平台,接入**抖音(抖店)、快手、小红书**三家电商平台的店铺客户消息收发能力,使入驻平台的商家店铺能够通过我们的系统接收和回复客户消息,并实现 **AI 自动回复**。
+
+### 1.2 核心能力
+
+| 能力 | 说明 |
+|------|------|
+| 消息接收 | 实时接收三个平台店铺的客户消息(文本、图片、卡片等) |
+| 消息发送 | 通过平台 API 向客户回复消息(文本、图片、商品卡片等) |
+| AI 自动回复 | 对接 AI 模型,根据客户消息自动生成回复内容 |
+| 多店铺管理 | 一个租户可绑定多个平台的多个店铺 |
+| 会话管理 | 统一管理跨平台的客户会话,支持人工接管 |
+
+### 1.3 三平台接入方式对比
+
+| 维度 | 抖音(抖店) | 快手 | 小红书 |
+|------|-------------|------|--------|
+| 开放平台 | 抖店开放平台 op.jinritemai.com | 快手电商开放平台 open.kwaixiaodian.com | 小红书开放平台 open.xiaohongshu.com |
+| 消息接收 | 飞鸽消息推送(WebSocket / HTTP 回调) | 快手消息服务(HTTP 回调) | 聚光平台私信通 API(HTTP 回调) |
+| 消息发送 | 飞鸽 API / 三方客服 API | 快手私信三方客服 API | 聚光私信 API |
+| 应用类型 | 自用型 / 第三方应用 | 自用型 / 第三方应用 | 品牌商 / ISV 服务商 |
+| 认证方式 | OAuth2.0 + access_token | OAuth2.0 + access_token | OAuth2.0 + access_token |
+| 消息类型 | 文本、图片、商品卡片、订单卡片等 | 文本、图片、商品卡片、订单卡片等 | 文本、图片、笔记卡片等 |
+| 回复时效 | 48小时内可回复 | 用户互动后 48 小时内 | 用户进线后 24 小时内 |
+| 主动触达 | 支持场景化主动私信 | 支持潜客主动触达 | 仅限回复场景 |
+
+---
+
+## 二、整体架构
+
+### 2.1 系统架构图
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│                              SaaS 平台                                      │
+│                                                                             │
+│  ┌──────────┐   ┌──────────────────────────────────────────────────────┐   │
+│  │ 管理后台  │   │                   消息中台服务                        │   │
+│  │ (fs-admin)│   │                                                      │   │
+│  │           │   │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │   │
+│  │ ·店铺管理 │   │  │ 抖音消息适配 │  │ 快手消息适配 │  │ 小红书消息适配│ │   │
+│  │ ·会话监控 │   │  │  (Douyin)   │  │  (Kuaishou) │  │(Xiaohongshu)│ │   │
+│  │ ·话术配置 │   │  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘ │   │
+│  │ ·数据统计 │   │         │               │               │         │   │
+│  └──────────┘   │  ┌──────┴───────────────┴───────────────┴──────┐  │   │
+│                 │  │              统一消息处理层                    │  │   │
+│  ┌──────────┐   │  │  ·消息标准化  ·会话管理  ·路由分发  ·限流     │  │   │
+│  │ 客服工作台│   │  └──────────────────────┬──────────────────────┘  │   │
+│  │(company-app)│                          │                          │   │
+│  │           │   │  ┌──────────────────────┴──────────────────────┐  │   │
+│  │ ·实时会话 │   │  │              AI 回复引擎                     │  │   │
+│  │ ·人工接管 │   │  │  ·意图识别  ·知识库匹配  ·LLM 生成  ·审核   │  │   │
+│  │ ·快捷话术 │   │  └────────────────────────────────────────────┘  │   │
+│  └──────────┘   └──────────────────────────────────────────────────────┘   │
+│                                                                             │
+│  ┌──────────────────────────────────────────────────────────────────────┐  │
+│  │                        基础设施层                                     │  │
+│  │  ·MySQL(主库 + 租户库)  ·Redis(缓存/会话)  ·MQ(消息队列)       │  │
+│  └──────────────────────────────────────────────────────────────────────┘  │
+└─────────────────────────────────────────────────────────────────────────────┘
+          ▲                                    ▲                           ▲
+          │ HTTP 回调                           │ HTTP 回调                 │ HTTP 回调
+          │                                     │                           │
+   ┌──────┴──────┐                     ┌────────┴───────┐          ┌──────┴──────┐
+   │  抖店飞鸽    │                     │  快手消息服务   │          │ 小红书聚光   │
+   │  消息推送    │                     │  消息推送       │          │ 私信通推送   │
+   └─────────────┘                     └────────────────┘          └─────────────┘
+```
+
+### 2.2 消息流转流程
+
+```
+客户发消息 → 平台推送 → 我们的回调接口 → 消息标准化 → 入库 → AI 处理 → 回复消息 → 调用平台 API → 客户收到回复
+```
+
+详细步骤:
+
+1. **客户在电商平台发消息**:买家在抖音/快手/小红书店铺的客服对话中发送消息
+2. **平台推送消息**:平台通过 HTTP 回调将消息推送到我们配置的回调地址
+3. **接收并验签**:我们的回调接口接收消息,验证签名确保消息来源合法
+4. **消息标准化**:将不同平台的消息格式转换为统一的内部消息模型
+5. **持久化存储**:将消息存入租户数据库,关联会话
+6. **AI 处理**:将消息发送给 AI 引擎,生成回复内容
+7. **发送回复**:调用对应平台的消息发送 API,将回复发送给客户
+8. **记录日志**:记录消息收发日志,更新会话状态
+
+---
+
+## 三、各平台接入详情
+
+### 3.1 抖音(抖店)接入
+
+#### 3.1.1 接入前置条件
+
+| 条件 | 说明 |
+|------|------|
+| 开放平台账号 | 注册抖店开放平台,完成企业认证 |
+| 应用创建 | 创建「第三方应用」(SaaS 平台作为服务商)或商家创建「自用型应用」 |
+| 应用类目 | 选择「商家后台系统」或「客服管理」类目 |
+| 权限申请 | 申请「飞鸽消息」权限包(含飞鸽会话消息推送、发送消息等) |
+| 店铺授权 | 商家在抖店后台授权应用访问店铺数据 |
+
+#### 3.1.2 核心接口
+
+**(1)消息接收 — 飞鸽会话消息推送**
+
+- **推送方式**:HTTP POST 回调
+- **消息 tag**:`143`(飞鸽会话消息)
+- **推送地址**:在开放平台控制台配置
+
+消息体结构:
+```json
+[
+  {
+    "tag": "143",
+    "msgId": "0443477XXXXXXX48874::xxx:1618990587:6837374XXXXXXX89128",
+    "data": {
+      "conversation_id": 7316734919177160000,
+      "content": "你好,请问在吗?",
+      "extra": "{}",
+      "server_msg_id": 1786312592802848,
+      "sender_role": "Buyer",
+      "customer_hint": "提示信息",
+      "type": "text",
+      "create_time": 1703560445,
+      "card_type": "",
+      "data_id": "",
+      "foot_text": "",
+      "doudian_open_id": "xxxxxx",
+      "aid": "1128",
+      "shop_id": 77977,
+      "pigeon_cid": "72123232377977"
+    }
+  }
+]
+```
+
+关键字段说明:
+
+| 字段 | 说明 |
+|------|------|
+| `conversation_id` | 会话 ID,回复消息时需要 |
+| `content` | 消息内容(文本消息为文字,图片消息为图片 URL) |
+| `sender_role` | 发送方角色:`Buyer`(买家)、`System`、`Robot`、`CurrentServer` |
+| `type` | 消息类型:`text`(文本)、`image`(图片)、`card`(卡片) 等 |
+| `server_msg_id` | 消息 ID,回复时需要引用 |
+| `shop_id` | 店铺 ID,用于区分不同店铺 |
+| `doudian_open_id` | 用户 Open ID |
+
+**(2)消息发送 — 飞鸽 API**
+
+发送文本消息接口:
+- **接口地址**:`https://openapi-fxg.jinritemai.com/pigeon/sendMessage`
+- **请求方式**:POST
+- **认证方式**:access_token(通过 OAuth2.0 获取)
+
+请求参数:
+```json
+{
+  "conversation_id": 7316734919177160000,
+  "msg_type": "text",
+  "content": "{\"text\":\"您好,有什么可以帮您?\"}",
+  "shop_id": "77977"
+}
+```
+
+**(3)三方客服 API(推荐)**
+
+抖店开放平台提供「三方客服 API」,允许第三方系统以客服身份接入飞鸽,实现消息收发:
+
+| 接口 | 说明 |
+|------|------|
+| 会话事件推送 | 客户进线、会话分配等事件推送 |
+| 接收消息推送 | 客户发送的消息实时推送 |
+| 发送消息 | 以客服身份向客户发送消息 |
+| 获取会话列表 | 获取当前客服接待的会话列表 |
+| 结束会话 | 主动结束会话 |
+
+#### 3.1.3 OAuth2.0 授权流程
+
+```
+商家点击授权 → 跳转抖店授权页 → 商家同意授权 → 回调带 code → 用 code 换 access_token → 刷新 token
+```
+
+- **授权 URL**:`https://openapi-fxg.jinritemai.com/oauth/authorize`
+- **Token URL**:`https://openapi-fxg.jinritemai.com/oauth/token`
+- **access_token 有效期**:通常 24 小时
+- **refresh_token 有效期**:通常 30 天
+
+#### 3.1.4 消息推送验签
+
+抖店使用 MD5 或 HMAC-SHA256 签名验证:
+
+```
+签名原文 = app_id + body + app_secret
+签名结果 = MD5(签名原文) 或 HMAC-SHA256(app_secret, 签名原文)
+```
+
+请求头中携带:
+- `event-sign`:签名值
+- `app-id`:应用 app_key
+
+#### 3.1.5 飞鸽插件接入(可选增强)
+
+飞鸽支持右侧工作台插件,可在客服工作台嵌入我们的 AI 面板:
+
+- 插件类型:机器人
+- 页面规范:宽度 410px,高度不限
+- 接入流程:创建应用 → 申请飞鸽插件权限 → 开发插件 → 上线
+
+---
+
+### 3.2 快手接入
+
+#### 3.2.1 接入前置条件
+
+| 条件 | 说明 |
+|------|------|
+| 开放平台账号 | 注册快手电商开放平台,完成企业认证 |
+| 应用创建 | 创建「第三方应用」(SaaS 服务商)或「自用型应用」 |
+| 权限申请 | 申请「客服管理」相关权限(客服质检、智能客服等) |
+| 店铺授权 | 商家授权应用访问店铺数据 |
+
+#### 3.2.2 核心接口
+
+**(1)消息接收 — 快手消息服务**
+
+- **推送方式**:HTTP POST 回调
+- **推送地址**:在快手开放平台控制台配置
+- **消息加密**:AES 加密,需使用 app_secret 解密
+
+消息体结构(解密后):
+```json
+{
+  "biz_type": "im_message",
+  "data": {
+    "conversation_id": "xxx",
+    "msg_id": "xxx",
+    "msg_type": "text",
+    "content": "{\"text\":\"你好\"}",
+    "from_open_id": "xxx",
+    "to_open_id": "xxx",
+    "create_time": 1703560445000,
+    "shop_id": 123456
+  }
+}
+```
+
+**(2)消息发送 — 快手私信三方客服 API**
+
+- **接口地址**:`https://open.kuaishou.com/openapi/message/send`
+- **请求方式**:POST
+- **认证方式**:access_token
+
+请求参数:
+```json
+{
+  "request_id": "uuid-xxx",
+  "open_id": "商家 openId",
+  "app_id": "应用 appId",
+  "kpn": "KUAISHOU",
+  "sub_biz": "KSIM_TO_ADIM",
+  "scene": "im_reply_msg",
+  "target_open_id": "客户 openId",
+  "msg_type": "text",
+  "content": "{\"text\":\"您好,有什么可以帮您?\"}"
+}
+```
+
+**(3)潜客主动触达**
+
+快手支持对潜客(10日内有互动行为的用户)主动发送消息:
+
+- **接口地址**:`https://open.kuaishou.com/openapi/kuailiao/potentialUsersPage`
+- **scene**:`im_potential_customer_msg`
+- **限制**:单 appid QPS 10;每日主动沟通额度有限
+
+#### 3.2.3 OAuth2.0 授权流程
+
+```
+商家点击授权 → 跳转快手授权页 → 商家同意授权 → 回调带 code → 用 code 换 access_token → 刷新 token
+```
+
+- **授权 URL**:`https://open.kuaishou.com/oauth2/authorize`
+- **Token URL**:`https://open.kuaishou.com/oauth2/access_token`
+- **系统参数**:appkey、timestamp、access_token、version、param、method、sign、signMethod
+
+#### 3.2.4 签名算法
+
+快手使用 HMAC-SHA256 签名:
+
+```
+签名原文 = 将除 sign 外的所有系统参数和业务参数按字母排序拼接
+签名结果 = HMAC-SHA256(signSecret, 签名原文)
+```
+
+#### 3.2.5 消息解密
+
+快手推送的消息使用 AES 加密:
+
+```
+解密步骤:
+1. Base64 解码密文
+2. 使用 app_secret 作为 AES Key
+3. AES/CBC/PKCS5Padding 解密
+4. 得到明文 JSON
+```
+
+---
+
+### 3.3 小红书接入
+
+#### 3.3.1 接入前置条件
+
+| 条件 | 说明 |
+|------|------|
+| 开放平台账号 | 注册小红书开放平台,完成企业认证 |
+| 应用创建 | 创建应用,选择「商家后台系统」或「企业ERP」类目 |
+| 私信通开通 | 在专业号平台开通「私信通」功能 |
+| 聚光平台授权 | 在聚光平台完成三方客服 API 对接配置 |
+| 店铺授权 | 商家授权应用 |
+
+**⚠️ 重要说明**:小红书的客服消息接入路径与其他两家不同,需要同时对接**开放平台 API** 和**聚光平台私信通**:
+
+- **开放平台**:用于订单、商品等业务消息推送(HTTP 回调)
+- **聚光平台私信通**:用于客户私信的收发(通过聚光平台配置回调地址 + Token)
+
+#### 3.3.2 核心接口
+
+**(1)消息接收 — 聚光平台私信通**
+
+小红书私信通通过聚光平台推送客户私信消息:
+
+- **推送方式**:HTTP POST 回调
+- **配置入口**:聚光平台 → 工具 → 私信 API 对接
+- **认证方式**:Token 验证(在聚光平台配置时获取)
+
+消息体结构:
+```json
+{
+  "event_type": "im_receive_msg",
+  "data": {
+    "conversation_id": "xxx",
+    "msg_id": "xxx",
+    "msg_type": "text",
+    "content": "你好,请问这个商品还有吗?",
+    "sender_id": "xxx",
+    "receiver_id": "xxx",
+    "create_time": 1703560445,
+    "seller_id": "xxx"
+  }
+}
+```
+
+**(2)消息发送 — 聚光私信 API**
+
+通过聚光平台配置的接口地址发送回复消息:
+
+- **接口地址**:由聚光平台分配(配置回调时获取)
+- **请求方式**:POST
+- **认证方式**:Bearer Token(聚光平台 Token)
+
+请求参数:
+```json
+{
+  "conversation_id": "xxx",
+  "msg_type": "text",
+  "content": "您好,商品还有库存,可以直接下单哦~"
+}
+```
+
+**(3)开放平台消息推送(业务消息)**
+
+小红书开放平台支持订单、商品、售后等业务消息推送:
+
+| 消息类型 | msgTag | 说明 |
+|---------|--------|------|
+| 订单状态变更 | `msg_fulfillment_status_change` | 下单、支付、发货、收货等 |
+| 收货信息变更 | `msg_fulfillment_receiver_change` | 地址修改 |
+| 商品上下架 | `msg_item_buyable` | 商品状态变更 |
+| 售后申请 | `msg_after_sale_create` | 退款/退货/换货申请 |
+
+推送消息体:
+```json
+[
+  {
+    "msgTag": "msg_fulfillment_status_change",
+    "sellerId": "xxx",
+    "data": "{\"order_id\":\"xxx\",\"status\":\"paid\"}"
+  }
+]
+```
+
+#### 3.3.3 OAuth2.0 授权流程
+
+```
+商家点击授权 → 跳转小红书授权页 → 商家同意授权 → 回调带 code → 用 code 换 access_token → 刷新 token
+```
+
+- **授权 URL**:`https://open.xiaohongshu.com/oauth/authorize`
+- **Token URL**:`https://open.xiaohongshu.com/oauth/token`
+
+#### 3.3.4 签名算法
+
+小红书使用 MD5 签名:
+
+```
+1. 将除 sign 外的系统参数和所有请求参数按字母排序
+2. 用 & 连接:app-key=xhs&canshu=test&timestamp=1625475843
+3. 拼接 url + 参数 + app-secret
+4. MD5 计算签名
+```
+
+请求头:
+```
+timestamp: 1625475843
+app-key: xhs
+sign: a7b7430de338783293443133ab9b9357
+```
+
+#### 3.3.5 私信通特殊限制
+
+| 限制项 | 说明 |
+|--------|------|
+| 开通条件 | 需为企业专业号 + 聚光平台推广资质认证 |
+| 回复时效 | 用户进线后 24 小时内可回复 |
+| 主动触达 | 仅限回复场景,不支持主动私信 |
+| 消息类型 | 支持文本、图片、视频;富文本内容会拆分 |
+| 表情限制 | 部分表情显示为文字 |
+| 月投流要求 | 聚光平台月投流超 3000 元才可生效 |
+
+---
+
+## 四、数据库设计
+
+### 4.1 主库表(公共/跨租户)
+
+```sql
+-- 平台店铺绑定表(主库)
+CREATE TABLE `platform_shop` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `tenant_id` bigint NOT NULL COMMENT '租户ID',
+  `platform` varchar(20) NOT NULL COMMENT '平台标识:douyin/kuaishou/xiaohongshu',
+  `shop_id` varchar(64) NOT NULL COMMENT '平台店铺ID',
+  `shop_name` varchar(128) DEFAULT NULL COMMENT '店铺名称',
+  `app_id` varchar(64) DEFAULT NULL COMMENT '应用ID/Key',
+  `app_secret` varchar(256) DEFAULT NULL COMMENT '应用Secret(加密存储)',
+  `access_token` varchar(512) DEFAULT NULL COMMENT '访问令牌(加密存储)',
+  `refresh_token` varchar(512) DEFAULT NULL COMMENT '刷新令牌(加密存储)',
+  `token_expire_time` datetime DEFAULT NULL COMMENT '令牌过期时间',
+  `callback_url` varchar(256) DEFAULT NULL COMMENT '回调地址',
+  `callback_token` varchar(128) DEFAULT NULL COMMENT '回调验证Token',
+  `callback_aes_key` varchar(256) DEFAULT NULL COMMENT '回调消息加密Key(加密存储)',
+  `status` tinyint NOT NULL DEFAULT '1' COMMENT '状态:0-禁用 1-启用',
+  `auth_status` tinyint NOT NULL DEFAULT '0' COMMENT '授权状态:0-未授权 1-已授权 2-已过期',
+  `last_sync_time` datetime DEFAULT NULL COMMENT '最后同步时间',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `del_flag` tinyint NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uk_tenant_platform_shop` (`tenant_id`, `platform`, `shop_id`),
+  KEY `idx_platform_shop` (`platform`, `shop_id`)
+) ENGINE=InnoDB COMMENT='平台店铺绑定表';
+```
+
+### 4.2 租户库表
+
+```sql
+-- 统一消息表
+CREATE TABLE `chat_message` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `msg_id` varchar(128) NOT NULL COMMENT '消息唯一ID(平台消息ID)',
+  `platform` varchar(20) NOT NULL COMMENT '平台:douyin/kuaishou/xiaohongshu',
+  `shop_id` varchar(64) NOT NULL COMMENT '平台店铺ID',
+  `conversation_id` varchar(128) NOT NULL COMMENT '会话ID',
+  `direction` tinyint NOT NULL COMMENT '方向:1-接收(客户发来) 2-发送(发给客户)',
+  `sender_type` varchar(20) NOT NULL COMMENT '发送者类型:customer/ai/agent/system',
+  `sender_id` varchar(64) DEFAULT NULL COMMENT '发送者ID',
+  `msg_type` varchar(20) NOT NULL COMMENT '消息类型:text/image/card/video',
+  `content` text COMMENT '消息内容(文本内容或JSON)',
+  `extra` text COMMENT '扩展信息(JSON,如图片URL、卡片数据等)',
+  `ai_reply_id` bigint DEFAULT NULL COMMENT 'AI回复记录ID',
+  `is_read` tinyint NOT NULL DEFAULT '0' COMMENT '是否已读:0-未读 1-已读',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uk_msg_id` (`msg_id`),
+  KEY `idx_conversation` (`conversation_id`, `create_time`),
+  KEY `idx_platform_shop` (`platform`, `shop_id`, `create_time`)
+) ENGINE=InnoDB COMMENT='统一消息表';
+
+-- 会话表
+CREATE TABLE `chat_conversation` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `conversation_id` varchar(128) NOT NULL COMMENT '会话ID',
+  `platform` varchar(20) NOT NULL COMMENT '平台',
+  `shop_id` varchar(64) NOT NULL COMMENT '平台店铺ID',
+  `customer_id` varchar(64) NOT NULL COMMENT '客户ID(平台OpenID)',
+  `customer_name` varchar(64) DEFAULT NULL COMMENT '客户昵称',
+  `customer_avatar` varchar(256) DEFAULT NULL COMMENT '客户头像',
+  `agent_id` bigint DEFAULT NULL COMMENT '当前接待客服ID(人工接管时)',
+  `status` tinyint NOT NULL DEFAULT '1' COMMENT '会话状态:1-进行中 2-已结束 3-待处理',
+  `ai_enabled` tinyint NOT NULL DEFAULT '1' COMMENT '是否启用AI回复:0-否 1-是',
+  `last_msg_time` datetime DEFAULT NULL COMMENT '最后消息时间',
+  `last_msg_content` varchar(512) DEFAULT NULL COMMENT '最后消息摘要',
+  `unread_count` int NOT NULL DEFAULT '0' COMMENT '未读消息数',
+  `source` varchar(64) DEFAULT NULL COMMENT '进线来源',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `uk_conversation_id` (`conversation_id`),
+  KEY `idx_platform_shop_status` (`platform`, `shop_id`, `status`, `last_msg_time`),
+  KEY `idx_customer` (`customer_id`)
+) ENGINE=InnoDB COMMENT='会话表';
+
+-- AI回复记录表
+CREATE TABLE `chat_ai_reply_log` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `conversation_id` varchar(128) NOT NULL COMMENT '会话ID',
+  `msg_id` varchar(128) NOT NULL COMMENT '原始消息ID',
+  `platform` varchar(20) NOT NULL COMMENT '平台',
+  `shop_id` varchar(64) NOT NULL COMMENT '平台店铺ID',
+  `input_content` text COMMENT '输入内容',
+  `ai_response` text COMMENT 'AI回复内容',
+  `ai_model` varchar(64) DEFAULT NULL COMMENT 'AI模型标识',
+  `reply_status` tinyint NOT NULL DEFAULT '0' COMMENT '回复状态:0-待回复 1-已回复 2-回复失败 3-人工拦截',
+  `reply_msg_id` varchar(128) DEFAULT NULL COMMENT '回复消息ID',
+  `confidence` decimal(5,4) DEFAULT NULL COMMENT '置信度',
+  `latency_ms` int DEFAULT NULL COMMENT 'AI响应耗时(ms)',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY (`id`),
+  KEY `idx_conversation` (`conversation_id`),
+  KEY `idx_msg_id` (`msg_id`)
+) ENGINE=InnoDB COMMENT='AI回复记录表';
+
+-- 话术库表
+CREATE TABLE `chat_quick_reply` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `tenant_id` bigint NOT NULL COMMENT '租户ID',
+  `platform` varchar(20) DEFAULT NULL COMMENT '适用平台(空表示通用)',
+  `category` varchar(64) DEFAULT NULL COMMENT '分类',
+  `title` varchar(128) NOT NULL COMMENT '话术标题',
+  `content` text NOT NULL COMMENT '话术内容',
+  `sort_order` int NOT NULL DEFAULT '0' COMMENT '排序',
+  `status` tinyint NOT NULL DEFAULT '1' COMMENT '状态:0-禁用 1-启用',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB COMMENT='话术库表';
+
+-- AI回复规则表
+CREATE TABLE `chat_ai_rule` (
+  `id` bigint NOT NULL AUTO_INCREMENT,
+  `tenant_id` bigint NOT NULL COMMENT '租户ID',
+  `platform` varchar(20) DEFAULT NULL COMMENT '适用平台',
+  `shop_id` varchar(64) DEFAULT NULL COMMENT '适用店铺(空表示全部)',
+  `rule_name` varchar(128) NOT NULL COMMENT '规则名称',
+  `rule_type` varchar(32) NOT NULL COMMENT '规则类型:keyword/intent/all',
+  `keyword` varchar(256) DEFAULT NULL COMMENT '关键词(逗号分隔)',
+  `intent` varchar(64) DEFAULT NULL COMMENT '意图标识',
+  `reply_content` text NOT NULL COMMENT '回复内容',
+  `priority` int NOT NULL DEFAULT '0' COMMENT '优先级(越大越优先)',
+  `status` tinyint NOT NULL DEFAULT '1' COMMENT '状态:0-禁用 1-启用',
+  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB COMMENT='AI回复规则表';
+```
+
+---
+
+## 五、核心模块设计
+
+### 5.1 模块结构
+
+在现有项目中新增以下模块/包:
+
+```
+fs-service/
+└── src/main/java/com/fs/
+    └── chat/
+        ├── config/                  # 配置
+        │   ├── ChatProperties.java
+        │   └── ChatMqConfig.java
+        ├── constant/                # 常量
+        │   ├── PlatformEnum.java
+        │   └── MsgTypeEnum.java
+        ├── controller/              # 回调接口
+        │   ├── DouyinCallbackController.java
+        │   ├── KuaishouCallbackController.java
+        │   └── XiaohongshuCallbackController.java
+        ├── adapter/                 # 平台适配器
+        │   ├── PlatformAdapter.java           # 适配器接口
+        │   ├── DouyinAdapter.java
+        │   ├── KuaishouAdapter.java
+        │   └── XiaohongshuAdapter.java
+        ├── client/                  # 平台API客户端
+        │   ├── DouyinClient.java
+        │   ├── KuaishouClient.java
+        │   └── XiaohongshuClient.java
+        ├── domain/                  # 实体
+        │   ├── ChatMessage.java
+        │   ├── ChatConversation.java
+        │   ├── ChatAiReplyLog.java
+        │   └── UnifiedMessage.java  # 统一消息模型
+        ├── mapper/                  # Mapper
+        ├── service/                 # 服务
+        │   ├── ChatMessageService.java
+        │   ├── ChatConversationService.java
+        │   ├── ChatAiService.java
+        │   ├── PlatformAuthService.java
+        │   └── impl/
+        └── mq/                      # 消息队列
+            ├── MessageConsumer.java
+            └── MessageProducer.java
+```
+
+### 5.2 统一消息模型
+
+```java
+public class UnifiedMessage {
+
+    private String platform;
+    private String shopId;
+    private String conversationId;
+    private String msgId;
+    private String msgType;
+    private String content;
+    private String senderType;
+    private String senderId;
+    private Long createTime;
+    private Map<String, Object> extra;
+}
+```
+
+### 5.3 平台适配器接口
+
+```java
+public interface PlatformAdapter {
+
+    String getPlatform();
+
+    UnifiedMessage normalize(String rawBody);
+
+    String sendTextMessage(String shopId, String conversationId, String text);
+
+    String sendImageMessage(String shopId, String conversationId, String imageUrl);
+
+    boolean verifySignature(HttpServletRequest request, String body);
+
+    void refreshToken(String shopId);
+}
+```
+
+### 5.4 回调接口设计
+
+三个平台使用独立的回调 URL,便于独立验签和处理:
+
+| 平台 | 回调地址 | 说明 |
+|------|---------|------|
+| 抖音 | `/api/chat/callback/douyin` | 接收飞鸽消息推送 |
+| 快手 | `/api/chat/callback/kuaishou` | 接收快手消息推送 |
+| 小红书 | `/api/chat/callback/xiaohongshu` | 接收聚光私信推送 |
+
+回调接口统一处理流程:
+
+```
+1. 接收 HTTP POST 请求
+2. 读取 body,调用对应适配器验签
+3. 验签通过后,调用适配器 normalize() 转换为统一消息
+4. 将统一消息发送到 MQ
+5. 立即返回成功响应(避免平台超时重推)
+```
+
+### 5.5 消息队列处理
+
+使用 MQ(RocketMQ / RabbitMQ)解耦消息接收与处理:
+
+```
+回调接口 → MQ(topic: chat-message-receive)→ 消费者处理
+                                                    ↓
+                                              1. 消息去重(msg_id 幂等)
+                                              2. 查找/创建会话
+                                              3. 消息入库
+                                              4. 更新会话状态
+                                              5. 触发 AI 回复流程
+```
+
+### 5.6 AI 回复引擎
+
+```
+收到客户消息
+    │
+    ├── 检查会话是否启用 AI
+    │       │
+    │       └── 否 → 仅通知人工客服
+    │
+    ├── 检查是否有人工接管
+    │       │
+    │       └── 是 → 不自动回复,仅转发给人工
+    │
+    ├── 匹配规则(关键词/意图)
+    │       │
+    │       ├── 命中规则 → 使用规则回复
+    │       │
+    │       └── 未命中 → 调用 LLM 生成回复
+    │
+    ├── 回复内容审核(敏感词过滤)
+    │
+    ├── 调用平台 API 发送回复
+    │
+    └── 记录 AI 回复日志
+```
+
+AI 回复调用链路:
+
+```
+ChatAiService.processMessage(unifiedMessage)
+    → 规则匹配(关键词 → 意图识别)
+    → 未命中则调用 AI 模型
+        → 构建上下文(最近 N 条消息 + 系统提示词 + 知识库)
+        → 调用 LLM API(FastGPT / OpenAI / 自部署模型)
+        → 获取回复内容
+    → 敏感词过滤
+    → 调用 PlatformAdapter.sendTextMessage() 发送
+    → 记录日志
+```
+
+---
+
+## 六、Token 管理方案
+
+### 6.1 Token 存储与刷新
+
+三个平台均使用 OAuth2.0,access_token 有有效期,需要自动刷新:
+
+```
+┌──────────────────────────────────────────────────────────┐
+│                    Token 管理器                           │
+│                                                          │
+│  · 启动时加载所有店铺 Token 到缓存                        │
+│  · 定时检查 Token 过期时间(提前 1 小时刷新)             │
+│  · 调用 API 前检查 Token 有效性                          │
+│  · Token 刷新失败时标记店铺授权过期,通知租户             │
+│  · Token 变更同步更新数据库和缓存                        │
+└──────────────────────────────────────────────────────────┘
+```
+
+### 6.2 Token 加密存储
+
+access_token、refresh_token、app_secret 等敏感信息在数据库中加密存储:
+
+- 使用 AES-256 加密
+- 密钥通过配置中心管理,不硬编码
+- 读取时解密,缓存中可存明文(Redis 已有租户前缀隔离)
+
+---
+
+## 七、多租户适配
+
+### 7.1 租户识别
+
+回调消息中携带 `shop_id`,通过 `platform_shop` 表反查 `tenant_id`,然后切换到对应租户数据源:
+
+```
+平台推送消息 → 解析 shop_id → 查主库 platform_shop 得到 tenant_id → 切换租户数据源 → 处理业务
+```
+
+### 7.2 数据隔离
+
+| 数据 | 存储位置 | 隔离方式 |
+|------|---------|---------|
+| 平台店铺绑定(platform_shop) | 主库 | tenant_id 字段 |
+| 消息、会话、AI 日志 | 租户库 | 按库隔离 |
+| 话术库、AI 规则 | 租户库 | 按库隔离 |
+| Token 缓存 | Redis | 租户前缀隔离 |
+
+---
+
+## 八、关键技术点
+
+### 8.1 消息幂等
+
+三个平台均可能重推消息,必须做幂等处理:
+
+- 使用 `msg_id`(平台消息 ID)作为幂等键
+- 入库前先查 `chat_message` 表是否已存在该 `msg_id`
+- Redis 缓存近期 `msg_id`(TTL 24h),先查缓存再查库
+
+### 8.2 回调接口响应时效
+
+| 平台 | 超时要求 | 处理策略 |
+|------|---------|---------|
+| 抖音 | 2 秒内返回 | 收到后立即返回 `{"code":0,"msg":"success"}`,异步处理 |
+| 快手 | 2 秒内返回 | 同上 |
+| 小红书 | 即时返回 200 | 同上 |
+
+**关键**:回调接口只做验签 + 发 MQ + 返回成功,不做任何耗时业务处理。
+
+### 8.3 消息回复时效
+
+| 平台 | 可回复时效 | 超时处理 |
+|------|-----------|---------|
+| 抖音 | 48 小时 | 超时无法回复,需等待客户再次发消息 |
+| 快手 | 48 小时 | 同上 |
+| 小红书 | 24 小时 | 同上 |
+
+AI 回复需在时效内完成,建议 AI 响应时间控制在 3 秒以内。
+
+### 8.4 并发与限流
+
+- **回调接口**:平台推送频率高,需支持高并发接收
+- **消息发送**:各平台 API 有 QPS 限制,需做限流
+  - 抖音:按店铺限流
+  - 快手:单 appid QPS 10
+  - 小红书:QPS 10(企业认证可提升)
+- **AI 调用**:LLM API 有并发限制,需做排队和降级
+
+### 8.5 敏感词过滤
+
+发送前必须过滤敏感词:
+
+- 各平台均有敏感词检测机制,违规消息会被拦截甚至封号
+- 在 AI 回复发送前增加敏感词过滤层
+- 支持租户自定义敏感词库
+- 过滤命中后替换为 `***` 或使用安全话术替代
+
+---
+
+## 九、接口清单
+
+### 9.1 回调接口(平台调用我们)
+
+| 接口 | 方法 | 说明 |
+|------|------|------|
+| `/api/chat/callback/douyin` | POST | 抖音飞鸽消息回调 |
+| `/api/chat/callback/kuaishou` | POST | 快手消息回调 |
+| `/api/chat/callback/xiaohongshu` | POST | 小红书私信回调 |
+| `/api/chat/callback/douyin/auth` | GET | 抖音授权回调 |
+| `/api/chat/callback/kuaishou/auth` | GET | 快手授权回调 |
+| `/api/chat/callback/xiaohongshu/auth` | GET | 小红书授权回调 |
+
+### 9.2 管理接口(我们前端调用)
+
+| 接口 | 方法 | 说明 |
+|------|------|------|
+| `/api/chat/shop/list` | GET | 获取店铺列表 |
+| `/api/chat/shop/bind` | POST | 绑定平台店铺 |
+| `/api/chat/shop/unbind/{id}` | POST | 解绑店铺 |
+| `/api/chat/shop/auth-url` | GET | 获取授权链接 |
+| `/api/chat/conversation/list` | GET | 会话列表 |
+| `/api/chat/conversation/detail` | GET | 会话详情 |
+| `/api/chat/message/list` | GET | 消息列表 |
+| `/api/chat/message/send` | POST | 发送消息(人工) |
+| `/api/chat/conversation/takeover` | POST | 人工接管 |
+| `/api/chat/conversation/release` | POST | 释放(恢复AI) |
+| `/api/chat/ai/rule/list` | GET | AI规则列表 |
+| `/api/chat/ai/rule/save` | POST | 保存AI规则 |
+| `/api/chat/ai/toggle` | POST | 开关AI回复 |
+| `/api/chat/quick-reply/list` | GET | 话术库列表 |
+| `/api/chat/quick-reply/save` | POST | 保存话术 |
+| `/api/chat/stats/overview` | GET | 数据统计概览 |
+
+---
+
+## 十、开发计划
+
+### 第一阶段:基础框架搭建
+
+1. 创建 chat 模块目录结构和基础类
+2. 实现统一消息模型和平台适配器接口
+3. 实现数据库表创建和 Mapper
+4. 实现 MQ 配置和消息生产者/消费者
+5. 实现 Token 管理器
+
+### 第二阶段:抖音接入
+
+1. 实现抖音适配器(DouyinAdapter)
+2. 实现抖音回调接口和验签
+3. 实现抖音消息发送客户端
+4. 实现抖音 OAuth2.0 授权流程
+5. 联调测试
+
+### 第三阶段:快手接入
+
+1. 实现快手适配器(KuaishouAdapter)
+2. 实现快手回调接口和验签 + AES 解密
+3. 实现快手消息发送客户端
+4. 实现快手 OAuth2.0 授权流程
+5. 联调测试
+
+### 第四阶段:小红书接入
+
+1. 实现小红书适配器(XiaohongshuAdapter)
+2. 实现小红书回调接口和验签
+3. 实现小红书消息发送客户端
+4. 对接聚光平台私信通
+5. 联调测试
+
+### 第五阶段:AI 回复引擎
+
+1. 实现规则匹配引擎(关键词/意图)
+2. 对接 LLM API(FastGPT / OpenAI)
+3. 实现上下文构建和知识库检索
+4. 实现敏感词过滤
+5. 实现人工接管机制
+
+### 第六阶段:管理后台
+
+1. 店铺管理页面
+2. 会话监控页面
+3. AI 规则配置页面
+4. 话术库管理页面
+5. 数据统计页面
+
+---
+
+## 十一、风险与注意事项
+
+### 11.1 平台风险
+
+| 风险 | 影响 | 应对 |
+|------|------|------|
+| 平台 API 变更 | 接口不可用 | 关注平台公告,预留适配器升级窗口 |
+| 权限审核不通过 | 无法使用某些接口 | 提前沟通平台运营,准备资质材料 |
+| Token 过期未刷新 | 消息收发中断 | 定时刷新 + 调用前检查 + 失败告警 |
+| 消息推送延迟 | 客户等待时间长 | 监控推送延迟,超时告警 |
+
+### 11.2 合规风险
+
+| 风险 | 应对 |
+|------|------|
+| 敏感信息泄露 | Token 加密存储,日志脱敏 |
+| 违规内容发送 | 敏感词过滤 + AI 回复审核 |
+| 用户隐私保护 | 不持久化用户敏感字段,遵守各平台数据安全规范 |
+| 诱导/骚扰用户 | 遵守各平台消息发送频率限制,不做主动营销推送 |
+
+### 11.3 技术风险
+
+| 风险 | 应对 |
+|------|------|
+| AI 回复不准确 | 置信度阈值控制 + 低置信度转人工 |
+| AI 响应超时 | 设置超时时间(3s),超时使用默认话术 |
+| 高并发消息积压 | MQ 削峰 + 消费者扩容 |
+| 多平台回调冲突 | 独立回调 URL + 独立线程池 |
+
+---
+
+## 十二、参考文档
+
+| 平台 | 文档地址 |
+|------|---------|
+| 抖店开放平台 | https://op.jinritemai.com/docs/guide-docs/10/99 |
+| 抖店飞鸽消息推送 | https://op.jinritemai.com/docs/message-docs/1456/6015 |
+| 抖店三方客服 API | https://op.jinritemai.com/docs/api-docs/61/1880 |
+| 抖音开放平台 IM | https://developer.open-douyin.com/docs/resource/zh-CN/dop/develop/openapi/search-management/private-message/send-msg |
+| 快手电商开放平台 | https://open.kwaixiaodian.com |
+| 快手开放平台客服 | https://open.kuaishou.com/docs/develop/functionAccessGuide/customerService.html |
+| 快手消息服务 | https://open.kwaixiaodian.com/docs/dev?pageSign=120a69028f0e9ea69145644317ae8bcd1614263915925 |
+| 小红书开放平台 | https://open.xiaohongshu.com/document/developer/file/4 |
+| 小红书消息推送 | https://xiaohongshu.apifox.cn/doc-2810938 |
+| 小红书私信通 | https://pro.xiaohongshu.com (专业号平台 → 内容与互动 → 私信通) |