route.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import { NextRequest, NextResponse } from 'next/server';
  2. import { auth } from '@/lib/auth';
  3. import { stripe, STRIPE_PLANS } from '@/lib/stripe';
  4. import { db } from '@/lib/db';
  5. import { users } from '@/lib/schema';
  6. import { eq } from 'drizzle-orm';
  7. export async function POST(request: NextRequest) {
  8. try {
  9. console.log('Creating checkout session...');
  10. // 验证 Stripe 对象
  11. if (!stripe) {
  12. console.error('Stripe object is undefined');
  13. return NextResponse.json(
  14. { error: 'Stripe 初始化失败' },
  15. { status: 500 }
  16. );
  17. }
  18. if (!stripe.checkout) {
  19. console.error('Stripe checkout is undefined');
  20. return NextResponse.json(
  21. { error: 'Stripe checkout 服务不可用' },
  22. { status: 500 }
  23. );
  24. }
  25. // 检查环境变量
  26. if (!process.env.STRIPE_SECRET_KEY) {
  27. console.error('STRIPE_SECRET_KEY is not configured');
  28. return NextResponse.json(
  29. { error: 'Stripe 配置错误' },
  30. { status: 500 }
  31. );
  32. }
  33. if (!process.env.NEXTAUTH_URL) {
  34. console.error('NEXTAUTH_URL is not configured');
  35. return NextResponse.json(
  36. { error: '应用配置错误' },
  37. { status: 500 }
  38. );
  39. }
  40. console.log('Stripe object validated successfully');
  41. // 检查用户认证
  42. const session = await auth();
  43. if (!session?.user?.email) {
  44. return NextResponse.json(
  45. { error: '请先登录' },
  46. { status: 401 }
  47. );
  48. }
  49. console.log('User authenticated:', session.user.email);
  50. // 获取用户信息
  51. const user = await db.query.users.findFirst({
  52. where: eq(users.email, session.user.email),
  53. });
  54. if (!user) {
  55. return NextResponse.json(
  56. { error: '用户不存在' },
  57. { status: 404 }
  58. );
  59. }
  60. console.log('User found:', user.id);
  61. // 检查用户是否已有活跃订阅
  62. const hasActiveSubscription = user.subscriptionStatus === 'active' &&
  63. user.subscriptionEndDate &&
  64. new Date(user.subscriptionEndDate) > new Date();
  65. if (hasActiveSubscription) {
  66. return NextResponse.json(
  67. { error: 'alreadySubscribed' },
  68. { status: 400 }
  69. );
  70. }
  71. const body = await request.json();
  72. const { locale = 'zh' } = body;
  73. // 只处理 Pro 订阅
  74. const plan = STRIPE_PLANS.pro;
  75. console.log('Using plan:', plan);
  76. // 检查价格 ID
  77. if (!plan.priceId || plan.priceId === 'price_test_demo') {
  78. console.warn('Using test configuration - creating one-time payment session for development');
  79. // 在开发环境中,创建一次性支付会话而不是订阅
  80. const checkoutSession = await stripe.checkout.sessions.create({
  81. payment_method_types: ['card'],
  82. line_items: [
  83. {
  84. price_data: {
  85. currency: 'usd',
  86. product_data: {
  87. name: plan.name,
  88. description: plan.description,
  89. },
  90. unit_amount: plan.price,
  91. },
  92. quantity: 1,
  93. },
  94. ],
  95. mode: 'payment', // 一次性支付模式
  96. success_url: `${process.env.NEXTAUTH_URL}/${locale}/payment/success?session_id={CHECKOUT_SESSION_ID}`,
  97. cancel_url: `${process.env.NEXTAUTH_URL}/${locale}?canceled=true`,
  98. customer_email: user.email,
  99. metadata: {
  100. userId: user.id,
  101. planId: 'pro',
  102. credits: plan.credits.toString(),
  103. planType: 'test_payment',
  104. },
  105. locale: locale === 'zh' ? 'zh' : 'en',
  106. });
  107. console.log('Test checkout session created:', checkoutSession.id);
  108. return NextResponse.json({
  109. sessionId: checkoutSession.id,
  110. url: checkoutSession.url
  111. });
  112. }
  113. // 创建 Stripe Checkout 会话
  114. console.log('Creating Stripe checkout session...');
  115. const checkoutSession = await stripe.checkout.sessions.create({
  116. payment_method_types: ['card'],
  117. line_items: [
  118. {
  119. price: plan.priceId,
  120. quantity: 1,
  121. },
  122. ],
  123. mode: 'subscription', // 订阅模式
  124. success_url: `${process.env.NEXTAUTH_URL}/${locale}/payment/success?session_id={CHECKOUT_SESSION_ID}`,
  125. cancel_url: `${process.env.NEXTAUTH_URL}/${locale}?canceled=true`,
  126. customer_email: user.email,
  127. metadata: {
  128. userId: user.id,
  129. planId: 'pro',
  130. credits: plan.credits.toString(),
  131. planType: 'subscription',
  132. },
  133. locale: locale === 'zh' ? 'zh' : 'en',
  134. });
  135. console.log('Checkout session created:', checkoutSession.id);
  136. return NextResponse.json({
  137. sessionId: checkoutSession.id,
  138. url: checkoutSession.url
  139. });
  140. } catch (error: any) {
  141. console.error('Error creating checkout session:', error);
  142. // 详细的错误处理
  143. if (error.code === 'resource_missing') {
  144. return NextResponse.json(
  145. { error: 'Stripe 价格配置不存在,请联系管理员' },
  146. { status: 500 }
  147. );
  148. }
  149. if (error.code === 'api_key_invalid') {
  150. return NextResponse.json(
  151. { error: 'Stripe API 密钥无效' },
  152. { status: 500 }
  153. );
  154. }
  155. return NextResponse.json(
  156. { error: error.message || '创建支付会话失败' },
  157. { status: 500 }
  158. );
  159. }
  160. }