2025-09-20 21:27:50 +08:00

188 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextRequest, NextResponse } from 'next/server';
import type { OAuthCallbackParams } from '@/app/types/google-oauth';
/**
* Google OAuth回调处理API
* 处理从Google OAuth返回的授权码完成用户认证
*/
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { code, state, inviteCode } = body;
// 验证必需参数
if (!code || !state) {
return NextResponse.json(
{
success: false,
message: 'Missing required parameters: code and state'
},
{ status: 400 }
);
}
// 解析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向Google换取access token和id_token
const googleClientId = '847079918888-o1nne8d3ij80dn20qurivo987pv07225.apps.googleusercontent.com';
const googleClientSecret = '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'; // 需要设置环境变量
if (!googleClientSecret) {
console.error('Google Client Secret未配置');
return NextResponse.json(
{
success: false,
message: 'Google Client Secret not configured'
},
{ status: 500 }
);
}
const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
code,
client_id: googleClientId,
client_secret: googleClientSecret,
redirect_uri: getRedirectUri(request),
grant_type: 'authorization_code',
}),
});
if (!tokenResponse.ok) {
const errorText = await tokenResponse.text();
console.error('Google token exchange failed:', errorText);
return NextResponse.json(
{
success: false,
message: 'Failed to exchange authorization code for tokens'
},
{ status: 400 }
);
}
const tokenData = await tokenResponse.json();
const { id_token } = tokenData;
if (!id_token) {
console.error('No id_token received from Google');
return NextResponse.json(
{
success: false,
message: 'No id_token received from Google'
},
{ status: 400 }
);
}
// 第二步使用id_token调用Java后端
const javaBaseUrl = process.env.NEXT_PUBLIC_JAVA_URL || 'https://77.app.java.auth.qikongjian.com';
const backendResponse = await fetch(`${javaBaseUrl}/api/auth/google/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({
idToken: id_token, // 使用从Google获取的id_token
action: 'auto', // 自动判断登录或注册
inviteCode: inviteCode || stateData.inviteCode || undefined
})
});
const backendResult = await backendResponse.json();
if (!backendResponse.ok || !backendResult.success) {
console.error('Java后端处理Google OAuth失败:', backendResult);
return NextResponse.json(
{
success: false,
message: backendResult.message || 'Google authentication failed'
},
{ status: backendResponse.status || 500 }
);
}
console.log('Google OAuth认证成功:', {
userId: backendResult.data?.user?.userId,
email: backendResult.data?.user?.email
});
// 返回成功结果
return NextResponse.json({
success: true,
data: {
token: backendResult.data.token,
user: backendResult.data.userInfo || backendResult.data.user,
message: 'Google authentication successful'
}
});
} catch (error: any) {
console.error('Google OAuth回调处理错误:', error);
return NextResponse.json(
{
success: false,
message: error.message || 'Internal server error during Google OAuth callback'
},
{ status: 500 }
);
}
}
/**
* 根据请求获取正确的redirect_uri
*/
function getRedirectUri(request: NextRequest): string {
const host = request.headers.get('host') || '';
const protocol = request.headers.get('x-forwarded-proto') || 'https';
if (host.includes('localhost') || host.includes('127.0.0.1')) {
return `${protocol}://${host}/api/auth/google/callback`;
} else if (host.includes('movieflow.net')) {
return 'https://www.movieflow.net/api/auth/google/callback';
} else if (host.includes('movieflow.ai')) {
return 'https://www.movieflow.ai/api/auth/google/callback';
} else {
// 默认使用生产环境
return 'https://www.movieflow.ai/api/auth/google/callback';
}
}
/**
* 处理GET请求如果需要
*/
export async function GET(request: NextRequest) {
return NextResponse.json(
{
success: false,
message: 'This endpoint only accepts POST requests'
},
{ status: 405 }
);
}