Configure 3D Secure for your Primer account
Follow the below process to start using 3DS on sandbox immediately. Do note that for 3DS to work in production, you will need to complete the process described in step 4.
To get 3DS configured and running, you need to:
- 1Set up your workflow
- 2Configure your Client Session
- 3Handle 3DS in Universal Checkout
- 4Onboard your 3DS profile to go live
1. Set up your workflow
Configuring 3DS settings for your payments takes place within the "Authorize payment" Action. Learn more here about how to set up a workflow to process payments.
In the configuration panel, you need to choose which 3DS option you want for all payments processed by this Action block:
No 3DS
3DS will not be used for any payments processed by this block. Payments will be declined when the Issuer requires authentication.
Adaptive 3DS
Use Primer’s proprietary Adaptive 3DS which will only carry out 3DS authentication if the payment would be declined without it.
Primer 3DS
3DS authentication will be handled by Primer's agnostic 3DS solution for payments processed by this block. This could either be a challenge or frictionless.
Processor 3DS
Your processor will present a 3DS challenge according to their configuration. This isn't compatible with Fallbacks as Primer is not involved in the flow.
2. Configure your Client Session
You need to pass the following field in POST/client-session
:
Field | Description | Required |
---|---|---|
| The customer's email address | Yes |
To improve 3DS success rates, it is recommended to pass the following field in POST/client-session
:
Field | Description | Required |
---|---|---|
The customer's billing address | Recommended |
In Sandbox, both the email address and billing address must be provided to trigger 3DS.
3. Handle 3DS in Universal Checkout
Install 3DS SDK
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.
123
❯ bundle exec pod installFramework 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:
123
❯ bundle exec pod installFramework 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:
1234567891011121314151617181920212223242526272829303132333435
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:
123
❯ bundle exec pod installConfiguring 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:
1234567
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:
123
❯ bundle exec pod installConfiguring Pod with statically linked Frameworks...
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
:
1
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:
1
gem 'cocoapods-pod-linkage`
Then, from the same folder (root of your app repo), run bundle install
in a terminal:
1234567
❯ bundle installFetching gem metadata from https://rubygems.org/.......Resolving dependencies...Fetching cocoapods-pod-linkage 0.0.1Installing cocoapods-pod-linkage 0.0.1Bundle 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:
1
plugin 'cocoapods-pod-linkage'
e.g.
12345678
linkage = ENV['USE_FRAMEWORKS']if linkage != nil Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green use_frameworks! :linkage => linkage.to_symend # 👇 Add this line here, below the framework linkage checkplugin 'cocoapods-pod-linkage'
Then, add the SDK and 3DS pods to your app target in the Podfile
:
12345678910111213
# ℹ️ 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:
12345678910111213141516171819202122232425
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 the3ds-android
library. Paste this code, make sure to replacesupported-3ds-sdk-version
with the right value. See the table below to get the correct one:12345
dependencies { /* Other dependencies... */ implementation "io.primer:3ds-android:{supported-3ds-sdk-version}"}
bashcopy
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:
Android
Primer SDK version | Primer 3DS SDK version |
---|---|
2.27.6+ | 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 |
iOS
Primer SDK version | Primer 3DS SDK version |
---|---|
>= 2.19.0 | >= 2.1.0 |
<= 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.
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 and the android.threeDsAppRequestorUrl
value must be an Android App Link in order to facilitate the redirection.
To configure the Universal Link correctly using Universal Checkout, follow these steps:
1234567891011121314
const settings: PrimerSettings = { // ... paymentMethodOptions: { threeDsOptions: { iOS?: { threeDsAppRequestorUrl?: string; } android?: { threeDsAppRequestorUrl?: string; } }, // ... }}
- 3
Follow Step 2 & 3 from the iOS guide.
- 4
Follow Steps 1 to 3 from the Android guide.
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
to false
.
Otherwise 3D Secure library initialization will fail due to security checks being performed.
is3DSSanityCheckEnabled
flag should only be used in development mode, and not in production release of your app.
123456
const settings: PrimerSettings = { // ... debugOptions: { is3DSSanityCheckEnabled: true, },}
4. Onboard your 3DS profile to go live
Before going live with 3DS on Primer, your account has to be configured with your 3DS profile(s). This 3DS profile consists of the following fields for each card network:
- Acquirer Merchant ID (MID)
- Acquirer BIN
- Merchant Category Code (MCC)
Please reach out to us directly via our Service Desk to configure this. If you don’t have access, please contact your account administrator for assistance.
Test 3D Secure
Monitor 3DS
You can monitor 3DS on Primer in three main ways:
- Payment status update webhook
- Payments API
- Payment timeline
1. Payment status update webhook
Subscribe to the payment status update webhook to receive notification updates each time your payment changes status.
As part of the webhook body, the threeDSecureAuthentication
object is included detailing the outcome. Below is an example of this object for a successful 3DS authentication:
12345
{ "responseCode": "AUTH_SUCCESS", "protocolVersion": "2.2.0", "challengeIssued": true}
2. Payments API
Using Primer's Payments API, you can retrieve the payment object, where the threeDSecureAuthentication
object is included detailing the outcome. This is available in the GET/payments/{paymentId}
request, alongside POST/payments
.
Below is an example for an unsuccessful 3DS authentication:
1234567
{ "responseCode": "AUTH_FAILED", "reasonCode": "CARD_AUTHENTICATION_FAILED", "reasonText": "Card Authentication Failed", "protocolVersion": "2.1.0", "challengeIssued": true}
3. Payment timeline
You can see all your Primer payments from the Payments timeline in the Primer Dashboard.
Navigate to the specific payment detailed timeline page. You will see the 3DS authentication event. Select this event to open the side drawer that contains the data tied to this 3DS event.