optimize: WeChat QR code auth flow and channel reliability

- Generate QR code server-side when iLink API returns SPA page URL
  (added qrcode + image crates for PNG generation)
- Strip bot_token from frontend response (new WeixinQrcodeStatusPublic type)
- Add request timeouts and shared HTTP client for QR code endpoints
- Fix TOCTOU race on reply_context double-lock (single lock scope)
- Extract do_send() helper to deduplicate sendmessage logic; resend now
  checks ret field for context expiry instead of HTTP status only
- Cap pending_messages buffer at 50 to prevent unbounded memory growth
- Generate stable X-WECHAT-UIN per backend instance instead of per request
- Extract ILINK_CHANNEL_VERSION constant (was hardcoded in 4 places)
- Add 5-minute client-side QR expiry timeout in frontend dialog
- Track consecutive polling errors and show warning after 3 failures
- Stabilise onAuthSuccess/onClose callback refs to prevent polling restarts
- Replace dead i18n key weixinOpenQrcode with weixinPollError

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
xintaofei
2026-04-02 11:22:51 +08:00
parent 0ef36ee918
commit d0e0aad525
17 changed files with 379 additions and 207 deletions

View File

@@ -1719,7 +1719,7 @@
"weixinQrcodeExpired": "انتهت صلاحية رمز QR.",
"weixinRefreshQrcode": "تحديث",
"weixinWaitingScan": "في انتظار المسح...",
"weixinOpenQrcode": "فتح رمز QR في المتصفح",
"weixinPollError": "الاتصال غير مستقر، جاري إعادة المحاولة...",
"connect": "اتصال",
"disconnect": "قطع الاتصال",
"test": "اختبار الاتصال",

View File

@@ -1719,7 +1719,7 @@
"weixinQrcodeExpired": "QR-Code abgelaufen.",
"weixinRefreshQrcode": "Aktualisieren",
"weixinWaitingScan": "Warten auf Scan...",
"weixinOpenQrcode": "QR-Code im Browser öffnen",
"weixinPollError": "Verbindung instabil, erneuter Versuch...",
"connect": "Verbinden",
"disconnect": "Trennen",
"test": "Verbindung testen",

View File

@@ -1719,7 +1719,7 @@
"weixinQrcodeExpired": "QR code expired.",
"weixinRefreshQrcode": "Refresh",
"weixinWaitingScan": "Waiting for scan...",
"weixinOpenQrcode": "Open QR code in browser",
"weixinPollError": "Connection unstable, retrying...",
"connect": "Connect",
"disconnect": "Disconnect",
"test": "Test Connection",

View File

@@ -1719,7 +1719,7 @@
"weixinQrcodeExpired": "El código QR ha expirado.",
"weixinRefreshQrcode": "Actualizar",
"weixinWaitingScan": "Esperando escaneo...",
"weixinOpenQrcode": "Abrir código QR en el navegador",
"weixinPollError": "Conexión inestable, reintentando...",
"connect": "Conectar",
"disconnect": "Desconectar",
"test": "Probar conexión",

View File

@@ -1719,7 +1719,7 @@
"weixinQrcodeExpired": "QR code expiré.",
"weixinRefreshQrcode": "Actualiser",
"weixinWaitingScan": "En attente du scan...",
"weixinOpenQrcode": "Ouvrir le QR code dans le navigateur",
"weixinPollError": "Connexion instable, nouvelle tentative...",
"connect": "Connecter",
"disconnect": "Déconnecter",
"test": "Tester la connexion",

View File

@@ -1719,7 +1719,7 @@
"weixinQrcodeExpired": "QRコードの有効期限が切れました。",
"weixinRefreshQrcode": "更新",
"weixinWaitingScan": "スキャン待ち...",
"weixinOpenQrcode": "ブラウザでQRコードを開く",
"weixinPollError": "接続が不安定です。再試行中...",
"connect": "接続",
"disconnect": "切断",
"test": "接続テスト",

View File

@@ -1719,7 +1719,7 @@
"weixinQrcodeExpired": "QR 코드가 만료되었습니다.",
"weixinRefreshQrcode": "새로고침",
"weixinWaitingScan": "스캔 대기 중...",
"weixinOpenQrcode": "브라우저에서 QR 코드 열기",
"weixinPollError": "연결이 불안정합니다. 재시도 중...",
"connect": "연결",
"disconnect": "연결 해제",
"test": "연결 테스트",

View File

@@ -1719,7 +1719,7 @@
"weixinQrcodeExpired": "Código QR expirado.",
"weixinRefreshQrcode": "Atualizar",
"weixinWaitingScan": "Aguardando escaneamento...",
"weixinOpenQrcode": "Abrir código QR no navegador",
"weixinPollError": "Conexão instável, tentando novamente...",
"connect": "Conectar",
"disconnect": "Desconectar",
"test": "Testar conexão",

View File

@@ -1719,7 +1719,7 @@
"weixinQrcodeExpired": "二维码已过期。",
"weixinRefreshQrcode": "刷新二维码",
"weixinWaitingScan": "等待扫码...",
"weixinOpenQrcode": "在浏览器中打开二维码",
"weixinPollError": "连接不稳定,正在重试...",
"connect": "连接",
"disconnect": "断开",
"test": "测试连接",

View File

@@ -1719,7 +1719,7 @@
"weixinQrcodeExpired": "二維碼已過期。",
"weixinRefreshQrcode": "重新整理",
"weixinWaitingScan": "等待掃碼...",
"weixinOpenQrcode": "在瀏覽器中打開二維碼",
"weixinPollError": "連接不穩定,正在重試...",
"connect": "連線",
"disconnect": "斷開",
"test": "測試連線",