Non-Seamless Flow - Android
This section provides step-by-step procedure for integrating the Tridentity SDK into an Android application using the non-seamless flow. In this approach, the SDK handles both the business logic and the UI rendering while supporting configuration for app-specific themes.
1. Gradle Changes
Add the required dependencies to your app's build.gradle file:
android {
dependencies {
implementation files('libs/<Tridentity_SDK>.aar')
// Other required dependencies for Tridentity SDK
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.biometric:biometric:1.1.0'
implementation 'org.bouncycastle:bcprov-jdk15+:1.46'
implementation 'com.nimbusds:nimbus-jose-jwt:7.4'
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
implementation 'com.scottyab:rootbeer-lib:0.1.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.23'
implementation 'com.romainpiel.shimmer:library:1.4.0@aar'
implementation 'com.airbnb.android:lottie:5.0.3'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'in.payu:payuanalytics:1.5.3'
implementation 'in.payu:payu-crash-logger:(1.1.1,1.2.0)'
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
}
}2. Manifest Changes
Tridentity SDK supports different modes of authenticating a transaction. As per business needs, permission has to be provided in App manifest to proceed with Tridentity SDK services. The following table shows the permissions needed as per the modes enabled
Modes supported in the SDK:
-
Push Notification
-
Push with Biometric
-
Offline OTP
Permission | Description | Mandatory for Modes |
|---|---|---|
Post notification | Mandatory for version13 and above to receive push notification |
|
Phone State | Mandatory to detect sim swap scenarios |
|
SMS | For auto send of SMS if SDK is enabled for binding the device |
|
Add the following permissions to your app's AndroidManifest.xml file:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SEND_SMS" />3. Configuration of SDK
Invoke the following method of the SDK to configure the client details. All the security checks and mandatory permissions required for the SDK will be validated during this call. In case if any security check fails or permission not granted, specific error message will be provided in the callback and the calling app should terminate the flow by showing appropriate message to the user.
Configure the SDK with client details using the appropriate parameters. This configuration validates security checks and permissions.
Parameters
| Parameter & Constraints | Remarks | Mandatory for Modes |
|---|---|---|
context mandatory | Application Context | All |
clientId mandatory | Will be shared offline | All |
env mandatory | Default - UAT. For production, to be passed as "PROD" | All |
themeConfigoptional | Theme config which can be configured in the SDK. If not passed, configuration set in the server or default value set in the SDK will be taken. Refer to UI customization for more details. | |
sessionIdleTimeout optional | This parameter controls automatic SDK termination based on inactivity. When a positive timeout value is provided, the SDK will automatically terminate after the specified idle period and return control to the application. If this parameter is not provided, set to 0, or set to a negative value, the idle timeout feature will be disabled. | |
askPushPermissionFromSDK optional | Set this parameter to true to allow the SDK to initiate a push notification permission request from the user. If the app has already requested notification permission, or if the permission has already been granted, pass false to skip the SDK-initiated prompt and avoid duplicate requests. | |
logoConfig optional | Configure and pass logo images to the SDK. Refer to Logo Configuration for details. |
Sample Configuration
val configObject = JSONObject()
configObject.put("env", "UAT") // UAT or PROD
configObject.put("clientId", "")
configObject.put("sessionIdleTimeout", 60000) // in milliseconds
configObject.put("themeConfig", themeConfig)
configObject.put("askPushPermissionFromSDK", true)
configObject.put("logoConfig", logoConfig)
TridentitySDK.getInstance().configSdk(context, configObject, object : ConfigStatusCallback {
override fun onSuccess(event: JSONObject) {
// Check the message flag in the response for configuration status
}
override fun onError(errorCode: Int, errorDesc: String) {
// Handle error — terminate flow and show appropriate message to the user
}
})Note:
From the response event in the onSuccess method, check for the message flag to get configuration status.
4. Set SIM Information (Conditional)
This method allows the client application to provide SIM-specific information (subscription ID and SIM index) to the SDK.
Enables the SDK to perform cross-verification of SIM information
Facilitates automatic deregistration when SIM movement/changes are detected
val jsonObject = JSONObject()
jsonObject.put("subscriptionId", 1) // subscription id from SubscriptionInfo
jsonObject.put("simIndex", 0) // as per user SIM selection
TridentitySDK.getInstance().setSimInfo(activity, jsonObject)5. Initialization of FCM
This section details how to pass the FCM token to the SDK for sending push notifications. This method should be called before initiating registration and whenever a new FCM token is generated.
It is applicable only if the authentication mode enabled is either "Push notification" or "Push with Biometric."
Parameters
| Parameter | Description |
|---|---|
context mandatory | Application Context |
fcmToken mandatory | Token generated by Firebase Messaging service |
Code Example
TridentitySDK.getInstance().registerFCM(applicationContext, token,
object : FCMRegistrationCallback {
override fun onSuccess(event: JSONObject) {
Log.d("TAG", "onSuccess: $event")
}
override fun onError(code: Int, error: String) {
// Handle error
}
}
)6. Customer Enrolment
This section details the process of enrolling a user for Tridentity authentication.
Parameters
| Parameter | Description |
|---|---|
activity mandatory | Instance of AppCompatActivity |
mobileNumber conditional | Mobile number of the user against which the card is registered, prefixed with country code. Mandatory if device binding is opted from the SDK. |
cif conditional | CIF number of the user against which the card is registered. |
Code Example
val regObject = JSONObject()
regObject.put("mobileNumber", "919876543210")
TridentitySDK.getInstance().initiateRegistration(
activity, regObject,
object : RegistrationStatusCallBack {
override fun onSuccess(event: JSONObject) {
// {"message":"Customer status retrieved","subParam":{"customerStatus":"registration_comm_success"}}
}
override fun onError(code: Int, error: String) {
// Handle error
}
override fun onTxnUpdated(event: JSONObject) {
runOnUiThread {
Log.d(TAG, "Reg onTxnUpdate: $event")
}
}
}
)
Note:From the response object in the onSuccess method, check for the message flag to get the status.
7. Check Registration Status
Use this method to check the current registration status of a user in the Tridentity system.
Parameters
| Parameter | Description |
|---|---|
context mandatory | Application Context |
clientId mandatory | Client ID |
mobileNumber conditional | Mobile number of the user against which the card is registered, prefixed with country code. Mandatory if device binding is opted from the SDK. |
cif conditional | CIF number of the user against which the card is registered. |
Code Example
val custObject = JSONObject()
custObject.put("mobileNumber", "919876543210")
TridentitySDK.getInstance().checkRegistrationStatus(context, custObject, object : RegistrationStatusCallBack {
override fun onSuccess(event: JSONObject) {
// Note: customerStatus : registration_comm_success is only considered as successful registration
}
override fun onError(code: Int, error: String) {
// Handle error
}
})8. Process Transaction
Invoke this method whenever a transaction has to be authenticated.
Parameters
Parameter & Constraints | Remarks | Mandatory for Modes |
|---|---|---|
context | Context of the transaction. | All |
remoteMessage | Message received from push notification |
|
buildNotification | Default value: False |
|
Code Example
TridentitySDK.getInstance().processTransaction(
applicationContext, remoteMessage.data, false,
object : UpdateTransactionCallback {
override fun onSuccess(event: JSONObject) {
// {"message":"Transaction updated successfully","subParam":{"txnId":"8716fd90-a128-493b-a45f-767fe62a14e4"}}
}
override fun onError(error: String) {
Log.e("processTransaction", error)
}
}
)9. Transaction History
Invoke this method to get the transaction data authenticated via Tridentity SDK. By default, 50 transactions can be viewed, with a limit of 10 and an offset of 4.
Parameters
| Parameter | Description |
|---|---|
activity mandatory | Instance of AppCompatActivity |
limit optional | Number of transaction records fetched per single request. Default is 10 records per request. |
offset optional | Page index. Default is 0-4. |
Sample JSON
val historyObject = JSONObject()
historyObject.put("limit", 10)
historyObject.put("offset", 0)Code Example
TridentitySDK.getTransactionHistory(
activity as AppCompatActivity, historyObject,
object : TransactionHistoryCallBack {
override fun onSuccess(event: JSONObject) {
// Handle success
}
override fun onError(error: String) {
// Handle error
}
override fun onTxnUpdated(event: JSONObject) {
runOnUiThread {
Log.d(TAG, "TxnHistory onTxnUpdate: $event")
}
}
}
)10. De-Registration
Invoke this method to deregister a customer from Tridentity.
TridentitySDK.getInstance().deRegistration(context, object : DeregisterCallBack {
override fun onSuccess(event: JSONObject) {
// {"code":"200","deRegReason":"User de-registered","message":"Device Deregistered Successfully"}
}
override fun onError(code: Int, error: String) {
// Handle error
}
})11. Logout SDK
Invoke this method to logout/terminate the Tridentity SDK session. If the SDK is open, it triggers session termination; if already logged out, it returns success with code 400 and message "Already logged out".
| Parameter | Description |
|---|---|
context mandatory | Instance of AppCompatActivity |
callback mandatory | SDKLogoutCallBack implementation. |
Code Example
private fun sdkLogOut() {
TridentitySDK.getInstance().logoutSDK(this, object : SDKLogoutCallBack {
override fun onSuccess(event: JSONObject) {
// {"message":"You have been signed out of SecurePay."}
}
override fun onError(code: Int, error: String) {
// Handle error
}
})
}UI Customization
The SDK allows UI customizations through a configuration object passed in as themeConfig.
UI Customization Parameters
| Parameter | Description | Example |
|---|---|---|
LabelCustomizationoptional |
Configurations: HeaderCustomization,TextCustomization. Sub Components: textColor, fontSize | labelConfigObject |
ToolbarCustomizationoptional |
Configurations: backgroundColor, textColor, fontSize | toolbarConfigObject |
ButtonCustomizationoptional |
Configurations: primaryButtonCustomization, secondaryButtonCustomization. Sub Components: enabledBackgroundColor, enabledTextColor, disabledBackgroundColor, disabledTextColor, fontSize, cornerRadius | buttonConfigObject |
Text Customization Parameters
| Parameter | Description | Example |
|---|---|---|
bottomSheetPermissionPopupConfigurationoptional | Text customization for permission popup: topHeaderText,topSubHeaderText, headerTextForContents, subTextForContents, buttonTextForAllowPermissions, buttonTextForSkipPermissions | permissionPopupConfig |
bottomSheetSimBindingProcessingPopupConfigurationoptional | Texts for SIM binding, number verification, biometric setup, etc. topHeaderText, topSubHeaderText, headerTextForContents, subTextForContents, numberVerificationProcessingText, numberVerifiedText, biometricSetupText, biometricVerifiedText, processingCircleColor | simBindingConfig |
bottomSheetRegistrationSuccessfulPopupConfigurationoptional | Success messages and buttonText topHeaderText, topSubHeaderText, headerTextForContents, subTextForContents, buttonText, buttonColor | registrationSuccessConfig |
bottomSheetFailureScreenConfigurationoptional | Error messages and buttonText topHeaderText, topSubHeaderText, headerTextForContents, subTextForContents, buttonText, buttonColor | failureScreenConfig |
TncScreenConfigurationoptional | tncPopUpOkButtonText | |
ConsentScreenConfigurationoptional | consentPopUpSkipButtonText, consentPopUpRegisterButtonText | |
DeRegPopupConfigurationoptional | topSubHeaderText, headerTextForContents, subTextForContents, okButtonText, cancelButtonText, | |
TransactionHistoryScreenConfigurationoptional | appBarText, topHeaderText, topSubHeaderText, headerTextForContents, subTextForContents, bottomBarTransactionsText, bottomBarOfflineOTPText | transactionHistoryConfig |
biometricTextConfigurationoptional | Customizes biometric-related messages for registration, transaction, and permission dialog flows. registration: maxAttemptsMessage transaction: maxAttemptsMessage permissionDialog.android: heading, message, buttonOKText, buttonSkipText | biometricTextConfig |
uiMessagesV1optional | pnTap: expiredOrNotFound |
Sample for ThemeConfig
var themeConfig = ThemeConfig()
var uICustomization = UICustomization()
var textCustomization = TextCustomization()
var labelCustomization = LabelCustomization()
var toolbarCustomization = ToolbarCustomization()
var buttonCustomization = ButtonCustomization()
toolbarCustomization.backgroundColor = "#25272C"
toolbarCustomization.textColor = "#1be077"
toolbarCustomization.fontSize = 10F
labelCustomization.headingCustomization?.textColor = "#000000"
labelCustomization.headingCustomization?.fontSize = 18F
labelCustomization.subHeadingCustomization?.textColor = "#000000"
labelCustomization.subHeadingCustomization?.fontSize = 14F
buttonCustomization.fontSize = 18F
buttonCustomization.buttonCornerRadius = 50
buttonCustomization.primaryButtonCustomization?.enabledBackgroundColor = "#9C27B0"
buttonCustomization.primaryButtonCustomization?.disabledBackgroundColor = "#F26522"
buttonCustomization.primaryButtonCustomization?.enabledTextColor = "#FFFFFF"
buttonCustomization.primaryButtonCustomization?.disabledTextColor = "#FFFFFF"
buttonCustomization.secondaryButtonCustomization?.enabledBackgroundColor = "#9C27B0"
buttonCustomization.secondaryButtonCustomization?.disabledBackgroundColor = "#F26522"
buttonCustomization.secondaryButtonCustomization?.enabledTextColor = "#FFFFFF"
buttonCustomization.secondaryButtonCustomization?.disabledTextColor = "#FFFFFF"
uICustomization.labelCustomization = labelCustomization
uICustomization.buttonCustomization = buttonCustomization
uICustomization.toolbarCustomization = toolbarCustomization
textCustomization.tncScreenConfiguration?.tncPopUpOkButtonText="OK"
textCustomization.consentScreenConfiguration?.consentPopUpSkipButtonText="skip now"
textCustomization.consentScreenConfiguration?.consentPopUpRegisterButtonText="Register"
textCustomization.deRegPopupConfiguration?.topSubHeaderText="ABC"
textCustomization.deRegPopupConfiguration?.headerTextForContents = "De-Register"
textCustomization.deRegPopupConfiguration?.subTextForContents =
"This action will De-Register from Secure Pay. Is this what you intended to do?"
textCustomization.deRegPopupConfiguration?.okButtonText = "OK"
textCustomization.deRegPopupConfiguration?.cancelButtonText = "Cancel"
textCustomization.transactionHistoryScreenConfiguration?.appBarText = "Swipe to Pay"
textCustomization.transactionHistoryScreenConfiguration?.topHeaderText = "Authentication History"
textCustomization.transactionHistoryScreenConfiguration?.topSubHeaderText = "abc"
textCustomization.transactionHistoryScreenConfiguration?.headerTextForContents = "abc"
textCustomization.transactionHistoryScreenConfiguration?.subTextForContents = "text"
textCustomization.transactionHistoryScreenConfiguration?.bottomBarTransactionsText = "Transactions"
textCustomization.transactionHistoryScreenConfiguration?.bottomBarOfflineOTPText = "Offline OTP"
textCustomization.biometricTextConfiguration?.registration?.maxAttemptsMessage =
"Maximum biometric attempts exceeded. Please try again later."
textCustomization.biometricTextConfiguration?.transaction?.maxAttemptsMessage =
"All Biometric Attempts exhausted"
textCustomization.biometricTextConfiguration?.permissionDialog?.android?.heading =
"Biometric Permission Required"
textCustomization.biometricTextConfiguration?.permissionDialog?.android?.message =
"This app needs Face ID/Finger print permission to secure your registration. Please enable it in app settings."
textCustomization.biometricTextConfiguration?.permissionDialog?.android?.buttonOKText = "Open Settings"
textCustomization.biometricTextConfiguration?.permissionDialog?.android?.buttonSkipText = "Skip"
textCustomization.uiMessagesV1?.pnTap?.expiredOrNotFound =
"No action can be taken against this transaction!"
themeConfig.uiCustomization = uICustomization
themeConfig.textCustomization = textCustomization
configObject.put("themeConfig", themeConfig)Logo Configuration
Pass logoConfig during SDK configuration (configSdk) to centralize branding assets. LogoConfig holds drawable resource IDs for:
- defaultLogo — Bank logo displayed everywhere
- roundedLogo — Rounded bank logo displayed on the Swipe to Pay screen slider
- gifLogo — Loader animation displayed during registration
Logo config implementation Android:
Data Class:
data class LogoConfig(
var defaultLogo: Int? = null,
var roundedLogo: Int? = null,
var gifLogo: Int? = null
)
Sample Code
val logoConfig = LogoConfig(
defaultLogo = R.drawable.ic_android_logo,
roundedLogo = R.drawable.ic_android_logo,
gifLogo = R.drawable.ic_android_logo_animated
)
// Pass logoConfig in configSdk (see section 3)
configObject.put("logoConfig", logoConfig)Error Codes
The table lists possible callback success and error codes, and their reasons:
| Code | Reason |
|---|---|
| 303 | Biometric is disabled. Please enable the same to register for biometric authentication |
| 305 | Device deregistered as unable to fetch records. |
| 308 | Invalid parameters provided. Please check your input and try again. |
| 310 | SDK timed out. Please try again |
| 311 | Unable to initialize SDK. Please try again later |
| 313 | SDK session terminated by user back navigation |
| 314 | Transaction Authentication request is 'Expired' due to Timeout |
| 331 | Device Debugging detected. For security, please disable to proceed. |
| 332 | Device security check failed. Please try from a more secure device |
| 333 | Device Rooting detected (JailBreak), Can't Proceed. |
| 361 | No network connection available. Please check your internet connection and try again |
| 367 | Device is in airplane mode. Please turn off airplane mode and try again |
| 368 | Your session has expired due to inactivity. Please open SecurePay again when needed. |
| 270 | Something went wrong. Please try again later. |
| 374 | Registration cancelled by the user |
| 380 | Device has no biometric hardware, biometric not enrolled, hardware error, or biometric removed mid-flow |
| 382 | User tapped "Cancel" on biometric prompt |
| 383 | User failed biometric authentication N times (counter >= maxAttempts) OR app backgrounded and no attempts left |
| 384 | System locked biometric due to too many OS-level failures (temporary or permanent lockout) |
| 390 | Please Insert SIM and try again |
| 391 | Required permissions not granted. Please allow access in settings and try again. |
| 392 | Device deregistered due to sim movement detection |
Updated 18 days ago