Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[iOS] Paymentsheet not showing available payment methods #313

Open
5 of 7 tasks
AndreasKuhlmann opened this issue Oct 17, 2023 · 6 comments
Open
5 of 7 tasks

[iOS] Paymentsheet not showing available payment methods #313

AndreasKuhlmann opened this issue Oct 17, 2023 · 6 comments

Comments

@AndreasKuhlmann
Copy link

Platform

  • Web
  • iOS
  • Android

Describe the bug
Paymentsheet not showing all available payment methods

To Reproduce
Steps to reproduce the behavior:

  1. Enable multiple payment methods in Stripe (Paypal, credit card etc.)
  2. Present paymentsheet on iOS
  3. Present paymentsheet on Android
  4. compare

Expected behavior
Paymentsheet on iOS should show the all available payment methods, like on Android

Screenshots
IMG_4416
IMG_4415

Using Function:

  • Payment Sheet / Payment Flow
  • Apple Pay
  • Google Pay
  • Identity Verification Sheet
@AndreasKuhlmann AndreasKuhlmann changed the title [iOS] Paymentsheet not showing available payment methods [iOS] Paymentheet not showing available payment methods Oct 17, 2023
@AndreasKuhlmann AndreasKuhlmann changed the title [iOS] Paymentheet not showing available payment methods [iOS] Paymentsheet not showing available payment methods Oct 24, 2023
@miraclemaker
Copy link

I'm seeing this issue too.

@larsblumberg
Copy link

@rdlabo availability of PayPal payment option is a core feature for this plugin, on iOS as well. The users of this plugin would be very thankful if you could share any insights on what we could expect from this plugin concerning PayPal on iOS. I am personally motivated to contribute improvements on this matter, however we do need some guidance from you on what you suggest to do here.

@AndreasKuhlmann
Copy link
Author

This is what I found out so far:

To show all available payment methods on iOS it is required to initialize the returnURL option of createPaymentSheet({}):

