For any question, we are one click away

Contact us

SDK Core process

Web View for 3DS

The diagram below shows the SDK Core payment process with 3DS redirect via Web View

sequenceDiagram participant MA as Mobile App participant MS as Mobile Server participant SDK as 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 -->> SDK: 5. generate seToken MA ->> MS: 6. send seToken to server MS ->> PG: 7. call payment API alt Payment finished PG -->> MS: 8. response with payment status (go to 16) else 3DS2 required PG -->> MS: 9. response with 3DS redirect MS ->> MA: 10. open Web View for 3DS MA ->> ACS: 11. client enters password ACS -->> PG: 12. redirect to Payment Gateway PG ->> PG: 13. make payment PG -->> MA: 14. redirect to returnUrl MA ->> MA: 15. close Web View end opt Callback is configured PG -->> MS: 16. callback notification end MS ->> PG: 17. check payment status MS ->> MA: 18. show payment result to the client
  1. Client creates an order
  2. Mobile Server registers that order in Payment Gateway via register.do. Use returnUrl parameter as a marker to close Web View after redirect from ACS on step 13.
  3. Mobile Server receives a unique order number mdOrder in response.
  4. Client fills in payment data in Mobile App.
  5. Mobile App calls SDK to create seToken. (Android: sdkCore.generateWithCard; iOS: CKCToken.generateWithCard).

    The public key used in the corresponding method is taken from the https://3dsec.berekebank.kz/payment/se/keys.do online resource. If multiple keys are available there, the first key should be used (note that the keys for UAT and production environments are different).

  6. Mobile App sends the seToken to Mobile Server.

  7. Mobile Server uses the seToken to make a payment via paymentorder.do request.

    • Use seToken instead of pan, cvc and expiry date.
    • Don't forget to send Cardholder name in TEXT field. If you don't collect Cardholder name just send CARDHOLDER.
  8. Mobile Server gets a response with no ACS redirect. It means that the payment is completed and we need to go to step 16.

  9. Mobile Server gets a response with ACS redirect.

  10. Mobile App opens Web View with ACS redirect data.

  11. Client enters their one time password to ACS form.

  12. ACS redirects the Client to Payment Gateway.

  13. Payment Gateway makes a payment.

  14. Payment Gateway redirects the Client to returnUrl, that can be used as a marker to close Web View.

  15. Mobile App closes Web View.

  16. Payment Gateway sends a callback notification to Merchant server if it's configured for the merchant.

  17. Mobile Server checks the final payment status via getOrderStatusExtended.do.

  18. Mobile App shows payment result to the Client.

IOS

iOS Integration

SDKCore.framework integration

You can integrate SDKCore.framework by adding it manually.

SDKCore.framework

Image 1. Adding the SDKCore.framework file

Image 2. Changing SDKCore.framework properties

Once done, import the framework in the ViewController.swift file.

//ViewController.swift
...
import SDKCore
...

How to work with API V1

External dependencies

For generation of the token, it is necessary to set the public key.

let publicKey: String =
      "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoIITqh9xlGx4tWA+aucb0V0YuFC9aXzJb0epdioSkq3qzNdRSZIxe/dHqcbMN2SyhzvN6MRVl3xyjGAV+lwk8poD4BRW3VwPUkT8xG/P/YLzi5N8lY6ILlfw6WCtRPK5bKGGnERcX5dqL60LhOPRDSYT5NHbbp/J2eFWyLigdU9Sq7jvz9ixOLh6xD7pgNgHtnOJ3Cw0Gqy03r3+m3+CBZwrzcp7ZFs41bit7/t1nIqgx78BCTPugap88Gs+8ZjdfDvuDM+/3EwwK0UVTj0SQOv0E5KcEHENL9QQg3ujmEi+zAavulPqXH5907q21lwQeemzkTJH4o2RCCVeYO+YrQIDAQAB-----END PUBLIC KEY-----"

Token generation method

let sdkCore = SdkCore()

let cardParams = CardParams(
     pan: "4111111111111111",
     cvc: "123",
     expiryMMYY: "12/28",
     cardholder: "TEST CARDHOLDER", 
     mdOrder: "mdOrder",
     pubKey: publicKey
)

