feat(weixin-ilink,gateway): 会话过期显式化 — 不再静默变哑/假 OK 重连,面板可见「需重扫」
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- 适配器新增过期状态机(plugins/channels/weixin_ilink/session_state.go):getupdates/sendmessage/getuploadurl 收到 errcode=-14 即 markExpired(ERROR 仅一次,只带 bot_id,token 永不入日志),扫码登录拿到新 token 或配置换新 token 时清除(惰性比对)
- Connect/HealthCheck 在过期时返回 ErrSessionExpired(可与 ErrNotConnected 区分):不再对死 token 设 connected=true 报假成功;发送路径同样返回该错误而不是笼统 ErrNotConnected
- 网关:POST /admin/channels/open 遇过期 → 409 session_expired + 明确文案(不再吞错回 200);GET /admin/channels 摘要新增 needsRescan/lastError(经可选接口类型断言读取,取不到不伪造)
- channelbridge:读循环非取消退出时把自身记账的 connected 置 false(热重载被替换者退出不抹掉新实例)
- login/login_admin:过期时 StartLogin 允许重新出码、LoginStatus 如实报 failed(原先可能把死 token 当 confirmed 重新落盘)
- Docs/api-client v0.39;新增 5 组测试 + 变异验证(去掉标记/恢复假成功/网关不填字段 均 FAIL)
This commit is contained in:
AskaEth committed 2026-10-03 18:00:01 +08:00
1 parent 2092094d0a
commit cdc370dc82
14 files changed
+975 -30

No files matched your search

+6 -4
View File
@@ -95,10 +95,12 @@ func (a *Adapter) ReadMessages(ctx context.Context, emit func(adapter.UnifiedMes
failures = 0
if resp.Errcode == errSessionExpired {
a.log.Warn("session expired (errcode=-14); stop polling, re-scan required")
a.mu.Lock()
a.connected = false
a.mu.Unlock()
// The bot token is dead: retrying cannot help and the poll loop would go
// mute for good. Record the explicit expired state (which also drops the
// connected flag and logs at ERROR) and stop the loop; the owner has to
// re-scan, and everything downstream sees ErrSessionExpired until a fresh
// token arrives.
a.markExpired(rescanReasonGetUpdates)
return
}
if resp.Ret != 0 {