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

157 lines
5.2 KiB
TypeScript
Raw Normal View History

// app/api/wechat/login/route.ts
// 微信小程序登录接口
import { NextRequest, NextResponse } from 'next/server'
import { query } from '@/lib/db'
// 使用真实的小程序AppID和Secret
const APPID = process.env.WECHAT_APPID || 'wxb8bbb2b10dec74aa'
const SECRET = process.env.WECHAT_APPSECRET || '3c1fb1f63e6e052222bbcead9d07fe0c'
// POST: 微信小程序登录
export async function POST(req: NextRequest) {
try {
const body = await req.json()
const { code, referralCode } = body
if (!code) {
return NextResponse.json(
{ error: '缺少code参数' },
{ status: 400 }
)
}
// 调用微信API获取session_key和openid
const wxUrl = `https://api.weixin.qq.com/sns/jscode2session?appid=${APPID}&secret=${SECRET}&js_code=${code}&grant_type=authorization_code`
const wxResponse = await fetch(wxUrl)
const wxData = await wxResponse.json()
if (wxData.errcode) {
console.error('微信登录失败:', wxData)
return NextResponse.json(
{ error: wxData.errmsg || '微信登录失败' },
{ status: 400 }
)
}
const { openid, session_key, unionid } = wxData
// 生成token
const token = Buffer.from(`${openid}:${Date.now()}`).toString('base64')
// 查询或创建用户
let user: any = null
let isNewUser = false
try {
// 先查询用户是否存在
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 = ?', [session_key, openid])
console.log('[WechatLogin] 用户已存在:', user.id)
} else {
// 创建新用户
isNewUser = true
const userId = 'user_' + Date.now().toString(36) + Math.random().toString(36).substr(2, 6)
const userReferralCode = generateInviteCode(openid)
const nickname = '用户' + openid.substr(-4)
// 处理推荐绑定
let referredBy = null
if (referralCode) {
const referrers = await query('SELECT id FROM users WHERE referral_code = ?', [referralCode]) as any[]
if (referrers.length > 0) {
referredBy = referrers[0].id
// 更新推荐人的推广数量
await query('UPDATE users SET referral_count = referral_count + 1 WHERE id = ?', [referredBy])
}
}
await query(`
INSERT INTO users (
id, open_id, session_key, nickname, avatar, referral_code, referred_by,
has_full_book, purchased_sections, earnings, pending_earnings, referral_count
) VALUES (?, ?, ?, ?, ?, ?, ?, FALSE, '[]', 0, 0, 0)
`, [
userId, openid, session_key, nickname,
'https://picsum.photos/200/200?random=' + openid.substr(-2),
userReferralCode, referredBy
])
// 获取新创建的用户
const newUsers = await query('SELECT * FROM users WHERE id = ?', [userId]) as any[]
user = newUsers[0]
console.log('[WechatLogin] 新用户创建成功:', userId)
}
} catch (dbError) {
console.error('[WechatLogin] 数据库操作失败,使用临时用户:', dbError)
// 数据库失败时使用临时用户信息
user = {
id: openid,
open_id: openid,
nickname: '用户' + openid.substr(-4),
avatar: 'https://picsum.photos/200/200?random=' + openid.substr(-2),
referral_code: generateInviteCode(openid),
has_full_book: false,
purchased_sections: [],
earnings: 0,
pending_earnings: 0,
referral_count: 0,
created_at: new Date().toISOString()
}
}
// 统一用户数据格式
const responseUser = {
id: user.id,
openId: user.open_id || openid,
unionid,
nickname: user.nickname,
avatar: user.avatar,
phone: user.phone,
wechatId: user.wechat_id,
referralCode: user.referral_code,
referredBy: user.referred_by,
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
}
return NextResponse.json({
success: true,
token,
user: responseUser,
isNewUser,
message: isNewUser ? '注册成功' : '登录成功'
})
} catch (error) {
console.error('登录接口错误:', error)
return NextResponse.json(
{ error: '服务器错误' },
{ status: 500 }
)
}
}
// 生成邀请码
function generateInviteCode(openid: string): string {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const hash = openid.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)
let code = ''
for (let i = 0; i < 6; i++) {
code += chars.charAt((hash + i) % chars.length)
}
return code
}