【问题标题】:Stripe error the customer has not entered their payment method in flutter条纹错误,客户没有在颤抖中输入他们的付款方式
【发布时间】:2021-12-13 18:57:54
【问题描述】:

我使用 Firebase CLI 在我的 Flutter 应用程序中集成了 flutter_stripe 2.0.1 插件。从 firebase 提供的 URL 获得 paymentIntent 的成功响应。但在 Stripe 控制面板中,付款状态是Incomplete

下面是我的 node.js 代码 index.js 文件

const functions = require('firebase-functions');
const stripe = require('stripe')(functions.config().stripe.testkey);

exports.stripePayment = functions.https.onRequest(async (req, res) => {  
    const paymentIntent = await stripe.paymentIntents.create({
        amount: 1,
        currency: 'usd'
    },
        function(err, paymentIntent) {
            if(err != null){
                console.log(err);
            } else {
                res.json({
                    paymentIntent: paymentIntent.client_secret,
                })
            }
        }
    )

});

下面是我的颤振代码

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  Stripe.publishableKey = stripePublishableKey;
  Stripe.merchantIdentifier = 'merchant.flutter.stripe.test'; //any string works
  await Stripe.instance.applySettings();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
      return MaterialApp(
        home: DashboradPage(),
      );
  }
}

class DashboradPage extends StatefulWidget {
  const DashboradPage({Key? key}) : super(key: key);

  @override
  _DashboradPageState createState() => _DashboradPageState();
}

class _DashboradPageState extends State<DashboradPage> {
  Map<String, dynamic>? paymentIntentData;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Stripe Examples'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            makePayment();
          },
          child: Text('Pay Amount'),
        ),
      ),
    );
  }

  Future<void> makePayment() async {
    final url = Uri.parse(
        'https://us-central1-stripeflutterdemo.cloudfunctions.net/stripePayment');

    final header = {'Content-Type': 'application/json'};
    try {
      final response = await http.get(url, headers: header);
      paymentIntentData = json.decode(response.body);
      await Stripe.instance.initPaymentSheet(
            paymentSheetParameters: SetupPaymentSheetParameters(
          paymentIntentClientSecret: paymentIntentData?['paymentIntent'] ?? '',
          applePay: true,
          googlePay: true,
          style: ThemeMode.light,
          merchantCountryCode: 'US',
          merchantDisplayName: 'Flutter Stripe Store Demo',
        ));
        setState(() {});
       displayPaymentSheet();
    } catch (e) {
      print(e);
      displaySnackbar(e.toString());
    }
  }

  Future<void> displayPaymentSheet() async {
    try {
      await Stripe.instance.presentPaymentSheet();
      // await Stripe.instance.presentPaymentSheet(
      //   parameters: PresentPaymentSheetParameters(
      //     clientSecret: paymentIntentData?['paymentIntent'] ?? '',
      //     confirmPayment: true,
      //   ),
      // );

      setState(() {
        paymentIntentData = null;
      });
      displaySnackbar('Payment succesfully completed');
    } catch (e) {
      print(e);
      displaySnackbar(e.toString());
    }
  }

  void displaySnackbar(String msg) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(msg),
      ),
    );
  }
}

下面是 makePayment() 中提到的 URL 的邮递员响应

我使用了支付单,当我点击支付按钮时,它会重定向到 web 视图(身份验证已完成),但在 Stripe 仪表板中,支付状态是未完成

Stripe Dashboard Payment Event 数据 PaymentIntent 状态:requires_payment_method, PaymentIntent 状态:requires_action