let cardParamsConfig = SDKCoreConfig(
    paymentMethodParams: .cardParams(params: cardParams)
)
let tokenResult = sdkCore.generateWithConfig(config: cardParamsConfig)

let bindignParams = BindingParams(
    pubKey: publicKey,
    bindingId: "das",
    cvc: "123",
    mdOrder: "mdOrder"
)
let bindingParamsConfig = SDKCoreConfig(
    paymentMethodParams: .bindingParams(params: bindignParams)
)
let tokenResult = sdkCore.generateWithConfig(config: bindingParamsConfig)

Models

CardParams

Property name Data type Default value Optional Description
mdOrder String - No order number
pan String - No card number
cvc String - No secret card code
expiryMMYY String - No expiry date for the card
cardHolder String - Yes first and last name of cardholder
pubKey String - No public key

BindingParams

Property name Data type Default value Optional Description
mdOrder String - No order number
bindingId String - No number of a stored credential for the card
cvc String - Yes secret code for the card
pubKey String - No public key

Field validation errors

ParamField Error Description
UNKNOWN - Unknown error
PAN required An empty field is specified
invalid Invalid value
invalid-format Invalid characters are used. Only numbers are available.
CVC required An empty field is specified
invalid Invalid value
EXPIRY required An empty field is specified
invalid Invalid value
invalid-format The format does not match the template MM/YY
CARDHOLDER required An empty field is specified
invalid Invalid value
invalid-format Invalid characters are used. Only characters and spaces are available.
BINDING_ID required An empty field is specified
invalid Invalid value
MD_ORDER required An empty field is specified
invalid Invalid value
PUB_KEY required An empty field is specified

Android

Android Integration

Connecting to a Gradle project by adding .aar library files

You must add the sdk_core-release.aar library file to the libs folder, then specify the dependency of the added library.

build.gradle.kts

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

dependencies {
    // dependency is mandatory to add
    implementation(group = "", name = "sdk_core-release", ext = "aar")
}

build.gradle

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

dependencies {
    // dependency is mandatory to add
    implementation(group: '', name: 'sdk_core-release', ext: 'aar')
}

Android Configuration

Logging

Internal processes are logged with the SDK-Core tag. You can also log your processes.

Logging is available through the Logger object.

...
    Logger.addLogInterface(object : LogInterface {
        override fun log(classMethod: Class<Any>, tag: String, message: String, exception: Exception?) {
                Log.i(tag, "$classMethod: $message", exception)
            }
        })
...

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

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

Example Kotlin_core (no GUI)

Example of cryptogram formation

import net.payrdr.mobile.payment.sdk.core.SDKCore
import net.payrdr.mobile.payment.sdk.core.TokenResult
import net.payrdr.mobile.payment.sdk.core.model.BindingParams
import net.payrdr.mobile.payment.sdk.core.model.CardParams
import net.payrdr.mobile.payment.sdk.core.validation.BaseValidator
import net.payrdr.mobile.payment.sdk.core.validation.CardCodeValidator
import net.payrdr.mobile.payment.sdk.core.validation.CardExpiryValidator
import net.payrdr.mobile.payment.sdk.core.validation.CardHolderValidator
import net.payrdr.mobile.payment.sdk.core.validation.CardNumberValidator
import net.payrdr.mobile.payment.sdk.core.validation.OrderNumberValidator

class MainActivity : AppCompatActivity() {
    // initialization of validators for card information entry fields
    private val cardNumberValidator by lazy { CardNumberValidator(this) }
    private val cardExpiryValidator by lazy { CardExpiryValidator(this) }
    private val cardCodeValidator by lazy { CardCodeValidator(this) }
    private val cardHolderValidator by lazy { CardHolderValidator(this) }
    private val orderNumberValidator by lazy { OrderNumberValidator(this) }
    private val sdkCore by lazy { SDKCore(context = this) }

