fix(weixin): 二维码回退用qrUrl生成 + 每次点击重新发全新码(修'过期')
用户实测: qrcode原始串编码微信扫出纯字符串(qrcode得用qrUrl liteapp链接); 过期的真正原因 是复用旧二维码(微信码有效期极短)。修: 二维码改回用 qrUrl(liteapp链接)生成; StartLogin 把复用窗口从90s降到5s(仅防连点),否则每次'扫码登录/刷新'都取消旧会话重发全新码——永远新鲜可扫。 build/vet/test+前端build 全绿,已部署。
This commit is contained in:
1 parent
b6b258498c
commit
bef398d47a
2 files changed
+12
-10
No files matched your search
@@ -120,7 +120,7 @@ export function WeixinLogin({
|
|||||||
.finally(() => setBusy(null));
|
.finally(() => setBusy(null));
|
||||||
};
|
};
|
||||||
|
|
||||||
const showQR = status === "waiting" || qrCode !== "";
|
const showQR = status === "waiting" || qrUrl !== "";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Surface gap="sm" className="space-y-3">
|
<Surface gap="sm" className="space-y-3">
|
||||||
@@ -147,8 +147,8 @@ export function WeixinLogin({
|
|||||||
|
|
||||||
{showQR ? (
|
{showQR ? (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{qrCode ? (
|
{qrUrl ? (
|
||||||
<QrImage value={qrCode} />
|
<QrImage value={qrUrl} />
|
||||||
) : (
|
) : (
|
||||||
<Notice tone="warn">二维码暂不可用,请点击「刷新二维码」重试。</Notice>
|
<Notice tone="warn">二维码暂不可用,请点击「刷新二维码」重试。</Notice>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -51,10 +51,11 @@ type loginSession struct {
|
|||||||
done chan error
|
done chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
// qrRefreshTTL bounds how long a WeChat bot QR is usable before StartLogin re-mints
|
// qrReuseWindow is how long a just-minted QR is reused on an immediate re-click
|
||||||
// a fresh one. iLink bot QRs are short-lived; an idempotent StartLogin must not keep
|
// before StartLogin re-mints a fresh one. WeChat bot QRs are short-lived, so a
|
||||||
// serving a long-expired QR (the user would scan it and get "二维码过期").
|
// "扫码登录/刷新二维码" click must yield a brand-new code — reusing an old QR is
|
||||||
const qrRefreshTTL = 90 * time.Second
|
// exactly what makes WeChat report "二维码过期".
|
||||||
|
const qrReuseWindow = 5 * time.Second
|
||||||
|
|
||||||
// StartLogin begins a scan-login and returns the QR code to display. It is
|
// StartLogin begins a scan-login and returns the QR code to display. It is
|
||||||
// idempotent: when a login is already in progress it returns the current QR
|
// idempotent: when a login is already in progress it returns the current QR
|
||||||
@@ -70,9 +71,10 @@ func (a *Adapter) StartLogin(ctx context.Context) (LoginQR, error) {
|
|||||||
return LoginQR{}, ErrAlreadyLoggedIn
|
return LoginQR{}, ErrAlreadyLoggedIn
|
||||||
}
|
}
|
||||||
if sess := a.loginSession; sess != nil {
|
if sess := a.loginSession; sess != nil {
|
||||||
// Idempotent for a fresh QR, but re-mint once the current QR has aged past
|
// Reuse only within a tiny window (a literal double-click); otherwise re-mint
|
||||||
// qrRefreshTTL so the panel's 刷新二维码 always yields a scannable code.
|
// a brand-new QR so the panel's "扫码登录/刷新二维码" never serves a stale,
|
||||||
if time.Since(sess.startedAt) < qrRefreshTTL {
|
// expired WeChat code. The old poll goroutine is cancelled.
|
||||||
|
if time.Since(sess.startedAt) < qrReuseWindow {
|
||||||
return LoginQR{Qrcode: sess.qrcode, Image: sess.image}, nil
|
return LoginQR{Qrcode: sess.qrcode, Image: sess.image}, nil
|
||||||
}
|
}
|
||||||
if sess.cancel != nil {
|
if sess.cancel != nil {
|
||||||
|
|||||||
Reference in new issue
Block a user