Risk SDK for Android

OSL Pay Risk SDK Overview

The OSL Pay Risk SDK collects device and risk-related parameters, which are submitted to the server. The server then returns a clientInfoToken. The integrating app uses this token in scenarios where risk intervention is required, serving as risk proof.

Internal dependencies

The OSL Pay Risk SDK integrates three risk management SDKs internally, which serve as the data sources for risk parameters. These include:


Collected parameters

ParameterTypeDescriptionSource
deviceIdRisk ParameterUnique device IDFingerprint
userAgentDevice ParameterBrowser UA informationDevice
forterMobileUidRisk ParameterDevice fingerprintForter SDK
agentOSDevice ParameterOperating systemDevice
browserWidthDevice ParameterScreen widthDevice
browserHeightDevice ParameterScreen heightDevice
appVersionDevice ParameterApp versionDevice
appnameDevice ParameterApp nameDevice
osVersionDevice ParameterOperating system versionDevice
brandDevice ParameterDevice brandDevice
modelDevice ParameterDevice modelDevice
browserTimezoneDevice ParameterTimezoneDevice
lanDevice ParameterLanguageDevice
deviceSessionIdRisk ParameterUnique device identifierCheckout
terminaltypeDevice ParameterFixed to 2, indicating an Android deviceDevice

Integrating OSL Pay Risk SDK

1.SDK compilation environment

The OSL Pay Risk SDK is compiled in the following environment:

  • id = "com.android.library", version.ref = "8.3.2"
  • id = "org.jetbrains.kotlin.android", version.ref = "2.0.21"
  • minSdk 24
  • targetSdk 36
  • compileSdk 36

2.Add OSL Pay Risk SDK dependency

Add the SDK's .aar file to the libs folder:

  • OslPayRiskSdk-release.aar ,OSL Pay Risk SDK compiled artifact

Then, configure it in the build.gradle file:

implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])

3.Add dependencies required by OSL Pay Risk SDK

Dependencies on third-party libraries:

     //2.Add dependencies
    //Official libraries
    implementation "androidx.core:core-ktx:1.13.1"
    implementation "androidx.appcompat:appcompat:1.7.0"

    //Third-party libraries
    implementation("com.squareup.okhttp3:okhttp:4.12.0")
    implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
    implementation 'com.google.code.gson:gson:2.13.2'
    implementation "com.github.fingerprintjs:fingerprint-android:2.2.0"
    implementation 'com.forter.mobile:fortersdk:3.0.10'
    implementation("com.checkout:checkout-sdk-event-logger-android:1.0.1")
    implementation("com.fingerprint.android:pro:2.10.0")

Configure repository addresses:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        //OSLPayRiskSDK接入
        maven { url 'https://jitpack.io' }
        maven {
            url "https://mobile-sdks.forter.com/android"
            credentials {
                username "forter-android-sdk"
                password "HvYumAfjVQYQFyoGsmNAefGdR84Esqig"
            }
        }
        maven { url = uri("https://maven.fpregistry.io/releases") }
    }
}

4.Required permissions for the SDK

The OSL Pay Risk SDK declares the following permissions:

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

5.Proguard configuration

OSL Pay Risk SDK depends on Retrofit and OkHttp. Add the following Proguard configuration:

# for OkHttp
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**

# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*

# OkHttp platform used only on JVM and when Conscrypt and other security providers are available.
# May be used with robolectric or deliberate use of Bouncy Castle on Android
-dontwarn okhttp3.internal.platform.**
-dontwarn org.conscrypt.**
-dontwarn org.bouncycastle.**

# for Retrofit
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod

# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations

# Keep annotation default values (e.g., retrofit2.http.Field.encoded).
-keepattributes AnnotationDefault

# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    @retrofit2.http.* <methods>;
}

# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**

# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit

# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*

# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>

# Keep inherited services.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface * extends <1>

# With R8 full mode generic signatures are stripped for classes that are not
# kept. Suspend functions are wrapped in continuations where the type argument
# is used.
-keep,allowoptimization,allowshrinking,allowobfuscation class kotlin.coroutines.Continuation

# R8 full mode strips generic signatures from return types if not kept.
-if interface * { @retrofit2.http.* public *** *(...); }
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>

# With R8 full mode generic signatures are stripped for classes that are not kept.
-keep,allowoptimization,allowshrinking,allowobfuscation class retrofit2.Response

