feat(wx-kf): 微信客服截图比价上游入口(服务号版平行实现)

在企业微信「微信客服」侧复刻服务号「发图 → 弹比价窗」的触发链路。下游(心跳下发
pending_compare → 前端弹窗 → 走比价)完全复用服务号 PoC, 本次仅新增上游入口。

- /wx/kf/callback: GET 接入验证(验签 + 解密 echostr 返回明文)+ POST 收 kf_msg_or_event
  事件 → sync_msg 增量拉消息 → 客户(origin=3)发来的图片 / 小程序卡片 → set_pending(测试设备, "meituan")
- wx_kf_client: access_token 进程内缓存 + sync_msg(按 open_kfid 游标续拉)+ 临时素材下载
- 回调加解密与公众号安全模式同源, 直接复用 wx_mp_crypto(receiveid 传 corpid), 未新写 crypto
- config 增 WX_KF_CORP_ID/SECRET/TOKEN/AES_KEY + wx_kf_callback_configured(全空=拒收, 上线零风险)
- 无新依赖、无 migration(信号进程内存、图片落文件)

依赖服务号 PoC 的下游(wx_poc_signal / device 心跳 / wx_mp_crypto), 故基于 poc/wx-screenshot-compare。
external_userid↔device 绑定 / 信号落库 / 平台识别沿用服务号 PoC 遗留(正式化用 unionid 绑定)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zzhyyyyy
2026-07-17 10:04:05 +08:00
parent e66f7fed8c
commit 19a8310b23
4 changed files with 307 additions and 0 deletions
+19
View File
@@ -147,6 +147,15 @@ class Settings(BaseSettings):
# 收图 → 给此 device_id 打 pending → 该设备下次心跳带回 → 前端弹选平台窗。
WX_POC_TEST_DEVICE_ID: str = ""
# ===== 微信客服(企业微信;截图比价上游入口 —— 服务号版的平行实现) =====
# 用户在「微信客服」会话发消息 → 企业微信 POST 事件到 /wx/kf/callback → 后端 sync_msg 拉消息。
# 回调加密与公众号「安全模式」同源(复用 wx_mp_crypto), 但 receiveid 用 corpid 且 echostr 需解密。
# 拉消息 / 下载图片走 qyapi, 需 access_token(corpid + secret 换取)。全空=回调端点拒收, 零风险。
WX_KF_CORP_ID: str = "" # 企业微信 corpid(回调解密 receiveid + 换 access_token)
WX_KF_SECRET: str = "" # 「微信客服」Secret(换 access_token)
WX_KF_TOKEN: str = "" # 客服「接收消息」回调的 Token(URL 验签 + 消息验签)
WX_KF_AES_KEY: str = "" # 客服「接收消息」回调的 EncodingAESKey(AES-256-CBC 解密)
@property
def wx_mp_configured(self) -> bool:
"""服务号网页授权凭证齐全(缺则落地页不发起授权,降级为无 openid)。"""
@@ -162,6 +171,16 @@ class Settings(BaseSettings):
"""消息接收回调凭证齐全(Token + AESKey + AppID)。缺则回调端点拒绝处理消息。"""
return bool(self.WX_MP_TOKEN and self.WX_MP_AES_KEY and self.WX_MP_APPID)
@property
def wx_kf_callback_configured(self) -> bool:
"""微信客服回调凭证齐全(CorpId + Token + AESKey + Secret)。缺则回调端点拒绝处理。"""
return bool(
self.WX_KF_CORP_ID
and self.WX_KF_TOKEN
and self.WX_KF_AES_KEY
and self.WX_KF_SECRET
)
# ===== 微信支付(商家转账到零钱 / 提现)=====
# 真实凭证放 .env(已 gitignore),证书 .pem 放 secrets/。WECHAT_APP_ID 同时用于
# 微信登录(code 换 openid)与转账,必须与 App 端开放平台 appid 一致。