Prmbr/src/app/api/credits/verify-payment/route.ts
2025-08-30 12:48:06 +08:00

126 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextResponse } from 'next/server'
import { auth } from '@/lib/auth'
import { stripe } from '@/lib/stripe'
import { addCredit } from '@/lib/services/credit'
import { prisma } from '@/lib/prisma'
import { headers } from 'next/headers'
export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url)
const sessionId = searchParams.get('session_id')
if (!sessionId) {
return NextResponse.json(
{ error: 'Session ID is required' },
{ status: 400 }
)
}
// 获取Better Auth会话
const session = await auth.api.getSession({
headers: await headers()
})
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const user = session.user
try {
// 从 Stripe 获取支付会话信息
const stripeSession = await stripe.checkout.sessions.retrieve(sessionId)
if (stripeSession.payment_status !== 'paid') {
return NextResponse.json(
{ error: 'Payment not completed' },
{ status: 400 }
)
}
// 验证支付会话属于当前用户
if (stripeSession.metadata?.userId !== user.id) {
return NextResponse.json(
{ error: 'Payment session does not belong to current user' },
{ status: 403 }
)
}
// 获取或创建用户数据
let userData = await prisma.user.findUnique({
where: { id: user.id }
})
// 如果用户不存在,创建用户
if (!userData) {
userData = await prisma.user.create({
data: {
id: user.id,
email: user.email,
name: user.name,
emailVerified: user.emailVerified ?? false,
subscriptionPlanId: 'free'
}
})
}
// 检查是否已经处理过这个支付会话
const existingCredit = await prisma.credit.findFirst({
where: {
referenceId: sessionId,
referenceType: 'stripe_session'
}
})
if (existingCredit) {
return NextResponse.json({
success: true,
message: 'Payment already processed',
amount: existingCredit.amount,
sessionId
})
}
// 从支付会话获取金额Stripe金额以分为单位
const amount = (stripeSession.amount_total || 0) / 100
if (amount <= 0) {
return NextResponse.json(
{ error: 'Invalid payment amount' },
{ status: 400 }
)
}
// 添加信用记录
await addCredit(
user.id,
amount,
'user_purchase',
`Stripe payment - Session: ${sessionId}`
// 充值的信用不会过期,不设置过期时间
)
return NextResponse.json({
success: true,
message: 'Payment verified and credits added',
amount,
sessionId
})
} catch (stripeError) {
console.error('Stripe error:', stripeError)
return NextResponse.json(
{ error: 'Failed to verify payment with Stripe' },
{ status: 500 }
)
}
} catch (error) {
console.error('Payment verification failed:', error)
return NextResponse.json(
{ error: 'Failed to verify payment' },
{ status: 500 }
)
}
}