createPaymentSheet( {…, returnURL: “my-app://path-in-your-app”,…} )

This makes sense, because stripe will redirect to external pages (PayPal.com, etc.) to fulfil payment and of cause needs to jump back somehow, when payment went through.

iOS or stripe seems to be here very strict and evaluates the url immediately after assignment (surprisingly not so on Android). If returnURL is not initialized external payment methodes are not shown on the payment sheet.
And if you assign any invalid url the app will show an error message on the payment sheet or will crash badly - at least on my device!

But for iOS a valid Url means a Url with a “Custom URI Scheme”: See here for more details:
https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app)

At the end of the day, you need add an entry into Info.plist like this:

...
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<!-- your app bundle name here: -->
<string>com.example.my-app</string>
<key>CFBundleURLSchemes</key>
<array>
<!—- your app name here: -->
<string>my-app</string>
</array>
</dict>
</array>
...

If you now assign “my-app://home/shop/payment-result” to returnURL, hopefully additional available payment methods should now be available and visible.

Of cause home/shop/payment-result must be a valid path in your application as well!

Btw, on redirect stripe adds a whole bunch of parameters as a query string that gives you all information you need to figure out what happened during payment.

Good Luck!

@DwieDima
Copy link

DwieDima commented Apr 5, 2024

Hi @AndreasKuhlmann

Thank you for sharing your insights, it helped a lot.

I have now got to the point where paypal is displayed as a payment method. when adding it, the paypal test setup page also appears (see screenshot).

After I click on "Authorize Test Setup" or "Fail Test Setup", a redirect occurs (URL is logged in Xcode with my.app.link://maps followed by params), but the InAppBrowser never closes and the method Stripe.confirmPaymentFlow() is never resolved. So the process hangs at this point and the payment method is never added.

Did you manage to pay with Paypal?
And what do you mean by "Of cause home/shop/payment-result must be a valid path in your application as well!". Do you need to declare it in Xcode?
Am I missing something here?

  public async confirmCreditCardSetup(
    setupIntentResponse: SetupIntentResponse
  ) {
    await Stripe.createPaymentFlow({
      setupIntentClientSecret: setupIntentResponse.clientSecret,
      customerId: setupIntentResponse.customerId,
      customerEphemeralKeySecret: setupIntentResponse.ephemeralKey,
      merchantDisplayName: 'My App Name',
      returnURL: 'my.app.link://maps', // maps is a valid url in my app.routing.module
      style: 'alwaysLight'
    });

    await Stripe.presentPaymentFlow();

// the process get stuck here. this Stripe.confirmPaymentFlow() never resolves 🥲    
const { paymentResult } = await Stripe.confirmPaymentFlow();
    if (paymentResult !== PaymentFlowEventsEnum.Completed) {
      return Promise.reject('Payment failed');
    }

    return Promise.resolve();
  }

@AndreasKuhlmann
Copy link
Author

Hi @DwieDima, "my.app.link" looks kind of strange to me. Not sure if this is a valid URL Scheme identifier. Try one without dots.
The "path" after in "my-app://path" must point to an existing component or navigation target

@DwieDima
Copy link

DwieDima commented Apr 5, 2024

Hi @AndreasKuhlmann

this was not the issue. I finally managed to add PayPal as payment method for future use.
For iOS you have to also call Stripe.handleURLCallback({ url }) when you receive the callback from Stripe, so the InAppBrowser closes correctly.

I also used Stripe.createPaymentFlow(), Stripe.presentPaymentFlow() and Stripe.confirmPaymentFlow()

instead of: Stripe.createPaymentSheet() and Stripe.presentPaymentSheet().

my URL SCHEME in Info.plist

	<dict>
			<key>CFBundleTypeRole</key>
			<string>Editor</string>
			<key>CFBundleURLName</key>
			<string>$(BUNDLE_IDENTIFIER)</string>
			<key>CFBundleURLSchemes</key>
			<array>
				<string>accept-a-payment</string>
			</array>
		</dict>
import {
  PaymentSheetEventsEnum,
  Stripe
} from '@capacitor-community/stripe';
import { App } from '@capacitor/app';

// I'm using here the BUNDLE_IDENTIFIER in my Info.plist
const REDIRECT_URL = 'com.company.appName://stripe-redirect'

@Injectable({
  providedIn: 'root'
})
export class PaymentService {

  constructor() {
    Stripe.initialize({
      publishableKey: environment.stripePublishableKey
    });

      // this is needed to complete the process, so the Stripe Browser is closed for returnUrl
      App.addListener('appUrlOpen', async (event) => {
      const url = event.url;
      const isStripeRedirect = url.includes(REDIRECT_URL);

      if (isStripeRedirect) {
        // the url from stripe redirect
        // com.company.appName://stripe-redirect?redirect_status=succeeded&setup_intent=seti_YOUR_SETI&setup_intent_client_secret=seti_YOUR_CLIENT_SECRET
        await Stripe.handleURLCallback({
          url
        });
      }
    });


 public async confirmCreditCardSetup(
    setupIntentResponse: SetupIntentResponse
  ) {
    await Stripe.createPaymentSheet({
      customerId: setupIntentResponse.customerId,
      setupIntentClientSecret: setupIntentResponse.clientSecret,
      customerEphemeralKeySecret: setupIntentResponse.ephemeralKey,
      merchantDisplayName: 'Company Name',
      style: 'alwaysLight',
      returnURL: REDIRECT_URL
    });

    const { paymentResult } = await Stripe.presentPaymentSheet();

    if (paymentResult !== PaymentSheetEventsEnum.Completed) {
      return Promise.reject('Payment failed');
    }

    return Promise.resolve();
  }
  }

result:

RPReplay_Final1712328419.MP4

@rdlabo rdlabo added the docs label Apr 13, 2024
@shiv19 shiv19 added the payment label Nov 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants