如何根据客户端传入的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
相关产品推荐
相关产品推荐

