Flutter stripe_payment Native pay not charged(Apple Pay and Google Pay)

2,134

Before look into the code, please make sure you have finished the following steps: 0. stripe_payment is added.

  1. Merchant Id has been created.
  2. Apple Pay has been enabled in Xcode.
  3. Stripe "Standard Key" and "Restricted Key" have been generated.
    • standard key contains publishable key and secret key
    • publishable key uses in Flutter project.
    • restricted key uses in Server side.

What i have been done for the native payment:

  1. calls paymentRequestWithNativePay() to get token.
  2. charges with own implemented charge method(on Server side, makes sure you use the restricted key and it has charge write permission).
  3. calls paymentRequestWithNativePay()
    void handleNativePayment(BuildContext context, String amountInStr) async {
        // I used environment configurations for ANDROID_PAY_MODE, use "test" in test mode
        // and uses "production" in production mode
        StripePayment.setOptions(StripeOptions(
            publishableKey: _publishableKey,
            merchantId: _merchantId,
            androidPayMode: EnvironmentConfig.ANDROID_PAY_MODE,
        ));
    
        // this is my service class talks to server side API 
        PaymentService paymentService = Provider.of<PaymentService>(
          context,
          listen: false,
        );
    
        Token token = await StripePayment.paymentRequestWithNativePay(
          androidPayOptions: AndroidPayPaymentRequest(
            totalPrice: amountInStr,
            currencyCode: _currencyCode,
          ),
          applePayOptions: ApplePayPaymentOptions(
            countryCode: _countryCode,
            currencyCode: _currencyCode,
            items: [
              ApplePayItem(
                type: 'final',
                label: paymentLabel,
                amount: amountInStr,
              )
            ],
          ),
        );
    
        // converts amount from string to int, and it is in cents
        dynamic chargeResult = await paymentService.charge({
          "token": token.tokenId,
          "amount": double.parse(amountInStr) * 100,
          "currency": _currencyCode,
        });
    
        if (chargeResult is ChargeResult) {
          _buildSnackBar(context, "Payment success", Colors.green);
        } else {
          _buildSnackBar(context, "Payment fail", Colors.red);
        }
    
        await StripePayment.completeNativePayRequest();
      }

  _buildSnackBar(BuildContext context, String content, Color color) {
    final snackBar = SnackBar(
      content: Text(content),
      backgroundColor: color,
    );
    Scaffold.of(context).showSnackBar(snackBar);
  }

Here's the PaymentService in Flutter. You need implement the server side charge API call with the Stripe restricted key.

class PaymentService {
  var logger = Logger(printer: PrettyPrinter());

  Future<dynamic> charge(Map<String, dynamic> data) async {
    Map<String, dynamic> charge = {
      "source": data["token"],
      "amount": data["amount"],
      "currency": data["currency"],
    };
    final response = await DioHttp.post('/stripe/payment/charge', charge);
    if (response.containsKey("results")) {
      return ChargeResult.fromMap(response["results"]);
    } else {
      String errorMessage = response["errors"][0]["description"];
      return errorMessage;
    }
  }
}

There's one more thing needs your attention:

When test with Android phone, don't use Stripe test cards numbers, it always gives you request failure(error codeOR-CCSEH-21). What you need to do is:

  1. sets android pay mode to 'test'.
  2. pays with your own/real card and it will pass(In below attached payment records, you can see the last payment contains my name, that's because i used my own card for the android google pay testing)

Hope it helps developers who needs it.

enter image description here enter image description here

Share:
2,134
Haifeng Zhang
Author by

Haifeng Zhang

Updated on December 28, 2022

Comments

  • Haifeng Zhang
    Haifeng Zhang over 1 year

    The stripe payment API call return status 200 but the amount isn't charged.

    I have a Flutter application uses Stripe payment.

    I have done:

    1. certification has been created.
    2. merchant id has been created.

    Followed the example of stripe_payment, I have my native payment method below:

    void _handleNativePayment(String amount) async {
        Token token = await StripePayment.paymentRequestWithNativePay(
          androidPayOptions: AndroidPayPaymentRequest(
            totalPrice: amount,
            currencyCode: _currencyCode,
          ),
          applePayOptions: ApplePayPaymentOptions(
            countryCode: _countryCode,
            currencyCode: _currencyCode,
            items: [
              ApplePayItem(
                type: 'final',
                label: _paymentLabel,
                amount: amount,
              )
            ],
          ),
        );
    
        await StripePayment.completeNativePayRequest();
    }
    

    When I run it on simulator, I can see the payment is done and can view the request on Stripe dashboard unfortunately the Payment is still 0.: enter image description here enter image description here enter image description here

  • Joelson Rocha
    Joelson Rocha about 3 years
    Were you able to put it into production? I Have an ERROR: Request Failed - Unexpected developer error, please try again later. My question is: in merchantId (Google Pay MerchantId or Stripe MerchantId). And where I inform Google Pay, the integration with Stripe, Google Pay has already authorized my application for production. The documentation is not clear about the steps to put into production.