Flutter Stripe PaymentIntent异常及代码问题求助
Flutter flutter_stripe支付模块问题修复方案
问题概述
- 无报错但PaymentIntent始终处于
requires_payment_method状态,支付无法完成 - 启用
confirmPayment时触发Null is not a subtype of String错误 - 新用户首次支付时触发服务端错误
用户代码片段
Flutter客户端代码
Future<void> initPayment({required String email, required int montant, required String nomOrga}) async{ try{ //1. Crée un payment intent sur le serveur final response = await http.post( Uri.parse("myFirebase URL"), body: { "email":email, "amount": (montant*100).toString(), }, ); print("email : $email - montant : $montant - organisation : $nomOrga"); final jsonResponse = jsonDecode(response.body); print(jsonResponse); //2. Initialise le payment sheet await Stripe.instance.initPaymentSheet(paymentSheetParameters: SetupPaymentSheetParameters( paymentIntentClientSecret: jsonResponse["paymentIntent"], merchantDisplayName: nomOrga, customerId: jsonResponse["customer"], customerEphemeralKeySecret: jsonResponse["ephemeralKey"], customFlow: true, ) ); //3. Présenter le paiement await Stripe.instance.presentPaymentSheet(); print("on a présenté la paymentsheet"); //4. Attacher la méthode de paiement au PaymentIntent et confirmer le paiement /*final paymentIntentResult = await Stripe.instance.confirmPayment( paymentIntentClientSecret: jsonResponse["client_secret"], );*/ print("on a fini confirmpayment"); //print(paymentIntentResult.status); /*if(paymentIntentResult.status == PaymentIntentsStatus.Succeeded){ //Paiement réussi quickConfirm("Paiement réussi", "Le paiement est réussi", context); }else{ quickAlert("Oups", "Le paiement a échoué", context); }*/ } catch(error){ if(error is StripeException){ quickAlert("Oups", "une erreur StripeException s'est produite\n${error.error.message}", context); }else{ quickAlert("Oups", "une erreur brol s'est produite\n${error}", context); } } }
服务端Firebase云函数代码
const functions = require("firebase-functions"); const stripe = require("stripe")("sk_test_..."); require("firebase-functions/logger/compat"); exports.stripePaymentIntentRequest = functions.https.onRequest(async (req, res) => { try{ let customerId; //Get the customer who's email matches the one sent by the client const customerList = await stripe.customers.list({ email: req.body.email, limit: 1, }); console.log(customerList); //Check if customer exists, if not create a new customer if(customerList.data.lenght !== 0){ customerId = customerList.data[0].id; } else { const customer = await stripe.customers.create({ email: req.body.email, }); customerId = customers.id; } //Creates a temporarysecret key linked with the customer const ephemeralKey = await stripe.ephemeralKeys.create( {customer: customerId}, {apiVersion: '2020-08-27'} ); //Creates a new payment intent with amount passed from the client const paymentIntent = await stripe.paymentIntents.create({ amount: parseInt(req.body.amount), currency: 'eur', customer: customerId, automatic_payment_methods: { enabled: true, }, }); console.log('on arrive au send'); console.log(res); res.send({ paymentIntent: paymentIntent.client_secret, ephemeralKey: ephemeralKey.secret, customer: customerId, publishableKey:'pk_test...', success: true, }); console.log('on a fini 200'); } catch(error) { console.log('il y a eu une erreur :', error.message); res.status(404).send({ success: false, error: error.message, }); } });
逐个问题修复
问题c:新用户创建时触发错误
问题根源:服务端代码存在两处拼写错误:
- 判断用户列表长度时用了
lenght,正确拼写是length - 创建新用户后,错误引用了
customers.id,实际应该是customer.id
修复后的服务端代码片段:
//Check if customer exists, if not create a new customer if(customerList.data.length !== 0){ // 修正拼写:lenght → length customerId = customerList.data[0].id; } else { const customer = await stripe.customers.create({ email: req.body.email, }); customerId = customer.id; // 修正变量名:customers → customer }
问题b:启用confirmPayment时触发Null is not a subtype of String错误
问题根源:Flutter代码中尝试获取jsonResponse["client_secret"],但服务端返回的对应字段是paymentIntent,该字段不存在导致返回null。
修复方案:
使用Payment Sheet时,presentPaymentSheet()已经自动完成支付确认流程,不需要额外调用confirmPayment,直接移除第4步的代码即可。如果一定要保留调用,需传入正确的字段:
final paymentIntentResult = await Stripe.instance.confirmPayment( paymentIntentClientSecret: jsonResponse["paymentIntent"], );
问题a:PaymentIntent始终处于requires_payment_method状态,支付未完成
问题根源:
- Flutter端初始化Payment Sheet时设置了
customFlow: true,禁用了自动确认流程,且未手动处理支付方法附加 - 服务端API版本较旧,可能存在兼容性问题
修复方案:
1. 调整Flutter端Payment Sheet配置
将customFlow: true改为customFlow: false,启用自动支付流程:
await Stripe.instance.initPaymentSheet(paymentSheetParameters: SetupPaymentSheetParameters( paymentIntentClientSecret: jsonResponse["paymentIntent"], merchantDisplayName: nomOrga, customerId: jsonResponse["customer"], customerEphemeralKeySecret: jsonResponse["ephemeralKey"], customFlow: false, // 改为false,启用自动流程 ) );
2. 完善支付结果判断逻辑
presentPaymentSheet()执行成功即代表支付完成,无需额外判断,直接处理成功逻辑:
//3. Présenter le paiement await Stripe.instance.presentPaymentSheet(); // 走到此处说明支付成功 quickConfirm("Paiement réussi", "Le paiement est réussi", context);
3. 服务端API版本优化
将Stripe API版本更新至较新版本(如2024-06-20),提升兼容性:
const ephemeralKey = await stripe.ephemeralKeys.create( {customer: customerId}, {apiVersion: '2024-06-20'} // 更新为最新API版本 );
验证步骤
- 部署修复后的服务端云函数
- 运行Flutter应用,使用测试卡
4242 4242 4242 4242、未来任意过期日期、任意CVC进行支付 - 查看Stripe后台,PaymentIntent状态应变为
succeeded
内容的提问来源于stack exchange,提问作者Bernard
相关产品推荐
相关产品推荐

