分享

如果你登录授权返回应用,发现网址是 http://localhost:3000/?error=auth_failed,把这个发给你的 cc 试试

================================================================================ SecondMe API 字段命名错误 - 登录失败问题修复 ================================================================================ 问题描述 ================================================================================ 症状:用户完成 SecondMe OAuth 授权后,被重定向回应用时看到: http://localhost:3000/?error=auth_failed 数据库中没有创建用户记录,说明 OAuth callback 处理失败。 ================================================================================ 问题诊断过程 ================================================================================ 步骤 1: 添加调试日志 在 src/app/api/auth/callback/route.ts 中添加详细日志: console.log('Token response:', JSON.stringify(tokenResult, null, 2)); console.log('User info response:', JSON.stringify(userData, null, 2)); console.log('User info:', { id: userInfo.id, email: userInfo.email }); 步骤 2: 查看服务器日志输出 日志显示: -------------- Token 交换成功 ✅ accessToken: "lba_at_xxx" refreshToken: "lba_rt_xxx" expiresIn: 604799 用户信息获取成功 ✅ { "code": 0, "data": { "userId": "********", // 注意:字段名是 userId,不是 id! "name": "***", "email": "***********", "avatar": "https://...", "selfIntroduction": "...", "profileCompleteness": 34, "route": "***********" } } 但是代码中使用 userInfo.id,结果是 undefined ❌ User info: { id: undefined, email: '***********' } 步骤 3: Prisma 错误信息 PrismaClientValidationError: Invalid prisma.user.upsert() invocation Argument `where` of type UserWhereUniqueInput needs at least one of `id` or `secondmeUserId` arguments. where: { secondmeUserId: undefined, // 传入了 undefined 导致错误 } ================================================================================ 根本原因 ================================================================================ 错误代码: where: { secondmeUserId: userInfo.id }, create: { secondmeUserId: userInfo.id } 问题: SecondMe API 返回的用户 ID 字段名是 "userId"(驼峰命名) 而不是 "id" 代码中使用 userInfo.id 获取不到值,返回 undefined 导致 Prisma upsert 操作失败 ================================================================================ 解决方案 ================================================================================ 文件:src/app/api/auth/callback/route.ts 修改前(错误): -------------- const userInfo = userData.data; console.log('User info:', { id: userInfo.id, email: userInfo.email }); const user = await prisma.user.upsert({ where: { secondmeUserId: userInfo.id }, // ❌ 错误 update: { ... }, create: { secondmeUserId: userInfo.id, // ❌ 错误 ... }, }); 修改后(正确): -------------- const userInfo = userData.data; console.log('User info:', { userId: userInfo.userId, email: userInfo.email }); const user = await prisma.user.upsert({ where: { secondmeUserId: userInfo.userId }, // ✅ 正确 update: { ... }, create: { secondmeUserId: userInfo.userId, // ✅ 正确 ... }, }); ================================================================================ SecondMe 用户信息 API 响应格式 ================================================================================ 端点:GET /api/secondme/user/info 完整响应格式: { "code": 0, "data": { "userId": "********", // 用户唯一标识符 "name": "***", // 显示名称 "email": "***********", // 邮箱或手机号 "avatar": "https://...", // 头像 URL "selfIntroduction": "个人简介", // 自我介绍 "profileCompleteness": 34, // 资料完整度(0-100) "route": "***********" // 用户路由/用户名 } } 重要字段说明: - userId: 用户唯一标识符,用于数据库关联 - name: 用户显示名称 - email: 可能是邮箱或手机号格式 - route: 用户的唯一路由标识,类似用户名 ================================================================================ 关键经验教训 ================================================================================ 教训 1: 不要假设 API 字段名 错误做法: 假设所有用户信息 API 都有 "id" 字段 直接使用 userInfo.id 正确做法: 先查看官方文档确认字段名 或者打印完整响应查看实际结构 使用准确字段名 userInfo.userId 教训 2: API 响应可能使用不同命名风格 观察: SecondMe Token 响应使用驼峰命名: accessToken, refreshToken, expiresIn SecondMe 用户信息也使用驼峰命名: userId, name, email, selfIntroduction 结论: 该 API 一致使用驼峰命名(camelCase) 不要混用下划线命名(snake_case) 教训 3: 添加详细日志帮助调试 推荐的日志点: 1. Token 交换后打印完整响应 2. 用户信息获取后打印完整响应 3. 关键字段值打印(如 userId, email) 示例: console.log('User info response:', JSON.stringify(userData, null, 2)); console.log('User info:', { userId: userInfo.userId, email: userInfo.email }); 教训 4: Prisma 错误信息很清晰 错误信息会明确指出: - 哪个字段值为 undefined - 期望哪些字段有值 示例: Argument `where` of type UserWhereUniqueInput needs at least one of `id` or `secondmeUserId` arguments. 这意味着 secondmeUserId 是 undefined,需要检查赋值。 ================================================================================ 其他 SecondMe API 字段参考 ================================================================================ 用户信息相关: - /api/secondme/user/info → data.userId, data.name, data.email, data.avatar 兴趣标签(Shades): - /api/secondme/user/shades → data.shades[] 数组 软记忆(Softmemory): - /api/secondme/user/softmemory → data.list[] 数组 聊天会话列表: - /api/secondme/chat/session/list → data.sessions[] 数组 ================================================================================ 修改文件清单 ================================================================================ 文件:src/app/api/auth/callback/route.ts 修改 1(第 84 行): 修改前:console.log('User info:', { id: userInfo.id, email: userInfo.email }); 修改后:console.log('User info:', { userId: userInfo.userId, email: userInfo.email }); 修改 2(第 88 行): 修改前:where: { secondmeUserId: userInfo.id }, 修改后:where: { secondmeUserId: userInfo.userId }, 修改 3(第 95 行): 修改前:secondmeUserId: userInfo.id, 修改后:secondmeUserId: userInfo.userId, ================================================================================ 验证成功的标准 ================================================================================ 步骤 1: 完成授权 在 SecondMe 页面授权应用 步骤 2: 自动回调 系统自动重定向回 http://localhost:3000/api/auth/callback?code=... 步骤 3: 后端处理 - Token 交换成功 - 获取用户信息成功 - 数据库创建用户记录 步骤 4: 设置会话 设置 user_id cookie 步骤 5: 重定向首页 重定向到 http://localhost:3000/ 步骤 6: 显示登录状态 页面显示: "欢迎回来!" "你已成功登录应用" "SecondMe 用户 ID: ********" 数据库验证: docker exec voteverse-db psql -U postgres -d voteverse -c "SELECT * FROM users;" 应该看到: id | secondme_user_id | created_at ------------------+------------------+------------ cmxxx... | ******** | 2025-02-10... ================================================================================ 快速检查清单 ================================================================================ 遇到类似问题时检查: □ API 响应中的实际字段名是什么? (打印完整响应查看) □ 代码中使用的字段名是否正确? (区分 userId vs id) □ 是否所有使用该字段的地方都修改了? (where、create、update 等) □ 是否添加了调试日志? (方便下次排查) □ 数据库表中是否真的创建了记录? (直接查询数据库验证) ================================================================================ 文档元信息 ================================================================================ 文档标题: SecondMe API 字段命名错误修复 问题字段: userInfo.id → userInfo.userId 影响范围: OAuth Callback 用户创建流程 修复日期: 2025-02-10 问题状态: ✅ 已解决 核心教训: 永远不要假设 API 字段名,查看文档或打印响应确认 SecondMe API 统一使用驼峰命名(camelCase) ================================================================================

评论

加载中...
登录 后可以发表评论