fix(channels): Loomy 真实微信 appId/uuid 正则修正 —— 之前是我编的值

## 用真上游实测逼出来的两处错误
批准出站主机后逐个平台打真上游,Loomy 报「授权页未包含二维码 uuid」。
核对参考常量后发现:

1. **appId 是我编的**:我写 `wx16e5c2b8e0c0e1f2`,参考是
   `wx18d60be432287cf8`。上游不认这个 appid,返回的页面里自然没有二维码。
   同时补上微信要求的固定片段 `#wechat_redirect`。
2. **uuid 正则不是参考的那条**:我写的是 `uuid="..."` 形式,而真实微信页把
   uuid 内嵌在 `<img class="js_qrcode_img" src="/connect/qrcode/<uuid>"/>`,
   兜底路径是 `l/qrconnect?uuid=<uuid>`。照参考 extractLoomyWechatUuid 的两条
   正则改写(它还带一个 `^[A-Za-z0-9_\-=+/]{6,64}$` 的字符集校验)。
3. UA 逐字统一为参考的 WECHAT_UA(`Chrome/120.0.0.0`)。

## 教训(值得记)
「照参考逐行移植」这一条,我在这两处做成了「凭印象写个看起来像的」。
**判据是端到端打真上游**,不是测试通过 —— 单测用的是我自己编的夹具,
夹具与生产同源出错时测试照样绿。这次是真上游把它逼出来的。

## 判据
- 测试夹具改为**真实微信页面形态**(`<img ... src="/connect/qrcode/<uuid>">`):
  用别的形态(如 `var uuid = "..."`)测出来的正则不是生产要用的那条。
- 生产实测:Loomy 从真微信拿到二维码 uuid(`open.weixin.qq.com/connect/qrcode/<uuid>`)。
- 四个新平台真上游全部 pending 且返回有效授权入口:
  qoder→qoder.com(真实 PKCE challenge)、zcode→bigmodel.cn、
  loomy→open.weixin.qq.com(真实 uuid)、raccoon→xiaohuanxiong.com(本地 code)
- 全量 core 回归通过;内核对照 v2.0.2 diff 为空。

## 出站主机授权
channels 的 27 个声明主机已全部在设置页批准(8 个新增 + 陈旧条目自动清理),
落盘到 .kernel-perms.json,重启后保留。
This commit is contained in:
JianFeeeee
2026-10-13 10:17:36 +08:00
parent 705e079285
commit ec5e6dd57c
2 changed files with 18 additions and 9 deletions

View File

@ -575,13 +575,17 @@ local PLATFORMS = {
-- 403=用户取消;402=二维码失效
flow = "wechat-poll",
wechat = {
-- appid / redirect_uri 照参考常量(原写的 appid 是我编的,上游不认);
-- 末尾 `#wechat_redirect` 是微信要求的固定片段,缺它对某些客户端会跳错页。
auth_url = "https://open.weixin.qq.com/connect/qrconnect"
.. "?appid=wx16e5c2b8e0c0e1f2&scope=snsapi_login&response_type=code"
.. "&redirect_uri=https%3A%2F%2Floomy.xunfei.cn%2Foauth%2Fwechat%2Fcallback&state={state}",
.. "?appid=wx18d60be432287cf8&scope=snsapi_login&response_type=code"
.. "&redirect_uri=https%3A%2F%2Floomy.xunfei.cn%2Foauth%2Fwechat%2Fcallback"
.. "&state={state}#wechat_redirect",
qr_url = "https://open.weixin.qq.com/connect/qrcode/{uuid}",
poll_url = "https://long.open.weixin.qq.com/connect/l/qrconnect",
-- 逐字照参考 WECHAT_UA(微信对空 UA / 爬虫 UA 可能拒绝)
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
.. " (KHTML, like Gecko) Chrome/120.0 Safari/537.36",
.. " (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
account_base = "https://account.xfyun.cn",
bind_path = "/login/thirdAccount/bind/auth",
access_key_id = "2thryby66wxi53sk",
@ -2157,10 +2161,12 @@ function plugin.start_login(req)
return { status = 200, json = out }
end
local html = resp.body or ""
-- 主正则 + 兜底(含 uuid 的查询串)
local uuid = html:match('uuid%s*=%s*"([^"]+)"')
or html:match("uuid%s*=%s*'([^']+)'")
or html:match("[?&]uuid=([%w%-_]+)")
-- 两条路径互为兜底(照参考 extractLoomyWechatUuid 的正则):
-- 主:<img class="js_qrcode_img" src="/connect/qrcode/<uuid>"/>
-- 兜底:var fordevtool = "…/connect/l/qrconnect?uuid=<uuid>"
-- ⚠️ 无需执行 JS —— 这是本方案能脱离浏览器的基础。
local uuid = html:match("/connect/qrcode/([%w_%-=+/]+)")
or html:match("l/qrconnect%?uuid=([%w_%-=+/]+)")
if not uuid or uuid == "" then
sess.state = "failed"
out.error = "微信授权页未包含二维码 uuid(页面结构可能已变化)"