Usage instructions

1.SDK usage overview

The SDK’s logic is straightforward—it collects parameters and returns a risk control token. It exposes only two methods:

  • com.osl.pay.risk.sdk.OslPayRiskSDK#init, Initializes the SDK
  • com.osl.pay.risk.sdk.control.OSLPayRiskControl#getClientInfoToken, Returns the risk control token

2.SDK initialization

The SDK internally depends on three risk-control SDKs, each of which must be initialized first, and each uses a different initialization method. For example, Checkout initializes asynchronously and takes around 2 seconds to complete. Therefore, we recommend initializing the SDK early in your Application, rather than at the moment of use.

Example code:

   class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // During development and testing, use OslPayRiskSDK.ENVIRONMENT_SANDBOX; In production, use OslPayRiskSDK.ENVIRONMENT_PROD
        val envConfig = OslPayRiskSDK.ENVIRONMENT_SANDBOX
        OslPayRiskSDK.init(this, environment = envConfig)
    }
}

3.Get the Risk Control token

Example code:

    fun getClientInfoToken() {
        viewModelScope.launch(Dispatchers.IO) {
            val result = OSLPayRiskControl.getClientInfoToken()
            if (result is ResultData.Success) {
                // If obtaining the risk control token is successful, result.data.clientInfoToken will provide the token
            } else {
                // If obtaining the risk control token fails
            }
        }
    }

The returned data is in JSON format.

 {
   "clientInfoToken": "c71889e7ca060e806772c118cf967d4f"
 }

SDK event tracking configuration (optional)

To continuously improve and optimize performance, versions 1.2.0 and above include pre-integrated data tracking powered by ByteDance's Volcano Engine (AppLog).

This feature is completely disabled by default and will not report any data in the backend. Tracking is only activated if the developer manually includes the required dependencies and executes the initialization code. You may choose whether to enable this feature based on your project requirements.

⚠️

Additional Notes

The SDK utilizes Volcengine AppLog's multi-instance mechanism to create its own dedicated tracking instance. Even if the host app has already integrated and is using AppLog, the SDK's event tracking will not conflict or interfere with the host app's tracking configurations or data reporting. You can enable the SDK tracking feature with complete peace of mind.

Option 1: Enable SDK

If you would like to help us improve by reporting SDK operational data, please follow the configuration steps below:

1.1 Add Volcano Engine Maven repository and dependency

First, configure the Volcano Engine Maven repository in your root-level settings.gradle:

dependencyResolutionManagement {
    repositories {
        // Existing repositories...
        // Volcano Engine repository
        maven {
            url = uri("https://artifact.bytedance.com/repository/Volcengine/")
        }
    }
}

Then, add the AppLog dependency to your module’s build.gradle (e.g., app/build.gradle):

// ByteDance Volcano Engine Tracking SDK (Required prerequisite for SDK tracking)
implementation 'com.bytedance.applog:RangersAppLog-Lite-global:6.17.7'

1.2 Configure ProGuard rules

To prevent build warnings/errors, add the following rule to your host App's proguard-rules.pro:

# Required warning suppression for RangersAppLog-Lite-global
-dontwarn android.os.SystemProperties

1.3 Initialize and activate tracking

Finally, initialize the SDK tracking in your Application class. Calling the initDataTracker method officially activates data reporting:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        
        // Dynamically retrieve environment configuration
        val envConfig = DebugUtils.envConfig
        val env = if (envConfig == DebugUtils.ENV_SANDBOX) {
            OslPayRiskSDK.ENVIRONMENT_SANDBOX
        } else {
            OslPayRiskSDK.ENVIRONMENT_PROD
        }
        
        // Initialize and enable SDK tracking
        OslPayRiskSDK.initDataTracker(this, environment = env)
    }
}

Option 2: Disable SDK tracking (default)

If you do not wish to enable tracking, you do not need to call the initialization code or include the AppLog dependency.

Important Note for Release Builds: Because the SDK contains internal calls to AppLog APIs, the R8/ProGuard obfuscation tool will throw warnings and interrupt the build if it cannot find those classes during a Release compilation.

To resolve this, you must add the following rules to your host App’s proguard-rules.pro to ignore these warnings:

