iOS: Redirect Handling
Some payment methods allow the user to authenticate in a companion app. When supported, the SDK automatically redirects the user to that app. This page covers the available options and their tradeoffs.
Want the short version? Jump to recommended setup.
Flow modes
When configuring native alternative payment screens via PONativeAlternativePaymentConfigurationV2, you choose one of two redirect modes.
Manual
In manual mode, the payment app redirects the user directly to the return_url set on the invoice - bypassing ProcessOut’s checkout page entirely. This is the recommended mode when using the SDK, as it results in a simpler redirect chain.
Some payment methods only support Universal Links as a
return_url. Custom scheme deep links may not be accepted depending on the payment method.
Automatic
In automatic mode, the user is first redirected to the ProcessOut checkout page in a browser, which then redirects to your return_url. The extra hop through ProcessOut’s checkout page provides wider compatibility - in particular, custom scheme deep links work reliably with automatic mode even for payment methods that would otherwise reject them. This is the default behavior.
Use automatic mode if you need custom scheme deep links specifically and cannot use Universal Links.
Return URL types
Regardless of flow mode, you need to specify an invoice.return_url that brings the user back to your app. There are two options.
Universal Links
Universal Links are HTTPS URLs associated with your domain that iOS routes directly to your app. They are the preferred option: majority of payment methods accept them, and they provide the best and most secure user experience.
Requirements:
-
Your domain must be configured for Universal Links. See Apple’s Supporting Associated Domains documentation.
-
On iOS 17.4+, set the
httpscallback on the redirect configuration (see below) to ensure that in-app browser is able intercept return URL. -
You must host a landing page at the return URL - required for the web redirect fallback to work correctly.
Custom scheme deep links
Custom scheme URLs (e.g. yourapp://payment-return) are simpler to set up but come with meaningful limitations:
-
Not accepted by all payment methods. Revolut, for example, requires Universal Links.
-
No landing page required - the custom scheme is intercepted directly.
-
Only reliably usable with automatic flow mode.
Use custom scheme deep links only if Universal Links are not an option for you.
User redirect confirmation
When the SDK determines that the user needs to be redirected to a third-party app to authenticate, it prompts the user to confirm before leaving the app. This gives users context about what is happening before they are taken elsewhere.
By default this confirmation is always shown. You can bypass it by setting enableHeadlessMode on the redirect object of your configuration:
let configuration = PONativeAlternativePaymentConfiguration(
...,
redirect: .init(enableHeadlessMode: true)
)When enabled, the SDK will redirect the user automatically (without prompting) - if the redirect requirement is detected during the initial payment information loading.
Web redirect fallback
When a direct deep link to the payment app is not possible, the SDK falls back to opening the payment flow in an in-app browser. At the end of the flow, the browser receives your return_url.
There is a limitation, in-app browser does not intercept Universal Links by default - it will open them in the browser rather than routing them to your app. There are two ways to handle this.
iOS 17.4+ https callback
https callbackIf your minimum deployment target allows it, set the https callback on the redirect object of your configuration. When set, the system intercepts the Universal Link return URL - significantly improving reliability compared to the landing page fallback alone.
Set this whenever you use Universal Links.
let configuration = PONativeAlternativePaymentConfiguration(
...,
redirect: .init(callback: .https(host: "yourapp.com", path: "/"))
)For the full API reference, see PONativeAlternativePaymentConfiguration/Redirect/callback.
Landing page
The landing page is an HTML page you host at your Universal Link URL. When the web fallback opens your return_url in a browser, this page is what the browser loads. Its job is to redirect the browser to a custom scheme deep link that your app handles - preserving all query parameters from the original URL.
This is your responsibility to build and host. It must be served from the domain associated with your app for Universal Links.
Minimum requirements:
-
Read query parameters from the incoming URL.
-
Construct a custom scheme deep link with those parameters preserved exactly.
-
Render an explicit button to trigger the redirect - do not rely solely on automatic redirect, as Chrome on Android is prone to suppressing them.
-
Optionally, attempt an automatic redirect as an enhancement, but the explicit button is mandatory.
The landing page is required for Android compatibility, and on iOS it covers cases where the https callback cannot be used (iOS below 17.4, or not configured).
Android does not support the
httpscallback mechanism within the embedded browser, so the landing page is always required. See the Android redirect handling guide for details.
Forwarding URLs to the SDK
Whenever your app receives an incoming URL - whether from a Universal Link or a custom scheme deep link - you must forward it to the SDK. Query parameters must be preserved exactly as received.
Universal Links
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if let url = userActivity.webpageURL {
ProcessOut.shared.processDeepLink(url: url)
}
}Custom scheme deep links
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
if let url = URLContexts.first?.url {
ProcessOut.shared.processDeepLink(url: url)
}
}Recommended setup
The following configuration gives you the best compatibility across payment methods and the smoothest user experience on iOS.
1. Use Manual flow mode
Set .flow to manual on your PONativeAlternativePaymentConfigurationV2. It produces a simpler redirect chain and is the recommended mode when integrating via the SDK.
2. Set a Universal Link as invoice.return_url
invoice.return_urlEnsures compatibility with all payment methods. Must be a URL on a domain associated with your app.
3. Set the https callback (iOS 17.4+)
https callback (iOS 17.4+)Greatly improves reliability of Universal Link interception inside in-app browser. Set this whenever Universal Links are used.
let configuration = PONativeAlternativePaymentConfiguration(
...,
redirect: .init(callback: .https(host: "yourapp.com", path: "/"))
)4. Host a landing page at your return URL
Required for the web redirect fallback. The page must preserve query parameters from the incoming URL and redirect to a custom scheme deep link that your app handles. Include an explicit button - do not rely solely on automatic redirect.
5. Forward all incoming URLs to the SDK
In your SceneDelegate, forward both Universal Links and custom scheme deep links to ProcessOut.shared.processDeepLink(url:) as shown in Forwarding URLs to the SDK. Never strip or modify query parameters.
Updated about 1 hour ago
