Skip to content

feat(channels): 新增微信客服渠道及入站附件支持 - #203

Open
orhuoxu wants to merge 17 commits into
OpenBMB:mainfrom
orhuoxu:wechat-wecom-attachment-rebased
Open

feat(channels): 新增微信客服渠道及入站附件支持#203
orhuoxu wants to merge 17 commits into
OpenBMB:mainfrom
orhuoxu:wechat-wecom-attachment-rebased

Conversation

@orhuoxu

@orhuoxu orhuoxu commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

变更说明

在微信客服渠道基础能力之上,增加客户发送图片和文件的入站处理,并复用现有附件系统。

主要改动

  • 新增微信客服渠道接入和消息路由能力。
  • 支持微信客服 image、file、mixed 消息归一化。
  • 通过企业微信 media/get 接口流式下载客户图片和文件。
  • 增加图片 2 MB、文件 20 MB 的渠道限制。
  • 正确处理媒体下载接口返回的 JSON 错误和 access_token 失效。
  • 修复 durable inbox 重放时附件类型恢复。
  • 复用现有附件解析、持久化和 Agent 处理链路。
  • 增加渠道、附件、重放和下载错误相关测试。

验证

  • backend/.venv/bin/python -m pytest backend/tests/test_wechat_kf_callback.py backend/tests/test_channel_wechat.py
  • backend/.venv/bin/ruff check backend/app/channels/adapters/wechat_kf.py backend/app/channels/service_wechat_kf_inbox.py backend/tests/test_wechat_kf_callback.py
  • git diff --check

测试结果:61 passed,Ruff 检查通过。

范围说明

  • 当前支持客户发给微信客服的入站图片和文件。
  • 本 PR 暂不涉及客服向客户发送图片和文件。

Comment thread backend/app/api/wechat_kf.py Fixed
@orhuoxu
orhuoxu force-pushed the wechat-wecom-attachment-rebased branch from 36be8ce to a2b252b Compare August 20, 2026 07:17
@orhuoxu
orhuoxu force-pushed the wechat-wecom-attachment-rebased branch from 2af012a to 22cadcb Compare August 21, 2026 02:05
@orhuoxu orhuoxu changed the title feat(channels): 新增微信客服渠道(基于最新主分支) feat(channels): 新增微信客服渠道及入站附件支持 Aug 21, 2026
@fadeoreo

Copy link
Copy Markdown
Collaborator
  1. 回调入口缺少时间戳新鲜度校验
    [wechat_kf.py:35](/Users/a1/Documents/openbmb 新项目/StaffDeck/backend/app/api/wechat_kf.py) 只校验 SHA1 签名,不限制 timestamp。虽然事件 ID 去重可以避免重复入库,但攻击者拿到一次合法请求后,可以长时间重放触发同步接口和资源消耗。建议限制时间窗口,例如 5 分钟,并补测试。
  2. 异常 provider payload 可能导致 500
    [wechat_kf.py:102](/Users/a1/Documents/openbmb 新项目/StaffDeck/backend/app/channels/adapters/wechat_kf.py) 假设 raw["text"] 一定是 dict:
    (raw.get("text") or {}).get("content")
    如果微信返回 malformed payload,text 是字符串或其他类型,会直接抛 AttributeError。建议归一化层对类型做判断,返回 None,并补 malformed fixture。
  3. 回调链路仍有较强的单 binding 假设
    微信客服账号表支持一个 binding 管多个 open_kfid,这点设计是对的;但回调过程中账号、binding 状态、config revision、scope 之间依赖较多,建议补充:
  • binding 重配期间回调
  • 客服账号解绑后旧回调
  • 多账号并发回调
  • cursor 更新成功但 worker 尚未处理时进程退出

@orhuoxu

orhuoxu commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

本次已完成微信客服回调链路边界问题修复,提交:b29d1bc

修改内容

  1. 增加回调时间戳新鲜度校验

    • 限制回调时间窗口为 5 分钟。
    • 拒绝非法、过期和未来时间戳。
    • 403 返回明确原因,便于调用方定位客户端时钟或重放问题。
  2. 防护异常 provider payload

    • textmixedmixed.msg_itemfileimageorigin 做类型校验。
    • malformed 消息安全跳过,不再因 .get() 调用触发 500。
    • sync_msg 返回的 msg_listhas_more 和消息帧增加格式校验。
  3. 加强 binding 与客服账号边界隔离

    • 回调开始时记录 config_revision,binding 重配期间拒绝旧代回调。
    • staging 时重新校验 binding 状态、配置版本、account scope 和 open_kfid 对应的 active 客服账号。
    • 客服账号解绑或禁用后,旧回调无法继续入库。
  4. 补强多账号并发与 cursor 恢复

    • 验证同一 binding 下多个 open_kfid 的 cursor 和事件目标相互隔离。
    • 保持先写 durable inbox、再推进账号 cursor 的顺序。
    • cursor 已更新但 worker 尚未处理时,服务重启后可由 staged worker 接管 received 事件。
    • cursor 持久化失败时,已暂存消息不会丢失。

验证

  • 微信客服回调测试:31 passed
  • 相关渠道和附件测试:87 passed
  • Ruff 检查通过。
  • git diff --check 通过。

@orhuoxu

orhuoxu commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author
  1. 回调入口缺少时间戳新鲜度校验
    [wechat_kf.py:35](/Users/a1/Documents/openbmb 新项目/StaffDeck/backend/app/api/wechat_kf.py) 只校验 SHA1 签名,不限制 timestamp。虽然事件 ID 去重可以避免重复入库,但攻击者拿到一次合法请求后,可以长时间重放触发同步接口和资源消耗。建议限制时间窗口,例如 5 分钟,并补测试。
  2. 异常 provider payload 可能导致 500
    [wechat_kf.py:102](/Users/a1/Documents/openbmb 新项目/StaffDeck/backend/app/channels/adapters/wechat_kf.py) 假设 raw["text"] 一定是 dict:
    (raw.get("text") or {}).get("content")
    如果微信返回 malformed payload,text 是字符串或其他类型,会直接抛 AttributeError。建议归一化层对类型做判断,返回 None,并补 malformed fixture。
  3. 回调链路仍有较强的单 binding 假设
    微信客服账号表支持一个 binding 管多个 open_kfid,这点设计是对的;但回调过程中账号、binding 状态、config revision、scope 之间依赖较多,建议补充:
  • binding 重配期间回调
  • 客服账号解绑后旧回调
  • 多账号并发回调
  • cursor 更新成功但 worker 尚未处理时进程退出

OK,你再审查一下

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants