You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 13集成Stripe API:如何在用户付款后升级订阅计划

解决Stripe订阅仅在付款完成后升级的问题

直接调用stripe.subscriptions.update会立即修改订阅记录,完全跳过付款验证环节,这就是你遇到问题的核心原因。正确的做法是通过Stripe Checkout引导用户完成付款流程,只有付款成功后再确认订阅升级,具体步骤如下:

1. 创建订阅升级的Checkout会话

在你的Next.js API中,不要直接更新订阅,而是生成一个Checkout会话,让用户通过Stripe的付款页面完成支付。Stripe会自动处理订阅的升级逻辑,只有付款成功后才会变更订阅。

示例代码:

// pages/api/subscription-upgrade.js
import stripe from '@/utils/stripe';

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: '仅支持POST请求' });
  }

  const { currentSubscriptionId, newPlanId, customerId } = req.body;

  try {
    const checkoutSession = await stripe.checkout.sessions.create({
      mode: 'subscription',
      // 指定要更新的现有订阅
      subscription_update: {
        subscription: currentSubscriptionId,
        // 可选:控制 prorate 计费方式,比如'none'表示不按剩余周期收费
        proration_behavior: 'create_prorations'
      },
      line_items: [
        {
          price: newPlanId,
          quantity: 1
        }
      ],
      // 付款成功后的跳转地址
      success_url: `${process.env.NEXT_PUBLIC_APP_URL}/dashboard?upgrade=success`,
      // 取消付款后的跳转地址
      cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/dashboard?upgrade=cancel`,
      // 关联用户的Stripe客户ID
      customer: customerId
    });

    res.status(200).json({ checkoutUrl: checkoutSession.url });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
}

2. 通过Webhook确认付款完成并更新本地数据

付款完成后,Stripe会发送checkout.session.completed的Webhook事件,你需要在后端监听这个事件,确认付款成功后,再更新自己数据库中的用户订阅信息(比如priceId、订阅状态等)。

示例Webhook处理代码:

// pages/api/webhooks/stripe.js
import stripe from '@/utils/stripe';
import { buffer } from 'micro';
import { updateUserSubscription } from '@/utils/db'; // 自定义的数据库更新函数

export const config = {
  api: {
    bodyParser: false
  }
};

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).end();
  }

  const buf = await buffer(req);
  const sig = req.headers['stripe-signature'];
  const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;

  let event;
  try {
    event = stripe.webhooks.constructEvent(buf, sig, webhookSecret);
  } catch (err) {
    return res.status(400).send(`Webhook验证失败: ${err.message}`);
  }

  // 处理付款完成事件
  if (event.type === 'checkout.session.completed') {
    const session = event.data.object;
    // 获取更新后的订阅详情
    const updatedSubscription = await stripe.subscriptions.retrieve(session.subscription);
    const newPriceId = updatedSubscription.items.data[0].price.id;
    
    // 更新本地数据库中的用户订阅信息
    await updateUserSubscription(session.customer, {
      stripeSubscriptionId: updatedSubscription.id,
      currentPriceId: newPriceId,
      subscriptionStatus: updatedSubscription.status
    });
  }

  res.status(200).json({ received: true });
}

关键注意事项

  • 绝对不能依赖前端的success_url回调来更新本地数据,因为前端可以被篡改,必须以Stripe发送的Webhook事件为准。
  • 如果是同价格的计划切换,Stripe会直接更新订阅而无需付款,但如果是升级到更高价格的计划,会强制用户完成付款流程。
  • 确保在Stripe后台配置好Webhook地址,并启用checkout.session.completed事件。

内容的提问来源于stack exchange,提问作者Emmanuel Dufitumukiza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 09:57:48