# Suppress "class not found" warnings for AppLog to ensure Release builds succeed (Required even if you are NOT using the tracking feature)
-dontwarn com.bytedance.applog.AppLog
-dontwarn com.bytedance.applog.InitConfig
-dontwarn com.bytedance.applog.IAppLogInstance

Notes

  1. Initialize the SDK in advance The SDK integrates multiple risk-control SDKs to collect risk parameters. Among them, Checkout has the longest initialization path. In sandbox testing, Checkout takes around 2 seconds to initialize asynchronously. Risk parameters can only be collected after Checkout is fully initialized, which takes about 400ms. Therefore, we recommend initializing the SDK in your Application early, rather than initializing it at the moment of use.
  2. Manage the validity of clientInfoToken Each call to the SDK’s getClientInfoToken method returns a new clientInfoToken. On the server side, however, the token is valid for 30 minutes. Make sure not to use it after it expires.
  3. Reuse clientInfoToken reasonably within its validity Since obtaining a clientInfoToken depends on Checkout collecting risk parameters (which takes about 400ms in sandbox testing), callers can reuse the token within its validity period according to their business scenario to avoid unnecessary delays.

Compatibility notes

Version compatibility

Our SDK relies on a third-party risk management SDK. It is crucial to ensure that the versions of these dependencies remain compatible to avoid runtime crashes or build failures. The following table outlines known version constraints:


Risk SDK versionDependency requirementDescription
1.0.2 and above
  • com.fingerprint.android:pro Version 2.10.0 of the Fingerprint SDK introduced breaking changes to the Configuration class constructor signature, making it incompatible with older versions.

Troubleshooting common issues

  1. If you are using com.fingerprint.android:pro version 2.11.0 or higher, you may encounter compilation errors regarding missing classes:
Missing class com.google.android.gms.location.CurrentLocationRequest$Builder (referenced from: android.location.Location com.fingerprintjs.android.fpjs_pro_internal.component4.component5(long))
Missing class com.google.android.gms.location.CurrentLocationRequest (referenced from: com.google.android.gms.location.CurrentLocationRequest com.fingerprintjs.android.fpjs_pro_internal.component4$1.$component5 and 3 other contexts)
Missing class com.google.android.gms.location.FusedLocationProviderClient (referenced from: com.google.android.gms.location.FusedLocationProviderClient com.fingerprintjs.android.fpjs_pro_internal.component4$1.$component9 and 11 other contexts)
Missing class com.google.android.gms.location.LocationServices (referenced from: android.location.Location com.fingerprintjs.android.fpjs_pro_internal.component4.D8871() and 2 other contexts)
Missing class com.google.android.gms.tasks.CancellationToken (referenced from: void com.fingerprintjs.android.fpjs_pro_internal.component4$1.component5(com.fingerprintjs.android.fpjs_pro_internal.aw))
Missing class com.google.android.gms.tasks.OnFailureListener (referenced from: void com.fingerprintjs.android.fpjs_pro_internal.component4$1.component5(com.fingerprintjs.android.fpjs_pro_internal.aw) and 2 other contexts)
Missing class com.google.android.gms.tasks.OnSuccessListener (referenced from: void com.fingerprintjs.android.fpjs_pro_internal.component4$1.component5(com.fingerprintjs.android.fpjs_pro_internal.aw) and 2 other contexts)
Missing class com.google.android.gms.tasks.Task (referenced from: void com.fingerprintjs.android.fpjs_pro_internal.component4$1.component5(com.fingerprintjs.android.fpjs_pro_internal.aw) and 2 other contexts)

If you encounter the build issues mentioned above, you can resolve them by adding the following ProGuard configurations:

-dontwarn com.google.android.gms.location.CurrentLocationRequest$Builder
-dontwarn com.google.android.gms.location.CurrentLocationRequest
-dontwarn com.google.android.gms.location.FusedLocationProviderClient
-dontwarn com.google.android.gms.location.LocationServices
-dontwarn com.google.android.gms.tasks.CancellationToken
-dontwarn com.google.android.gms.tasks.OnFailureListener
-dontwarn com.google.android.gms.tasks.OnSuccessListener
-dontwarn com.google.android.gms.tasks.Task

Reference files

  1. Risk SDK for Web
  2. Checkout Android SDK
  3. Fingerprint Android SDK
  4. Forter's Android SDK
  5. OSL Pay Risk SDK Demo - Android Github