This document serves as a guide for the integrator of Ravelin’s Android 3DS SDK, providing details on how the 3DS SDK should be configured and integrated into an Android application.
Ravelin’s Android 3DS SDK supports a minimum Android version Android 5 (API Level 21).
Developed as a standard Android Library, Ravelin
provides a single AAR
artifact along with the Maven POM
file that lists dependencies.
We also include:
The Android 3DS SDK follows semantic versioning - The version can be
described as MAJOR.MINOR.PATCH
, where:
The Ravelin 3DS SDK is built and tested according to the following supporting EMV 3DS documentation. Therefore, this guide should be used in conjunction with the following specifications:
This section provides technical details on how to integrate the Android 3DS SDK into your application. The integration process requires basic knowledge of the gradle build tool.
Before attempting to use Gradle for Ravelin, ensure that you have a valid username and password for the Maven private repository as well as the repository address. This can be obtained from a Ravelin integrations engineer.
IMPORTANT - Do not store the repository credentials within Source Control. The credentials can be
stored in a user’s gradle.properties
file. The filename should also be added to your project
.gitignore file to avoid pushing it into your VCS.
ravelinRepoUsername = username
ravelinRepoPassword = password
ravelinRepoUrl = url
Within the Project level build.gradle.kts
, make sure the repositories include the appropriate
Ravelin maven repository:
allprojects {
repositories {
/* other repositories */
maven {
credentials {
username = properties["ravelinRepoUsername"] as? String
password = properties["ravelinRepoPassword"] as? String
}
authentication {
create<BasicAuthentication>("basic")
}
setUrl(properties["ravelinRepoUrl"])
}
}
}
Then in the Module level build.gradle.kts
add the Ravelin 3DS SDK to the app dependencies:
dependencies {
/* other dependencies */
implementation("com.ravelin.threeds2service:threeds2service-sdk:x.y.z")
}
The library will be fetched with its own dependencies as described in the POM file. These dependencies are described in Dependencies.
Occasionally, Ravelin releases updates for its SDKs, and that includes the Ravelin 3DS SDK. Such updates may introduce breaking changes. In such cases, we normally release an additional document describing those breaking changes. Normally, upon a new release, our integration team will contact your integration analysts and provide some information and guidance about the new release and about best practices to conduct the integration. In addition, it is recommended to check the release notes section in the developer docs for additional information about the changes in each release.
This section refers to ConfigParameters. Make sure you have an environment code before using the Ravelin 3DS SDK.
The Ravelin 3DS SDK defines backup rules in its Manifest file. In case you have backup rules in your own application manifest file, make sure to merge the 3DS SDK backup rules, otherwise they will be override during the Manifest merging process and that may result with an unexpected behaviour.
<application
android:dataExtractionRules="@xml/backup_rules_31_and_above"
android:fullBackupContent="@xml/backup_rules_until_30" tools:targetApi="s" />
Extraction rules for Android API >= 12:
<data-extraction-rules disableIfNoEncryptionCapabilities="false">
<include domain="sharedpref" path="."/>
<include domain="file" path="."/>
<exclude domain="sharedpref" path="secret_shared_prefs.xml"/>
<exclude domain="file" path="datastore/user_pref.pb"/>
</data-extraction-rules>
Extraction rules for Android API < 12:
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules >
<cloud-backup disableIfNoEncryptionCapabilities="false">
<include domain="sharedpref" path="."/>
<include domain="file" path="."/>
<exclude domain="sharedpref" path="secret_shared_prefs2.xml"/>
<exclude domain="file" path="datastore/user_pref.pb"/>
</cloud-backup>
</data-extraction-rules>
The Ravelin 3DS SDK provides an authentication service for payment transactions which is supported by different Card schemes. Each card scheme provides a public key for device data encryption, a key chain to verify the authenticity of signed certificates that arrive from the ACS and the Card scheme logos. In order to comply with the PCI 3DS SDK 1.1v requirements these values cannot be bundled with the SDK. In order to protect this data, the Ravelin 3DS SDK fetches the data from a remote host over a secured TLS link protected by an API token. The metadata downloaded from the host is stored in an encrypted storage.
The following list consists of card schemes, Ravelin 3DS SDK is certified with:
Card Scheme | Directory Server ID |
---|---|
Visa |
A000000003 |
Mastercard |
A000000004 |
JCB (Japan Credit Bureau) |
A000000065 |
CB (Cartes Bancaires) |
A000000042 |
Diners Club/Discover |
A000000152 |
Amex (American Express) |
A000000025 |
UnionPay |
A000000333 |
The integrator needs to set the directory server Id parameter when calling the API for creation of transactions with an argument matching a value from the table above.
A copy of the SDK object is generated when calling the get()
function from
the ThreeDS2ServiceInstance
class companion object. This helps assuring that only a single copy of
the SDK class is generated during the life cycle of the application. The following code snippet is
an example of how to access this object:
fun provides3dsSdk(): ThreeDS2Service = ThreeDS2ServiceInstance.get()
The SDK needs to be initialised, exactly one time throughout the lifecycle of the application, before it can be used. The SDK initialisation function initialize is a suspended function and therefore, may be called from a coroutine or from another suspend function. Note: If you haven’t worked with coroutines before, please refer to the official documentation in Coroutines. In the following example, the SDK is being initialised from a view model using the view model scope.
protected var coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
Log.e(TAG, "coroutine terminated with an error: ${exception.message}")
}
fun initSdk() =
viewModelScope.launch(coroutineContext + coroutineExceptionHandler) {
threeDS2Service.initialize(
application,
configParameters,
locale,
darkUiCustomization,
lightUiCustomization,
this
)
}
In this example, we have used a life cycle aware coroutine scope (the viewModelScope
). It may be that within your app, you define an unmanaged CoroutineScope
object.
In that case you may want to also define a SupervisorJob
of type CompletableJob
to gain a better control over exceptions in child coroutines and their cancellation.
The coroutineExceptionHandler
is of importance if you are interested in catching exceptions from child coroutines, including coroutines which are created inside the 3DS SDK.
We recommend applying both of them as catching all exceptions by the application may provide invaluable information in case of thrown
exceptions from the SDK.
In case that you’re not interested in catching exceptions from child coroutines you may apply
the initialize
function in the following way:
fun initSdk() =
viewModelScope.launch(coroutineContext) {
try {
threeDS2Service.initialize(
application,
configParameters,
locale,
darkUiCustomization,
lightUiCustomization,
null
)
} catch (e: InvalidInputException) {
//handle exception
} catch (e: SDKAlreadyInitializedException) {
//handle exception
} catch (e: SDKRuntimeException) {
//handle exception
}
}
i.e. the application will catch only direct exceptions thrown by the initialisation function and let the SDK handle all child coroutines exceptions.
Parameters
Parameter | Type | Description |
---|---|---|
application | Context | The application context. |
configParameters | ConfigParameters? | Please see [ConfigParameters] |
locale | String? | Provides information about the default Locality* |
darkUiCustomization | UiCustomization? | Please see [UiCustomization] |
lightUiCustomization | UiCustomization? | Please see [UiCustomization] |
coroutineScope | CoroutineScope? | Scope of the coroutine calling this suspend function |
(*) Please provide a String the following format:
"${language}-${country}"
This section describes the Android 3DS API.
An interface which defines a set of methods for initialising the SDK. To generate an instance of
ConfigParameters, one should use the ConfigParametersBuilder
. The ConfigParametersBuilder consists
of the following function members:
setEnvironment
The environment is a String value that will be given to the integrator during the integration stage. The integrator needs to call the function with this argument. Please make sure you own such a value before working with the API.
Method signature
fun setEnvironment(environment: String)
Parameters
Parameter | Type | Description |
---|---|---|
environment | String | Designated environment given to the user during the integration stage. |
the following is an example of how to generate the ConfigurationParameters object:
ConfigParametersBuilder.Builder()
.setEnvironment("Environment value provided during the integration stage").build()
According to the EMVCo 3DS SDK specification, the integrator shall be given the option to customise the challenge UI in the native scenario (The HTML UI is set by the ACS and cannot be customised by the SDK). The following table, lists the customisable parameters of each component in the UI:
Component | Possible customisation |
---|---|
Toolbar | background color, button text, header text, text color, font, font size |
Buttons* | background color, corner radius, text color, font, font size |
TextBoxes | border color, corner radius, border width, text color, font, font size |
Labels | heading label text color, heading label font size, heading label font, non-heading label text color, non-heading label font size, non-heading label font |
(*) There are several types of configurable buttons: SUBMIT, CONTINUE, NEXT, CANCEL and RESEND
UI customisation is optional and the user may choose to use it or not. In case that the user decides to ignore UI customisation, the SDK will use its default themes and styles. The integrator may customise the UI of both the light and dark themes or neither of them. The following code snippet shows how to customise the light mode theme (the dark mode customisation should be configured in the same manner but called with dark mode arguments):
fun getSdkLightUiCustomization() = UiCustomization().apply {
val defaultButtonCustomization = defaultLightButtonCustomization()
setToolbarCustomization(lightToolbarCustomization())
setButtonCustomization(defaultButtonCustomization, UiCustomization.ButtonType.NEXT)
setButtonCustomization(lightCancelButtonCustomization(), UiCustomization.ButtonType.CANCEL)
setButtonCustomization(defaultButtonCustomization, UiCustomization.ButtonType.CONTINUE)
setButtonCustomization(defaultButtonCustomization, UiCustomization.ButtonType.SUBMIT)
setButtonCustomization(lightResendButtonCustomization(), UiCustomization.ButtonType.RESEND)
setLabelCustomization(lightLabelCustomization())
setTextBoxCustomization(lightTextBoxCustomization())
}
private fun defaultLightButtonCustomization() = ButtonCustomization().apply {
setBackgroundColor("#FF80CBC4")
setCornerRadius(50)
setTextColor("#FF000000")
setTextFontName("sans-serif.ttf")
setTextFontSize(16)
}
private fun lightToolbarCustomization() = ToolbarCustomization().apply {
setBackgroundColor("#FFF44336")
setTextColor("#FF76FF03")
setTextFontName("Shizuru-Regular.ttf")
setTextFontSize(14)
setButtonText("Cancel")
setHeaderText("Secure Checkout")
}
private fun lightCancelButtonCustomization() = ButtonCustomization().apply {
setTextColor("#FF000000")
setTextFontName("sans-serif.ttf")
setTextFontSize(16)
}
private fun lightResendButtonCustomization() = ButtonCustomization().apply {
setCornerRadius(50)
setBackgroundColor("#FFF6DDDC")
setTextColor("#FF000000")
setTextFontName("sans-serif.ttf")
setTextFontSize(16)
}
private fun lightLabelCustomization() = LabelCustomization().apply {
setHeadingTextColor("#FF000000")
setHeadingTextFontName("sans-serif.ttf")
setHeadingTextFontSize(22)
setTextColor("#FF000000")
setTextFontName("sans-serif.ttf")
setTextFontSize(15)
}
private fun lightTextBoxCustomization() = TextBoxCustomization().apply {
setBorderColor("#FF000000")
setCornerRadius(50)
setBorderWidth(6)
setTextColor("#FF333333")
setTextFontName("sans-serif.ttf")
setTextFontSize(16)
}
The values set in the above code snippet were only used as an illustration.
According to the EMVCo SDK Specification, the SDK throws four types of exceptions when errors occur:
Exception | Description |
---|---|
InvalidInputException |
Occurs due to invalid data provided to the SDK. |
SDKAlreadyInitializedException |
Occurs when initialize is called on an already initialised ThreeDS2Service object. |
SDKNotInitializedException |
Occurs due to an attempted usage of an uninitialised ThreeDS2Service object. |
SDKRuntimeException |
Internal SDK Error. Will contain information describing the error cause more in depth. |
While in the Challenge Flow, instead of throwing exceptions, the SDK reports errors
via ChallengeStatusReceiver.runtimeError(RuntimeErrorEvent)
. This RuntimeErrorEvent
has both the
error message and error code.
During initialisation (see Initialise the SDK), the SDK performs a number of required security checks. These checks may result in warnings that are handed over to your Application. It’s up to you to act upon these warnings - The SDK will continue to operate as normal should you decide to, for example, ignore them.
Below is a list of the possible warnings the SDK may emit:
Code | Description | Severity Level |
---|---|---|
SW01 |
The device is jailbroken. | HIGH |
SW02 |
The integrity of the SDK has been tampered. | HIGH |
SW03 |
An emulator is being used to run the App. | HIGH |
SM04 |
A debugger is attached to the App. | MEDIUM |
SW05 |
The OS or the OS version is not supported. | HIGH |
The SDK will take additional security measures to protect itself and to protect the app, acc. to PCI 3DS SDK - Security Standard 1.1v.
In order to make authentication requests, we require a Transaction
object. To create a
new Transaction
object you need to call the createTransaction(...)
function on the
threeDS2Service object.
The createTransaction(...)
may fail due to the following reasons:
– SDKNotInitializedException
when called on a non initialized SDK.
– SDKRuntimeException
when unable to find or open the directory server keys.
– InvalidInputException
when it fails to identify the message version or the directory server ID
given to it as arguments.
The following code snippet demonstrate a possible way to call the function and catch its exceptions :
fun generateAuthenticationRequest(directoryServerId: String, messageVersion: String) =
try {
transaction = threeDS2Service.createTransaction(directoryServerId, messageVersion)
val authenticationParameters =
transaction?.getAuthenticationRequestParameters()
} catch (ex: InvalidInputException) {
//handle exception
} catch (ex: SDKNotInitializedException) {
//handle exception
} catch (ex: SDKRuntimeException) {
//handle exception
}
Parameters
Parameter | Type | Description |
---|---|---|
directoryServerId | String | The Directory Server ID is a Registered Application Provider Identifier (Directory server Id) that is unique to the Payment System |
messageVersion | String | Protocol version that should be used by all 3DS components along the transaction |
The requestor application should call this function to free resources designated to the Ravelin 3DS SDK. Like the initialize
function, which prepares the 3DS SDK,
it should be called only once through out the life cycle of the application.
Calling this method, without initialising the SDK first, will cause an SDKNotInitializedException
exception to be thrown.
Call this function before terminating the application or when you know, you won’t require the SDK anymore while the application is still alive.
Function signature
fun cleanup(applicationContext: Context)
Parameters
Parameter | Type | Description |
---|---|---|
applicationContext | Context | Directory Server ID for which the Transaction is being created |
getAuthenticationRequestParameters
In order to make an authentication request, the Ravelin 3DS SDK should prepare a set of parameters. This process includes the following operations: – Encrypting the device data, with the directory server public key. – Generating an ephemeral public key for a possible challenge. – Generating an SDK transaction ID. – Sharing the SDK application ID, which is generated during the first initialisation of the SDK for every app installation. – Sharing the SDK reference number. – Sharing the message version used by the SDK.
Method signature
fun getAuthenticationRequestParameters(): AuthenticationRequestParameters?
doChallenge
When the ACS(Access Control Server) requires a challenge to take place, the requestor application starts the challenge by calling the doChallenge
function with proper challenge parameters.
The function receives the current Activity as a reference. It is required to start the challenge Activity.
The challengeParameters
parameter is an instance of the ChallengeParameters class and it implements an interface with the same name. Please see Challenge parameters.
The challengeStatusReceiver
parameter is a callback which defines the required behavior of the SDK upon completion. Please see Challenge flow results.
Once started, the SDK is on charge and communicates directly with the ACS. It also generates its own
Activity to display the challenge UI.
The user shall also set a time limitation in the timeOut
parameter. This parameter defines how long a challenge may persist. The challenge will be automatically completed when this time limitation is reached.
The minimal value for this parameter should not be lower than 5 minutes. Setting a value lower than 5 will not result with an error but
the SDK will set the timeout to 5 minutes by default.
Function signature
fun doChallenge(
currentActivity: Activity?,
challengeParameters: ChallengeParameters?,
challengeStatusReceiver: ChallengeStatusReceiver?,
timeOut: Int
)
Parameters
Parameter | Type | Description |
---|---|---|
currentActivity | Activity? | The activity in which doChallenge(...) is called. |
challengeParameters | ChallengeParameters? | Set of parameters required to perform a challenge. |
challengeStatusReceiver | ChallengeStatusReceiver? | Optional callback defines how to handle the challenge result. |
timeOut | Int | Time limitation in minutes for finishing a challenge. Its minimum value is 5 minutes. |
getProgressView
**When called, this method generates a processing screen which displays the Android default progress bar and the DS logo. The processing screen is an indication to the user that some activity is taking place in the background either by the application or by the 3DS SDK. The processing screen should be displayed only in 2 cases: – The requestor application is making an authentication request. In that case the processing screen will be displayed during the AReq/ARes messaging. – The first CReq/CRes cycle.
Please note that ProgressDialog
was depracated in Android API 26 but it is still a requirement of the EMVCo specification and part of the Transaction
contract.
Function signature
fun getProgressView(currentActivity: Activity?): ProgressDialog?
Parameters
Parameter | Type | Description |
---|---|---|
currentActivity | Activity? | The activity in which getProgressView(...) is called. |
close
Call this function when the transaction is completed. This function cleans resources related to the transaction.
Calling any of the other functions on a closed transaction will result with an SDKRuntimeException
thrown by the 3DS SDK.
Method signature
fun close()
The ACS(Access Control Server) performs a Transaction Risk Analysis to decide whether to authenticate the user or not.
When the ACS have doubts about the TRA verdict it may ask for a challenge to take place. The requestor application may initiate a challenge by calling the doChallenge
function with appropriate parameters (see Transaction operations for more details).
One of the parameters of the doChallenge
function is an instance of the ChallengeParameters
class. This class implements the ChallengeParameters
contract. The class can be found in the 3DS SDK. Its constructor function looks as follows:
/**
* The ChallengeParameters class shall hold the parameters that are required to conduct the challenge process.
* Note: It is mandatory to set values for these parameters.
*
* @param threeDSServerTransactionID Transaction identifier assigned by the 3DS Server to uniquely identify a single transaction.
* @param acsTransactionID Transaction ID assigned by the ACS to uniquely identify a single transaction.
* @param acsRefNumber EMVCo assigns the ACS this identifier after running the EMV 3-D Secure Testing and Approvals process on the ACS.
* @param acsSignedContent ACS signed content. This data includes the ACS URL, ACS ephemeral public key, and SDK ephemeral public key.
* @param threeDSRequestorAppURL is the 3DS Requestor App URL. If the app sets the URL, then the SDK shall pass the URL in the CReq.
*/
@Parcelize
@Serializable
data class ChallengeParameters(
@SerialName("threeDSServerTransactionID")
private var threeDSServerTransactionID: String? = null,
@SerialName("acsTransactionID")
private var acsTransactionID: String? = null,
@SerialName("acsRefNumber")
private var acsRefNumber: String? = null,
@SerialName("acsSignedContent")
private var acsSignedContent: String? = null,
@SerialName("threeDSRequestorAppURL")
private var threeDSRequestorAppURL: String? = null
) : Parcelable, ChallengeParameters
Please note that the first four parameters may be found in the authentication response message while the last parameter is an optional one.
The threeDSRequestorAppURL
consists of the requestor application URL. It may be used in an Out-Of-Band (OOB) authentication. When set, the Authentication App will receive the value
from the ACS. This will enable the authentication app to open the requestor merchant app again when authentication is complete.
More information about how to set this parameter can be found in the spec EMV 3-D Secure - Protocol and Core Functions Specification version 2.2.0 and in technical guides about launching intents of other packages.
Please note that the 3DS transaction ID has to be concatenated to it.
After invoking the doChallenge
function, the Challenge Flow starts and the 3DS SDK takes control over the user interface.
This means that the Activity
provided via the doChallenge
function, should not be finished or
replaced by another Activity
. The doChallenge
function receives a callback object of type ChallengeStatusReceiver
.
This contract defines all the possible ways in which a challenge flow may end. The challenge may terminate with one
of the following outcomes:
– Completed - The challenge flow ended and a transaction status is available.
– Cancellation - The user decides to cancel the challenge (by pressing the cancel button in the Challenge screen top-bar).
– Time out - The challenge will result with a time out when the challenge isn’t finished during the predefined time, set by the application when calling the doChallenge(...)
function.
– Runtime error - The 3DS SDK tackled a runtime error during the challenge process.
– Protocol error - The 3DS SDK received an error message from the ACS and had to terminate the challenge.
When any of these are invoked, the Challenge is considered as finished. As a result, the 3DS SDK dismisses the Challenge screen, closes the transaction, cleans up resources and returns control back to the application.
The ChallengeStatusReceiver
interface needs to be implemented by the requestor app. You may find an example of how to implement this contract in the sample app.
The Ravelin 3DS SDK supports a dark mode theme. The integrator may provide customisation for both light and dark
modes. In case that you prefer not to provide an optional UiCustomisation
object for customising
the UI components, the 3DS SDK will use its default values for both the light and the dark modes.
As part of complying with The EMVCo. standard, the Ravelin 3DS SDK collects information about the user device, which helps assessing its authenticity. To do so, enabling several permissions, by the integrators application, is required. Nonetheless, except for few of them, adding these permissions is not mandatory, and the user may theoretically still be able to authenticate without applying them. The more device information collected by the SDK, the lower is the risk for a user to receive a challenge verdict as the ACS have less uncertainty when making a transaction risk analysis. In case your app is targeting Android SDK 13 or higher, you may decide to revoke those permissions your app has no longer need for, after finishing the 3DS SDK initialization. To revoke permissions you can use the revokeSelfPermissionsOnKill(Collection) API. The following table lists the permissions required by the SDK and may be added to the manifest file:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
Permission | INTERNET |
---|---|
Why is it needed? | Connection to the network |
When to ask for the permission? | Install time |
comments | Probably the most important permission as the SDK requires connectivity to the Internet in order to be able to authenticate |
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
Permission | ACCESS_NETWORK_STATE |
---|---|
Why is it needed? | Validate user authenticity - Access to device ip address. |
When to ask for the permission? | Install time |
comments | - |
<uses-permission android:name="com.google.android.gms.permission.AD_ID"></uses-permission>
Permission | AD_ID |
---|---|
Why is it needed? | Validate user authenticity - Mandatory by google starting from April 2022 inn order to fetch the application advertisement ID |
When to ask for the permission? | Install time |
comments | - |
<uses-permission
android:name="com.google.android.gms.permission.ACCESS_FINE_LOCATION"></uses-permission>
Permission | Precise Location |
---|---|
Why is it needed? | Validate user authenticity - Validate user authenticity - Used to Access device location and Wifi connection features |
When to ask for the permission? | Install time for API level 21 & 22 and below and install & runtime for API level 23 and above |
comments | Request together with the ACCESS_COARSE_LOCATION |
<uses-permission
android:name="com.google.android.gms.permission.ACCESS_COARSE_LOCATION"></uses-permission>
Permission | READ_PHONE_STATE |
---|---|
Why is it needed? | Validate user authenticity - Validate user authenticity - Used to Access device location |
When to ask for the permission? | Install time for API level 21 & 22 and below and install & runtime for API level 23 and above |
comments | - |
<uses-permission
android:name="com.google.android.gms.permission.READ_PHONE_STATE"></uses-permission>
Permission | READ_PHONE_STATE |
---|---|
Why is it needed? | Validate user authenticity - Validate user authenticity - Used to retrieve telephony identifiers |
When to ask for the permission? | Install time for API levels 21 & 22 and runtime for API level 23 and above |
comments | - |
<uses-permission android:name="com.google.android.gms.permission.SEND_SMS"></uses-permission>
Permission | Telephony information |
---|---|
Why is it needed? | Validate user authenticity - Validate user authenticity - Used to retrieve telephony identifiers |
When to ask for the permission? | Install time for API levels 21 & 22 and runtime for API level 23 and above |
comments | - |
<uses-permission
android:name="com.google.android.gms.permission.READ_PHONE_NUMBERS"></uses-permission>
Permission | Telephony information |
---|---|
Why is it needed? | Validate user authenticity - Validate user authenticity - Used to retrieve telephony identifiers |
When to ask for the permission? | Install time for API levels 21 & 22 and runtime for API level 23 and above |
comments | - |
<uses-permission
android:name="com.google.android.gms.permission.ACCESS_WIFI_STATE"></uses-permission>
Permission | Wi-Fi network information |
---|---|
Why is it needed? | Validate user authenticity - Validate user authenticity - Used for accessing Wifi network attributes |
When to ask for the permission? | Installation time permission from API 21 and above |
comments | - |
<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
Permission | BLUETOOTH - Bluetooth device identifiers |
---|---|
Why is it needed? | Validate user authenticity - Used for accessing Bluetooth adapter and paired devices attributes |
When to ask for the permission? | Installation time permission from API 18 and above |
comments | - |
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"></uses-permission>
Permission | Bluetooth connection to paired devices |
---|---|
Why is it needed? | Validate user authenticity - Bluetooth parameters related to paired devices |
When to ask for the permission? | Installation time permission from API 18 and above |
comments | - |
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"></uses-permission>
Permission | CHANGE_NETWORK_STATE |
---|---|
Why is it needed? | Validate user authenticity - Request network parameters |
When to ask for the permission? | Installation time permission |
comments | - |
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"></uses-permission>
Permission | REQUEST_INSTALL_PACKAGES |
---|---|
Why is it needed? | Validate user authenticity - Checks whether the application can install non market packages. |
When to ask for the permission? | Installation time permission |
comments | Beware that this is a signature permission |
The Ravelin 3DS SDK was designed to meet the requirements set in PCI 3DS SDK - Security Standard 1.1v. Nevertheless, these requirements entail constant updates and improvements as security threats become more and more sophisticated.
Apart from complying with the requirements indicated by the EMVCo and the PCI specifications (please refer to Supporting documentation), some additional measures can be taken by the integrator, in order to mitigate some potential security threats. A full list of risks and vulnerabilities and their potential mitigations is outside the scope of this guide. Yet few important measures may be practised to make it harder for attackers to exploit your app. The following list includes only suggestions and/or recommendations:
Action | Category | Description | Additional requirements / comments |
---|---|---|---|
Avoid setting android:debuggable=“true” in the Manifest.xml file under the application tag | Confidentiality / Integrity | This makes it easier for attackers to exploit your app | - |
Avoid setting android:allowBackup=“true” in the Manifest.xm file the application tag | Confidentiality / Integrity | It gives potential attacker the ability to manually backup the app into a readable file with simple ADB shell commands | These files may contain sensitive data about your users and expose your application secrets. This recommendation is harder to meet with. As an alternative you add a backup configuration file (Mandatory from Android 12). |
It is recommended to avoid logging sensitive data | Confidentiality | A potential attacker may exploit sensitive information about the device, the user or the 3DS messages. | - |
Keep your secrets safe | Confidentiality / Integrity | Secrets within the app may be discovered through reverse engineering or even due to the nature of the package file anatomy. | Opt to encrypt such valuable data by using the KeyStore or an Encrypted shared preference. |
Protection against reverse engineering | Confidentiality / Integrity | The Ravelin 3DS SDK is taking different measures to maintain the integrity of both the app and the SDK. Nevertheless the integrator can increase the integrity of the app by obfuscating its source code. | Opt to obfuscate your source code. This will make reverse engineering your code much harder. |
The SDK was built with AGP 7.2.2, Gradle Wrapper version 7.6 and compiled with the help of the Kotlin plugin version 1.7.21.
Please see below a list of dependencies used by the Ravelin 3DS SDK:
Dependency Name | Version |
---|---|
ViewBinding (Apache2) | 7.2.2 |
Kotlinx-Serialization-Core (Apache2) | 1.4.1 |
Kotlinx-Serialization-Json (Apache2) | 1.4.1 |
Kotlinx-Coroutines-Core (Apache2) | 1.6.4 |
retrofit2-kotlinx-serialization-converter (Apache2) | 0.8.0 |
AppCompat (Apache2) | 1.5.1 |
Google-Android-Material (Apache2) | 1.7.0 |
Androidx-Activity-Ktx (Apache2) | 1.6.1 |
Androidx-Fragment-Ktx (Apache2) | 1.5.5 |
Androidx-ConstraintLayout (Apache2) | 2.1.4 |
Androidx-RecyclerView (Apache2) | 1.2.1 |
Androidx-CardView (Apache2) | 1.0.0 |
Androidx-Lifecycle-ViewModel-Ktx (Apache2) | 2.5.1 |
Androidx-LifeCycle-ViewModel-SavedState (Apache2) | 2.5.1 |
Androidx-LifeCycle-Process (Apache2) | 2.5.1 |
Androidx-LifeCycle-Common-Java8 (Apache2) | 2.5.1 |
Retrofit2 (Apache2) | 2.9.0 |
Retrofit2-Converter-Scalars (Apache2) | 2.9.0 |
okhttp3 (Apache2) | 4.9.2 |
Timber (Apache2) | 5.0.1 |
Androidx-Security (Apache2) | 1.1.0-alpha04 |
Bouncycastle (Apache2) | 1.70 |
Coil (Apache2) | 2.2.2 |
Nimbus (Apache2) | 8.15 |
Please append manually the following google play services (To take advantage of the google play services it is also required that google play services are installed on the user device):
Dependency Name | Comment for manual integration |
---|---|
Play-Services-Ads-Identifier (Apache2) | (Optional) Needed for fetching the application AD_ID |
Play-services-location (Apache2) | (Optional) Needed in order to access LocationServices API |
Play-services-base (Apache2) | (Optional) Needed for SSL Security provider update check |
Was this page helpful?