For any question, we are one click away

Contact us

3DS2 SDK process

The diagram below shows the 3DS2 SDK payment process.

Be aware that many issuers' ACS don't work properly with 3DS Mobile SDKs.

sequenceDiagram participant MA as Mobile App participant MS as Mobile Server participant SDK2 as 3DS2 SDK participant PG as Payment Gateway participant 3DS as 3DSS/ACS/DS MA ->> MS: 1. client creates an Order MS ->> PG: 2. register order via API PG -->> MS: 3. unique order number (mdOrder) MA ->> MA: 4. client enters data MA ->> MS: 5. send payment data to server MS ->> PG: 6. call payment API with threeDSSDK alt Payment finished PG -->> MS: 7. response with payment status (go to 22) else 3DS2 required PG -->> MS: 8. response with 3DS2 SDK keys MS ->> MA: 9. send keys to Mobile App MA ->> SDK2: 10. init 3DS2 SDK SDK2 -->> MA: 11. collect device data MA ->> MS: 12. send device data MS ->> PG: 13. second payment API call PG -->> MS: 14. acs signed content MS ->> MA: 15. send acs data MA ->> SDK2: 16. init Challenge flow SDK2 ->> ACS: 17. communicates via CReq/CRes ACS -->> PG: 18. confirms transaction with AReq SDK2 -->> MA: 19. 3DS procedure is over MS ->> PG: 20. finish 3DS2 payment PG ->> PG: 21. make payment end opt Callback is configured PG -->> MS: 22. callback notification end MS ->> PG: 23. check payment status MS ->> MA: 24. show payment result to Client
  1. Client creates an Order
  2. Mobile Server registers that order in Payment Gateway via register.do.
  3. Mobile Server receives a unique order number mdOrder in response.
  4. Client fills in payment data
  5. Mobile App sends payment data to Mobile Server
  6. Mobile Server uses that payment data to make a payment via paymentorder.do request
    • Send threeDSSDK=true to indicate that 3DS2 SDK should be used
  7. Mobile Server gets a response with no ACS keys. It means that payment is completed and we need to go to step 22
  8. Mobile Server gets a response with ACS keys.
    • Response must contain threeDSServerTransId and threeDSSDKKey
    • Response should not contain threeDSMethodURL which is used in case of browser based redirect to ACS
  9. Mobile Server sends 3DS2 SDK data to Mobile App
  10. Mobile App initiates 3DS2 SDK via createTransaction method
    • directoryServerID depends on Payment System (for tests A000000003 can be used)
    • messageVersion is 2.1.0 for now
    • pemPublicKeyfor Android and for iOS is a pem certificate that is got in response in threeDSSDKKey on step 10
    • dsRootfor Android and for iOS depends on Payment System. Download test key
  11. 3DS2 SDK collects device data and encrypts it
  12. Mobile App sends encrypted device data to Mobile Server
  13. Mobile Server initiates second payment API call via paymentorder.do request
    • sdkEncData encrypted device data that is returned in createTransaction method in 3DS2 SDK
    • threeDSServerTransactionID is returned in response to first payment call on step 10 in threeDSServerTransId parameter
    • threeDSSDKReferenceNumber is returned in createTransaction method in 3DS2 SDK
    • sdkEphemPubKey is returned in createTransaction method in 3DS2 SDK
    • sdkAppID is returned in createTransaction method in 3DS2 SDK
    • sdkTransID is returned in createTransaction method in 3DS2 SDK
  14. Payment Gateway returns new special parameters for 3DS2 SDK
  15. Mobile Server sends those parameters to Mobile App
  16. Mobile App initiates challenge flow via doChallenge method
    • doChallenge acsTransactionIDparameter corresponds to threeDSAcsTransactionId in Payment Gateway response
    • doChallenge acsRefNumberparameter corresponds to threeDSAcsRefNumber in Payment Gateway response
    • doChallenge acsSignedContentparameter corresponds to threeDSAcsSignedContent in Payment Gateway response
    • doChallenge 3DSServerTransactionIDparameter corresponds to threeDSServerTransId in Payment Gateway response
  17. 3DS2 SDK communicates with issuers ACS via CReq/CRes API until Client confirms his payment
  18. ACS sends RReq to Payment Gateway to confirm or reject the payment
  19. 3DS2 SDK informs Mobile App that 3DS2 flow is over via ChallengeStatusReceiver
  20. Mobile Server finalizes the payment with finish3dsVer2Payment.do
  21. Payment Gateway makes a payment
  22. Payment Gateway sends callback notification to Merchant server if it's configured for merchant
  23. Mobile Server checks the final payment status via getOrderStatusExtended.do
  24. Mobile App shows payment result to client

