refactor(weixin-ilink): 措辞纠正 —「会话过期」→「会话被 iLink 拒绝」(零逻辑改动)
事实(主人 2026-10-03 确认):iLink 的 bot token 是长期凭据(一个月前扫码的仍可用);errcode=-14 是 iLink 侧拒绝/作废该会话,不是时间性过期;且至今未观测到真实 -14(当日全部日志 0 次)。此前代码把这些写成「过期」,属沿用的旧命名,现纠正。 - 纯改名/文案:ErrSessionExpired→ErrSessionRejected、errSessionExpired→errcodeSessionRejected、expired/expiredToken→rejected/rejectedToken、markExpired/expiredLocked/expiredState→markRejected/rejectedLocked/rejectedState;409 错误码 session_expired→session_rejected - 行为一字未改:显式标记 / Connect 不假 OK / 面板 needsRescan+lastError / 扫码或换新 token 即清除 全部保留 - 微信协议自身的「二维码过期」与 auth 的 JWT/refresh 过期一律未动(那些是真·时间性过期) - Docs/api-client v0.39 补事实说明;顺手收尾 3 处残留注释(admin.go / channelbridge/inbound.go / readloop_test.go)
This commit is contained in:
1 parent
cdc370dc82
commit
a51aadeef4
14 files changed
+205
-192
No files matched your search
@@ -145,7 +145,7 @@ func (a *Adapter) runLogin(sess *loginSession, sessCtx context.Context) {
|
||||
// completeLogin persists the confirmed credentials and marks the session live.
|
||||
// It writes cfg under a.mu, then clears the session under loginMu (never nesting
|
||||
// the two locks), and finally signals the waiting Connect path. A confirmed scan
|
||||
// delivers a fresh bot_token, which is the canonical way OUT of the expired state
|
||||
// delivers a fresh bot_token, which is the canonical way OUT of the rejected state
|
||||
// (session_state.go): the rescan flag is cleared here.
|
||||
func (a *Adapter) completeLogin(sess *loginSession, status qrcodeStatusResp) {
|
||||
a.mu.Lock()
|
||||
@@ -175,14 +175,14 @@ func (a *Adapter) completeLogin(sess *loginSession, status qrcodeStatusResp) {
|
||||
// completeBindedRedirect treats binded_redirect as an already-bound outcome: the
|
||||
// scanned bot is already linked to this instance, so the server issues no new
|
||||
// credentials and any existing token remains valid. Because NO new token arrives,
|
||||
// an expired session stays expired here — binded_redirect carries no proof that a
|
||||
// a rejected session stays rejected here — binded_redirect carries no proof that a
|
||||
// token iLink already rejected with errcode=-14 works again, so the adapter does
|
||||
// not claim a live session on the strength of it. A confirmed scan (completeLogin)
|
||||
// is what clears the expired state.
|
||||
// is what clears the rejected state.
|
||||
func (a *Adapter) completeBindedRedirect(sess *loginSession) {
|
||||
a.log.Info("weixin_ilink: login already bound (binded_redirect)")
|
||||
a.mu.Lock()
|
||||
a.connected = a.cfg.BotToken != "" && !a.expiredLocked()
|
||||
a.connected = a.cfg.BotToken != "" && !a.rejectedLocked()
|
||||
a.loginStatus = LoginStatusConfirmed
|
||||
a.loginDetail = loginBindedRedirectDetail
|
||||
a.mu.Unlock()
|
||||
@@ -218,12 +218,12 @@ func (a *Adapter) failLogin(sess *loginSession, err error) {
|
||||
// localTokenList returns the locally-held bot tokens to advertise on
|
||||
// get_bot_qrcode, so an already-bound bot can be detected (binded_redirect). On a
|
||||
// fresh bind it returns an empty (non-nil) slice so the wire carries `[]` rather
|
||||
// than `null`, matching the official client. An EXPIRED token is deliberately not
|
||||
// advertised: it is not a usable bind, and offering it lets the server answer
|
||||
// binded_redirect (no new credentials) — which would leave the owner stuck with a
|
||||
// dead token and no way back. Reporting `[]` asks for a real rebind.
|
||||
// than `null`, matching the official client. A token iLink REJECTED is deliberately
|
||||
// not advertised: it is not a usable bind, and offering it lets the server answer
|
||||
// binded_redirect (no new credentials) — which would leave the owner stuck with an
|
||||
// unusable credential and no way back. Reporting `[]` asks for a real rebind.
|
||||
func (a *Adapter) localTokenList() []string {
|
||||
if expired, _ := a.expiredState(); expired {
|
||||
if rejected, _ := a.rejectedState(); rejected {
|
||||
return []string{}
|
||||
}
|
||||
a.mu.RLock()
|
||||
|
||||
Reference in new issue
Block a user