> ## Documentation Index
> Fetch the complete documentation index at: https://primer.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Get started

> [tab] Web
>
> #### Install 3DS SDK
>
> > [!NOTE]
> >
> > There are no additional requirements to enable 3D Secure on Web. You are all set to create a payment with 3D Secure!
>
> #### Execute 3D Secure
>
> Universal Checkout drop-in and headless automatically renders the 3DS challenge when required by your workflow.
>
> #### Testing 3D Secure
>
> To validate your 3D Secure integration, you can use our dedicated testing guide, which includes sample cards,
> challenge flows, and different scenarios. For full details, see the [3DS Testing Guide](https://primer.io/docs/testing/3d-secure.md).

> [tab] iOS
>
> #### Install Primer3DS SDK
>
> > [!NOTE]
> >
> > 3D Secure on iOS requires the addition of the `Primer3DS` library to your project.
>
> ##### With CocoaPods
>
> First, modify your `Podfile` like so:
>
> ```code theme={"dark"}
> source 'https://github.com/CocoaPods/Specs.git'
> source 'https://github.com/primer-io/primer-podspecs.git'
>
> use_frameworks!
>
> target 'PrimerSDK_Example' do
>   pod 'PrimerSDK'
>   pod 'Primer3DS'
>     // ...
> end
> ```
>
> Then run `pod install` to install `Primer3DS` on your workspace.
>
> > [!NOTE]
> >
> > In case you encounter an error that the bundle needs signing, add the following post-install script in your podfile.
> >
> > ```ruby theme={"dark"}
> > post_install do |installer|
> >   installer.pods_project.targets.each do |target|
> >     if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle"
> >       target.build_configurations.each do |config|
> >           config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
> >       end
> >     end
> >   end
> > end
> > ```
>
> > [!CAUTION]
> >
> > In case you notice the warning "WARNING! Failed to import Primer3DS" when you initialize the `PrimerSDK`, add the following post-install script in the end of your pod file.
> >
> > ```ruby theme={"dark"}
> > target 'MyApp' do
> >   pod 'PrimerSDK'
> >   pod 'Primer3DS'
> >
> >   # ...
> >
> >   # This is what needs to be added
> >   post_install do |installer|
> >     installer.pods_project.targets.each do |target|
> >       if target.name == "PrimerSDK"
> >         target.build_configurations.each do |config|
> >           config.build_settings['OTHER_LDFLAGS'] = '$(inherited) -framework "Primer3DS"'
> >         end
> >       end
> >     end
> >   end
> > end
> > ```
>
> ##### With Swift Package Manager
>
> To add PrimerSDK with Swift Package Manager;
>
> 1. Select your project, and then navigate to `Package Dependencies`
>
> 2. Click on the **+** button at the bottom-left of the `Packages` section
>
> 3. Paste [https://github.com/primer-io/primer-sdk-3ds-ios](https://github.com/primer-io/primer-sdk-3ds-ios) into the **Search Bar**
>
> 4. Press **Add Package**
>
> 5. Let Xcode download the package and set everything up
>
>    ![Adding Primer 3DS](https://mintcdn.com/primer-cc826789/paB-PZurGrOqghVc/payment-services/3d-secure/ios/swift-package-manager-2.png?fit=max\&auto=format\&n=paB-PZurGrOqghVc\&q=85\&s=78b9678c30a49d53cb2773c37dbd9e43)
>
> > [!CAUTION]
> >
> > If `Primer3DS` is not installed, 3DS will fail. In the case of a 3DS triggered by the workflow, the `primerDidFailWithError` functions will be called.
>
> #### Interoperability matrix
>
> To ensure compatibility, please verify a supported Primer 3DS SDK [version](https://github.com/primer-io/primer-sdk-3ds-ios/tags) matches your current Primer SDK Version.
> Below are the supported interoperable versions:
>
> | Primer SDK version | Primer 3DS SDK version |
> | :- | :- |
> | `>= 2.44.0` | `>= 2.7.0` |
> | `2.43.0 - 2.44.0` | `2.6.0` |
> | `2.35.0 - 2.43.0` | `2.4.2 - 2.5.x` |
> | `2.24.0 - 2.34.0` | `2.3.0 - 2.4.1` |
> | `2.19.0 - 2.23.0` | `2.1.0 - 2.2.1` |
> | `<= 2.18.3` | `2.0.0 - 2.0.2` |
>
> #### Handle Out-of-Band (OOB) redirects (Optional)
>
> Starting from 3D Secure protocol version 2.2.0, you can enhance the user experience by implementing
> an automatic redirect from another (authentication) application during an OOB challenge to your application once the challenge
> is successfully completed. This feature allows for a seamless transition and improved user flow.
>
> > [!WARNING]
> >
> > If this feature is not implemented, the user will have to come back to your application manually to complete their payment, which adds significant friction.
>
> To enable this feature, ensure that you include the `threeDsAppRequestorUrl` parameter when configuring the `PrimerThreeDsOptions` object.
>
> Please note that the `threeDsAppRequestorUrl` value **must** be an [iOS Universal Link](https://developer.apple.com/ios/universal-links/).
> Additionally, it is essential that your application is configured to handle the Universal Link properly in order to facilitate the redirection.
>
> To configure the Universal Link correctly using Universal Checkout, follow these steps:
>
> 1. Pass your Universal Link (e.g. `https://{UNIVERSAL_LINK}`) as `threeDsAppRequestorUrl` in the `PrimerThreeDsOptions` object of your settings.
>
> ```swift theme={"dark"}
> let settings = PrimerSettings(
>   // ...
>   paymentMethodOptions: PrimerPaymentMethodOptions(
>     threeDsOptions: PrimerThreeDsOptions(
>       threeDsAppRequestorUrl: "https://{UNIVERSAL_LINK}"
>     ),
>   ),
>   // ...
> )
> ```
>
> 2. Implement the `application(_:continue:restorationHandler:) -> Bool` in your `AppDelegate` and call `Primer.shared.application(_:continue:restorationHandler:)` function.
>
> ```swift theme={"dark"}
> import PrimerSDK
> import UIKit
>
> @UIApplicationMain
> class AppDelegate: UIResponder, UIApplicationDelegate {
>
>   // ...
>
>   func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
>     return Primer.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
>   }
> }
> ```
>
> 3. Implement the `application(_:open:options:) -> Bool` in your `AppDelegate` and call `Primer.shared.application(_:continue:restorationHandler:)` function.
>
> ```swift theme={"dark"}
> import PrimerSDK
> import UIKit
>
> @UIApplicationMain
> class AppDelegate: UIResponder, UIApplicationDelegate {
>
>   // ...
>
>   func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
>     return Primer.shared.application(app, open: url, options: options)
>   }
> }
> ```
>
> #### Execute 3D Secure
>
> Universal Checkout drop-in and headless automatically render the 3DS challenge when required by your workflow.
>
> > [!WARNING]
> >
> > **Headless Mode UI Consideration**
> >
> > When using Headless Checkout, ensure no custom `UIWindow` instances, overlays, or modal presentations are active when 3DS authentication begins. The 3DS processing screen may appear behind your UI if custom window levels are in use.
> >
> > Drop-In Checkout handles this automatically.
>
> If your application is not installed from a trusted source (e.g. a debug version, not installed from the store, or used on a simulator), try to set
> `PrimerDebugOptions.is3DSSanityCheckEnabled` to `false`.
> Otherwise 3D Secure library initialization will fail due to security checks being performed.
>
> > [!WARNING]
> >
> > `is3DSSanityCheckEnabled` flag should only be used in development mode, and not in production release of your app.
>
> ```swift theme={"dark"}
> let settings = PrimerSettings(
>   // ...
>   debugOptions: PrimerDebugOptions(
>     is3DSSanityCheckEnabled: false
>   )
>   // ...
> )
> ```
>
> #### Troubleshooting
>
> * If you notice a console warning "Failed to import Primer3DS" on the SDK initialization, go to *Scheme settings* and select `Manual order`.
>
>   ![Dependencies](https://mintcdn.com/primer-cc826789/paB-PZurGrOqghVc/payment-services/3d-secure/ios/Dependencies.png?fit=max\&auto=format\&n=paB-PZurGrOqghVc\&q=85\&s=d09f2b4bc2b0a3811d18a2ea6c2c6a63)
>
> #### Testing 3D Secure
>
> To validate your 3D Secure integration, you can use our dedicated testing guide, which includes sample cards, challenge flows,
> and different scenarios. For full details, see the [3DS Testing Guide](https://primer.io/docs/testing/3d-secure.md).

> [tab] Android
>
> #### Install 3DS SDK
>
> > [!NOTE]
> >
> > 3D Secure on Android requires the addition of the `io.primer:3ds-android` library to your project.
>
> Amend the dependencies section of your app's `build.gradle` to include the `3ds-android` library:
>
> ```kotlin Kotlin theme={"dark"}
> dependencies {
>     implementation(platform("io.primer:bom:<version>"))
>     implementation("io.primer:android")
>     implementation("io.primer:3ds-android")
> }
> ```
>
> ```groovy Groovy theme={"dark"}
> dependencies {
>     implementation platform('io.primer:bom:<version>')
>     implementation 'io.primer:android'
>     implementation 'io.primer:3ds-android'
> }
> ```
>
> > [!NOTE]
> >
> > Replace `<version>` with your Primer SDK version. The BOM sets the library version, so leave it out. [Version alignment](https://primer.io/docs/sdk/android/v2.x.x/installation.md#version-alignment) explains how versions are set, including on older SDK versions.
>
> #### Interoperability matrix
>
> Primer SDK internally uses Primer 3DS SDK as a `compile` time dependency. In order for the SDKs to work properly,
> the versions used internally and the one imported to your code **must** match. From SDK 2.54.0, Gradle aligns them for you.
> On earlier versions, use the BOM or the version from this table:
>
> | Primer SDK version | Primer 3DS SDK version |
> | :- | :- |
> | `2.54.0+` | Same as the Primer SDK version |
> | `2.53.1` | `1.9.0` |
> | `2.47.0 - 2.53.0` | `1.8.0` |
> | `2.46.0 - 2.47.0` | `1.7.0` |
> | `2.41.0 - 2.45.1` | `1.6.2` |
> | `2.32.0 - 2.40.1` | `1.5.0` |
> | `2.27.6 - 2.31.0` | `1.4.3` |
> | `2.27.0 - 2.27.5` | `1.4.2` |
> | `2.25.0 - 2.27.0` | `1.4.1` |
> | `2.24.0 - 2.25.0` | `1.4.0` |
> | `2.21.0 - 2.24.0` | `1.3.0` |
> | `2.17.2 - 2.20.0` | `1.2.0` |
> | `2.16.0 - 2.17.1` | `1.1.2` |
> | `2.15.0 - 2.15.1` | `1.1.1` |
> | `2.0.0 - 2.14.1` | `1.1.0` |
>
> To validate that the 3DS SDK is imported correctly:
>
> 1. Clean and sync your project
> 2. Validate that library can be found in `External Libraries` section (if you use Android Studio)
>
>    ![Add 3DS Android](https://mintcdn.com/primer-cc826789/paB-PZurGrOqghVc/payment-services/3d-secure/android/add_3ds_android.png?fit=max\&auto=format\&n=paB-PZurGrOqghVc\&q=85\&s=749d49c1cb6a8ef28502c087eefb3f7f)
>
> #### Handle Out-of-Band (OOB) redirects (Optional)
>
> Starting from 3D Secure protocol version 2.2.0, you can enhance the user experience by implementing
> an automatic redirect from another (authentication) application during an OOB challenge to your application once the challenge
> is successfully completed. This feature allows for a seamless transition and improved user flow.
>
> > [!WARNING]
> >
> > If this feature is not implemented, the user will have to come back to your application manually to complete their payment, which adds significant friction.
>
> To enable this feature, ensure that you include the `threeDsAppRequestorUrl` parameter when configuring the `PrimerThreeDsOptions` object.
>
> Please note that the `threeDsAppRequestorUrl` value **must** be a [Android App Link](https://developer.android.com/training/app-links).
> Additionally, it is essential that your application is configured to handle the App Link properly in order to facilitate the redirection.
>
> To configure the App Link correctly using Universal Checkout, follow these steps:
>
> 1. Add the following to your `AndroidManifest.xml` file:
>
> ```xml theme={"dark"}
> <activity
>   android:name="io.primer.android.threeds.ui.ThreeDsActivity"
>   android:exported="true"
>   tools:node="merge">
>   <intent-filter
>     android:autoVerify="true"
>     tools:targetApi="m">
>     <action android:name="android.intent.action.VIEW" />
>
>     <category android:name="android.intent.category.DEFAULT" />
>     <category android:name="android.intent.category.BROWSABLE" />
>
>     <data
>       android:host="{yourdomain.com}"
>       android:pathPrefix="/3ds"
>       android:scheme="https" />
>   </intent-filter>
> </activity>
> ```
>
> 2. Replace the value of `android:host` with your web domain name, ensuring not to modify any other configuration
> 3. Once you've made the necessary changes, verify the App Link configuration by following the guidelines provided in the [Android documentation](https://developer.android.com/training/app-links/verify-android-applinks).
> 4. Pass your App Link (e.g. `https://{yourdomain.com}/3ds`) as `threeDsAppRequestorUrl` in the `PrimerThreeDsOptions` object of your settings.
>
> ```kotlin theme={"dark"}
> val settings = PrimerSettings(
>   // ...
>   paymentMethodOptions = PrimerPaymentMethodOptions(
>     threeDsOptions = PrimerThreeDsOptions("https://{yourdomain.com}/3ds")
>   )
>   // ...
> )
> ```
>
> #### Execute 3D Secure
>
> Universal Checkout drop-in and headless automatically render the 3DS challenge when required by your workflow.
>
> If your application is not installed from a trusted source (e.g. a debug version, not installed from the store, or used on an emulator), try to set
> [`PrimerDebugOptions.is3DSSanityCheckEnabled`](https://primer.io/docs/sdk/android/v2.x.x/common-objects/PrimerSettings#param-is3-ds-sanity-check-enabled) to `false`.
> Otherwise 3D Secure library initialization will fail due to security checks being performed.
>
> > [!CAUTION]
> >
> > `is3DSSanityCheckEnabled` flag should only be used in development mode, and not in production release of your app.
>
> #### Testing 3D Secure
>
> To validate your 3D Secure integration, you can use our dedicated testing guide, which includes sample cards,
> challenge flows, and different scenarios. For full details, see the [3DS Testing Guide](https://primer.io/docs/testing/3d-secure.md).

> [tab] React Native
>
> #### Install 3DS SDK
>
> > [!NOTE]
> >
> > 3D Secure on React Native requires the addition of the 3DS SDK on iOS and Android.
>
> ##### On iOS
>
> Adding 3D Secure to iOS via React Native requires the addition of the `Primer3DS` pod to your Podfile.
>
> Depending on how you are using CocoaPods, you may need to add additional configuration to your Podfile. We support three methods for integration: **static library**, **dynamic framework** and **static framework**.
>
> You can check which of the three your project is using by running `bundle exec pod install` in the `ios` folder of your project and checking the output.
>
> e.g.
>
> ```shell theme={"dark"}
> bundle exec pod install
> Framework build type is static library
> ...
> ```
>
> ###### Using static libraries
>
> By default, react native apps link pods as static libraries. You can check if your app is using static libraries by running `bundle exec pod install`. If it is, you should see the following first line of output:
>
> ```shell theme={"dark"}
> bundle exec pod install
> Framework build type is static library
> ....
> ```
>
> To correctly link the 3DS pod as a static library, open `Podfile` inside the `ios` directory of your React Native project in a text editor, then add the following:
>
> ```ruby theme={"dark"}
> target 'MyApp' do
>
>   # ... other CocoaPods config ...
>
>   pod 'Primer3DS'
>
>   post_install do |installer|
>
>     # ... other post_install step config ...
>
>     # Add this block, taking care to choose the correct config.build_settings['OTHER_SWIFT_FLAGS'] based on the directive below.
>     installer.pods_project.targets.each do |target|
>       if target.name == "primer-io-react-native" || target.name == "PrimerSDK"
>         target.build_configurations.each do |config|
>           config.build_settings['FRAMEWORK_SEARCH_PATHS'] = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/Primer3DS"
>           config.build_settings['LIBRARY_SEARCH_PATHS'] = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/Primer3DS"
>           config.build_settings['SWIFT_INCLUDE_PATHS'] = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/Primer3DS"
>
>           # Note, depending on your integration type, you must choose one of the following settings:
>           # If you are using frameworks, add the following line
>           config.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited) -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Primer3DS/Primer3DS.modulemap"'
>
>           # If you are using static libraries, instead add this line
>           config.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited) -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Primer3DS/Primer3DS.framework/Modules/Primer3DS.modulemap"'
>
>           config.build_settings['OTHER_LDFLAGS'] = '$(inherited) -weak_library -l"Primer3DS"'
>         end
>       end
>     end
>
>     # ... other post_install step config ...
>
>   end
>
> end
> ```
>
> Finally run `bundle exec pod install` to finish setting up.
>
> ###### Using dynamic frameworks
>
> Although React Native uses static libraries by default, native iOS apps commonly use dynamic frameworks. You can check if your app is using dynamic frameworks by running `bundle exec pod install`. If it is, you should see the following first line of output:
>
> ```shell theme={"dark"}
> bundle exec pod install
> Configuring Pod with dynamically linked Frameworks
> ...
> ```
>
> To correctly link the 3DS pod as a dynamic framework, simply add it to the `Podfile` inside the `ios` directory of your React Native project using a text editor:
>
> ```ruby theme={"dark"}
> target 'MyApp' do
>
>   # ... other RN iOS config ...
>
>   pod 'Primer3DS'
>
> end
> ```
>
> Finally run `bundle exec pod install` to finish setting up.
>
> As it is dynamically linked, it will automatically be detected by our iOS SDK at runtime, so no additional config is needed.
>
> ###### Using static frameworks
>
> Static frameworks are a less common use case, but we are able to support it by configuring your Podfile to allow a mix of statically and dynamically linked frameworks, with the 3DS pod being linked dynamically.
>
> You can check if your app is using static frameworks by running `bundle exec pod install`. If it is, you should see the following first line of output:
>
> ```shell theme={"dark"}
> bundle exec pod install
> Configuring Pod with statically linked Frameworks
> ...
> ```
>
> > [!WARNING]
> >
> > Note: it might be that your `Podfile` is overriding the `use_frameworks` directive elsewhere, in which case the above shell output may appear incorrect.
> >
> > Check for the following in the app target of your `Podfile`:
> >
> > ```ruby theme={"dark"}
> > use_frameworks! :linkage => :static
> > ```
> >
> > If this is present, then you are using static frameworks by default, even if the shell output for `bundle exec pod install` says differently.
>
> Because the 3DS pod is resolved by our SDK at runtime, an additional plugin is required to ensure that it can be loaded correctly.
>
> Start by adding the following to the end of the `Gemfile` in the root of your app repo:
>
> ```ruby theme={"dark"}
> gem 'cocoapods-pod-linkage'
> ```
>
> Then, from the same folder (root of your app repo), run `bundle install` in a terminal:
>
> ```shell theme={"dark"}
> bundle install
> Fetching gem metadata from https://rubygems.org/.......
> Resolving dependencies...
> Fetching cocoapods-pod-linkage 0.0.1
> Installing cocoapods-pod-linkage 0.0.1
> Bundle complete! 3 Gemfile dependencies, 40 gems now installed.
> Bundled gems are installed into `./vendor/bundle`
> ```
>
> Add the plugin to your `Podfile` by including the line:
>
> ```ruby theme={"dark"}
> plugin 'cocoapods-pod-linkage'
> ```
>
> e.g.
>
> ```ruby theme={"dark"}
> linkage = ENV['USE_FRAMEWORKS']
> if linkage != nil
>   Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
>   use_frameworks! :linkage => linkage.to_sym
> end
>
> # 👇 Add this line here, below the framework linkage check
> plugin 'cocoapods-pod-linkage'
> ```
>
> Then, add the SDK and 3DS pods to your app target in the `Podfile`:
>
> ```ruby theme={"dark"}
>
> # ℹ️ This is already present if you are using static frameworks
> # If this is not present then the USE_FRAMEWORKS environmental variable will be set to `static`
> use_frameworks! :linkage => :static
>
> target 'MyApp' do
>
>   # ... other CocoaPods config ...
>
>   # 👇 Add these lines to ensure both the SDK pod and 3DS pod are linked dynamically
>   pod 'PrimerSDK', :linkage => :dynamic
>   pod 'Primer3DS', :linkage => :dynamic
>
> end
> ```
>
> Then, add the following to the `post_install` block:
>
> ```ruby theme={"dark"}
> target 'MyApp' do
>
>   # ... other CocoaPods config ...
>
>   post_install do |installer|
>
>     # ... other post_install step config ...
>
>     # Add this entire block
>     installer.pods_project.targets.each do |target|
>       if target.name == "primer-io-react-native" || target.name == "PrimerSDK"
>         target.build_configurations.each do |config|
>           config.build_settings['FRAMEWORK_SEARCH_PATHS'] = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/Primer3DS"
>           config.build_settings['LIBRARY_SEARCH_PATHS'] = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/Primer3DS"
>           config.build_settings['SWIFT_INCLUDE_PATHS'] = "$(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/Primer3DS"
>           config.build_settings['OTHER_LDFLAGS'] = '$(inherited) -framework Primer3DS'
>         end
>       end
>     end
>
>     # ... other post_install step config ...
>
>   end
>
> end
> ```
>
> Note: We recommend putting the above immediately after the call to `react_native_post_install`.
>
> Finally, run `bundle exec pod install` to finish setting up.
>
> ##### On Android
>
> 3D Secure on Android requires the addition of the `io.primer:3ds-android` library to your project.
>
> 1. Navigate to the `./android` directory in your React Native project.
>
> 2. Amend the dependencies section of your app's `build.gradle` to include the `3ds-android` library:
>
>    ```groovy build.gradle theme={"dark"}
>    dependencies {
>      /* Other dependencies... */
>      implementation 'io.primer:3ds-android'
>    }
>    ```
>
> > [!NOTE]
> >
> > Leave out the version. From React Native SDK 2.49.0, the SDK sets it for you. On earlier versions, see [Android library versions](https://primer.io/docs/sdk/react-native/v2.x.x/installation.md#android-library-versions).
>
> #### Interoperability matrix
>
> Primer SDK internally uses Primer 3DS SDK as a `compile` time dependency. In order for the SDKs to work properly,
> the versions used internally and the one imported to your code **must** match.
>
> Here is a breakdown of supported interoperable versions:
>
> | Primer React Native SDK version | Primer 3DS Android SDK version | Primer 3DS IOS SDK version |
> | :- | :- | :- |
> | `>= 2.49.0` | Set by the SDK | `>= 2.7.0` |
> | `2.48.0` | `1.9.0` | `>= 2.7.0` |
> | `2.42.0 - 2.47.1` | `1.8.0` | `>= 2.7.0` |
> | `2.41.0 - 2.42.0` | `1.7.0` | `2.6.0 - 2.7.0` |
> | `2.35.0 - 2.40.0` | `1.6.2` | `2.4.2 - 2.5.x` |
> | `2.34.1 - 2.35.0` | `1.6.2` | `2.3.0 - 2.4.2` |
> | `2.27.2 - 2.34.0` | `1.5.0` | `2.3.0 - 2.4.2` |
> | `2.24.0 - 2.27.1` | `1.4.3` | `2.3.0 - 2.4.2` |
> | `2.21.0 - 2.23.0` | `1.4.2` | `2.3.0 - 2.4.2` |
> | `2.20.0` | `1.4.0` | `2.1.0 - 2.2.1` |
> | `2.19.0 - 2.19.2` | `1.3.0` | `2.1.0 - 2.2.1` |
> | `2.17.2 - 2.18.0` | `1.2.0` | `2.0.0 - 2.0.2` |
> | `2.16.0 - 2.17.1` | `1.1.2` | `2.0.0 - 2.0.2` |
> | `2.15.0 - 2.15.1` | `1.1.1` | `2.0.0 - 2.0.2` |
>
> #### Handle Out-of-Band (OOB) redirects (Optional)
>
> Starting from 3D Secure protocol version 2.2.0, you can enhance the user experience by implementing
> an automatic redirect from another (authentication) application during an OOB challenge to your application once the challenge
> is successfully completed. This feature allows for a seamless transition and improved user flow.
>
> > [!WARNING]
> >
> > If this feature is not implemented, the user will have to come back to your application manually to complete their payment, which adds significant friction.
>
> To enable this feature, ensure that you include the `threeDsAppRequestorUrl` parameter when configuring the `threeDsOptions`
> property of your settings for each platform.
>
> Please note that the `ios.threeDsAppRequestorUrl` value **must** be an [iOS Universal Link](https://developer.apple.com/ios/universal-links/) and the `android.threeDsAppRequestorUrl` value **must** be an [Android App Link](https://developer.android.com/training/app-links) in order to facilitate the redirection.
>
> To configure the Universal Link correctly using Universal Checkout, follow these steps:
>
> 1. Pass your iOS Universal Link (e.g. `https://{UNIVERSAL_LINK}`) as `threeDsAppRequestorUrl`, and your Android App Link
>    (e.g. `https://{yourdomain.com}/3ds`) in the `threeDsOptions` object of your settings.
>
> ```tsx theme={"dark"}
> const settings: PrimerSettings = {
>   // ...
>   paymentMethodOptions: {
>     threeDsOptions: {
>       iOS?: {
>         threeDsAppRequestorUrl?: string;
>       }
>       android?: {
>         threeDsAppRequestorUrl?: string;
>       }
>     },
>     // ...
>   }
> }
> ```
>
> 2. Follow Step 2 & 3 from the [iOS guide](https://primer.io/docs/payment-services/3d-secure/get-started.md#handle-out-of-band-oob-redirects-optional).
>
> 3. Follow Steps 1 to 3 from the [Android guide](https://primer.io/docs/payment-services/3d-secure/get-started.md#handle-out-of-band-oob-redirects-optional-2).
>
> #### Execute 3D Secure
>
> Universal Checkout drop-in and headless automatically render the 3DS challenge when required by your workflow.
>
> If this application is not installed from a trusted source (e.g. a debug version, not installed from store, or used on an emulator), try to set
> [`PrimerDebugOptions.is3DSSanityCheckEnabled`](https://primer.io/docs/sdk/react-native/v2.x.x/common-objects/PrimerSettings#param-is3-ds-sanity-check-enabled) to `false`.
> Otherwise 3D Secure library initialization will fail due to security checks being performed.
>
> > [!CAUTION]
> >
> > `is3DSSanityCheckEnabled` flag should only be used in development mode, and not in production release of your app.
>
> ```tsx theme={"dark"}
> const settings: PrimerSettings = {
> 	// ...
> 	debugOptions: {
> 		is3DSSanityCheckEnabled: true,
> 	},
> }
> ```
>
> #### Testing 3D Secure
>
> To validate your 3D Secure integration, you can use our dedicated testing guide, which includes sample cards,
> challenge flows, and different scenarios. For full details, see the [3DS Testing Guide](https://primer.io/docs/testing/3d-secure.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.