IOS

iOS Integration

For integration SDK ThreeDS:

Image 1. Adding the ThreeDSSDK.framework file


Image 2. Adding the ThreeDSSDK.framework file


iOS Configuration

Example ThreeDSSDK

Full example you can find: TransactionManager

import UIKit
import ThreeDSSDK

....

var _service: ThreeDS2Service = Ecom3DS2Service()

// Init ThreeDS SDK try _service.initialize(configParameters: ConfigParameters(), locale: Locale.current.languageCode, uiCustomization: _setUpTheme()) var _sdkTransaction = try _service.createTransaction(directoryServerID: "", messageVersion: nil, publicKeyBase64: "", rootCertificateBase64: "", logoBase64: "")

// get progress view var _sdkProgressDialog = try _sdkTransaction!.getProgressView()

// Show progress dialog _sdkProgressDialog?.show()

// get authentication request parameters, to be sent to the payment gateway var authParameters = _sdkTransaction!.getAuthenticationRequestParameters() var deviceData = authParameters.getDeviceData() var ephemeralPublickKey = authParameters.getSDKEphemeralPublicKey() var threeDSSDKAppId = authParameters.getSDKAppID() var threeDSSDKTransId = authParameters.getSDKTransactionID()

// if you get error during initial sdk, you can close spinner. // _sdkProgressDialog?.close()

// Set challenge parameters and start challenge flow let challengeParameters = ChallengeParameters() challengeParameters.setAcsSignedContent("acsSignedContent") challengeParameters.setAcsRefNumber("acsReferenceNumber") challengeParameters.setAcsTransactionID("acsTransID") challengeParameters.set3DSServerTransactionID("threeDSServerTransID") // Start challenge flow self._sdkTransaction?.doChallenge(challengeParameters: challengeParameters, challengeStatusReceiver: self, timeOut: 5)

// If you get error during sdk flow, you can finish sdk transaction // _sdkTransaction?.close()

// Delegate functions extension TransactionManager: ChallengeStatusReceiver { public func completed(completionEvent e: CompletionEvent) {} public func cancelled() {} public func timedout() {} public func protocolError(protocolErrorEvent e: ProtocolErrorEvent) {} public func runtimeError(runtimeErrorEvent: RuntimeErrorEvent) {} }

Android

Android integration

Connecting the 3DS2 library

You need to add the sdk_threeds-release.aar library file to the libs folder, then specify the dependency on the added library.

In SDK versions <= 2.5.5 add the sdk_listeners_android.jar file to the libs folder. Since SDK 2.5.6 there is no need to add the sdk_listeners_android.jar file.

build.gradle.kts

    allprojects {
    repositories {
       // ...
       flatDir {
          dirs("libs")
       }
    }
}

