Enable Tap to Phone Android SDK
Enable Tap to Phone payments on your platform's Android application
The Tap to Phone Android SDK is currently in Beta.Rainforest reserves the right to introduce breaking changes during this period. You will be notified of any updates prior to the release.
Please contact Rainforest support or your Platform Success Manager for more information on this feature.
Feature requirements🔐 Rainforest must enable the platform to access this feature
💲 Billing fees associated to this feature
Implement Tap to Phone Android SDK into your platform's Android application with five steps:
- Provide Rainforest your application information for Tap to Phone onboarding
- Install SDK dependencies
- Set up your application to use the SDK
Tap to phone onboarding
Android Tap to Phone onboarding may take up to 2 weeksPlease provide the following onboarding requirements as soon as possible. Onboarding is required to take Sandbox and Production payments.
In order to take Android Tap to Phone payments, Rainforest must perform Android Tap to Phone onboarding on your behalf. Rainforest will need you to provide the following information for onboarding:
- App package name
- App signing key fingerprint
- App Google Play integrity keys
Package name
Your application's package name (example: com.rainforestpay.mobilepay)
Signing key fingerprint
You must generate a signing key and give us the fingerprint for the key. We only need the fingerprint, not the key itself.
# generate a new key
keytool -genkey -v -keystore my-signing-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-signing-key-alias
[provide keystore and key password when prompted]
# get fingerprint of key
keytool -exportcert -alias my-signing-key-alias -keystore my-signing-keystore.jks -storepass [password provided above] | \
openssl sha256 -binary | \
openssl base64
Google Play integrity keys
In order to verify your application and owner identity, we need to decrypt verification information from the Google Play Store.
Your app needs Play Integrity enabled:
- Go to app dashboard in the Play console
- Go to Test and release > App Integrity
- Select Link cloud project
- Follow prompts to link your project
Rainforest will need your Google Play Integrity keys to decrypt the Integrity Verification response:
- Go to app dashboard in the Play console
- Go to Test and release > App Integrity
- Play Integrity API Settings > Classic requests
- Choose option to "Manage and download my response encryption keys"
- Follow directions to download the decryption and verifications
- Provide Rainforest with the
DECRYPTION_KEYandVERIFICATION_KEYvalues
Device Requirements
Certain features and criteria must be met to accept Tap to Phone payments on a device:
- Android 11.0 (API level 30) or higher operating system.
- Has NFC capabilities.
- Has location permissions enabled for host application.
- Has bluetooth permissions enabled for host application.
- Has identity security enabled on the device via face recognition, fingerprint or passcode.
Import SDK dependencies
Use our maven repos
Rainforest hosts its SDK in a Gitlab-provided Maven repository. Configure your application with the maven repo URL
# settings.gradle.kts
repositories {
google()
mavenCentral()
# CloudCommerce AAR
maven { url = uri("https://gitlab.com/api/v4/projects/77749278/packages/maven") }
# Rainforest SDK AAR
maven { url = uri("https://gitlab.com/api/v4/projects/77784047/packages/maven") }
}Install Rainforest SDK dependencies
The Rainforest Tap UI utilizes the Jetpack Compose library. The dependency should be configured and enabled.
- Add Compose at the project level
# build.gradle.kts plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.kotlin.compose) apply false } - Apply and enable Compose at the module level
# app/build.gradle.kts plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.compose) } ... android { buildFeatures { compose = true } } ... dependencies { implementation(platform(libs.androidx.compose.bom)) implementation(libs.androidx.compose.ui) implementation(libs.androidx.compose.ui.graphics) implementation(libs.androidx.compose.ui.tooling.preview) implementation(libs.androidx.compose.material3) debugImplementation(libs.androidx.compose.ui.tooling) }
Add permissions
Add required permissions to app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.NFC" />Application setup
Application inheritance
Your application must inherit from TapToPhoneApplication. Inheriting from TapToPhoneApplication will require implementing the getPaymentsEnvironment function.
package com.rainforestpay.capyshopandroid
import android.util.Log
import com.rainforestpay.sdk.Environment
import com.rainforestpay.sdk.tap.TapToPhoneApplication
class ExampleApplication : TapToPhoneApplication() {
override fun getPaymentsEnvironment(): Environment {
return Environment.SANDBOX
}
}Session permissions
Create a session to grant the SDK permissions to process a payin with the permission group payment_sdk and pass the session_key into the Rainforest SDK.
"statements": [
{
"permissions": ["group#payment_sdk"],
"constraints": {
"merchant": {
"merchant_id": "REPLACE_ME"
}
}
}
]
Device registration
Each device with your platform's application must be registered as a Rainforest device registration.
Devices must be registered to a merchant in order to process payments, which is completed via the create device registration endpoint. You'll need to pass:
registration_code: set toANDROID_SDKmerchant_id: the merchant to process payments on with the devicedevice_name: the friendly name of the device, this will only appear in the Rainforest API and not in any Tap to Phone flows
{
"registration_code": "ANDROID_SDK",
"merchant_id": "sbx_mid_example",
"device_name": "Example device"
}The Device Registration ID will be utilized when presenting a payin and initiating the Tap to Phone payment flow through the Rainforest SDK. You should create a Rainforest Device Registration when your application is downloaded to the Android device and represents that specific Android device.
Each device that will utilize the Rainforest SDK for Tap to Phone must have it's own unique Rainforest Device Registration ID and cannot be shared across devices. Only one payin can be presented at a time on a Rainforest Device Registration.
Implementing the payment flow
1. Create a TapToPhone instance
TapToPhone instanceTo do this you will need:
-
a session key with the correct permissions
-
a device registration ID
You will create this instance early in the application lifecycle. It will also need to be created when you have a new session key.
val tapToPhone = RainforestPay.tapToPhone(context, environment, deviceRegistrationId, sessionKey) // where context is an instance of `android.app.Activity`
2. Prepare the device to take a tap payment
You will prepare the SDK at the start of your checkout flow
val prepareResult = tapToPhone.prepare()3. Present payin using TapDialog
Presenting a payin requires:
- an initialized and prepared instance of the
TapToPhoneclass - a payin config ID
Render the payin when you're ready to start the tap transaction
TapCardDialog(
activity = activity,
ttp = ttp,
payinConfigId = payinConfigId,
deviceRegistrationId = deviceRegistrationId,
onSuccess = { paymentResponse ->
Log.d("TapUiDialog", "TapUiDialog onSuccess: $paymentResponse")
},
onError = { errMsg ->
Log.d("TapUiDialog", "TapUiDialog onError: $errMsg")
},
onCancel = {
Log.d("TapUiDialog", "TapUiDialog onCancel")
}
)
SDK Reference
RainforestPay
RainforestPay| Method | Returns | Description |
|---|---|---|
tapToPhone(ctx: Context, env: Environment, deviceRegistrationId: String, sessionKey: String) | TapToPhoneInterface | Creates the TTP instance; call when you have a new session |
Environment (enum)
Environment (enum)SANDBOX · PRODUCTION
TapToPhoneInterface
TapToPhoneInterfaceProperties
| Property | Type | Description |
|---|---|---|
isPrepared | StateFlow<Boolean> | true after a successful prepare() call |
events | Flow<TtpEvent> | Stream of lifecycle events; collect to drive custom UI |
Methods (all suspend unless noted)
| Method | Returns | Description |
|---|---|---|
checkPermissions() | CheckPermissionsResult | Checks device permissions (biometrics, Bluetooth, Location); returns result showing which permission the device has. |
setup() | SetupResult | Checks device permissions; runs prepare() on first call |
prepare() | PrepareSession | Fetches auth token + merchant data; initializes Mastercard SDK |
presentPayin(activity, payinConfigId) | PaymentResponse | Loads PayinConfig, captures NFC tap, polls until terminal status. This is called by the TapDialog |
cancelPresented() | Unit | Cancels an in-progress ta |
TapUI (Composable)
TapUI (Composable)Built-in Compose dialog. Requires ttp.isPrepared == true.
TapUI(
activity: Activity,
ttp: TapToPhoneInterface,
payinConfigId: String,
deviceRegistrationId: String,
onSuccess: (PaymentResponse) -> Unit,
onError: (Exception) -> Unit,
onCancel: () -> Unit,
autoDismissOnComplete: Boolean = false, // skips post-tap result screens and returns control by to host app to display results
)TtpEvent (sealed interface)
TtpEvent (sealed interface)Events emitted in order during a normal transaction:
| Event | Payload | Description |
|---|---|---|
Preparing | message: String | prepare() started |
Prepared | session: PrepareSession | Device ready to accept a tap |
PayinConfigLoaded | cfg: PayinConfigResponseData | PayinConfig fetched |
PresentingStarted | message: String | NFC reader active |
TapStarted | message: String | Card detected |
TapComplete | message: String | Tap data captured |
Approved | message: String | Payin approved |
Declined | reason: String | Payin declined |
Canceled | message: String | Flow canceled |
Error | message: String | Error during flow |
Info | message: String | Informational/debug event |
Collect from ttp.events to drive custom UI state.
PaymentResponse
PaymentResponsedata class PaymentResponse(
val status: PaymentResponseStatus, // SUCCESS | FAILURE
val payin: PayinData,
)
// Convenience:
val isSuccess: Boolean
val isFailure: Booleandata class PayinData(
val payinId: String,
val status: String, // "PROCESSING" | "FAILED" | "CANCELED"
val amount: Int, // in cents
)RainforestException
RainforestExceptionThrown by TTP methods on failure.
class RainforestException(
val code: RainforestErrorCode,
message: String,
cause: Throwable? = null,
)| Code | Message |
|---|---|
API | API request failed |
APP_CONFIGURATION | Device verification failed. Please try re-installing the app. If that does not work, contact support. |
AUTHORIZATION | Preparation has expired. Please prepare again. |
CARD_READER | There a failure when trying to read the card. Often because the card is not held in place long enough to full read the card. |
CARD_READER_SESSION | Card reader session error |
DATA | There was an issue loading required data. Please try again. If this continues to happen, please contact support. |
DEVICE_IN_USE | The device registration is already presenting. Cancel the presented payin to continue. |
DEVICE_INSECURE | A security issue has been found with the device. See error message for details. |
DEVICE_INSECURE_ENVIRONMENT | The device runtime environment has insecure setup. |
DEVICE_INSECURE_IDENTITY | The device requires passcode, fingerprint, or face recognition security to accept Tap to Phone payments. |
INVALID_PAYIN_CONFIG | Invalid payin config |
LOCATION | Cannot determine location. Location is required to accept Tap to Phone payments. |
MERCHANT | Merchant is invalid. Contact support. |
MISSING_PERMISSION_BLUETOOTH | The device does not have bluetooth permissions enabled. |
MISSING_PERMISSION_LOCATION | The device does not have location permissions enabled. |
NOT_READY | SDK not prepared |
NOT_SUPPORTED | Tap to Phone payments are not supported on this device. |
NOT_SUPPORTED_NFC | NFC is not supported on this device. |
PAYIN_CANCELED | Payin canceled |
SERVICE | Something went wrong on our end. Please try again. If this continues to happen, please contact support. |
TIMEOUT | An operation timed out. Please try again or contact customer support. |
UNKNOWN | Unknown error |
TapToPhoneApplication (abstract)
TapToPhoneApplication (abstract)Your Application class must extend this class and implement the getPaymentsEnvironment() method.
class MyApp : TapToPhoneApplication() {
override fun getPaymentsEnvironment(): Environment = Environment.SANDBOX
}Updated about 5 hours ago