fix(weixin_ilink): 入站按条密钥 + 出站上传地址(真机双 bug)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

Bug A(入站取不到字节)真因两层:① 引用位置错——真实在
`file_item.media.encrypt_query_param`,旧 mediaOf 只扫平铺 url/cdn_url;
② 密钥来源错——官方口径是**随每条附件下发**的 `*_item.media.aes_key`
(图片优先 `image_item.aeskey`),旧代码却把整个 bot_token 当 base64 取尾 16 字节,
而真机 token 形如 `<id>@im.bot:<38hex>`,第 12 字符 `@` 处即非法。
(对照证据:官方包 @tencent-weixin/openclaw-weixin 2.4.9 源码,只读未入库;
design/08 §3.3 的「token base64 尾 16 字节」据此判定为错误口径,待文档更正。)
Bug B(出站):① sendToOne 遇媒体构建失败直接 return ⇒ 连文本一起丢(改为逐条跳过
+ 带来源 WARN;全部媒体失败仍发文本,无文本且全挂才诚实报错);② getUploadURL 发空
body 且只认 4 个猜测键 ⇒ 补齐官方请求体字段 + 依次认 upload_full_url / upload_param。
测试:media_key_test(6 条,真机形态夹具 + 转义钉住)+ send_media_failure_test(6 条)。
变异 6 条(M-A1/A2/A3/B1/B3a/B3b)均先确认变异体可编译、贴红行、还原复绿。
诚实边界:出站媒体**仍发不出去**(PUT vs 官方 POST、响应头 x-encrypted-param、
nativeMediaItem 嵌套形状三项未做)—— 故意只修到「拿到上传地址」,不扩大切片。
This commit is contained in:
AskaEth committed 2026-10-04 22:33:41 +08:00
1 parent 15181e7063
commit 6cb41a8794
7 files changed
+1047 -52

No files matched your search

+9
View File
@@ -83,6 +83,15 @@ var (
ErrProactiveWindow = errors.New("weixin_ilink: proactive push outside 24h window")
// ErrMediaTooLarge 在下载超过 MaxMediaSize 时返回。
ErrMediaTooLarge = errors.New("weixin_ilink: media exceeds size limit")
// ErrNoMediaKey 在入站附件既没有按条 aes_key、也无法用 bot_token 兜底时返回。
ErrNoMediaKey = errors.New("weixin_ilink: inbound media carries no aes_key")
// ErrKeyNotAES128 在按条 aes_key 既不是 16 字节原始密钥、也不是 32 位十六进制
// 密钥串时返回。宁可诚实报错,也不拿长度不对的东西去解密。
ErrKeyNotAES128 = errors.New("weixin_ilink: aes key is neither 16 raw bytes nor 32 hex chars")
// ErrNoUploadURL 在 getuploadurl 返回成功响应、却既没有完整上传地址也没有可拼接
// 的上传参数时返回。它与 ErrSessionRejected 是两类失败:前者是协议字段缺失,后者
// 是凭据被 iLink 拒绝(必须重新扫码)。
ErrNoUploadURL = errors.New("weixin_ilink: getuploadurl returned no upload url")
)
// Config 保存 weixin-ilink 适配器的设置。它由渠道层从环境/配置读取,并可通过