dependencies { // dependency for connecting the confirmation functionality via 3DS implementation(group = "", name = "sdk_threeds-release", ext = "aar") implementation("com.google.code.gson:gson:2.8.5") implementation("com.squareup.okhttp3:okhttp:3.11.0") implementation("com.google.android.gms:play-services-ads:17.2.1") implementation("com.google.android.gms:play-services-location:16.0.0") }

build.gradle

    allprojects {
    repositories {
       // ...
       flatDir {
          dirs 'libs'
       }
    }
}

dependencies { // dependency for connecting the confirmation functionality via 3DS implementation(group = "", name = "sdk_threeds-release", ext = "aar") implementation("com.google.code.gson:gson:2.8.5") implementation("com.squareup.okhttp3:okhttp:3.11.0") implementation("com.google.android.gms:play-services-ads:17.2.1") implementation("com.google.android.gms:play-services-location:16.0.0") }

Android Configuration

Payment execution with confirmation via 3DS2

private val factory = Factory()

threeDS2Service = factory.newThreeDS2Service() val configParams = factory.newConfigParameters() val uiCustomization = factory.newUiCustomization() threeDS2Service.initialize( context, configParams, "en-US", uiCustomization, sslContext, // Optional field (needs if you want to pass a custom SSL certificate) trustManager, // Optional field (needs if you want to pass a custom SSL certificate) )

// An example of creating a transaction with custom SSL certificate. // To create a transaction with a custom certificate, you need to create an SSLContext object and a TrustManager. // Then pass it to initialize method of threeDS2Service. // Both (sslContext and trustManager) parameters must be passed, or neither (they are optional). // // threeDS2Service.initialize( // context, // configParams, // "en-US", // uiCustomization, // sslContext, // Optional field // trustManager, // Optional field // )

val dsRoot: String = "MII346GU349HDE5FH..." //your root-certificate in base64 format val transaction = threeDS2Service.createTransaction("F000000000", "", "2.1.0", dsRoot)

// An example of creating a transaction with deviceInfo encryption with a transmitted RSA key. // val rsaPem: String = ... // val dsRoot: String = ... // transaction = threeDS2Service.createTransaction( // "", // rsaPem, // "2.1.0", // dsRoot // )

// An example of creating a transaction with deviceInfo encryption with a transmitted EC key. // val ecPem: String = ... // val directoryServerID: String = ... // val dsRoot: String = ... // transaction = threeDS2Service.createTransaction( // directoryServerID, // ecPem, // "2.1.0", // dsRoot // )

// Available data, to be sent to the payment gateway val authRequestParams = transaction.authenticationRequestParameters!! val encryptedDeviceInfo: String = authRequestParams.deviceData val sdkTransactionID: String = authRequestParams.sdkTransactionID val sdkAppId: String = authRequestParams.sdkAppID val sdkEphmeralPublicKey: String = authRequestParams.sdkEphemeralPublicKey val sdkReferenceNumber: String = authRequestParams.sdkReferenceNumber

val challengeParameters = factory.newChallengeParameters()

// Parameters for starting Challenge Flow. challengeParameters.acsTransactionID = paymentOrderSecondStepResponse.threeDSAcsTransactionId challengeParameters.acsRefNumber = paymentOrderSecondStepResponse.threeDSAcsRefNumber challengeParameters.acsSignedContent = paymentOrderSecondStepResponse.threeDSAcsSignedContent challengeParameters.set3DSServerTransactionID(paymentOrderResponse.threeDSServerTransId)

// Listener to handle the Challenge Flow execution process. val challengeStatusReceiver: ChallengeStatusReceiver = object : ChallengeStatusReceiver {

override fun cancelled() {}

override fun protocolError(protocolErrorEvent: ProtocolErrorEvent) {}

override fun runtimeError(runtimeErrorEvent: RuntimeErrorEvent) {}

override fun completed(completionEvent: CompletionEvent) {}

override fun timedout() {} }

val timeOut = 5

// Starting Challenge Flow. transaction.doChallenge( activity, challengeParameters, challengeStatusReceiver, timeOut )

You can see a complete code sample in the file net.payrdr.mobile.payment.sample.kotlin.threeds.ThreeDSActivity.

Features of app self-test with connected 3DS2

When initializing the ThreeDS2Service, the application performs a series of self-compromising checks. The list with warnings is returned using the ThreeDS2Service.getWarnings method If there are no warnings, an empty list is returned.

The list of checks includes:

1) Checking root access on the device (according to rule SW01) * It returns a warning when triggered The device is rooted. 2) Checking to install the app only from approved app stores (according to rule SW02) * It returns a warning when triggered The integrity of the SDK has been tampered. * By default, sdk allows installation of the application only from the Play Market. * If it is necessary to add other markets (for example, App Gallery), they can be passed to configParams.

