diff --git a/app.py b/app.py index be2fbb22..97d0563c 100755 --- a/app.py +++ b/app.py @@ -2677,8 +2677,19 @@ def wechat_callback(): state = request.args.get('state') error = request.args.get('error') - # 错误处理 - if error or not code or not state: + # 错误处理:用户拒绝授权 + if error: + if state in wechat_qr_sessions: + wechat_qr_sessions[state]['status'] = 'auth_denied' + wechat_qr_sessions[state]['error'] = '用户拒绝授权' + print(f"❌ 用户拒绝授权: state={state}") + return redirect('/auth/signin?error=wechat_auth_denied') + + # 参数验证 + if not code or not state: + if state in wechat_qr_sessions: + wechat_qr_sessions[state]['status'] = 'auth_failed' + wechat_qr_sessions[state]['error'] = '授权参数缺失' return redirect('/auth/signin?error=wechat_auth_failed') # 验证state @@ -2693,14 +2704,28 @@ def wechat_callback(): return redirect('/auth/signin?error=session_expired') try: - # 获取access_token + # 步骤1: 用户已扫码并授权(微信回调过来说明用户已完成扫码+授权) + session_data['status'] = 'scanned' + print(f"✅ 微信扫码回调: state={state}, code={code[:10]}...") + + # 步骤2: 获取access_token token_data = get_wechat_access_token(code) if not token_data: + session_data['status'] = 'auth_failed' + session_data['error'] = '获取访问令牌失败' + print(f"❌ 获取微信access_token失败: state={state}") return redirect('/auth/signin?error=token_failed') - # 获取用户信息 + # 步骤3: Token获取成功,标记为已授权 + session_data['status'] = 'authorized' + print(f"✅ 微信授权成功: openid={token_data['openid']}") + + # 步骤4: 获取用户信息 user_info = get_wechat_userinfo(token_data['access_token'], token_data['openid']) if not user_info: + session_data['status'] = 'auth_failed' + session_data['error'] = '获取用户信息失败' + print(f"❌ 获取微信用户信息失败: openid={token_data['openid']}") return redirect('/auth/signin?error=userinfo_failed') # 查找或创建用户 / 或处理绑定 @@ -2808,7 +2833,15 @@ def wechat_callback(): except Exception as e: print(f"❌ 微信登录失败: {e}") + import traceback + traceback.print_exc() db.session.rollback() + + # 更新session状态为失败 + if state in wechat_qr_sessions: + wechat_qr_sessions[state]['status'] = 'auth_failed' + wechat_qr_sessions[state]['error'] = str(e) + return redirect('/auth/signin?error=login_failed') diff --git a/src/components/Auth/WechatRegister.js b/src/components/Auth/WechatRegister.js index 67f81447..3b1e2076 100644 --- a/src/components/Auth/WechatRegister.js +++ b/src/components/Auth/WechatRegister.js @@ -33,6 +33,8 @@ const getStatusColor = (status) => { case WECHAT_STATUS.EXPIRED: return "orange.600"; // ✅ 橙色文字 case WECHAT_STATUS.LOGIN_SUCCESS: return "green.600"; // ✅ 绿色文字 case WECHAT_STATUS.REGISTER_SUCCESS: return "green.600"; + case WECHAT_STATUS.AUTH_DENIED: return "red.600"; // ✅ 红色文字 + case WECHAT_STATUS.AUTH_FAILED: return "red.600"; // ✅ 红色文字 default: return "gray.600"; } }; @@ -194,6 +196,33 @@ export default function WechatRegister() { }); } } + // 处理用户拒绝授权 + else if (status === WECHAT_STATUS.AUTH_DENIED) { + clearTimers(); + if (isMountedRef.current) { + toast({ + title: "授权已取消", + description: "您已取消微信授权登录", + status: "warning", + duration: 3000, + isClosable: true, + }); + } + } + // 处理授权失败 + else if (status === WECHAT_STATUS.AUTH_FAILED) { + clearTimers(); + if (isMountedRef.current) { + const errorMsg = response.error || "授权过程出现错误"; + toast({ + title: "授权失败", + description: errorMsg, + status: "error", + duration: 5000, + isClosable: true, + }); + } + } } catch (error) { logger.error('WechatRegister', 'checkWechatStatus', error, { sessionId: wechatSessionId }); // 轮询过程中的错误不显示给用户,避免频繁提示 diff --git a/src/services/authService.js b/src/services/authService.js index 53c6ad46..48f95004 100644 --- a/src/services/authService.js +++ b/src/services/authService.js @@ -147,6 +147,8 @@ export const WECHAT_STATUS = { LOGIN_SUCCESS: 'login_success', REGISTER_SUCCESS: 'register_success', EXPIRED: 'expired', + AUTH_DENIED: 'auth_denied', // 用户拒绝授权 + AUTH_FAILED: 'auth_failed', // 授权失败 }; /** @@ -157,6 +159,8 @@ export const STATUS_MESSAGES = { [WECHAT_STATUS.SCANNED]: '扫码成功,请在手机上确认', [WECHAT_STATUS.AUTHORIZED]: '授权成功,正在登录...', [WECHAT_STATUS.EXPIRED]: '二维码已过期', + [WECHAT_STATUS.AUTH_DENIED]: '用户取消授权', + [WECHAT_STATUS.AUTH_FAILED]: '授权失败,请重试', }; export default authService;