We have released a new version. Documentation for our latest version can be found here.
Last Updated: 08 October 2024 | Change Log
Challenge Display & Verification
If the authentication response outcome
is challenged
and the authentication.version
is 2.x.x
(3DS2) you can use the SDK to provide the improved 3DS2 Challenge display for mobile devices.
If the authentication.version
is 1.x.x
(3DS1) you must follow the 3DS1 Challenge display. The integration more closely follows the steps for web.
3DS2 Challenge display
If the authentication.version
is 2.x.x
you will need the following values from the authentication response to use in the SDK.
Access Name | Value from | Cardinal SDK Name |
---|---|---|
challenge.reference | authentication response | transactionId |
challenge.payload | authentication response | payload |
The Access 3DS API will be periodically tested against the latest version of the Cardinal SDK. Current tested Cardinal SDK version: v2.2.5
SDK challenge display:
Customize Challenge Interface
As part of SDK setup you can customize the challenge user interface
3DS1 Challenge display
If the authentication.version
is 1.x.x
use the following steps to display the challenge screen.
3DS version 1 was implemented by issuers long before smartphones existed so offers a degraded experience compared to version 2. We expect version 1 traffic from issuers to drop during 2021.
Challenge form (webView)
POST the request to the challenge.url
with the challenge.jwt
and optional MD
.
The MD
field allows you to pass url parameters (max 1024 characters) in the challenge form that is included/echoed in the response url (challenge.returnUrl
).
iOS
Add a WKWebView to your Storyboard and UIViewController and enable JavaScript
@IBOutlet var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() webView.configuration.preferences.javaScriptEnabled = true }
Implement a method similar to the code snippet below in your UIViewController
let iframeSrcDoc = """ <html> <body onload='document.frmLaunch.submit();'> <form name='frmLaunch' method='POST' action='\(challengeUrl)'> <input type='hidden' name='JWT' value='\(jwt)'> <input type='hidden' name='MD' value='\(md)'> </form> </body> </html> """ // A viewport meta tag is used to scale the content nicely to the device's screen size let html = """ <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <iframe srcdoc="\(iframeSrcDoc)" width="100%" height="400" frameborder="0"> </iframe> </body> </html> """ webView.loadHTMLString(html, baseURL: URL(string: "about:srcdoc")!)
Android
Add a WebView to your fragment and enable JavaScript
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val webView = view.findViewById<WebView>(...) webView.settings.javaScriptEnabled = true }
Implement a method similar to the code snippet below in your Fragment
val iframeSrcDoc = """ <html> <body onload='document.frmLaunch.submit();'> <form name='frmLaunch' method='POST' action='$challengeUrl'> <input type='hidden' name='JWT' value='$jwt'> <input type='hidden' name='MD' value='$md'> </form> </body> </html> """ // A viewport meta tag is used to scale the content nicely to the device's screen size val html = """ <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <iframe srcdoc="$iframeSrcDoc" width="100%" height="400" frameborder="0"> </iframe> </body> </html> """ webView.loadData(html, "text/html; charset=utf-8", "UTF-8")
Intercept challenge return
Intercept the POST request to your challenge.returnUrl
iOS
Have your UIViewController adopt the WKNavigationDelegate protocol
Point the navigationDelegate property of your WKWebView to your UIViewController, just before the call to webView.loadHTMLString
webView.navigationDelegate = self
Implement the following method in your UIViewController to be notified when the challenge has been completed
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { if navigationAction.request.url!.absoluteString == "<value of your challenge return url>" { // TODO: add your logic } decisionHandler(.allow) }
Android
Intercept the POST request to your challenge return urlCreate a class that extends WebViewClient and override the onLoadResource method to be notified when the challenge has been completed
private class CustomWebViewClient: WebViewClient() { override fun onLoadResource(view: WebView?, url: String?) { if (url.toString() == "<value of your challenge return url>") { // TODO: add your logic } super.onLoadResource(view, url) } }
Set the webViewClient property of your WebView to an instance of this class, just before the call to webView.loadData()
webView.webViewClient = CustomWebViewClient()
Verification
Once the challenge has been completed, a verification request needs to be made to verify the result of the challenge.
You should only request the verification from your backend system, not call it directly from the mobile application using the Access credentials.
POST your verification request to our 3ds:verify
action link received in your authentication response.
Verification example request
You must use v2
and later of the API for the Android/iOS SDK
POST https://try.access.worldpay.com/verifications/customers/3ds/verification
Verification request body:
{ "transactionReference": "unique-transactionReference", "merchant": { "entity": "default" }, "challenge": { "reference": "123456789" } }
Verification responses
Here are examples of the verification responses you would receive.
{ "outcome": "authenticated", "transactionReference": "unique-transactionReference", "authentication": { "version": "2.1.0", "authenticationValue": "MAAAAAAAAAAAAAAAAAAAAAAAAAA=", "eci": "05", "transactionId": "c5b808e7-1de1-4069" } }
Use the values: version
, authenticationValue
, eci
, transactionId
from the request when authorizing a payment. The values prove that the verification was successful, and that the fraud liability has shifted to the issuer.
Parameter | Description |
---|---|
authentication.version | The version of 3DS used to process the transaction. Note Required for Mastercard's Identity Check transactions in Authorization. |
authentication.authenticationValue | A cryptographic value that provides evidence of the outcome of a 3DS verification.
Used when authorizing a payment. |
authentication.eci | Electronic Commerce Indicator (ECI). Indicates the outcome of the 3DS authentication.
You will need to use this when you are authorizing a payment. |
authentication.transactionId | A transaction identifier. If provided, you should use it as part of your payment authorization. If the authentication.version has a major version of:
|
Next steps