Android integration guide
The Bouncer Insight Android SDK integration guide.

Installation

1
dependencies {
2
implementation "com.getbouncer:cardverify-ui:2.1.0004"
3
implementation "com.getbouncer:insights:2.1.0004"
4
5
// you must select one of the following tensorflow-lite libraries. See the
6
// above chart to understand how each will affect the size of your app.
7
8
// If you're already using tensorflow lite elsewhere in your project, make
9
// sure you depend on the TFLite framework.
10
implementation 'org.tensorflow:tensorflow-lite:2.4.0'
11
12
// If you need to support both ARM and x86 devices (< 1% of all android
13
// devices), include this dependency.
14
implementation 'com.getbouncer:tensorflow-lite:2.1.0004'
15
16
// If you only plan to support ARM devices, use this library
17
implementation 'com.getbouncer:tensorflow-lite-arm-only:2.1.0004'
18
}
Copied!
If you are already using CardScan, leave that dependency in place.
By default, all of the ML models used to scan are downloaded during the call to CardScanActivity.warmUp. However, if you're concerned about scanning in areas with poor network connectivity, you may also want to include default versions of the scanning ML models in your app. Doing so will guarantee that scan will be available regardless of download speed or network connectivity.
There are two options for including ML models by default into your app: 1. minimal models 2. full models
See the charts above to determine how each of these dependencies will impact the size of your app.

Full Models

The full models are the same as those downloaded over the network. By adding this dependency to your app, you can ensure the maximum performance of the SDK regardless of network connection, but at the cost of a larger SDK.
1
dependencies {
2
implementation "com.getbouncer:scan-payment-full:2.1.0004"
3
}
Copied!

Minimal Models

The minimal models perform slightly slower than the full ML models. The SDK will attempt to download the full versions of the models during CardScanActivity.warmUp, which will override the minimal models. However, in the event the download takes too long or fails, the minimal ML models ensure that the scan will still function with only a small impact to performance.
1
dependencies {
2
implementation "com.getbouncer:scan-payment-minimal:2.1.0004"
3
}
Copied!

Alternative camera implementations

By default, bouncer uses the Android Camera 1 API. To use Camera2 or CameraX, add one of the following imports:
1
implementation "com.getbouncer:scan-camerax:2.1.0004"
2
3
// OR
4
5
implementation "com.getbouncer:scan-camera2:2.1.0004"
Copied!

Using Bouncer Insight

Bouncer Insight for Android consists of the following parts:
  1. 1.
    The bouncer card scanner for adding payment methods to user accounts
  2. 2.
    An instrumented payment method add form
  3. 3.
    Instrumented user events (signup, login)

Scanning to add a card

1. Library warm up

CardVerify will download ML models for use in verifying the authenticity of payment cards. To ensure these models are downloaded by the time CardVerify runs, please make sure to call the warmUp method on CardVerify as early in the app flow as possible. In most cases, this can be done in the onApplicationCreate method of your app. Note that warmUp processes on a background thread and will not affect your app's startup time.
Adding an application lifecycle listener
If your app doesn't already listen to application lifecycle events, you can extend the Application object and connect it using your manifest by setting android:name on your application node:
1
<application
2
android:icon="..."
3
android:label="..."
4
android:roundIcon="..."
5
android:name=".MyApplication">
6
7
...
8
9
</application>
Copied!
Create a class with the same name:
1
public class MyApplication extends Application {
2
public static final String API_KEY = "<your_api_key_here>";
3
4
@Override
5
public void onCreate() {
6
super.onCreate();
7
8
/*
9
* CardVerify will download ML models for use in verifying the
10
* authenticity of payment cards. To ensure these models are downloaded
11
* by the time CardVerify runs, please be sure to call the `warmUp`
12
* method on CardVerify as early in the app flow as possible. In most
13
* cases, this can be done in the `onApplicationCreate` method of your
14
* app. Note that `warmUp` processes on a background thread and will not
15
* affect your app's startup time.
16
*/
17
CardVerifyActivity.warmUp(this, API_KEY);
18
}
19
}
Copied!

2. Starting the flow

