diff --git a/app/api/auth/google/callback/route.ts b/app/api/auth/google/callback/route.ts index 709c9da..cb79f02 100644 --- a/app/api/auth/google/callback/route.ts +++ b/app/api/auth/google/callback/route.ts @@ -1,175 +1,10 @@ import { NextRequest, NextResponse } from 'next/server'; -import type { OAuthCallbackParams } from '@/app/types/google-oauth'; /** * Google OAuth回调处理API - * 处理从Google OAuth返回的授权码,完成用户认证 + * 注意:POST 方法已废弃,业务逻辑已移至 /users/oauth/callback 页面 + * 此文件现在仅用于处理 Google 的 GET 回调重定向 */ -export async function POST(request: NextRequest) { - console.log('🎯 Google OAuth Callback API 被调用'); - console.log('📍 Request URL:', request.url); - console.log('📍 Request method:', request.method); - - try { - const body = await request.json(); - console.log('📦 Request body:', body); - const { code, state, inviteCode } = body; - - // 验证必需参数 - if (!code || !state) { - return NextResponse.json( - { - success: false, - message: 'Missing required parameters: code and state' - }, - { status: 400 } - ); - } - - // 移除开发模式模拟,始终调用真实接口 - console.log('🚀 开始处理Google OAuth回调,调用真实接口'); - - // 解析state参数 - let stateData: any = {}; - try { - stateData = JSON.parse(state); - } catch (e) { - console.warn('无法解析state参数:', state); - return NextResponse.json( - { - success: false, - message: 'Invalid state parameter' - }, - { status: 400 } - ); - } - - console.log('Google OAuth回调处理开始:', { - codeLength: code.length, - stateData, - inviteCode - }); - - // 直接将authorization code传递给Java后端处理 - console.log('准备调用Java后端验证Google authorization code...'); - - // 第二步:调用Java验证接口(只验证不创建用户) - const javaBaseUrl = 'https://auth.test.movieflow.ai'; - console.log('🔧 使用固定的 javaBaseUrl:', javaBaseUrl); - console.log('开始调用Java验证接口:', javaBaseUrl); - - const verifyResponse = await fetch(`${javaBaseUrl}/api/auth/google/callback`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - }, - body: JSON.stringify({ - code: code, // Google authorization code - state: state, // state参数 - inviteCode: inviteCode || stateData.inviteCode || undefined, - skipUserCreation: true // 🔑 关键:只验证不创建用户 - }) - }); - - console.log('Java验证接口响应状态:', verifyResponse.status); - const verifyResult = await verifyResponse.json(); - - if (!verifyResponse.ok || !verifyResult.success) { - console.error('Java验证接口处理失败:', verifyResult); - return NextResponse.json( - { - success: false, - message: verifyResult.message || 'Google token verification failed' - }, - { status: verifyResponse.status || 500 } - ); - } - - console.log('Google Token验证成功:', { - email: verifyResult.data?.email, - name: verifyResult.data?.name - }); - - // 第三步:调用Python注册接口进行用户创建和积分发放 - const smartvideoBaseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'https://77.smartvideo.py.qikongjian.com'; - console.log('开始调用Python注册接口:', smartvideoBaseUrl); - - const registerResponse = await fetch(`${smartvideoBaseUrl}/api/user_fission/register_with_invite`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json', - }, - body: JSON.stringify({ - email: verifyResult.data.email, - name: verifyResult.data.name, - auth_type: 'GOOGLE', - google_user_info: verifyResult.data, - invite_code: inviteCode || stateData.inviteCode || undefined - }) - }); - - console.log('Python注册接口响应状态:', registerResponse.status); - const registerResult = await registerResponse.json(); - - if (!registerResponse.ok || !registerResult.successful) { - console.error('Python注册接口处理失败:', registerResult); - return NextResponse.json( - { - success: false, - message: registerResult.message || 'User registration failed' - }, - { status: registerResponse.status || 500 } - ); - } - - console.log('Google OAuth注册成功:', { - userId: registerResult.data?.user_id, - email: registerResult.data?.email - }); - - // 返回成功结果(统一格式) - return NextResponse.json({ - success: true, - data: { - token: registerResult.data.token, - user: { - userId: registerResult.data.user_id, - userName: registerResult.data.name, - name: registerResult.data.name, - email: registerResult.data.email, - authType: registerResult.data.auth_type, - isNewUser: true - }, - message: 'Google OAuth registration successful with credit rewards' - } - }); - - } catch (error: any) { - console.error('Google OAuth回调处理错误:', error); - - // 检查是否是网络连接错误 - if (error.code === 'ECONNREFUSED' || error.message?.includes('fetch failed')) { - console.error('网络连接失败,可能是Java后端服务不可用'); - return NextResponse.json( - { - success: false, - message: 'Backend service unavailable. Please try again later.' - }, - { status: 503 } - ); - } - - return NextResponse.json( - { - success: false, - message: error.message || 'Internal server error during Google OAuth callback' - }, - { status: 500 } - ); - } -} /** * 根据请求获取正确的redirect_uri diff --git a/app/users/oauth/callback/page.tsx b/app/users/oauth/callback/page.tsx index 1f0b7a0..40b9313 100644 --- a/app/users/oauth/callback/page.tsx +++ b/app/users/oauth/callback/page.tsx @@ -78,58 +78,126 @@ export default function OAuthCallback() { console.log('State数据:', stateData); console.log('最终使用的邀请码:', finalInviteCode); - // 调用Next.js API路由处理授权码(新的两步流程:Java验证 + Python注册) - console.log('调用Next.js API路由:', '/api/auth/google/callback'); + // 直接处理 OAuth 回调(两步流程:Java验证 + Python注册) + console.log('开始直接处理 OAuth 回调,无需经过 API 路由'); - const response = await fetch('/api/auth/google/callback', { + // 第一步:调用Java验证接口(只验证不创建用户) + const javaBaseUrl = 'https://auth.test.movieflow.ai'; + console.log('🔧 调用 Java 验证接口:', javaBaseUrl); + + const verifyResponse = await fetch(`${javaBaseUrl}/api/auth/google/callback`, { method: 'POST', headers: { - 'Accept': 'application/json', 'Content-Type': 'application/json', + 'Accept': 'application/json', }, body: JSON.stringify({ - code: params.code, - state: params.state, - ...(finalInviteCode && { inviteCode: finalInviteCode }) + code: params.code, // Google authorization code + state: params.state, // state参数 + inviteCode: finalInviteCode, // 邀请码 + skipUserCreation: true // 🔑 关键:只验证不创建用户 }) }); - if (!response.ok) { - // 处理HTTP错误状态 - const errorText = await response.text(); - console.error('OAuth API调用失败:', response.status, errorText); - throw new Error(`OAuth API调用失败 (${response.status}): ${errorText}`); + console.log('Java验证接口响应状态:', verifyResponse.status); + const verifyResult = await verifyResponse.json(); + + if (!verifyResponse.ok || !verifyResult.success) { + console.error('Java验证接口处理失败:', verifyResult); + throw new Error(verifyResult.message || 'Google token verification failed'); } - const result = await response.json(); - console.log('OAuth API响应:', result); + console.log('Google Token验证成功:', { + email: verifyResult.data?.email, + name: verifyResult.data?.name + }); - if (result.success) { - console.log('Google登录成功:', result); - setStatus("success"); - setMessage("Login successful! Redirecting to dashboard..."); - - // 保存用户信息到localStorage (使用认证库的统一键名) - if (result.data?.user) { - localStorage.setItem('currentUser', JSON.stringify(result.data.user)); - } - if (result.data?.token) { - localStorage.setItem('token', result.data.token); - } + // 第二步:调用Python注册接口进行用户创建和积分发放 + const smartvideoBaseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'https://77.smartvideo.py.qikongjian.com'; + console.log('🔧 调用 Python 注册接口:', smartvideoBaseUrl); - // 2秒后跳转到主页 - setTimeout(() => { - // 修复: Google登录成功后应该跳转到主页面,而不是来源页面 - const returnUrl = '/movies'; - window.location.href = returnUrl; - }, 2000); - } else { - throw new Error(result.message || 'Google登录失败'); + const registerResponse = await fetch(`${smartvideoBaseUrl}/api/user_fission/register_with_invite`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body: JSON.stringify({ + email: verifyResult.data.email, + name: verifyResult.data.name, + auth_type: 'GOOGLE', + google_user_info: { + email: verifyResult.data.email, + name: verifyResult.data.name, + picture: verifyResult.data.picture || '', + googleId: verifyResult.data.googleId || verifyResult.data.id || '', + verified: verifyResult.data.verified || true, + inviteCode: finalInviteCode + }, + invite_code: finalInviteCode + }) + }); + + console.log('Python注册接口响应状态:', registerResponse.status); + const registerResult = await registerResponse.json(); + + if (!registerResponse.ok || !registerResult.successful) { + console.error('Python注册接口处理失败:', registerResult); + throw new Error(registerResult.message || 'User registration failed'); } + console.log('Google OAuth注册成功:', { + userId: registerResult.data?.user_id, + email: registerResult.data?.email + }); + + // 处理成功结果 + console.log('Google登录成功:', registerResult); + setStatus("success"); + setMessage("Login successful! Redirecting to dashboard..."); + + // 保存用户信息到localStorage + const userData = { + userId: registerResult.data.user_id, + userName: registerResult.data.name, + name: registerResult.data.name, + email: registerResult.data.email, + authType: registerResult.data.auth_type || 'GOOGLE', + isNewUser: true, + inviteCode: registerResult.data.invite_code + }; + + localStorage.setItem('currentUser', JSON.stringify(userData)); + if (registerResult.data.token) { + localStorage.setItem('token', registerResult.data.token); + } + + // 2秒后跳转到主页 + setTimeout(() => { + const returnUrl = '/movies'; + window.location.href = returnUrl; + }, 2000); + } catch (error: any) { console.error("OAuth callback error:", error); + // 检查是否是网络连接错误 + if (error.code === 'ECONNREFUSED' || error.message?.includes('fetch failed')) { + console.error('网络连接失败,可能是后端服务不可用'); + setStatus("error"); + setMessage('Backend service unavailable. Please try again later.'); + return; + } + + // 检查是否是 JSON 解析错误 + if (error.message?.includes('JSON') || error.name === 'SyntaxError') { + console.error('响应数据解析失败:', error); + setStatus("error"); + setMessage('Invalid response format from backend services'); + return; + } + + // 处理邮箱冲突错误 if (error.type === 'EMAIL_CONFLICT') { setStatus("conflict"); setMessage(error.message);