Stripe支付状态始终为'requires_source'问题排查求助
问题分析与解决方案
核心问题定位
requires_source状态说明Stripe尚未获取到有效支付来源(如信用卡信息),同时Firebase Cloud Functions返回状态与Stripe实际事件不符,大概率是Webhook事件接收/解析错误或支付流程逻辑缺失导致。
分步排查与修复
1. 校验Stripe Webhook配置与签名验证
- 确认Firebase Functions的Webhook端点已在Stripe Dashboard中正确配置,且启用
payment_intent.succeeded、payment_intent.payment_failed等关键事件。 - 必须通过Stripe签名验证确保事件合法性,避免伪造。Cloud Functions中示例代码:
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET; const admin = require('firebase-admin'); admin.initializeApp(); exports.stripeWebhook = functions.https.onRequest(async (req, res) => { const sig = req.headers['stripe-signature']; let event; try { // 必须用rawBody解析,不能用req.body(Firebase默认会解析JSON,破坏签名验证) event = stripe.webhooks.constructEvent(req.rawBody, sig, endpointSecret); } catch (err) { return res.status(400).send(`Webhook Error: ${err.message}`); } // 打印日志排查实际接收的事件 console.log(`事件类型: ${event.type}, 支付状态: ${event.data.object.status}`); switch (event.type) { case 'payment_intent.succeeded': const paymentIntent = event.data.object; // 支付成功后写入数据库 await admin.database().ref(`payments/${paymentIntent.id}`).set({ status: 'succeeded', amount: paymentIntent.amount, createdAt: paymentIntent.created }); break; case 'payment_intent.payment_failed': const failedIntent = event.data.object; // 支付失败执行对应操作 await admin.database().ref(`payments/${failedIntent.id}`).update({ status: 'failed', errorMsg: failedIntent.last_payment_error?.message }); break; default: console.log(`未处理事件类型: ${event.type}`); } res.json({received: true}); });
2. 补全Flutter端支付来源绑定逻辑
requires_source状态的直接原因是Payment Intent未关联支付方式,Flutter端需确保确认支付时传入支付来源:
import 'package:stripe/stripe.dart'; // 创建支付方式 final paymentMethod = await Stripe.instance.createPaymentMethod( PaymentMethodParams.card( card: CardDetails( number: '4242424242424242', // Stripe测试卡号 expMonth: 12, expYear: 2025, cvc: '123', ), ), ); // 确认支付,传入支付方式ID final confirmResponse = await Stripe.instance.confirmPaymentIntent( clientSecret: '从后端获取的Payment Intent Client Secret', data: PaymentIntentConfirmData( paymentMethodId: paymentMethod.id, ), );
3. 修正后端状态获取逻辑
- 禁止依赖前端传递的支付状态,必须以Stripe Webhook事件中
event.data.object.status为准。 - 检查Cloud Functions代码,确保没有错误使用前端参数覆盖Stripe事件返回的状态。
4. 校验Payment Intent创建参数
创建Payment Intent时需指定必要参数,避免因配置缺失导致状态异常:
const paymentIntent = await stripe.paymentIntents.create({ amount: 1000, // 单位:分,对应10美元 currency: 'usd', payment_method_types: ['card'], // 若不需要手动捕获,可省略capture_method,默认自动捕获 capture_method: 'automatic' }); // 返回clientSecret给前端用于支付确认 return {clientSecret: paymentIntent.client_secret};
额外排查点
- 检查Stripe Dashboard的支付日志,查看Payment Intent的历史状态变化,确认是否存在失败的支付尝试。
- 确保Firebase Functions的Node.js版本与Stripe SDK兼容(推荐Node.js 18+)。
- 用Stripe测试卡号模拟场景:4242 4242 4242 4242(成功支付)、4000 0000 0000 0002(支付失败)。
内容的提问来源于stack exchange,提问作者İsmail Ayberk Gün
相关产品推荐
相关产品推荐