    override fun onCreate(savedInstanceState: Bundle?) {
        // installation of validators on the card information entry fields
        cardNumberInput.setupValidator(cardNumberValidator)
        cardExpiryInput.setupValidator(cardExpiryValidator)
        cardCodeInput.setupValidator(cardCodeValidator)
        cardHolderInput.setupValidator(cardHolderValidator)
        mdOrderInput.setupValidator(orderNumberValidator)

        // creation of an object and initialization of fields for a new card
        val params = NewPaymentMethodCardParams(
            pan = cardNumberInput.text.toString(),
            cvc = cardCodeInput.text.toString(),
            expiryMMYY = cardExpiryInput.text.toString(),
            cardHolder = cardHolderInput.text.toString(),
            pubKey = pubKeyInput.text.toString()
        )
        // method call to get the cryptogram for a new card
        sdkCore.generateWithConfig(SDKCoreConfig(params))

        // Creation of an object and initialization of fields for the linked card
        val params = NewPaymentMethodStoredCardParams(
            storedPaymentId = "storedPaymentMethodId",
            cvc = "123",
            pubKey = pubKeyInput.text.toString()
        )
        // method call to get the cryptogram for the linked card
        sdkCore.generateWithConfig(SDKCoreConfig(params))
    }
}

Models

NewPaymentMethodCardParams

Property name Data type Default value Optional Description
pan String - No card number
cvc String - No secret card code
expiryMMYY String - No expiry date for the card
cardHolder String - No first and last name of the cardholder
pubKey String - No public key

NewPaymentMethodStoredCardParams

Property name Data type Default value Optional Description
storedPaymentId String - No number of a stored credential for the card
cvc String - No secret code for the card
pubKey String - No public key

TokenResult

Property name Data type Default value Optional Description
token String - No token as string
errors Map - No error while generating token

Field validation errors

ParamField Error Description
PAN required An empty field is specified
invalid Invalid value
invalid-format Invalid characters are used. Only numbers are available.
CVC required An empty field is specified
invalid Invalid value
EXPIRY required An empty field is specified
invalid Invalid value
invalid-format The format does not match the template MM/YY.
CARDHOLDER required An empty field is specified
invalid Invalid value
invalid-format Invalid characters are used. Only characters and spaces are available.
PUB_KEY required An empty field is specified
STORED_PAYMENT_ID requrired An empty field is specified
invalid Invalid value

How to work with API V1

External dependencies

For generation of the token, it is necessary to set the public key.

val publicKey: String =
    "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoIITqh9xlGx4tWA+aucb0V0YuFC9aXzJb0epdioSkq3qzNdRSZIxe/dHqcbMN2SyhzvN6MRVl3xyjGAV+lwk8poD4BRW3VwPUkT8xG/P/YLzi5N8lY6ILlfw6WCtRPK5bKGGnERcX5dqL60LhOPRDSYT5NHbbp/J2eFWyLigdU9Sq7jvz9ixOLh6xD7pgNgHtnOJ3Cw0Gqy03r3+m3+CBZwrzcp7ZFs41bit7/t1nIqgx78BCTPugap88Gs+8ZjdfDvuDM+/3EwwK0UVTj0SQOv0E5KcEHENL9QQg3ujmEi+zAavulPqXH5907q21lwQeemzkTJH4o2RCCVeYO+YrQIDAQAB-----END PUBLIC KEY-----"

Token generation method

// TokenResult with CardParams
val cardParams: CardParams = CardParams(
    mdOrder = "mdOrder",
    pan = "4111111111111111",
    cvc = "123",
    expiryMMYY = "12/28",
    cardHolder = "TEST CARDHOLDER",
    pubKey = "publicKey"
)
val tokenResult = sdkCore.generationWithConfig(paymentCardParams = cardParams)

// TokenResult with BindingParams
val bindingParams: BindingParams = BindingParams(
    mdOrder = "mdOrder",
    bindingID = "das",
    cvc = "123",
    pubKey = "publicKey"
)

val tokenResult = sdkCore.generationWithConfig(paymentCardParams = bindingParams)

React Native

To implement integration of Mobile SDK Core into a React Native application, you need to configure a bridge — a wrapper in Kotlin/Java or Swift/Objective-C that will accept calls from JavaScript and forward them to the native SDK code.

Bridges in React Native allow your JS code to call native library methods as easily as regular asynchronous functions: you declare a native module with methods that return results via a Promise, React Native automatically links these methods to JavaScript, and then you work with them in the app without deep platform API knowledge.

