capacitor-community / stripe

Stripe Mobile SDK wrapper for Capacitor
MIT License
185 stars 75 forks source link

Android : paymentSheetFailed #293

Closed tomatlscomm closed 1 year ago

tomatlscomm commented 1 year ago

Platform

Describe the bug Hi.

On Android only, i keep getting an paymentSheetFailed error when on Stripe.presentPaymentSheet() function. I have correctly implemented the plugin, following the documentation, on a fresh ionic app to test, on a very simple way, so i'm pretty sure not to have a plugin conflict or whatever.

The exact same code is properly working on iOS.

Work state

├── @capacitor-community/stripe@5.0.1 ├── @capacitor/android@5.0.4 ├── @capacitor/app@5.0.2 ├── @capacitor/cli@5.0.4 ├── @capacitor/core@5.0.4 ├── @capacitor/haptics@5.0.2 ├── @capacitor/ios@5.0.4 ├── @capacitor/keyboard@5.0.2 ├── @capacitor/status-bar@5.0.2 ├── @ionic/vue-router@7.0.9 ├── @ionic/vue@7.0.9 ├── @vitejs/plugin-legacy@4.0.4 ├── @vitejs/plugin-vue@4.2.3 ├── @vue/eslint-config-typescript@11.0.3 ├── @vue/test-utils@2.3.2 ├── cypress@12.13.0 ├── eslint-plugin-vue@9.14.1 ├── eslint@8.41.0 ├── ionicons@7.1.1 ├── jsdom@21.1.2 ├── typescript@4.9.5 ├── vite@4.3.9 ├── vitest@0.29.8 ├── vue-router@4.2.1 ├── vue-tsc@1.6.5 └── vue@3.3.4

Product Name: Product URL : Using Function:

Simple javascript code raising the error :

import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/vue';
import ExploreContainer from '@/components/ExploreContainer.vue';
import { Stripe, PaymentSheetEventsEnum } from '@capacitor-community/stripe';

Stripe.initialize({
  publishableKey: "pk_test_XXX",
})
.then( async() => {

    (async () => {
      // be able to get event of PaymentSheet
      Stripe.addListener(PaymentSheetEventsEnum.Completed, () => {
        console.log('PaymentSheetEventsEnum.Completed');
      });

      let paymentIntent = "pi_XXX";
      let customer = "cus_XXX";
      let ephemeralKey = "ek_test_XXX";

      // prepare PaymentSheet with CreatePaymentSheetOption.
      await Stripe.createPaymentSheet({
        paymentIntentClientSecret: paymentIntent,
        customerId: customer,
        customerEphemeralKeySecret: ephemeralKey,
      });

      // present PaymentSheet and get result.
      const result = await Stripe.presentPaymentSheet();

      if (result.paymentResult === PaymentSheetEventsEnum.Completed) {
        // Happy path
        alert('PaymentSheetEventsEnum.Completed');
      }
      else if (result.paymentResult === PaymentSheetEventsEnum.Canceled) {
        alert('PaymentSheetEventsEnum.Canceled');
      }
      else {
        alert('ERROR');
      }

    })();

  });

Is this problem known ?

Thank you in advance for your help and support

dadoadk commented 1 year ago

Instead of: const result = await Stripe.presentPaymentSheet(); try this: const { paymentResult } = await Stripe.presentPaymentSheet();

now you can check if (paymentResult && paymentResult === PaymentSheetEventsEnum.Completed) {

tomatlscomm commented 1 year ago

Hi. Thank you for your help. However this doesn't resolve the problem.

On Android, paymentResult is still equal to paymentSheetFailed with your code.

On iOS, with the exact same code, and the exact same paymentIntentClientSecret / customerId / customerEphemeralKeySecret, the payment sheet is correctly presented to the user.

tomatlscomm commented 1 year ago

OK i've found the issue.

On android only, the parameter merchantDisplayName of createPaymentSheet is required in order to work. Without this parameter, the presentPaymentSheet function will fail.

If this is not an issue, the documentation (https://stripe.capacitorjs.jp/docs/payment-sheet) and the examples provided should by updated, this will save a lot of time to other people encountering this issue.

larsblumberg commented 8 months ago

@tomatlscomm thanks a ton for your hint to include the merchantDisplayName field when calling createPaymentSheet(). This fixes the problem that presentPaymentSheet() returns a failure code on Android.