主要更新: - 后台菜单精简(9项→6项) - 新增搜索功能(敏感信息过滤) - 分销绑定和提现系统完善 - 数据库初始化API(自动修复表结构) - 用户管理:显示绑定关系详情 - 小程序:上下章导航优化、匹配页面重构 - 修复hydration和数据类型问题
161 lines
4.9 KiB
TypeScript
161 lines
4.9 KiB
TypeScript
/**
|
||
* 小程序登录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 })
|
||
}
|
||
}
|