Open AndreasKuhlmann opened 11 months ago
I'm seeing this issue too.
@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.
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!
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();
}
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
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:
https://github.com/capacitor-community/stripe/assets/26873275/bdc2532c-c436-42da-b72e-0f2e16a97b52
Platform
Describe the bug Paymentsheet not showing all available payment methods
To Reproduce Steps to reproduce the behavior:
Expected behavior Paymentsheet on iOS should show the all available payment methods, like on Android
Screenshots
Using Function: