React集成Stripe时Webhook返回空Metadata问题求助
解决Stripe Webhook中Metadata为空的问题
要让Webhook的payment_intent.succeeded事件中包含自定义Metadata,不能在前端的confirmPayment方法中添加Metadata——因为前端属于公开环境,Metadata的设置必须在后端创建Payment Intent时完成,这是Stripe的安全设计要求。
核心解决方案步骤
后端创建Payment Intent时添加Metadata
所有需要传递的产品、用户等信息,必须在后端调用Stripe SDK创建Payment Intent时,通过metadata字段传入。这是唯一能让Metadata出现在Webhook事件中的方式。前端从后端获取Client Secret
前端不再直接生成Payment Intent,而是调用后端接口获取client_secret,再传入stripe.confirmPayment中完成支付流程。
具体代码示例
1. 后端代码(以Node.js为例)
const stripe = require('stripe')('你的Stripe私密密钥'); // 后端接口:创建Payment Intent并返回client_secret app.post('/create-payment-intent', async (req, res) => { // 从前端请求中获取需要存入Metadata的信息 const { productId, productName, userId } = req.body; const paymentIntent = await stripe.paymentIntents.create({ amount: 1500, // 支付金额(单位:分,示例为15日元) currency: 'jpy', // 在这里设置需要传递的Metadata metadata: { product_id: productId, product_name: productName, user_id: userId, order_note: '用户定制备注' // 其他自定义信息 }, automatic_payment_methods: { enabled: true, }, }); res.json({ clientSecret: paymentIntent.client_secret }); });
2. 前端代码修改
更新handleSubmit逻辑,先调用后端接口获取client_secret,再执行支付确认:
const handleSubmit = async (e) => { e.preventDefault(); setIsLoading(true); try { // 第一步:调用后端接口获取client_secret,传递产品信息 const response = await fetch('/create-payment-intent', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ productId: 'prod_XXXXXX', productName: '日式咖啡套装', userId: 'user_123456' }), }); const { clientSecret } = await response.json(); // 第二步:执行支付确认 const result = await stripe.confirmPayment({ elements, clientSecret, // 传入从后端获取的client_secret confirmParams: { return_url: `${your url}/thanks`, }, }); // 支付结果处理 if (result.error) { setFinishedPayment(false); setMessage(result.error.message || '支付失败,请重试'); } else { console.log('支付成功,跳转至感谢页'); } } catch (err) { setMessage('网络错误,请稍后再试'); } setIsLoading(false); };
关键说明
- Metadata的键值对均为字符串类型,若需传递数字/布尔值,需先转为字符串。
- 后端的Stripe私密密钥绝对不能暴露在前端代码中,必须保存在服务器环境变量里。
- 设置完成后,当
payment_intent.succeeded事件触发时,Webhook返回的事件对象中data.object.metadata会包含你设置的所有信息,直接读取并存入数据库即可。
内容的提问来源于stack exchange,提问作者ほせまさ
相关产品推荐
相关产品推荐

