feat: VOD 自动退款 plugin + 截流媒体传输 + 日报修复
变更概览
本 MR 包含话题 TOPIC-20260227-002 上积压的全部 9 个 commit, 分三组:
1. VOD 自动退款 plugin (本次主体, 4 commit)
| commit | 说明 |
|---|---|
bef349c |
feat: 首版实现 — OCR + CMS + 本地去重 |
dbf5e1b |
refactor: 拆成 app/refund/ plugin, 高内聚低耦合 |
1216126 |
refactor: 两张表合并为单表 refund_events |
34a9829 |
chore: env 文档 + pre-existing 测试修复 + 封装改进 |
功能: 监听「雷石-VOD技术支持总群」收到的微信支付成功截图, 经 OCR 提取商户单号 + 金额后, 按贠磊 2026-04-14 最终确认的规格自动调 CMS 接口完成退款, 群内回复 "已退款 X.XX 元". 异常(OCR 失败/查无订单/金额超限/退款失败等)不回群, 只发飞书告警给技术人员.
架构: `app/refund/` plugin 目录, 8 个文件职责单一; 对 `main_headless.py` 只加 5 行调用; 默认 REFUND_ENABLED=false 合并后不影响现有行为.
业务规则 (贠磊确认):
- state=(5, 999) 双查共存, order_tp 遍历 /orderlabel 全集
- 成功判定 errmsg 含 "成功[X条]" 且 X≥1
- 金额单位分, 50 元上限转人工
- 后端 errcode=10001 幂等兜底 + 本地 pay_id 去重优化
安全与灰度:
- 金额双重校验 (OCR vs CMS pay_fee 不一致即中止)
- REFUND_DRY_RUN=true 支持只查单不真调退款
- 扫描窗口限近 N 分钟, 启动不暴扫历史
- 单条炸不影响同批其他消息
测试: 58 个单元测试, 覆盖 OCR 解析 / CMS 三接口 / Store 去重 / Service 端到端 8 场景.
实测: pay_id=CC12T20260413211921489140 真实订单已退款成功 14.90 元.
2. 截流批量推送补齐媒体传输 (1 commit, 遗留)
`ca1ea4e3` — wxbot-clint 侧截流群图片到达时即上传媒体, 批量推送携带 msg_type + file_url; 向后兼容旧客户端.
3. 日报请求体大小系列修复 (4 commit, 遗留)
`d8abf314` `ea36cf91` `d5c0ecad` `7e6f1e17` — 解决日报 API 400 错误: 从限制张数演进到只保留单张 7MB 大小限制, 充分利用 API 10MB/item 容量.
部署说明
新增 env (已写入 .env.example)
``` REFUND_ENABLED=false # 总开关, 合并后保持关闭 REFUND_DRY_RUN=true # 首次开启建议先跑灰度 REFUND_MAX_AMOUNT_FEN=5000 # 上限 50 元
详见 .env.example 完整 11 项
```
灰度路径
- 合并后 REFUND_ENABLED=false, 先观察其他变更稳定性
- 启用时先 REFUND_DRY_RUN=true 跑 1-2 天观察 OCR 命中率
- 确认无误后关掉 DRY_RUN 正式生效
新增依赖
- 无新 pip 依赖
- OCR 复用现有 DASHSCOPE_API_KEY
测试
206 passed / 19 skipped / 0 failed (修复了 3 个 pre-existing 失败)
风险评估
- 默认关闭: REFUND_ENABLED=false, 合并即生效的只有日报/截流修复和 bot_core._offline 初始化修复, 无行为变化
- DB 兼容: refund_events 用 CREATE IF NOT EXISTS, 首次运行自动建表
- 回滚: revert 本 MR 即可, 无破坏性 schema 变更
Checklist
- 58 个新增单测全绿
- 206 个全量测试全绿
- .env.example 已更新
- 贠磊接口规格完整落地
- 默认开关关闭, 不影响现有行为
- pre-existing 测试已顺手修复