如何仅在Stripe支付成功后将表单数据发送至Webhook?
实现方案
核心逻辑是将表单数据与Stripe支付会话绑定,仅在支付成功触发Webhook时才获取并处理表单数据,具体步骤如下:
1. 调整表单提交流程:后端生成带表单数据的Stripe会话
不要直接使用预先生成的Stripe结账链接,改为表单提交到后端,由后端创建包含表单数据的Stripe Checkout会话,再返回会话URL供前端重定向。
后端示例(Node.js/Express)
const stripe = require('stripe')('你的Stripe秘钥'); const express = require('express'); const app = express(); app.use(express.urlencoded({ extended: true })); // 处理表单提交的端点 app.post('/submit-form', async (req, res) => { // 接收表单所有字段 const formData = { full_name: req.body.full_name, height: req.body.height, weight: req.body.weight, exercise_days: req.body.exercise_days, job_type: req.body.job_type, selected_product: req.body.selected_product }; // 根据所选产品获取对应的Stripe价格ID(提前在Stripe后台创建好产品和价格) const priceId = getPriceIdByProduct(formData.selected_product); // 创建Stripe Checkout会话,将表单数据存入metadata const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], line_items: [ { price: priceId, quantity: 1, }, ], mode: 'payment', success_url: 'https://your-domain.com/success', // 支付成功后跳转页 cancel_url: 'https://your-domain.com/cancel', // 取消支付跳转页 // 关键:把表单数据绑定到会话的metadata中 metadata: formData }); // 重定向到Stripe结账页面 res.redirect(session.url); }); // 辅助函数:根据产品名称匹配Stripe价格ID function getPriceIdByProduct(productName) { switch(productName) { case '产品A': return 'price_xxxxxx'; case '产品B': return 'price_yyyyyy'; default: throw new Error('无效产品'); } }
前端示例(HTML/JS)
<form id="productForm"> <input type="text" name="full_name" required placeholder="全名"> <input type="number" name="height" required placeholder="身高"> <input type="number" name="weight" required placeholder="体重"> <input type="number" name="exercise_days" required placeholder="每周运动天数"> <select name="job_type" required> <option value="office">办公室</option> <option value="manual">体力劳动</option> </select> <select name="selected_product" required> <option value="产品A">产品A</option> <option value="产品B">产品B</option> </select> <button type="submit">提交并支付</button> </form> <script> document.getElementById('productForm').addEventListener('submit', async (e) => { e.preventDefault(); const formData = new FormData(e.target); await fetch('/submit-form', { method: 'POST', body: formData }).then(res => { // 重定向到Stripe结账页面 window.location.href = res.url; }); }); </script>
2. 配置Stripe Webhook监听支付成功事件
仅当用户完成支付时,Stripe会触发checkout.session.completed事件,此时可从事件中提取Stripe支付信息和绑定的表单数据。
后端Webhook端点示例(Node.js/Express)
app.post('/stripe-webhook', express.raw({type: 'application/json'}), async (req, res) => { const sig = req.headers['stripe-signature']; const webhookSecret = '你的Stripe Webhook签名密钥'; // 从Stripe后台获取 let event; try { // 验证Stripe签名,防止伪造请求 event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret); } catch (err) { return res.status(400).send(`Webhook Error: ${err.message}`); } // 处理支付成功事件 if (event.type === 'checkout.session.completed') { const session = event.data.object; // 提取Stripe支付核心信息 const stripePaymentData = { session_id: session.id, payment_intent_id: session.payment_intent, amount_total: session.amount_total, customer_email: session.customer_details.email }; // 提取之前绑定的表单数据 const formData = session.metadata; // 这里执行你的业务逻辑:比如合并数据存入数据库、发送通知邮件等 console.log('支付成功,合并数据:', {...stripePaymentData, ...formData}); } res.json({received: true}); });
3. 关键配置与注意事项
- Stripe后台配置:进入Stripe Dashboard → 开发者 → Webhooks,添加你的Webhook端点(如
https://your-domain.com/stripe-webhook),勾选checkout.session.completed事件,复制签名密钥用于后端验证。 - Metadata限制:Stripe会话的metadata最多支持50个键,每个键值对不超过500字符。若表单包含大字段(如长文本),可先将表单数据存入自有数据库,仅把数据ID存入metadata,支付成功后再通过ID查询完整数据。
- 签名验证必须执行:跳过签名验证会导致恶意请求伪造支付成功事件,引发数据泄露或错误通知。
内容的提问来源于stack exchange,提问作者Luciano Pizarro
相关产品推荐
相关产品推荐

