1. 现象

NapCat WebUI 登录页(/webui/qq_login)点「刷新二维码」,页面毫无反应。二维码不变,扫码也无效。接口不报错,浏览器控制台干净。

2. 根因

NapCat 的登录状态机卡死,RefreshQRcode 变成了空操作。

QQ 登录二维码是一次性的:NapCat 向腾讯要一次码,之后一直复用。重启后状态机会重新走一遍登录流程,才会再次要码。

本例中账号 08:15 快速登录失败后进入扫码模式,之后 9 小时无人扫码,状态机挂起。此时:

接口返回含义
POST /api/QQLogin/RefreshQRcode{"code":0,"data":null,"message":"success"}返回成功但什么都没做
POST /api/QQLogin/GetQQLoginQrcode{"code":0,"data":{"qrcode":"https://txz.qq.com/p?k=..."}}返回的是冻结的旧码
POST /api/QQLogin/CheckLoginStatus{"isLogin":false,"qrcodeurl":"<同一个旧码>"}证实码没换

关键点:接口返回 code:0 / success 不代表刷新成功。 前端 refreshQRCode() 是 fire-and-forget(await a.post(...) 不取返回值),所以失败也不会在任何地方报出来。

注意二维码不是图片,而是一个 URL(https://txz.qq.com/p?k=xxx),由前端本地渲染成 QR。所以看返回体积小(42 字节)是正常的,不是异常信号。

3. 判定方法

看 k= 参数变不变。不变 = 卡死。

# 取到 qrcode URL
curl -s -X POST -H "Authorization: Bearer $C" \
  http://127.0.0.1:6099/api/QQLogin/GetQQLoginQrcode
# 点一次刷新,再取一次。k= 相同即卡死。
curl -s -X POST -H "Authorization: Bearer $C" \
  http://127.0.0.1:6099/api/QQLogin/RefreshQRcode

也可直接看服务日志,重启后会出现新的「二维码解码URL」行:

sudo journalctl -u napcat-<账号>.service --since "1 min ago" | grep "二维码"

4. 解决

sudo systemctl restart napcat-<账号>.service

重启后 RefreshQRcode 恢复正常,k= 每次刷新都变。

验证:

# 重启后连点两次刷新,k= 应该不同

5. 附:NapCat WebUI 认证方式(排查时需要)

WebUI 的凭据不是直接用 token,要换一次:

# 1. 算 hash:SHA256(token + ".napcat")
H=$(printf "<webui_token>.napcat" | sha256sum | cut -d' ' -f1)

# 2. 换 Credential
curl -s -X POST -H "Content-Type: application/json" \
  -d "{\"hash\":\"$H\"}" http://127.0.0.1:6099/api/auth/login
# -> {"code":0,"data":{"Credential":"eyJ..."}}

# 3. 后续请求带 Authorization: Bearer <Credential>

token 在 NapCat/config/webui.json,找不到时可在启动日志里 grep token=。

前端调用链(从 static/assets/*.js 反查):

refreshQRCode()      { await a.post("/QQLogin/RefreshQRcode") }          // 不取返回值
getQQLoginQrcode()   { return (await a.post("/QQLogin/GetQQLoginQrcode")).data.data.qrcode }
checkQQLoginStatus() { return (await a.post("/QQLogin/CheckLoginStatus")).data.data }
loginWithToken(t,r)  { const n = SHA256(t + ".napcat"); await le.post("/auth/login", {hash:n, totpCode:r}) }

另外 POST /api/QQLogin/RestartNapCat 也是 NapCat 自带的恢复入口,效果近似重启。

6. 识别要点

  • NapCat 登录页刷新无反应 → 先看 k= 变不变,别怀疑网络和 nginx。
  • 登录二维码本身约 2 分钟就过期。只要长时间没人扫,就会进入这个卡死态。
  • 接口返回 success ≠ 真的刷新了。前端是 fire-and-forget,不会报错。
  • 一般性结论:NapCat 长时间停留在扫码登录页,刷新会失效,重启服务是标准解法。

7. 相关笔记


本文归档于个人知识库 · 领域:CS & AI · 模块:04 Project_CS_AI/AI apps