From 06a6392cfdefa3400317e5b49971c4b79a58cace Mon Sep 17 00:00:00 2001
From: zhinianboke <115088296+zhinianboke@users.noreply.github.com>
Date: Sat, 2 Aug 2025 12:58:04 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
static/index.html | 65 +++++++++++++++++++++++++++++++++++++++++++++++
utils/qr_login.py | 13 +++++++---
2 files changed, 75 insertions(+), 3 deletions(-)
diff --git a/static/index.html b/static/index.html
index ce91944..f6c5706 100644
--- a/static/index.html
+++ b/static/index.html
@@ -7883,6 +7883,12 @@
document.getElementById('qrCodeImage').style.display = 'none';
document.getElementById('statusText').textContent = '正在生成二维码,请耐心等待...';
document.getElementById('statusSpinner').style.display = 'none';
+
+ // 隐藏验证容器
+ const verificationContainer = document.getElementById('verificationContainer');
+ if (verificationContainer) {
+ verificationContainer.style.display = 'none';
+ }
}
// 显示二维码图片
@@ -7957,6 +7963,12 @@
document.getElementById('statusSpinner').style.display = 'none';
clearQRCodeCheck();
break;
+ case 'verification_required':
+ document.getElementById('statusText').textContent = '需要手机验证';
+ document.getElementById('statusSpinner').style.display = 'none';
+ clearQRCodeCheck();
+ showVerificationRequired(data);
+ break;
}
}
} catch (error) {
@@ -7964,6 +7976,59 @@
}
}
+ // 显示需要验证的提示
+ function showVerificationRequired(data) {
+ if (data.verification_url) {
+ // 隐藏二维码区域
+ document.getElementById('qrCodeContainer').style.display = 'none';
+ document.getElementById('qrCodeImage').style.display = 'none';
+
+ // 显示验证提示
+ const verificationHtml = `
+
+
+
+
+
账号需要手机验证
+
+
+ 检测到账号存在风控,需要进行手机验证才能完成登录
+
+
+
+
+
+ 验证步骤:
+ 1. 点击上方按钮打开验证页面
+ 2. 按照页面提示完成手机验证
+ 3. 验证完成后,重新扫码登录
+
+
+
+ `;
+
+ // 创建验证提示容器
+ let verificationContainer = document.getElementById('verificationContainer');
+ if (!verificationContainer) {
+ verificationContainer = document.createElement('div');
+ verificationContainer.id = 'verificationContainer';
+ document.querySelector('#qrCodeLoginModal .modal-body').appendChild(verificationContainer);
+ }
+
+ verificationContainer.innerHTML = verificationHtml;
+ verificationContainer.style.display = 'block';
+
+ // 显示Toast提示
+ showToast('账号需要手机验证,请按照提示完成验证', 'warning');
+ }
+ }
+
// 处理扫码成功
function handleQRCodeSuccess(data) {
if (data.account_info) {
diff --git a/utils/qr_login.py b/utils/qr_login.py
index 8ad32f0..39d0068 100644
--- a/utils/qr_login.py
+++ b/utils/qr_login.py
@@ -48,7 +48,7 @@ class QRLoginSession:
def __init__(self, session_id: str):
self.session_id = session_id
- self.status = 'waiting' # waiting, scanned, success, expired, cancelled
+ self.status = 'waiting' # waiting, scanned, success, expired, cancelled, verification_required
self.qr_code_url = None
self.qr_content = None
self.cookies = {}
@@ -56,6 +56,7 @@ class QRLoginSession:
self.created_time = time.time()
self.expire_time = 300 # 5分钟过期
self.params = {} # 存储登录参数
+ self.verification_url = None # 风控验证URL
def is_expired(self) -> bool:
"""检查是否过期"""
@@ -281,13 +282,14 @@ class QRLoginManager:
is True
):
# 账号被风控,需要手机验证
- session.status = 'cancelled'
+ session.status = 'verification_required'
iframe_url = (
resp.json()
.get("content", {})
.get("data", {})
.get("iframeRedirectUrl")
)
+ session.verification_url = iframe_url
logger.warning(f"账号被风控,需要手机验证: {session_id}, URL: {iframe_url}")
break
else:
@@ -331,7 +333,7 @@ class QRLoginManager:
await asyncio.sleep(2)
# 超时处理
- if session.status not in ['success', 'expired', 'cancelled']:
+ if session.status not in ['success', 'expired', 'cancelled', 'verification_required']:
session.status = 'expired'
logger.info(f"二维码监控超时,标记为过期: {session_id}")
@@ -354,6 +356,11 @@ class QRLoginManager:
'session_id': session_id
}
+ # 如果需要验证,返回验证URL
+ if session.status == 'verification_required' and session.verification_url:
+ result['verification_url'] = session.verification_url
+ result['message'] = '账号被风控,需要手机验证'
+
# 如果登录成功,返回Cookie信息
if session.status == 'success' and session.cookies and session.unb:
result['cookies'] = self._cookie_marshal(session.cookies)