You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:新用户创建时触发错误

问题根源:服务端代码存在两处拼写错误:

  1. 判断用户列表长度时用了lenght,正确拼写是length
  2. 创建新用户后,错误引用了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状态,支付未完成

问题根源:

  1. Flutter端初始化Payment Sheet时设置了customFlow: true,禁用了自动确认流程,且未手动处理支付方法附加
  2. 服务端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版本
);

验证步骤

  1. 部署修复后的服务端云函数
  2. 运行Flutter应用,使用测试卡4242 4242 4242 4242、未来任意过期日期、任意CVC进行支付
  3. 查看Stripe后台,PaymentIntent状态应变为succeeded

内容的提问来源于stack exchange,提问作者Bernard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 00:37:09