Files
soul/app/api/miniprogram/login/route.ts

161 lines
4.9 KiB
TypeScript
Raw Normal View History

/**
* 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 })
}
}