From Stripe
payment_intent.payment_failed
View event detail
Event data
{
  "id": "pi_3JpZh7SIKwX0CSUQ0sUoM9wK",
  "object": "payment_intent",
  "last_payment_error": {
    "message": "As per Indian regulations, export transactions require a description. More info here: https://stripe.com/docs/india-exports",
    "param": "description",
    "payment_method": {
      "id": "pm_1JpZijSIKwX0CSUQ7u91wths",
      "object": "payment_method",
      "billing_details": {
        "address": {
          "city": null,
          "country": "US",
          "line1": null,
          "line2": null,
          "postal_code": "45612",
          "state": null
        },
        "email": null,
        "name": null,
        "phone": null
      },
      "card": {
        "brand": "visa",
        "checks": {
          "address_line1_check": null,
          "address_postal_code_check": "unchecked",
          "cvc_check": "unchecked"
        },
        "country": "US",
        "exp_month": 4,
        "exp_year": 2044,
        "fingerprint": "EK9VAoccqqCLBqQk",
        "funding": "credit",
        "generated_from": null,
        "last4": "4242",
        "networks": {
          "available": [
            "visa"
          ],
          "preferred": null
        },
        "three_d_secure_usage": {
          "supported": true
        },
        "wallet": null
      },
      "created": 1635431806,
      "customer": null,
      "livemode": false,
      "metadata": {
      },
      "type": "card"
    },
    "type": "invalid_request_error"
  },
  "livemode": false,
  "next_action": null,
  "status": "requires_payment_method",
  "amount": 1,
  "amount_capturable": 0,
  "amount_received": 0,
  "application": null,
  "application_fee_amount": null,
  "canceled_at": null,
  "cancellation_reason": null,
  "capture_method": "automatic",
  "charges": {
    "object": "list",
    "data": [
    ],
    "has_more": false,
    "total_count": 0,
    "url": "/v1/charges?payment_intent=pi_3JpZh7SIKwX0CSUQ0sUoM9wK"
  },
  "client_secret": "pi_3JpZh7SIKwX0CSUQ0sUoM9wK_secret_oVhK5CmrcHjImvFMyoo51GCXy",
  "confirmation_method": "automatic",
  "created": 1635431705,
  "currency": "usd",
  "customer": null,
  "description": null,
  "invoice": null,
  "metadata": {
  },
  "on_behalf_of": null,
  "payment_method": null,
  "payment_method_options": {
    "card": {
      "installments": null,
      "network": null,
      "request_three_d_secure": "automatic"
    }
  },
  "payment_method_types": [
    "card"
  ],
  "receipt_email": null,
  "review": null,
  "setup_future_usage": "off_session",
  "shipping": null,
  "source": null,
  "statement_descriptor": null,
  "statement_descriptor_suffix": null,
  "transfer_data": null,
  "transfer_group": null
}

以下是 iPhone 截图

【问题讨论】:

    标签: flutter google-cloud-functions stripe-payments


    【解决方案1】:

    根据 Stripe documentationrequired_payment_method 消息作为 status 表示您没有将付款方式附加到您的付款意图:

    在创建 PaymentIntent 时,它的状态为 requires_payment_method,直到附加了付款方式。

    有一个官方document 解释如何将 Stripe 支付与您的 Firebase 后端集成。它提供了使用 Stripe 正确设置付款所需的所有代码和步骤。在 index.js 文件内的 sample code 中,它们在使用 stripe.paymentIntents.create() 创建支付意图时包含其他对象

    const payment = await stripe.paymentIntents.create(
        {
          amount,
          currency,
          customer,
          Payment_method, //payment method when creating the payment intent
          off_session: false,
          confirm: true,
          confirmation_method: 'manual',
        },
        { idempotencyKey }
      );
    

    由于您的样本缺少付款方式,它可以解释您收到的错误,因为 PaymentIntent 是在没有付款方式的情况下创建的。我建议按照指南涵盖所有必需的步骤,以避免可能出现的进一步错误。您还可以查看完整的示例代码,该代码已记录并可针对您的用例和flutter_stripe 库进行自定义。

    【讨论】:

    • 感谢您的详细回答。但是如果我对 index.js 文件进行任何更改,它会引发 408 错误。你能告诉我上面代码中的更改吗,尽管它是一个演示应用程序,我们将集成到我们的项目中。
    • A 408 error 表示请求缺少必需的参数。有一个related question,其中必填参数在使用 Stripe 支付的 Flutter 应用程序中显示此错误。您可以查看flutter_stripedocumentation,因为有一个示例应用程序可以帮助您制定正确的请求。
    猜你喜欢
    • 2021-05-18
    • 2020-10-06
    • 2021-07-26
    • 2021-09-27
    • 2021-07-02
    • 2021-04-15
    • 2021-05-11
    • 1970-01-01
    • 2017-12-01
    相关资源
    最近更新 更多