To start the flow, CardVerifyActivity provides a start method which takes the required parameters and launches the flow. Be sure to include a unique ID for the user that you will use to look up the user later.
Kotlin
Java
1
class LaunchActivity : Activity, CardVerifyActivityResultHandler {
2
3
override fun onCreate(savedInstanceState: Bundle?) {
4
super.onCreate(savedInstanceState)
5
setContentView(R.layout.activity_launch)
6
7
findViewById(R.id.scanCardButton).setOnClickListener { _ ->
8
CardVerifyActivity.start(
9
activity = LaunchActivity.this,
10
apiKey = MyApplication.API_KEY,
11
userId = MyUser.id // your unique ID for the user
12
)
13
}
14
}
15
16
override fun onActivityResult(
17
requestCode: Int,
18
resultCode: Int,
19
data: Intent
20
) {
21
super.onActivityResult(requestCode, resultCode, data)
22
23
if (CardVerifyActivity.isVerifyResult(requestCode)) {
24
CardVerifyActivity.parseVerifyResult(resultCode, data, this)
25
}
26
}
27
28
override fun cardScanned(
29
instanceId: String?,
30
scanId: String?,
31
scanResult: ScanResult
32
) {
33
// The user scanned a card. Details of the card are in the `scanResult`
34
// variable.
35
}
36
37
override fun enterManually(scanId: String?) {
38
// The user wants to manually enter a card, launch the manual card entry
39
// activity
40
}
41
42
override fun userCanceled(scanId: String?) {
43
// The user canceled the scan.
44
}
45
46
override fun cameraError(scanId: String?) {
47
// The scan failed because of a camera error.
48
}
49
50
override fun analyzerFailure(scanId: String?) {
51
// The scan failed to analyze images from the camera.
52
}
53
54
override fun canceledUnknown(scanId: String?) {
55
// The scan was canceled due to unknown reasons.
56
}
57
}
Copied!
1
class LaunchActivity
2
extends AppCompatActivity
3
implements CardVerifyActivityResultHandler {
4
5
private static final String API_KEY = "<your_api_key_here>";
6
7
@Override
8
protected void onCreate(@Nullable Bundle savedInstanceState) {
9
super.onCreate(savedInstanceState);
10
setContentView(R.layout.activity_launch);
11
12
findViewById(R.id.scanCardButton).setOnClickListener(v ->
13
CardVerifyActivity.start(
14
activity = LaunchActivity.this,
15
apiKey = MyApplication.API_KEY,
16
userId = MyUser.id // your unique ID for the user
17
)
18
);
19
}
20
21
@Override
22
protected void onActivityResult(
23
int requestCode,
24
int resultCode,
25
@Nullable Intent data
26
) {
27
super.onActivityResult(requestCode, resultCode, data);
28
29
if (CardVerifyActivity.isVerifyResult(requestCode)) {
30
CardVerifyActivity.parseVerifyResult(resultCode, data, this);
31
}
32
}
33
34
@Override
35
public void cardScanned(
36
@Nullable String instanceId,
37
@Nullable String scanId,
38
@NotNull ScanResult scanResult
39
) {
40
// The user scanned a card. Details of the card are in the `scanResult`
41
// variable.
42
}
43
44
@Override
45
public void enterManually(@Nullable String scanId) {
46
// The user wants to manually enter a card, launch the manual card entry
47
// activity
48
}
49
50
@Override
51
public void userCanceled(@Nullable String scanId) {
52
// the user canceled the scan
53
}
54
55
@Override
56
public void cameraError(@Nullable String scanId) {
57
// scan was canceled due to a camera error
58
}
59
60
@Override
61
public void analyzerFailure(@Nullable String scanId) {
62
// scan was canceled due to a failure to analyze camera images
63
}
64
65
@Override
66
public void canceledUnknown(@Nullable String scanId) {
67
// scan was canceled for an unknown reason
68
}
69
}
Copied!
To use Zero Fraud, invoke the CardVerifyActivity.start method and add implement the CardVerifyActivityResultHandler to be notified when a user has successfully scanned a card or has asked to enter details manually.

Instrumenting the payment card form

Soon, Bouncer will provide a payment card entry form. Until then, Bouncer Insights is designed to use your own existing payment card entry form.

Using your own card entry form

