/** * 小程序登录API * 使用code换取openId和session_key * * 小程序配置: * - AppID: wxb8bbb2b10dec74aa * - AppSecret: 85d3fa31584d06acdb1de4a597d25b7b */ import { NextResponse } from 'next/server' const MINIPROGRAM_CONFIG = { appId: 'wxb8bbb2b10dec74aa', appSecret: '3c1fb1f63e6e052222bbcead9d07fe0c', // 2026-01-25 修正 } /** * POST - 小程序登录,获取openId */ export async function POST(request: Request) { try { const body = await request.json() const { code } = body if (!code) { return NextResponse.json({ success: false, error: '缺少登录code' }, { status: 400 }) } console.log('[MiniLogin] 收到登录请求, code:', code.slice(0, 10) + '...') // 调用微信接口获取openId const wxUrl = `https://api.weixin.qq.com/sns/jscode2session?appid=${MINIPROGRAM_CONFIG.appId}&secret=${MINIPROGRAM_CONFIG.appSecret}&js_code=${code}&grant_type=authorization_code` const response = await fetch(wxUrl) const data = await response.json() console.log('[MiniLogin] 微信接口返回:', { errcode: data.errcode, errmsg: data.errmsg, hasOpenId: !!data.openid, }) if (data.errcode) { return NextResponse.json({ success: false, error: `微信登录失败: ${data.errmsg || data.errcode}` }, { status: 400 }) } const openId = data.openid const sessionKey = data.session_key const unionId = data.unionid if (!openId) { return NextResponse.json({ success: false, error: '获取openId失败' }, { status: 500 }) } // 创建或更新用户 - 连接数据库 let user: any = null let isNewUser = false try { const { query } = await import('@/lib/db') // 查询用户是否存在 const existingUsers = await query('SELECT * FROM users WHERE open_id = ?', [openId]) as any[] if (existingUsers.length > 0) { // 用户已存在,更新session_key user = existingUsers[0] await query('UPDATE users SET session_key = ?, updated_at = NOW() WHERE open_id = ?', [sessionKey, openId]) console.log('[MiniLogin] 用户已存在:', user.id) } else { // 创建新用户 - 使用openId作为用户ID(与微信官方标识保持一致) isNewUser = true const userId = openId // 直接使用openId作为用户ID const referralCode = 'SOUL' + openId.slice(-6).toUpperCase() const nickname = '微信用户' + openId.slice(-4) await query(` INSERT INTO users ( id, open_id, session_key, nickname, avatar, referral_code, has_full_book, purchased_sections, earnings, pending_earnings, referral_count ) VALUES (?, ?, ?, ?, ?, ?, FALSE, '[]', 0, 0, 0) `, [ userId, openId, sessionKey, nickname, '', // 头像留空,等用户授权 referralCode ]) const newUsers = await query('SELECT * FROM users WHERE id = ?', [userId]) as any[] user = newUsers[0] console.log('[MiniLogin] 新用户创建成功, ID=openId:', userId.slice(0, 10) + '...') } } catch (dbError) { console.error('[MiniLogin] 数据库操作失败:', dbError) // 数据库失败时使用openId作为临时用户ID user = { id: openId, // 使用openId作为用户ID open_id: openId, nickname: '微信用户', avatar: '', referral_code: 'SOUL' + openId.slice(-6).toUpperCase(), purchased_sections: '[]', has_full_book: false, earnings: 0, pending_earnings: 0, referral_count: 0, created_at: new Date().toISOString() } } // 统一用户数据格式 const responseUser = { id: user.id, openId: user.open_id || openId, nickname: user.nickname, avatar: user.avatar, phone: user.phone, wechatId: user.wechat_id, referralCode: user.referral_code, hasFullBook: user.has_full_book || false, purchasedSections: typeof user.purchased_sections === 'string' ? JSON.parse(user.purchased_sections || '[]') : (user.purchased_sections || []), earnings: parseFloat(user.earnings) || 0, pendingEarnings: parseFloat(user.pending_earnings) || 0, referralCount: user.referral_count || 0, createdAt: user.created_at } // 生成token const token = `tk_${openId.slice(-8)}_${Date.now()}` console.log('[MiniLogin] 登录成功, userId:', responseUser.id, isNewUser ? '(新用户)' : '(老用户)') return NextResponse.json({ success: true, data: { openId, user: responseUser, token, }, isNewUser }) } catch (error) { console.error('[MiniLogin] 登录失败:', error) return NextResponse.json({ success: false, error: '登录失败' }, { status: 500 }) } }