IOS

  1. Integrate SDKCore into your project according to the iOS Integration section.

  2. Verify that for the SDKCore.xcframework framework the Embed column has Embed & Sign selected.

  3. Create a Swift module RadarSdkBridge.swift with the following content:

    import Foundation
    import React
    import SDKCore
    
    @objc(RadarSdk)
    class RadarSdkBridge: NSObject {
        private let sdkCore = SdkCore()
    
        @objc
        func generateNewCardToken(
            _ pan: String,
            cvc: String,
            expiryMMYY: String,
            cardHolder: String,
            mdOrder: String,
            pubKey: String,
            resolver resolve: RCTPromiseResolveBlock,
            rejecter reject: RCTPromiseRejectBlock
        ) {
            do {
                let params = CardParams(
                    pan: pan,
                    cvc: cvc,
                    expiryMMYY: expiryMMYY,
                    cardholder: cardHolder,
                    mdOrder: mdOrder,
                    pubKey: pubKey
                )
                let config = SDKCoreConfig(paymentMethodParams: .cardParams(params: params))
                let result = try sdkCore.generateWithConfig(config: config)
                resolve(result.token)
            } catch {
                reject("TOKEN_ERROR", error.localizedDescription, error)
            }
        }
    
        @objc
        func generateStoredCardToken(
            _ storedPaymentId: String,
            cvc: String,
            pubKey: String,
            mdOrder: String,
            resolver resolve: RCTPromiseResolveBlock,
            rejecter reject: RCTPromiseRejectBlock
        ) {
            do {
                let params = BindingParams(
                    pubKey: pubKey,
                    bindingId: storedPaymentId,
                    cvc: cvc,
                    mdOrder: mdOrder
                )
                let config = SDKCoreConfig(paymentMethodParams: .bindingParams(params: params))
                let result = try sdkCore.generateWithConfig(config: config)
                resolve(result.token)
            } catch {
                reject("TOKEN_ERROR", error.localizedDescription, error)
            }
        }
    
        @objc
        static func requiresMainQueueSetup() -> Bool {
            return false
        }
    }
  4. Implement the Objective-C bridge in the RadarSdkBridge.m file:

    #import <React/RCTBridgeModule.h>
    
    @interface RCT_EXTERN_MODULE(RadarSdk, NSObject)
    
    RCT_EXTERN_METHOD(generateNewCardToken:
      (NSString *)pan
      cvc:(NSString *)cvc
      expiryMMYY:(NSString *)expiryMMYY
      cardHolder:(NSString *)cardHolder
      mdOrder:(NSString *)mdOrder
      pubKey:(NSString *)pubKey
      resolver:(RCTPromiseResolveBlock)resolve
      rejecter:(RCTPromiseRejectBlock)reject
    )
    
    RCT_EXTERN_METHOD(generateStoredCardToken:
      (NSString *)storedPaymentId
      cvc:(NSString *)cvc
      pubKey:(NSString *)pubKey
      mdOrder:(NSString *)mdOrder
      resolver:(RCTPromiseResolveBlock)resolve
      rejecter:(RCTPromiseRejectBlock)reject
    )
    
    @end

Android

  1. Download sdk_core-release.aar and sdk_logs-release.aar and copy them into the android/app/libs/ folder according to the Android Integration section.

  2. Add a flat repository and dependencies to the android/app/build.gradle file:

    android {
        // … rest of your project configuration …
    }
    
    repositories {
        flatDir {
            dirs 'libs'
        }
    }
    
    dependencies {
        // … other dependencies …
        implementation(name: 'sdk_core-release', ext: 'aar')
        implementation(name: 'sdk_logs-release', ext: 'aar')
    }