val factory = Factory()
val threeDS2Service = factory.newThreeDS2Service()
val configParams = factory.newConfigParameters()
val trustedAppStores = listOf<String>("com.android.vending", "com.huawei.appmarket")

configParams.removeParam("security", "trustedAppStores") configParams.addParam("security", "trustedAppStores", StringUtils.makeString(trustedAppStores))

3) Checking application signature mismatch (according to rule SW02) * It returns a warning when triggered The integrity of the SDK has been tampered. * An example of passing a signature in configParams:

val factory = Factory()
val threeDS2Service = factory.newThreeDS2Service()
val configParams = factory.newConfigParameters()
val youAppSignature = //signature of your application

configParams.removeParam("security", "appSignature") configParams.addParam("security", "appSignature", youAppSignature)

4) Checking for malicious applications on the device (according to rule SW02) * It returns a warning when triggered The integrity of the SDK has been tampered. * By default, applications with the following package names are denied: * de.robv.android.xposed * de.robv.android.xposed.installer * com.saurik.substrate * If it is necessary to set your own list of prohibited applications, the names of their packages can be passed to configParams.

val factory = Factory()
val threeDS2Service = factory.newThreeDS2Service()
val configParams = factory.newConfigParameters()
val maliciousApps = listOf<String>("com.zhiliaoapp.musically", "com.othersapp.harmful")

configParams.removeParam("security", "maliciousApps") configParameters.addParam("security", "maliciousApps", StringUtils.makeString(maliciousApps))

5) Checking to run the application from under the emulator (according to rule SW03) * It returns a warning when triggered An emulator is being used to run the App. 6) Checking for the presence of a debugger connected to the application (according to rule SW04) * It returns a warning when triggered A debugger is attached to the App. 7) Checking that the Android version is up-to-date (according to rule SW05) * It returns a warning when triggered The OS or the OS version is not supported. * Versions over API 16 (JELLY BEAN) are considered to be up-to-date (safe)

Under documentation/threeds you can find more information describing the available ConfigParameters and UiCustomization parameters to customize the 3DS screen, as well as a description of the 3DS SDK server application interaction process

Example of a confirmation code input screen:

drawing

Logging

Internal processes are logged with SDK-ThreeDS tag. Also you can log your processes. Logging is available through the class ThreeDSLogger which has an instance available through static field INSTANCE. - To add log- interfaces you should call ThreeDSLogger-method addLogInterface().

For example to log into LogCat:

...
     ThreeDSLogger.INSTANCE.addLogInterface(object : net.payrdr.mobile.payment.sdk.threeds.LogInterface {
        override fun log(classMethod: Class<*>, tag: String, message: String, p3: Throwable?) {
            Log.i(tag, "$classMethod: $message")
        }
    })
...

The default is the tag SDK-ThreeDS. You can set your own one if you like.

...
     ThreeDSLogger.INSTANCE.log(this.javaClass, "MyTag", "My process", null)
...

FAQ

3DS2 stub

3DS2 stub can be used with the SDK. SDK screens depend on the order amount in 3DS2 stub

Radio group

Amount: 111

Multiple choice

Amount: 222

Web (embedded HTML)

Amount: 333

One-Time password

Amount: any other

Categories:
eCommerce SDK
Categories
Search results