The Ravelin Mobile SDKs are critical to our ability to provide informed decisions to our clients.
Like the JavaScript library, the SDK enables:
We have two modules/dependencies within the SDK:
You may choose which functionality of the SDK to use. However, at a minimum, we advise that you use
the SDK to generate a reliable device ID and to send the additional device details for your app
traffic. Device IDs are critical throughout our fraud prevention tool, especially for use in our
graph database.
Use ravelin-core
for deviceId, fingerprinting and tracking activity and ravelin-encrypt
if using
card encryption.
The table below lists the available artefacts:
Artefact | Private release version | Public release version |
---|---|---|
ravelin-core | 3.0.3 | 3.1.0 |
ravelin-encrypt | 3.0.3 | 3.1.0 |
Before you can integrate with the Ravelin mobile SDK for Android, you will need:
ravelin-core
and ravelin-encrypt
are now public and may be accessed without credentials from Ravelin Maven/CloudRepo repository.Before you can integrate with the Ravelin mobile SDK for Android, you will need:
If you have any questions on getting started, please ask us in your Ravelin support channel on Slack.
The SDK supports a minimum Android API level: 21 - 5.0.0 LOLLIPOP
with some exceptions around
encryption (see below).
For Encryption:
Encryption, is available only for Android API level: 22 5.1 LOLLIPOP_MR1 and above, where you can
use the ravelin-encrypt
module which relies on native encryption.
The SDK is mainly written in Kotlin and compatible with Kotlin plugin version 1.8.20
There are two methods for installing the Ravelin Android SDK: via Gradle, or manually with a precompiled AAR file. Our preferred method is installation through Gradle, due to its ease of maintenance. In case you still prefer to install the SDK manually, make sure to also append its dependencies (described in Bundled Libraries).
Please note that the following setup is basic and doesn’t include buildSrc
configurations, version catalogs or convention plugins.
Both ravelin-core
and ravelin-encrypt
are public since version 3.1.0 and may be accessed without the use of credentials.
The artefacts may be imported from a maven repository as shown below:
allprojects {
repositories {
/* other repositories */
maven {
setUrl("https://maven.ravelin.com/public/repositories/core-android/")
}
}
}
The next step is to add the dependencies in the Module level build.gradle
(build.gradle.kts
) add Ravelin to the app dependencies:
dependencies {
/* other dependencies */
implementation 'com.ravelin.sdk:ravelin-core:3.1.0'
implementation 'com.ravelin.sdk:ravelin-encrypt:3.1.0'
}
dependencies {
/* other dependencies */
implementation("com.ravelin.sdk:ravelin-core:3.1.0")
implementation("com.ravelin.sdk:ravelin-encrypt:3.1.0")
}
Before attempting to use Gradle for Ravelin, ensure that you have a valid username and password for
the private Maven repository. This can be obtained from a Ravelin integrations engineer.
The credentials are required only for ravelin-core
and ravelin-encrypt
version 3.0.3 and below.
IMPORTANT - Do not store the repository credentials within Source Control. They can be stored in
the user’s gradle.properties
file.
// ~/.gradle/gradle.properties
ravelinRepoUsername=username
ravelinRepoPassword=password
Within the Project level build.gradle
, make sure the repositories include the appropriate Ravelin
maven repository:
allprojects {
repositories {
/* other repositories */
maven {
name "Ravelin"
credentials {
username "$ravelinRepoUsername"
password "$ravelinRepoPassword"
}
url "https://maven.ravelin.com/repositories/releases/"
}
}
}
In Kotlin DSL:
allprojects {
repositories {
/* other repositories */
maven {
credentials {
username = properties["ravelinRepoUsername"] as? String
password = properties["ravelinRepoPassword"] as? String
}
setUrl("https://maven.ravelin.com/repositories/releases/")
}
}
}
The next step is to add the dependencies in the Module level build.gradle
(build.gradle.kts
) add Ravelin to the app dependencies:
dependencies {
/* other dependencies */
implementation 'com.ravelin.sdk:ravelin-core:3.0.3'
implementation 'com.ravelin.sdk:ravelin-encrypt:3.0.3'
}
dependencies {
/* other dependencies */
implementation("com.ravelin.sdk:ravelin-core:3.0.3")
implementation("com.ravelin.sdk:ravelin-encrypt:3.0.3")
}
The Ravelin library may be imported as a standard AAR. Please be advised that we do not recommend manual installation and strongly advise that you use Gradle.
A common way to add the library into the project is to add it into a library in the Project
level build.gradle
(build.gradle.kts
) make sure the repositories include the local libraries
directory. Assuming that the AARs are stored within libs
:
Groovy:
allprojects {
repositories {
/* other repositories */
flatDir {
dirs 'libs'
}
}
}
Kotlin DSL
allprojects {
repositories {
/* other repositories */
flatDir {
dirs("libs")
}
}
}
Then in the Module level build.gradle
(build.gradle.kts
), add Ravelin to the app dependencies:
Groovy
dependencies {
implementation(name: 'ravelin', ext: 'aar')
}
Kotlin DSL
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar"))))
}
When building your project you will probably see a warning which says: ‘Using flatDir should be avoided because it doesn’t support any meta-data formats.’ You may ignore this warning. Alternatively, you may generate a new module in your application and fetch the library through this new module.
The Ravelin SDK is defining backup rules in its Manifest file. In case you have backup rules in your application manifest file, make sure to merge the 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"
/>
Backup rules for API level >= 31:
<?xml version="1.0" encoding="utf-8"?>
<data-extraction-rules disableIfNoEncryptionCapabilities="false">
<include
domain="sharedpref"
path="." />
<exclude
domain="sharedpref"
path="my_secret_shared_pref_data.xml" />
</data-extraction-rules>
Backup rules for API level < 31:
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<include
domain="sharedpref"
path="." />
<exclude
domain="sharedpref"
path="my_secret_shared_pref_data.xml" />
</full-backup-content>
There are two methods of updating the Ravelin Android SDK: via Gradle, or manually with a precompiled AAR file. Our preferred method is through Gradle, due to its ease of maintenance.
In the Module level build.gradle
change the dependencies to the latest SDK version number.
Groovy
dependencies {
/* other dependencies */
implementation 'com.ravelin.sdk:ravelin-core:3.1.0'
implementation 'com.ravelin.sdk:ravelin-encrypt:3.1.0'
}
To verify the latest Ravelin SDK version check our Release Notes section.
The Ravelin library may be imported as a standard AAR. Please be advised that we do not recommend manual update and strongly advise that you use Gradle.
Please follow the same steps mentioned in the Installing Manually sectionand make sure you are using the latest SDK version AAR.
For a better experience with Ravelin SDK each app has to provide a way for accessing users information. Here is a list of what each permission allows us to get from the users:
Information about users localization
In addition, the ACCESS_FINE_LOCATION permission is required in order to get the connection MAC address.
Information about users phone
Information about devices bluetooth.
Information about network capabilities.
Information about devices wireless connection interface.
Information about installed packages.
Allows internet connection access to background processes.
The SDK will retry events in case of issues like no internet connection or server errors. Since the retry is a background process that relies on internet connection this permission is needed for the retry functionality to work. If you do not grant this permission the retry functionality will not work and silently fail.
Please ensure only the publishable API key is used. The live secret API key should never be embedded into the app – it should only be used for server-to-server communications.
The Ravelin Android SDK has three static instance accessors:
RavelinSDK.createInstance
RavelinSDK.getSharedInstance
RavelinSDK.cleanup
While the first accessor is aimed to generate an instance of the SDK, the other two, should access
the singleton if its already been created. Calling getSharedInstance
or cleanup
before an
instance was created shall result with a RavelinError
returned to the application via
the RavelinCallback#failure
callback.
Calling RavelinSDK#createInstance
a second time will not create a second instance but will instead
return a previously created instance.
When the application finishes its use of the SDK, a cleanup
accessor should be called. It is aimed
to clear SDK resources and the SDK instance itself.
Kotlin
First call:
// MyApplication.kt
// using callbacks
RavelinSDK.createInstance(this, "publishable_key_live", object : RavelinCallback<RavelinSDK>() {
override fun success(ravelin: RavelinSDK) {
Log.d("Ravelin Setup Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("Ravelin Setup Error", error.message)
}
})
// without a callback
val ravelin: RavelinSDK = RavelinSDK.createInstance(this, "publishable_key_live")
Subsequent calls:
// MyActivity.kt
// using callback
RavelinSDK.getSharedInstance(object : RavelinCallback<RavelinSDK>() {
override fun success(ravelin: RavelinSDK) {
Log.d("Ravelin Setup Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("Ravelin Setup Error", error.message)
}
})
// without a callback
val ravelin: RavelinSDK = RavelinSDK.getSharedInstance()
Cleaning Resources:
RavelinSDK.cleanup(object : RavelinCallback<String>() {
override fun success(response: String) {
Log.d("Ravelin Setup Success", response)
}
override fun failure(error: RavelinError) {
Log.e("Ravelin Setup Error", error.message)
}
})
Java
First call:
// MyApplication.java
// null-safe inside callback
class Example {
RavelinSDK instance = RavelinSDK.Companion.createInstance(this, "publishable_key_live", new RavelinCallback<RavelinSDK>() {
@Override
public void success(RavelinSDK ravelinSDK) {
Log.d("Ravelin Setup Success", "hooray");
}
@Override
public void failure(@NotNull RavelinError ravelinError) {
Log.e("Ravelin Setup Error", ravelinError.getMessage());
}
});
// no callback, not null safe
RavelinSDK instance2 = RavelinSDK.Companion.createInstance(this, "publishable_key_live");
}
Subsequent calls:
// MyActivity.java
// null-safe with handled error message
class Example {
RavelinSDK instance1 = RavelinSDK.getSharedInstance(new RavelinCallback<RavelinSDK>() {
@Override
public void success(RavelinSDK ravelinSDK) {
Log.d("Ravelin Setup Success", "hooray");
}
@Override
public void failure(@NotNull RavelinError ravelinError) {
Log.e("Ravelin Setup Error", error.getMessage());
}
});
// nullable, no error message
RavelinSDK instance2 = RavelinSDK.Companion.getSharedInstance();
}
Cleaning Resources:
class Example {
void main() {
RavelinSDK.Companion.cleanup(new RavelinCallback<String>() {
@Override
public void success(String response) {
Log.d("Ravelin Setup Success", response);
}
@Override
public void failure(@NotNull RavelinError ravelinError) {
Log.e("Ravelin Setup Error", ravelinError.getMessage());
}
});
}
}
After first initialization, the SDK instance can be referenced anywhere
using RavelinSDK.getSharedInstance(...)
.
This section is relevant only to those apps which rely on the WorkManager API and initialize it manually.
Should this use case apply to your app, please make sure to meet the following requirement:
Configuration.Provider
Interface. A minimal setting of
the configuration object would be:Kotlin
class YourApplication : Application(), Configuration.Provider {
//...
override fun onCreate() {
super.onCreate()
val configuration = workManagerConfiguration
WorkManager.initialize(this, configuration)
}
override fun getWorkManagerConfiguration(): Configuration =
Configuration.Builder()
.build()
//...
}
Java
public class YourApplication extends Application implements Configuration.Provider {
//...
@Override
public void onCreate() {
super.onCreate();
Configuration config = getWorkManagerConfiguration();
WorkManager.initialize(this, config);
}
@NonNull
@NotNull
@Override
public Configuration getWorkManagerConfiguration() {
return new Configuration.Builder().build();
}
//...
}
Depending on your integration, you may want to encrypt card details via the SDK. The SDK can be used
to allow the secure sharing of card information with Ravelin whilst removing the need to handle
PCI-compliant data. When collecting the card details,
using CardDetails(pan, month, year, nameOnCard)
. pan
, month
, year
are required,
while nameOnCard
is optional.
The CardDetails
are then passed into the encryptCard
method along with the appropriate RSA key
to produce an EncryptedCard
instance with encrypted ciphers. Encrypted cards are validated prior
to encryption. You can perform this validation yourself by calling CardDetails#validate
. The
optional callback parameter will inform you of a success or failure. In case of a failure the method
returns null, and if successful the newly created valid CardDetails
is created with extra values
stripped, ready to be encrypted.
Ravelin Android encryption is only available for Android 5.1 LOLLIPOP_MR1
API level: 22 and above,
since it uses the native encryption provided within the standard Ravelin SDK.
Validation is performed, confirming that expiry dates are valid, that the PAN is at least 12 characters and that the name on the card is valid. Should any validation checks fail, nil is returned from the method. Pass an error by ref to determine the cause of failure if any occurs.
The basic checks performed by the validation are:
Please note, the use of encryption is entirely optional and not required as part of your
integration. If you are confused about whether or not you should use encryption, please contact an
integration engineer. If you do not want to use encryption at all, please make sure not to
use encryptCard
.
Kotlin
val cardDetails = CardDetails("1234 1234 1234 1234", "02", "18", "Dr Jilly McJillson")
// null safe callback
RavelinEncrypt().encryptCard(cardDetails, "RSA-Key",
object : EncryptCallback<EncryptedCard>() {
override fun failure(error: EncryptError) {
Log.d("Card encryption Error", error.message)
}
override fun success(result: EncryptedCard?) {
Log.d("Card encryption Success", result.toString())
}
})
// nullable
val encryptedCard = RavelinEncrypt().encryptCard(cardDetails, "2|rsakeykeykeykeykeykey")
Java
class Example {
final CardDetails cardDetails = new CardDetails("1234 1234 1234 1234", "02", "18", "Dr Jilly McJillson");
// null safe callback
EncryptedCard encryptedCard = RavelinEncrypt().encryptCard(cardDetails, "RSA-Key",
new EncryptCallback<CardDetails>() {
public void failure(EncryptError error) {
Log.d("Card encryption Error", error.getMessage());
}
public void success(CardDetails result) {
Log.d("Card encryption Success", result.toString());
}
});
}
// nullable
class Example {
final EncryptedCard encryptedCard = RavelinEncrypt().encryptCard(cardDetails, "2|rsakeykeykeykeykeykey");
}
Kotlin
val cardDetails = CardDetails("1234 1234 1234 1234", "02", "18", "Dr Jilly McJillson")
cardDetails.validate(object : EncryptCallback<CardDetails>() {
override fun failure(error: EncryptError) {
Log.d("Card Validation Error", error.message)
}
override fun success(result: CardDetails?) {
Log.d("Card Validation Success", "hooray")
}
})
RavelinEncrypt().encryptCard(cardDetails, "RSA-Key",
object : EncryptCallback<EncryptedCard>() {
override fun failure(error: EncryptError) {
Log.d("Card encryption Error", error.message)
}
override fun success(result: EncryptedCard?) {
Log.d("Card encryption Success", result.toString())
}
})
Java
class Example {
final CardDetails cardDetails = new CardDetails("1234 1234 1234 1234", "02", "18", "Dr Jilly McJillson");
// null safe callback
CardDetailks cardDetails = cardDetails.validate(new EncryptCallback<CardDetails>() {
@Override
public void success(CardDetails result) {
Log.e("Card Validation Success", "hooray");
}
@Override
public void failure(EncryptError error) {
Log.e("Card Validation Error", error.getMessage());
}
});
EncryptedCard encryptedCard = RavelinEncrypt().encryptCard(cardDetails, "RSA-Key",
new EncryptCallback<CardDetails>() {
@Override
public void failure(EncryptError error) {
Log.d("Card encryption Error", error.getMessage());
}
@Override
public void success(CardDetails result) {
Log.d("Card encryption Success", result.toString());
}
});
}
Using the Ravelin Android SDK, you can capture various built in events along with your own custom events that can later be viewed in the Ravelin dashboard. This can be very useful for analysts to gain additional context during an investigation. For example, if you can see that a user is going through unexpected parts of your customer journey at a set speed on a new device that could indicate suspicious activity.
Track events may be called with either a RavelinRequestCallback
callback or no callback. Using a
callback, the network request will be triggered immediately.
These are the available predefined events:
The full documentation is present on the javadocs to better help implementation.
To be used at any appropriate checkpoint to profile a user’s device.
Sends the device Fingerprint to Ravelin. If a Fingerprint has not been generated by this point, it will be generated by calling this method.
Ensure that the customerId is set before trackFingerprint() is called.
Only takes an optional callback
.
Kotlin
// set Customer ID
ravelin.customerId = "12346578"
// immediately call asynchronously
ravelin.trackFingerprint(object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
// set Customer ID
void main() {
ravelin.setCustomerId("12346578");
// immediately call asynchronously
ravelin.trackFingerprint(new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
To indicate when the user hits a new page. We would like this to be used for every new page or screen the user goes to.
Required pageName
, optional payload
to be serialized and optional callback
. Note: payload is
of type LinkedHashMap<String, Any?>? but will accept only the following types for the value entry:
Number?, String?, Boolean?, List<Any?>? where Any? could include combinations of Number?, String?
and Boolean? In case you require support for additional types, please contact us and we would
support them in future versions.
Kotlin
// immediately call asynchronously
ravelin.trackPage(
"Product List - Toothbrushes",
linkedMapOf("Property 1" to "Custom", "Property 2" to "Data"),
object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
void main() {
// immediately call asynchronously
final LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("Proeprty 1", "Custom");
map.put("Proeprty 2", "Data");
ravelin.trackPage("Product List - Toothbrushes", map, new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
To be used when a user performs a search.
There is an optional searchValue property that can be added to let us know about the search term.
Required pageTitle
, optional searchValue
to be serialized and optional callback
.
Kotlin
// immediately call asynchronously
ravelin.trackSearch(
"Product List - Toothbrushes",
"search value",
object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
void main() {
// immediately call asynchronously
ravelin.trackSearch("Product List - Toothbrushes", "Search value", new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
To be used when a user selects or changes a product option like colour, size or delivery option.
There is an optional option
property that can be added to let us know about the what option was
selected, we suggest using one of the following values colour
, size
, date
, time
, seat
, ticketType
, delivery option
, but other values are accepted.
There is also an optional optionValue
property that can be sent to let us know what value was
selected.
Required pageTitle
, optional option
and optionValue
to be serialized and optional callback
.
Kotlin
// immediately call asynchronously
ravelin.trackSelectOption(
"Product Page",
"Option",
"Option Value",
object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
void main() {
// immediately call asynchronously
ravelin.trackSelectOption("Product Page", "Option", "Option Value", new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
To be used when an item is added or removed from the cart.
There are two optional properties itemName
and quantity
that can be added to let us know the
product name and the quantity.
Required pageTitle
, optional itemName
and quantity
to be serialized and optional callback
.
Kotlin
// immediately call asynchronously
ravelin.trackAddToCart("Product Page", "Item Name", 5, object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
void main() {
// immediately call asynchronously
ravelin.trackAddToCart("Product Page ", "Item Name", 5, new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
To be used when an item is added or removed from the wishlist.
There is an optional itemName
property that can be added to let us know the product name.
Required pageTitle
, optional itemName
to be serialized and optional callback
.
Kotlin
// immediately call asynchronously
ravelin.trackAddToWishlist("Product Page", "Item Name", object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
void main() {
// immediately call asynchronously
ravelin.trackAddToWishlist("Product Page", "Item Name", new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
To be used when a user changes the language of the application. The language
is an optional parameter and it should be compatible with ISO-639.
Examples for accepted values: en, en-us, en-gb, da, cs, EN-GB, EN-US, En-uS
When language
is not set, this track session event may only indicate that the application language has changed without the actual new value.
Required pageTitle
, optional language
to be serialized and optional callback
.
Kotlin
// immediately call asynchronously
ravelin.trackLanguageChange("Product Page", "en-us", object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
void main() {
// immediately call asynchronously
ravelin.trackLanguageChange("Product Page", "en-us", new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
To be used when a user changes the currency used by the application. The currency
itself is an optional parameter and it should be compatible with ISO-4217.
Examples for accepted values: EUR, USD, NZD, eur, usd, nzd, nZd
When currency
is not set, this track session event may only indicate that the application currency has changed without the actual new value.
Required pageTitle
, optional currency
to be serialized and optional callback
.
Kotlin
// immediately call asynchronously
ravelin.trackCurrencyChange("Product Page", "EUR", object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
void main() {
// immediately call asynchronously
ravelin.trackCurrencyChange("Product Page", "EUR", new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
To be used when the user interacts with product content like plays a video, expands a photo, expands product details.
There is an optional contentType
property to let us know what content the user interacted with, we
suggest using one of the following values video
, photo
, productDescription
, deliveryOptions
,
but other values are accepted.
Required pageTitle
, optional contentType
to be serialized and optional callback
.
Kotlin
// immediately call asynchronously
ravelin.trackViewContent("Product Page", "Content Type", object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
java
class Example {
void main() {
// immediately call asynchronously
ravelin.trackViewContent("Product Page", "Content Type", new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
Tracks a user or app event.
Required eventType
, optional pageTitle
, optional payload
to be serialized and
optional callback
.
Note: payload is of type LinkedHashMap<String, Any?>? but will accept only the following types for the value entry: Number?, String?, Boolean?, List<Any?>? where Any? could include combinations of Number?, String? and Boolean? In case you require support for additional types, please contact us and we would support them in future versions.
Kotlin
// immediately call asynchronously
ravelin.trackEvent(
"app open",
"login activity",
linkedMapOf(
"Property 1" to "Custom",
"Property 2" to 1,
"Property 3" to true,
"Property4" to null,
"Property 5" to listOf(1, null, true, 1.234)
),
object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
void main() {
final LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("Proeprty 1", "Custom");
map.put("Proeprty 2", 1);
map.put("Proeprty 3", true);
map.put("Proeprty 4", null);
List<Object> list = new ArrayList();
list.add(1);
list.add(null);
list.add(true);
list.add(1.234);
// immediately call asynchronously
ravelin.trackEvent("app open", "login activity", map, new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
Tracks a user login event.
Required customerId
, optional pageTitle
, optional payload
to be serialized and
optional callback
.
Note: payload is of type LinkedHashMap<String, Any?>? but will accept only the following types for the value entry: Number?, String?, Boolean?, List<Any?>? where Any? could include combinations of Number?, String? and Boolean? In case you require support for additional types, please contact us and we would support them in future versions.
Kotlin
// immediately call asynchronously
ravelin.trackLogIn(
"15464811",
"login activity",
linkedMapOf("Class" to "Mage"),
object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
void main() {
final HashMap<String, String> map = new LinkedHashMap<>();
map.put("Class", "Mage");
// immediately call asynchronously
ravelin.trackLogIn("app open", "login activity", map, new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
}
);
}
}
Tracks a user logout event.
pageTitle
and payload
are optional serialized parameters. callback
is optional.
Note: payload is of type LinkedHashMap<String, Any?>? but will accept only the following types for the value entry: Number?, String?, Boolean?, List<Any?>? where Any? could include combinations of Number?, String? and Boolean? In case you require support for additional types, please contact us and we would support them in future versions.
Kotlin
// immediately call asynchronously
ravelin.trackLogOut(
"User Account",
linkedMapOf("Class" to "Mage"),
object : RavelinRequestCallback() {
override fun success() {
Log.e("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
void main() {
final HashMap<String, String> map = new LinkedHashMap<>();
map.put("Class", "Mage");
// immediately call asynchronously
ravelin.trackLogOut("login activity", map, new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(@NotNull RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
This method is used primarily by the Ravelin PasteEventListener
but can be used directly if
required.
Required value
, optional pageTitle
and optional callback
.
Kotlin
// immediately call asynchronously
ravelin.trackPaste("checkout activity", pastedCharacters, object : RavelinRequestCallback() {
override fun success() {
Log.d("API Request Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("API Request Error", error.message)
}
})
Java
class Example {
void main() {
// immediately call asynchronously
ravelin.trackPaste("login activity", pastedCharacters, new RavelinRequestCallback() {
@Override
public void success() {
Log.d("API Request Success", "hooray");
}
@Override
public void failure(RavelinError error) {
Log.e("API Request Error", error.getMessage());
}
});
}
}
The PasteEventListener
is a TextWatcher
that reports back when a user has pasted into an input
box through a PasteEventListener.OnPaste
interface.
Internally, the PasteEventListener
will report back to Ravelin the pasted text after obfuscating
input. The input should be obfuscated automatically as part of PasteEventListener
- this is
important because we don’t want to be accidentally sent sensitive information that may be copied and
pasted (for example BINs).
This is primarily for use on PAN input fields but may be used anywhere.
Kotlin
val view = // Your EditText
view.addTextChangedListener(
PasteListener("page", object : PasteListener.OnPaste() {
fun pasted() {
Log.d("Paste Event", "user has pasted some content")
}
})
)
Java
class Example {
void main() {
EditText view = // Your EditText
view.addTextChangedListener(
new PasteListener("page", new PasteListener.OnPaste() {
@Override
public void pasted() {
Log.d("Paste Event", "user has pasted some content");
}
})
);
}
}
This section is relevant for application providers who use proguard to optimise and obfuscate their source code and app resources.
Since version 3.1.0, both ravelin-core
and ravelin-encrypt
source code is obfuscated with the help of proguard. To avoid additional obfuscation/optimisation/shrinking
of these libraries or to avoid obfuscation of lower versions than 3.1.0, please add the following keep rules to your proguard configuration file:
-keep interface com.ravelin.** { *; }
-keep,includecode class com.ravelin.** { *; }
The Ravelin SDK generates a unique DeviceId during the initialisation stage.
The following code snippets show how to access the deviceId.
class Example {
fun getDeviceId(): String = run {
val ravelinSdk = RavelinSDK.getSharedInstance()
ravelinSdk.getDeviceId()
}
}
class Example {
String getDeviceId() {
RavelinSdk ravelinSdk = RavelinSDK.Companion.getSharedInstance();
if (ravelinSdk != null) {
return ravelinSdk.getDeviceId();
} else {
return null;
}
}
}
In the following form, we collect card details from the customer, encrypt them and send that encrypted values (the cipher) back to your server.
class ShopApplication : Application() {
override fun onCreate() {
// Create instance referencing the application.
// This can be done anywhere if the application does not extend Application
RavelinSDK.createInstance(this, "api_key_123456789",
object : RavelinCallback<RavelinSDK>() {
override fun success(instance: RavelinSDK) {
Log.e("Ravelin Setup Success", "hooray")
}
override fun failure(error: RavelinError) {
Log.e("Ravelin Setup Error", error.message)
}
})
}
}
class ShopActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val customerId = "1234" // get customerId from your login process
val ravelin = RavelinSDK.getSharedInstance(object : RavelinCallback<RavelinSDK>() {
override fun success(result: RavelinSDK) {
result.customerId =
customerId // set customer id either directly or via trackLogin method
// this id will then be sent with all subsequent tracking events
result.orderId = "your own order ID" // set order id to your own order reference
result.trackPage("Shopping Page")
}
override fun failure(error: RavelinError) {
Log.e("Ravelin Setup Error", error.message)
}
})
val cardNumberTextView = findViewById<TextView>(R.id.pan)
val expirationMonthTextView = findViewById<TextView>(R.id.expiration_month)
val expirationYearTextView = findViewById<TextView>(R.id.expiration_year)
val nameOnCardTextView = findViewById<TextView>(R.id.name_on_card)
findViewById<Button>(R.id.payButton).setOnClickListener {
val pan = cardNumberTextView.text.toString()
val month = expirationMonthTextView.text.toString()
val year = expirationYearTextView.text.toString()
val name = nameOnCardTextView.text.toString()
val cardDetails = CardDetails(pan, month, year, name)
if (ravelin != null) {
ravelin.encryptCard(
cardDetails,
"RSA-KEY",
object : RavelinCallback<EncryptedCard>() {
override fun success(result: EncryptedCard) {
Log.e("Card Encryption Success", "hooray")
sendEncryptedDetailsToYourServer(encryptedCardDetails)
}
override fun failure(error: RavelinError) {
Log.e("Card Encryption Error", error.message)
}
})
}
}
}
}
public class ShopApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// Create instance referencing the application.
// This can be done anywhere if the application does not extend Application
RavelinSDK.Companion.createInstance(this, "api_key_123456789", new RavelinCallback<RavelinSDK>() {
@Override
public void success(RavelinSDK result) {
Log.e("Ravelin Setup Success", "hooray");
}
@Override
public void failure(@NotNull RavelinError error) {
Log.e("Ravelin Setup Error", error.getMessage());
}
});
}
}
public class ShopActivity extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final String customerId = "1234"; // get customerId from your login process
final RavelinSDK ravelin = RavelinSDK.Companion.getSharedInstance(new RavelinCallback<RavelinSDK>() {
@Override
public void success(RavelinSDK result) {
result.setCustomerId(customerId); // set customer id either directly or via trackLogin method
// this id will then be sent with all subsequent tracking events
result.setOrderId("your own order ID"); // set order id to your own order reference
result.trackPage("Shopping Page");
}
@Override
public void failure(RavelinError error) {
Log.e("Ravelin Setup Error", error.getMessage());
}
});
final TextView cardNumberTextView = findViewById(R.id.pan);
final TextView expirationMonthTextView = findViewById(R.id.expiration_month);
final TextView expirationYearTextView = findViewById(R.id.expiration_year);
final TextView nameOnCardTextView = findViewById(R.id.name_on_card);
findViewById(R.id.payButton).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String pan = cardNumberTextView.getText().toString();
String month = expirationMonthTextView.getText().toString();
String year = expirationYearTextView.getText().toString();
String name = nameOnCardTextView.getText().toString();
CardDetails cardDetails = new CardDetails(pan, month, year, name);
if (ravelin != null) {
ravelin.encryptCard(cardDetails, "RSA-KEY", new RavelinCallback<EncryptedCard>() {
@Override
public void success(EncryptedCard result) {
Log.e("Card Encryption Success", "hooray");
sendEncryptedDetailsToYourServer(encryptedCardDetails);
}
@Override
public void failure(@NotNull RavelinError error) {
Log.e("Card Encryption Error", error.getMessage());
}
});
}
}
});
}
}
Once the cipher is received by your server, the API request to Ravelin in which a fraud recommendation is requested should use this cipher value:
/* Server-side */
var card = JSON.parse(request.params['ravelinCipherText']);
card.methodType = 'paymentMethodCipher';
var action = request('https://pci.ravelin.com/v2/checkout?score=true', {
// ...
'paymentMethod': card,
});
createInstance
createInstance(application: Application, apiKey: String, callback: RavelinCallback<RavelinSDK>? = null) : RavelinSDK?
Create a singleton instance of the Ravelin SDK with your Publishable API Key.
Parameters
Parameter | Type | Description |
---|---|---|
application | Application | The Android Application class that this instance is attached to. |
apiKey | String | Your Publishable API Key. See Authentication for where to find this. |
callback | RavelinCallback | Optional callback. |
Return value
A nullable singleton instance of the class
Create a new instance of the RavelinSDK. If this is called a second time, no new instance is created.
getSharedInstance
getSharedInstance(callback: RavelinCallback<RavelinSDK>? = null): RavelinSDK?
Method for accessing the required methods for communicating with Ravelin APIs.
Only to be called after the Ravelin SDK has been first initialised using your Publishable API Key
and/or RSA key otherwise the RavelinCallback#failure
callback method is triggered.
Parameters
Parameter | Type | Description |
---|---|---|
callback | Application | An optional callback that is responsible to warn whether the RavelinSDK instance could be retrieved with success or not. |
Return Value
An instance of a previously created RavelinSDK, null if it is not existent.
getDeviceId()
Utility method that allows user to know the unique identifier that represents users device.
A String identifying the device - persistent across Google accounts.
trackFingerprint
trackFingerprint(callback: RavelinRequestCallback? = null)
Fingerprints the device and sends results to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
callback | RavelinRequestCallback? | Optional callback for the API response. |
trackPage
trackPage(pageTitle: String, payload: LinkedHashMap<String, Any?>? = null, callback: RavelinRequestCallback? = null)
Sends a track page event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page. |
payload | LinkedHashMap<String, Any?>? | Additional data to be sent to Ravelin. |
callback | RavelinRequestCallback? | Optional callback for the API responses. |
trackSearch
trackSearch(pageTitle: String, searchValue: String? = null, callback: RavelinRequestCallback? = null)
Sends a track search event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page. |
searchValue | String? | Optional string that was used to perform a search. |
callback | RavelinRequestCallback? | Optional callback for the API responses. |
trackSelectOption
trackSelectOption(pageTitle: String, option: String? = null, optionValue: String? = null, callback: RavelinRequestCallback? = null)
Sends a track selected option event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page. |
option | String? | The name of the option, optional. Example: {colour, size, date, time, seat, ticketType} |
optionValue | String? | The value of the option, optional. Example: {blue, M, 14, first class} |
callback | RavelinRequestCallback? | Optional callback for the API responses. |
trackAddToCart
trackAddToCart(pageTitle: String, itemName: String? = null, quantity: Int? = 0, callback: RavelinRequestCallback? = null)
Sends a track add to cart event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page. |
itemName | String? | The name of the item, optional. |
quantity | String? | The quantity of the item, optional. |
callback | RavelinRequestCallback? | Optional callback for the API responses. |
trackRemoveFromCart
trackRemoveFromCart(pageTitle: String, itemName: String? = null, quantity: Int? = 0, callback: RavelinRequestCallback? = null)
Sends a track remove from cart event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page. |
itemName | String? | The name of the item, optional. |
quantity | String? | The quantity of the item, optional. |
callback | RavelinRequestCallback? | Optional callback for the API responses. |
trackAddToWishlist
trackAddToWishlist(pageTitle: String, itemName: String? = null, callback: RavelinRequestCallback? = null)
Sends a track add to wishlist event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page. |
itemName | String? | The name of the item, optional. |
callback | RavelinRequestCallback? | Optional callback for the API responses. |
trackRemoveFromWishlist
trackRemoveFromWishlist(pageTitle: String, itemName: String? = null, callback: RavelinRequestCallback? = null)
Sends a track remove from wishlist event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page. |
itemName | String? | The name of the item, optional. |
callback | RavelinRequestCallback? | Optional callback for the API responses. |
trackLanguageChange
trackLanguageChange(pageTitle: String, language: String? = null, callback: RavelinRequestCallback? = null)
Sends a track language changed event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page. |
language | String? | An ISO-639-1 representation of the new language, optional. |
callback | RavelinRequestCallback? | Optional callback for the API responses. |
trackCurrancyChange
trackCurrancyChange(pageTitle: String, currency: String? = null, callback: RavelinRequestCallback? = null)
Sends a track currency changed event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page. |
currency | String? | An ISO-4217 representation of the new currency, optional. |
callback | RavelinRequestCallback? | Optional callback for the API responses. |
trackViewContent
trackViewContent(pageTitle: String, contentType: String? = null, callback: RavelinRequestCallback? = null)
Sends a track view content event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The title of the current page. |
contentType | String? | The type of the content, optional. Examples: {video, photo, productDescription, deliveryOptions} |
callback | RavelinRequestCallback? | Optional callback for the API responses. |
trackEvent
trackEvent(eventType: String, pageTitle: String? = null, payload: LinkedHashMap<String, Any?>? = null, callback: RavelinRequestCallback? = null)
Sends a track event to Ravelin. Use this method to send custom events and data to analyse in your dashboard.
Parameters
Parameter | Type | Description |
---|---|---|
eventType | String | The type of triggered event. |
pageTitle | String? | The title of the current page. |
payload | LinkedHashMap<String, Any?>? | Optional object to be serialized and transmitted with the event. |
callback | RavelinRequestCallback | Optional callback for the API request communication. |
trackLogIn
trackLogIn(customerId: String, pageTitle: String? = null, payload: LinkedHashMap<String, Any?>? = null, callback: RavelinRequestCallback? = null)
Sends a track login event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
customerId | String | The Customer identifier as a String. |
pageTitle | String | The page where the login occurred. |
payload | LinkedHashMap<String, Any?> | Additional data to be sent to Ravelin. |
callback | RavelinRequestCallback | Optional callback for the API responses. |
trackLogOut
trackLogOut(pageTitle: String? = null, payload: LinkedHashMap<String, Any?>? = null, callback: RavelinRequestCallback? = null)
Ends current Ravelin session and sends logout event to Ravelin.
Parameters
Parameter | Type | Description |
---|---|---|
pageTitle | String | The page where the logout occurred . |
payload | LinkedHashMap<String, Any?>? | Additional data to be sent to Ravelin. |
callback | RavelinRequestCallback | Optional callback for the API responses. |
trackPaste
trackPaste(value: String, pageTitle: String? = null, callback: RavelinRequestCallback? = null)`
Track a paste event with the content tracked.
Parameters
Parameter | Type | Description |
---|---|---|
value | String | Pasted text string. |
pageTitle | String | Optional. The page where the pasting occurred. |
callback | RavelinRequestCallback | Optional callback for the API responses. |
Customer ID
Your chosen customer ID
Kotlin
ravelin.customerId
ravelin.customerId = "cust-1"
Java
ravelin.getCustomerId();
ravelin.setCustomerId("cust-1");
Temp Customer ID
A temporary customer ID that will always be non-blank. Setting to a null, blank or empty value will generate a new temporary customer ID.
Kotlin
ravelin.tempCustomerId
ravelin.tempCustomerId = "temp-1"
Java
ravelin.getTempCustomerId();
ravelin.setTempCustomerId("temp-1");
Order ID
The ID for this specific order.
Kotlin
ravelin.orderId
ravelin.orderId = "930393-BBB"
Java
ravelin.getOrderId();
ravelin.setOrderId("930393-BBB");
Session ID
A temporary session ID that will always be non-blank. Setting to a null, blank or empty value will generate a new session ID.
Kotlin
ravelin.sessionId
ravelin.sessionId = null
Java
ravelin.getSessionId();
ravelin.setSessionId(null);
Device ID
A unique device identifier that is calculated at runtime.
ravelin.getDeviceId()
ravelin.getDeviceId();
encryptCard
encryptCard(cardDetails: CardDetails, rsaKey: String, callback: RavelinCallback<EncryptedCard>? = null)
Encrypt provided [CardDetails] ready to be sent to Ravelin
Parameters
Parameter | Type | Description |
---|---|---|
cardDetails | CardDetails | the plain text [CardDetails] to be encrypted |
rsaKey | String | the RSA key provided |
callback | RavelinCallback | to handle null-safe results or handle errors |
Return value
A nullable encrypted card details
Providing this library would not have been possible without the stellar works upon which it relies:
Dependency Name | Version | Comment for manual integration |
---|---|---|
*** Serialization*** | ||
Kotlin Serialization(Apache2) | 1.5.0 | |
Kotlin Serialization Converter(Apache2) | 1.0.0 | |
Coroutines | ||
Kotlin Coroutines(Apache2) | 1.6.4 | |
Retrofit (Apache2) | 2.9.0 | |
Http Client | ||
okhttp3 (Apache2) | 4.10.0 | |
okhttp3-logging-interceptor (Apache2) | 4.10.0 | |
Architecture Components | ||
KTX (Apache2) | 1.9.0 | |
WorkManager (Apache2) | 2.8.1 | |
AppCompat (Apache2) | 1.6.1 | Only when integrating Ravelin encryption |
Local Database | ||
Room (Apache2) | 2.5.2 | |
Room Ktx (Apache2) | 2.5.2 | |
Room Compiler (Apache2) | 2.5.2 | for Annotation processing with Kapt |
Security Crypto (Apache2) | 1.1.0-alpha04 | |
Dependency Injection | ||
Dagger2 (Apache2) | 2.46.1 | |
Dagger2-Android (Apache2) | 2.46.1 | |
Dagger-Compiler (Apache2) | 2.46.1 | for Annotation processing with Kapt |
Dagger-Android-Processor (Apache2) | 2.46.1 | for Annotation processing with Kapt |
Logging | ||
Timber (Apache2) | 5.0.1 | |
Location | ||
Play-services-location (Apache2) | 21.0.1 |
Important! Due to a breaking change in play-services-location in version 21.0.0, use versions older than 3.0.1 only in case you are working with play-services-location older than version 21.0.0. In case you have a version of play-services-location equal or greater than 21.0.0, please use Ravelin SDK version 3.0.1+.
This is a special release. Only ravelin-core library is updated in this release.
ravelin-core
library is now public and can be accessed without credentials.trackCurrencyChange
and trackLanguageChange
are now available.ravelin-core
library source code is obfuscated again with proguard. Please see Proguard rules required to avoid additional obfuscation of the library by the app provider.trackPaste
session tracking function.This is a special version of ravelin-core introducing several updates aimed only for clients of play-services-location older than 21.0.0. We have no plans to introduce new features or releases related to this version in the future, hence we recommend to use it only in case you are working with play-services-location older than version 21.0.0.
trackPaste
session tracking function.This is a special release. Only ravelin-encrypt library is updated in this release.
cleanup
to clean resources when the application finishes its
work with the SDK.Timber
for logging messages.Fatal Exception: java.lang.IllegalStateException: error must not be null
Fatal Exception: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
Was this page helpful?