forked from 77media/video-flow
随堂测验
This commit is contained in:
parent
5ff071f6c0
commit
7ae003a133
280
docs/jiekou.md
280
docs/jiekou.md
@ -1,241 +1,121 @@
|
|||||||
# Google OAuth 前端改造指南
|
# Google OAuth 前端接入说明
|
||||||
|
|
||||||
## 📋 改造目标
|
该文档面向前端同学,描述最新的 Google 登录/注册接入方式。
|
||||||
让Google OAuth注册用户也能享受积分发放和邀请奖励功能。
|
|
||||||
|
|
||||||
## 🔄 新的流程设计
|
---
|
||||||
|
|
||||||
|
## 一、整体流程
|
||||||
|
|
||||||
### **改造后流程**:
|
|
||||||
```
|
```
|
||||||
1. 前端接收Google OAuth回调
|
用户 → Google 授权 → 回到前端回调页
|
||||||
2. 前端 → Java验证接口(只验证,不创建用户)
|
前端回调页读取 code/state → 调用 Python /api/oauth/google
|
||||||
3. 前端 → Python注册接口(创建用户 + 积分发放)
|
Python 返回 token/user 给前端 → 前端完成登录态落地
|
||||||
4. 返回完整的用户信息和token
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠️ 前端修改步骤
|
## 二、Google 控制台配置
|
||||||
|
|
||||||
### 📍 修改文件
|
在 Google Cloud Console → API 与服务 → 凭据 → 选择"Web 应用的客户端 ID":
|
||||||
**文件**: `video-flow/app/api/auth/google/callback/route.ts`
|
|
||||||
|
|
||||||
### 🔧 核心修改
|
### Authorized JavaScript origins(已授权的 JavaScript 来源)
|
||||||
|
- `https://www.movieflow.net`
|
||||||
|
- `https://www.movieflow.ai`
|
||||||
|
|
||||||
#### **第一步:调用Java验证接口**
|
### Authorized redirect URIs(已授权的重定向 URI)
|
||||||
```typescript
|
- `https://www.movieflow.net/api/auth/google/callback`
|
||||||
// 调用Java callback进行Google Token验证(不创建用户)
|
- `https://www.movieflow.ai/api/auth/google/callback`
|
||||||
const javaBaseUrl = process.env.NEXT_PUBLIC_JAVA_URL || 'https://auth.test.movieflow.ai';
|
|
||||||
|
|
||||||
const verifyResponse = await fetch(`${javaBaseUrl}/api/auth/google/callback`, {
|
本地调试(可选):
|
||||||
method: 'POST',
|
- JavaScript origins: `http://localhost:3000`
|
||||||
headers: {
|
- Redirect URIs: `http://localhost:3000/api/auth/google/callback`
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Accept': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
code: code, // Google authorization code
|
|
||||||
state: state, // state参数
|
|
||||||
inviteCode: inviteCode, // 邀请码
|
|
||||||
skipUserCreation: true // 🔑 关键:只验证不创建用户
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const verifyResult = await verifyResponse.json();
|
---
|
||||||
|
|
||||||
|
## 三、前端调用
|
||||||
|
|
||||||
|
### 第一步:Google 授权回调
|
||||||
|
在前端回调页(`/api/auth/google/callback`)读取 Google 返回的 `code` 与 `state`。
|
||||||
|
|
||||||
|
### 第二步:调用 Python 接口
|
||||||
|
- **路径**:`POST ${NEXT_PUBLIC_SMARTVIDEO_URL}/api/oauth/google`
|
||||||
|
- **请求体**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "string",
|
||||||
|
"state": "string",
|
||||||
|
"invite_code": "string | null"
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### **第二步:调用Python注册接口**
|
- **响应**:
|
||||||
```typescript
|
```json
|
||||||
// 调用Python注册接口进行用户创建和积分发放
|
{
|
||||||
const smartvideoBaseUrl = process.env.NEXT_PUBLIC_SMARTVIDEO_URL || 'https://smartvideo.test.movieflow.ai';
|
"success": true,
|
||||||
|
"data": {
|
||||||
const registerResponse = await fetch(`${smartvideoBaseUrl}/api/user_fission/register_with_invite`, {
|
"token": "string",
|
||||||
method: 'POST',
|
"user": {
|
||||||
headers: {
|
"userId": "string",
|
||||||
'Content-Type': 'application/json',
|
"userName": "string",
|
||||||
'Accept': 'application/json',
|
"name": "string",
|
||||||
},
|
"email": "string",
|
||||||
body: JSON.stringify({
|
"authType": "GOOGLE",
|
||||||
email: verifyResult.data.email,
|
"avatar": "string",
|
||||||
name: verifyResult.data.name,
|
"isNewUser": true
|
||||||
auth_type: 'GOOGLE',
|
|
||||||
google_user_info: verifyResult.data,
|
|
||||||
invite_code: inviteCode || stateData.inviteCode || undefined
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const registerResult = await registerResponse.json();
|
|
||||||
```
|
|
||||||
|
|
||||||
#### **第三步:返回统一格式结果**
|
|
||||||
```typescript
|
|
||||||
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'
|
"message": "Google OAuth successful"
|
||||||
}
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 后端接口文档
|
|
||||||
|
|
||||||
### 🔵 Java验证接口
|
|
||||||
|
|
||||||
#### **接口地址**
|
|
||||||
```
|
|
||||||
POST /api/auth/google/callback
|
|
||||||
```
|
|
||||||
|
|
||||||
#### **请求参数**
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
code: string, // Google authorization code
|
|
||||||
state: string, // state参数(可包含邀请码信息)
|
|
||||||
inviteCode?: string, // 邀请码(可选)
|
|
||||||
skipUserCreation: boolean // true=只验证不创建用户
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### **成功响应**
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
success: true,
|
|
||||||
message: "Google Token验证成功",
|
|
||||||
data: {
|
|
||||||
email: string, // 用户邮箱
|
|
||||||
name: string, // 用户姓名
|
|
||||||
picture: string, // 头像URL
|
|
||||||
googleId: string, // Google用户ID
|
|
||||||
verified: boolean, // 是否已验证
|
|
||||||
inviteCode: string // 邀请码(如果有)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### **错误响应**
|
### 前端代码示例
|
||||||
```typescript
|
```typescript
|
||||||
{
|
const baseUrl = process.env.NEXT_PUBLIC_SMARTVIDEO_URL;
|
||||||
success: false,
|
const res = await fetch(`${baseUrl}/api/oauth/google`, {
|
||||||
error: "TOKEN_EXCHANGE_FAILED" | "INVALID_ID_TOKEN",
|
method: 'POST',
|
||||||
message: string
|
headers: {
|
||||||
}
|
'Content-Type': 'application/json',
|
||||||
```
|
'Accept': 'application/json'
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 🔵 Python注册接口
|
|
||||||
|
|
||||||
#### **接口地址**
|
|
||||||
```
|
|
||||||
POST /api/user_fission/register_with_invite
|
|
||||||
```
|
|
||||||
|
|
||||||
#### **请求参数**
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
email: string, // 用户邮箱
|
|
||||||
name?: string, // 用户姓名(可选)
|
|
||||||
auth_type: "GOOGLE", // 认证类型(固定为GOOGLE)
|
|
||||||
google_user_info: { // Google用户信息(来自Java验证接口)
|
|
||||||
email: string,
|
|
||||||
name: string,
|
|
||||||
picture: string,
|
|
||||||
googleId: string,
|
|
||||||
verified: boolean,
|
|
||||||
inviteCode?: string
|
|
||||||
},
|
},
|
||||||
invite_code?: string // 邀请码(可选)
|
body: JSON.stringify({ code, state, invite_code })
|
||||||
}
|
});
|
||||||
```
|
|
||||||
|
|
||||||
#### **成功响应**
|
const result = await res.json();
|
||||||
```typescript
|
if (result.success) {
|
||||||
{
|
const { token, user } = result.data;
|
||||||
successful: true, // 注意:是 successful 不是 success
|
// 持久化 token & user
|
||||||
message: "Google OAuth注册成功",
|
} else {
|
||||||
data: {
|
// 统一错误提示 result.message
|
||||||
user_id: string, // 用户ID(UUID格式)
|
|
||||||
email: string, // 用户邮箱
|
|
||||||
name: string, // 用户姓名
|
|
||||||
auth_type: "GOOGLE", // 认证类型
|
|
||||||
invite_code?: string, // 邀请码
|
|
||||||
token?: string // 认证token(如果有)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### **错误响应**
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
successful: false,
|
|
||||||
message: string, // 错误信息
|
|
||||||
detail?: string // 详细错误信息
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔧 环境变量配置
|
## 四、环境变量
|
||||||
|
|
||||||
确保以下环境变量已配置:
|
- `NEXT_PUBLIC_SMARTVIDEO_URL`:后端 Python 服务地址
|
||||||
|
|
||||||
```bash
|
|
||||||
# Java认证服务地址
|
|
||||||
NEXT_PUBLIC_JAVA_URL=https://auth.test.movieflow.ai
|
|
||||||
|
|
||||||
# Python积分服务地址
|
|
||||||
NEXT_PUBLIC_SMARTVIDEO_URL=https://smartvideo.test.movieflow.ai
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚠️ 重要注意事项
|
## 五、错误处理
|
||||||
|
|
||||||
### 🔍 **关键变更**
|
常见错误码:
|
||||||
1. **接口变更**: `/api/auth/google/login` → `/api/auth/google/callback`
|
- `GOOGLE_TOKEN_EXCHANGE_FAILED`:授权码交换失败
|
||||||
2. **参数变更**:
|
- `INVALID_ID_TOKEN`:ID Token 无效
|
||||||
- 移除: `idToken`, `action`
|
- `UPSTREAM_AUTH_ERROR`:用户服务异常
|
||||||
- 新增: `code`, `state`, `skipUserCreation: true`
|
|
||||||
3. **响应字段**: Python返回 `successful`,Java返回 `success`
|
|
||||||
4. **用户ID字段**: Python返回 `user_id`,前端映射为 `userId`
|
|
||||||
|
|
||||||
### 🚨 **错误处理**
|
前端统一处理:基于 `success=false` 与 `message` 提示用户。
|
||||||
- Java验证失败 → 停止流程,返回错误
|
|
||||||
- Python注册失败 → 返回详细错误信息
|
|
||||||
- 网络异常 → 提供用户友好提示
|
|
||||||
|
|
||||||
### 🧪 **测试检查点**
|
|
||||||
- [ ] Google OAuth验证是否成功
|
|
||||||
- [ ] 用户是否正确创建并获得积分
|
|
||||||
- [ ] 邀请码功能是否正常
|
|
||||||
- [ ] 错误处理是否完善
|
|
||||||
- [ ] 前端页面跳转是否正常
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎯 预期效果
|
## 六、安全建议
|
||||||
|
|
||||||
改造完成后,Google OAuth用户将获得:
|
- 启用 PKCE
|
||||||
|
- 在 `state` 中绑定 CSRF 防护信息
|
||||||
✅ **注册奖励积分**
|
- 确保回调地址与发起授权时的 `redirect_uri` 完全一致
|
||||||
✅ **邀请码奖励功能**
|
|
||||||
✅ **邀请人奖励积分**
|
|
||||||
✅ **统一的用户体验**
|
|
||||||
✅ **完整的积分记录**
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*文档版本: v2.0*
|
文档版本:v4.0
|
||||||
*更新时间: 2025-01-22*
|
更新时间:2025-09-23
|
||||||
*适用范围: video-flow前端项目*
|
适用范围:video-flow 前端项目
|
||||||
Loading…
x
Reference in New Issue
Block a user