Native Module Implementation in Kotlin

  1. Create the RadarSdkModule.kt file in the android/app/src/main/java/.../radar/ directory:

    package com.mobilesdkdemo.radar
    
    import com.facebook.react.bridge.Promise
    import com.facebook.react.bridge.ReactApplicationContext
    import com.facebook.react.bridge.ReactContextBaseJavaModule
    import com.facebook.react.bridge.ReactMethod
    import net.payrdr.mobile.payment.sdk.core.SDKCore
    import net.payrdr.mobile.payment.sdk.core.model.SDKCoreConfig
    import net.payrdr.mobile.payment.sdk.core.model.CardParams
    import net.payrdr.mobile.payment.sdk.core.model.BindingParams
    
    class RadarSdkModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
        override fun getName(): String = "RadarSdk"
    
        private val sdkCore by lazy { SDKCore(context = reactApplicationContext) }
    
        @ReactMethod
        fun generateNewCardToken(
            pan: String,
            cvc: String,
            expiryMMYY: String,
            cardHolder: String,
            mdOrder: String,
            pubKey: String,
            promise: Promise
        ) {
            try {
                val params = CardParams(
                    pan = pan,
                    cvc = cvc,
                    expiryMMYY = expiryMMYY,
                    cardHolder = cardHolder,
                    mdOrder = mdOrder,
                    pubKey = pubKey
                )
                val config = SDKCoreConfig(paymentCardParams = params)
                val result = sdkCore.generateWithConfig(config)
                promise.resolve(result.token)
            } catch (e: Exception) {
                promise.reject("TOKEN_ERROR", e)
            }
        }
    
        @ReactMethod
        fun generateStoredCardToken(
            storedPaymentId: String,
            cvc: String,
            pubKey: String,
            mdOrder: String,
            promise: Promise
        ) {
            try {
                val params = BindingParams(
                    bindingID = storedPaymentId,
                    mdOrder = mdOrder,
                    cvc = cvc,
                    pubKey = pubKey
                )
                val config = SDKCoreConfig(paymentCardParams = params)
                val result = sdkCore.generateWithConfig(config)
                promise.resolve(result.token)
            } catch (e: Exception) {
                promise.reject("TOKEN_ERROR", e)
            }
        }
    }
  2. Create the RadarSdkPackage.kt package in the same directory:

    package com.mobilesdkdemo.radar
    
    import com.facebook.react.ReactPackage
    import com.facebook.react.bridge.NativeModule
    import com.facebook.react.bridge.ReactApplicationContext
    import com.facebook.react.uimanager.ViewManager
    
    class RadarSdkPackage : ReactPackage {
        override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> =
            listOf(RadarSdkModule(reactContext))
    
        override fun createViewManagers(
            reactContext: ReactApplicationContext
        ): List<ViewManager<*, *>> = emptyList()
    }
  3. Register the created package in MainApplication.kt:

    package com.mobilesdkdemo
    
    import android.app.Application
    import com.facebook.react.PackageList
    import com.facebook.react.ReactApplication
    import com.facebook.react.ReactNativeHost
    import com.facebook.react.ReactHost
    import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
    import com.facebook.react.defaults.DefaultReactNativeHost
    import com.facebook.soloader.SoLoader
    import com.mobilesdkdemo.radar.RadarSdkPackage
    
    class MainApplication : Application(), ReactApplication {
    
        override val reactNativeHost: ReactNativeHost =
            object : DefaultReactNativeHost(this) {
                override fun getPackages(): List<ReactPackage> =
                    PackageList(this).packages.apply {
                        add(RadarSdkPackage()) // Register the package
                    }
    
                override fun getJSMainModuleName(): String = "index"
                override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
                override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
                override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
            }
    
        override val reactHost: ReactHost
            get() = getReactNativeHost(applicationContext, reactNativeHost)
    
        override fun onCreate() {
            super.onCreate()
            SoLoader.init(this, false)
            if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
                load()
            }
        }
    }

Usage in React Native

Use the methods from JavaScript/TypeScript as follows:

import { NativeModules } from 'react-native';
const { RadarSdk } = NativeModules;

// Generate a token for a new card const token = await RadarSdk.generateNewCardToken( '4111111111111111', // PAN '123', // CVC '12/25', // Expiry MM/YY 'CARDHOLDER NAME', // Cardholder name 'mdOrder', // Obtained when registering the order '-----BEGIN PUBLIC KEY-----...' // Public key from /payment/se/keys.do );

// Generate a token for a stored card const bindToken = await RadarSdk.generateStoredCardToken( 'bindingId', // Stored card ID '123', // CVC '-----BEGIN PUBLIC KEY-----…', // Public key from /payment/se/keys.do 'mdOrder' // Obtained when registering the order );

Demo Application

An example integration of Mobile SDK Core into a React Native application can be found on GitHub.

Categories:
eCommerce SDK
Categories
Search results