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

如何根据客户端传入的Stripe Price ID生成对应结账会话?

解决方案

1. 修复Price ID导入错误

报错enterprisePriceId is not defined是因为你的导入语句遗漏了该ID,先修正导入:

const { webUrl, stripeSecret, stripeWebhookSecret, basicPriceId, scaledPriceId, enterprisePriceId } = require('../production');

2. 从请求体获取用户选中的价格ID

客户端需要在请求中传递用户选择的价格ID(比如命名为selectedPriceId),控制器里先接收这个参数:

const { currency, selectedPriceId } = req.body;

3. 验证价格ID合法性

为避免恶意传入无效ID,添加白名单验证:

const validPriceIds = [basicPriceId, scaledPriceId, enterprisePriceId];
if (!validPriceIds.includes(selectedPriceId)) {
  return res.status(400).send({ error: { message: "无效的价格ID" } });
}

4. 生成对应结账会话

将验证后的selectedPriceId传入Stripe会话的line_items中:

const session = await stripe.checkout.sessions.create({
  mode: "subscription",
  customer: req.user.stripe_customer[currency],
  line_items: [
    {
      price: selectedPriceId,
      quantity: 1,
    },
  ],
  success_url: `${webUrl}/users/${req.user._id}/activations/?session_id={CHECKOUT_SESSION_ID}`,
  cancel_url: `${webUrl}/canceled.html`,
});

完整修改后的控制器代码

module.exports.createCheckoutSession = async (req, res) => {
    const { currency, selectedPriceId } = req.body;

    if (req.isAuthenticated()) {
        if (!(req.user.stripe_customer && req.user.stripe_customer[currency])) {
            const new_stripe_customer = await stripe.customers.create({
                email: req.user.email,
                name: req.user.username,
                metadata: {
                    user_id: req.user._id.toString(),
                },
            });

            let update = {};
            update[`stripe_customer.${currency}`] = new_stripe_customer.id;
            update['customer_name'] = new_stripe_customer.name;
            await User.findByIdAndUpdate(req.user._id, update);

            if (!req.user.stripe_customer) {
                req.user.stripe_customer = {};
                req.user.stripe_customer[currency] = new_stripe_customer.id;
            } else {
                req.user.stripe_customer[currency] = new_stripe_customer.id;
            }
            const user = await User.findById(req.user.id);
            user.stripeId = new_stripe_customer.id;
            await user.save();
        }
        try {
            // 验证传入的价格ID是否合法
            const validPriceIds = [basicPriceId, scaledPriceId, enterprisePriceId];
            if (!validPriceIds.includes(selectedPriceId)) {
                return res.status(400).send({ error: { message: "无效的价格ID" } });
            }

            const session = await stripe.checkout.sessions.create({
                mode: "subscription",
                customer: req.user.stripe_customer[currency],
                line_items: [
                    {
                        price: selectedPriceId,
                        quantity: 1,
                    },
                ],
                success_url: `${webUrl}/users/${req.user._id}/activations/?session_id={CHECKOUT_SESSION_ID}`,
                cancel_url: `${webUrl}/canceled.html`,
            });
            return res.redirect(303, session.url);

        } catch (e) {
            res.status(400);
            return res.send({
                error: {
                    message: e.message,
                }
            });
        }
    }
    req.flash('error', "您必须先登录才能修改账单");
    res.render('/login');
}

客户端配合修改

客户端发起请求时,需将用户选中的价格ID作为selectedPriceId传入请求体,示例:

fetch('/create-checkout-session', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    currency: 'usd',
    selectedPriceId: '用户选中的价格ID'
  }),
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:35:27