If you plan to build or already have your own card entry form, you can add bouncer instrumentation to the form.
1
const val RESULT_CARD = "card_params"
2
3
class AddCardActivity : AppCompatActivity(), CoroutineScope {
4
5
private val viewBinding by lazy { ActivityCardAddBinding.inflate(layoutInflater) }
6
private val bouncerInstrumentation by lazy { BouncerInstrumentedPaymentCardForm(this) }
7
8
override fun onCreate(savedInstanceState: Bundle?) {
9
super.onCreate(savedInstanceState)
10
setContentView(viewBinding.root)
11
12
viewBinding.addCardButton.setOnClickListener {
13
// Submit instrumentation to Bouncer servers
14
bouncerInstrumentation.onFormSubmit(this@AddCardActivity, "my_user_id")
15
setResult(Activity.RESULT_OK, Intent().putExtra(RESULT_CARD, viewBinding.cardAddWidget.cardParams))
16
finish()
17
}
18
19
try {
20
// Instrument the composite stripe CardMultilineWidget by describing the contents of the widget in order
21
bouncerInstrumentation.instrumentComposite(
22
view = viewBinding.cardAddWidget,
23
subviewOrder = listOf(
24
PaymentCardFormFieldType.CardNumber,
25
PaymentCardFormFieldType.Expiry,
26
PaymentCardFormFieldType.Cvc,
27
PaymentCardFormFieldType.PostalCode,
28
),
29
)
30
} catch (e: IncorrectViewCount) {
31
// If the wrong number of subviews is specified, determine how many are required
32
Log.e("Demo", "Invalid subview order for cardAddWidget, expected ${e.expectedViewCount}")
33
}
34
35
// Instrument an additional card holder name text field
36
bouncerInstrumentation.instrument(viewBinding.cardHolderName, PaymentCardFormFieldType.CardHolderName)
37
}
38
39
override val coroutineContext: CoroutineContext = Dispatchers.Default
40
}
Copied!
If you're not using the CardVerifyActivity.warmUp() at application start, you'll have to manually set your API key before instrumenting your payment form. You can do this by setting:
1
com.getbouncer.scan.framework.Config.apiKey = "<your_api_key_here>"
Copied!

Instrumenting User Events

For better fraud accuracy, add Bouncer instrumentation to the following events for your users:
  1. 1.
    User Creation
  2. 2.
    User Login
If you're not using the CardVerifyActivity.warmUp() at application start, you'll have to manually set your API key before instrumenting your user events. You can do this by setting:
1
com.getbouncer.scan.framework.Config.apiKey = "<your_api_key_here>"
Copied!

Tracking user creation

In your user signup flow, create an EventTracker by calling BouncerUserInstrumentation.trackUserCreate. Optionally, you can provide a unique device identifier if you have one.
1
class SignUpActivity : AppCompatActivity() {
2
3
private val bouncerTracker = BouncerUserInstrumentation.trackUserCreate()
4
5
// ...
6
7
private fun createUser(userName: String, password: String): Boolean {
8
// create a user
9
val user = MyApi.createUser(userName, password)
10
if (user != null) {
11
bouncerTracker.recordSuccess(
12
context = this,
13
userId = user.id,
14
loginIdentifier = userName,
15
)
16
}
17
18
return user != null
19
}
20
}
Copied!

Tracking user login

In your user login flow, create an EventTracker by calling BouncerUserInstrumentation.trackUserLogin. Optionally, you can provide the user ID and unique device identifier if you have them.
1
class UserLoginActivity : AppCompatActivity() {
2
3
private val bouncerTracker = BouncerUserInstrumentation.trackUserLogin()
4
5
// ...
6
7
private fun userLogIn(userName: String, password: String): Boolean {
8
// log the user in
9
val user = MyApi.getUserFromUserName(userName)
10
val authToken = user?.logIn(password)
11
12
if (authToken != null) {
13
bouncerTracker.recordSuccess(this, userName, user.id, metaData = null)
14
} else {
15
bouncerTracker.recordFailure(this, userName, user?.id, metaData = null)
16
showLoginFailed()
17
}
18
19
return authToken != null
20
}
21
}
Copied!

Getting a fraud risk score from Bouncer

Before allowing a transaction to proceed, your servers should query Bouncer servers with the userId, payment method identifier (e.g. stripe token), transaction amount, and transaction currency. Bouncer servers will respond with a risk score. See the Server Integration Guide for details.
Last modified 4mo ago