Checkout Android SDK
A comprehensive Android SDK for integrating payment processing into your Android applications. This SDK provides a secure, user-friendly checkout experience with support for multiple payment methods, currencies, and customization options.
Table of Contents
- Overview
- Features
- Installation
- Quick Start
- Basic Usage
- Configuration
- Callbacks
- Advanced Features
- Example App
- Troubleshooting
- Architecture
- API Reference
Overview
The Checkout Android SDK allows you to integrate payment processing into your Android app with just a few lines of code. It handles the complex payment flow, security, and user interface, so you can focus on your app's core functionality.
What does it do?
- π³ Processes payments securely
- π Supports multiple currencies and payment methods
- π± Handles both card and digital wallet payments
- π Manages security and encryption automatically
Features
β Multiple Payment Methods: Credit/Debit cards, Google Pay, Samsung Pay, and more
β Multi-Currency Support: Process payments in various currencies
β Localization: Support for English and Arabic languages
β Security: Built-in encryption and security measures
β Card Scanner: Scan card details using device camera
β Real-time Validation: Instant feedback on payment details
Requirements
- Android API level 24 (Android 7.0) or later
- Android Studio 4.0 or later
- Kotlin 1.5.0 or later (recommended) or Java 8+
Installation
1. Add Repository
To integrate the Checkout Android SDK, you need to add the required repositories. The setup differs slightly depending on the Gradle version and DSL (Kotlin or Groovy) you are using.
For projects using Compile SDK version 34 and above
Use the Kotlin DSL (typically in settings.gradle.kts):
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven("https://jitpack.io")
}
}
For older Gradle versions (Groovy DSL)
Use the Groovy DSL in your root build.gradle:
allprojects {
repositories {
google()
jcenter()
maven { url 'https://jitpack.io' }
}
}
2. Add the SDK Dependency
Add the following to yourapp/build.gradle
:
Kotlin DSL (for build.gradle.kts)
dependencies {
implementation("com.github.Tap-Payments:Checkout-Android:1.0.2")
}
Groovy DSL (for build.gradle)
dependencies {
implementation 'com.github.Tap-Payments:Checkout-Android:1.0.2'
}
Quick Start
Here's how to get started with the Checkout SDK in just 5 minutes:
1. Add Permissions
Add the following permissions to yourAndroidManifest.xml
as well in the runtime of the app:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.NFC"/>
2. Add the Checkout View (XML)
In your activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background_wallpaper"
android:orientation="vertical">
<company.tap.tapcheckout_android.TapCheckout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/_2sdp"
android:id="@+id/checkout_pay"
/>
</LinearLayout>
3. Initialize SDK and Build Configuration
package your.project.name
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import company.tap.tapcheckout_android.CheckoutConfiguration
import company.tap.tapcheckout_android.TapCheckoutStatusDelegate
import org.json.JSONArray
import org.json.JSONObject
/**
* MainActivity integrates the Tap Checkout Android SDK into your app.
* Implements TapCheckoutStatusDelegate to receive payment callbacks.
*/
class MainActivity : AppCompatActivity(), TapCheckoutStatusDelegate {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
/**
* PUBLIC KEY:
* This unique key is obtained after registering your app's Bundle ID
* in the Tap Dashboard. It is used to authenticate your application as a merchant.
*/
val publicKey = "your_public_key"
/**
* BUILDING THE CHECKOUT CONFIGURATION:
* Configuration is passed as a LinkedHashMap<String, Any>.
* This map defines payment options, UI behavior, customer details, and more.
*/
val configuration = LinkedHashMap<String, Any>().apply {
// Core settings
put("open", true) // Automatically open checkout on init
put("hashString", "") // Hash for security (can be generated server-side)
put("checkoutMode", "page")
put("language", "en") // Language: "en" or "ar"
put("themeMode", "dark") // Theme: "dark" or "light"
// Supported payment options
put("supportedPaymentMethods", "ALL") // Allow all payment methods
put("paymentType", "ALL") // Allow all payment types
put("selectedCurrency", "SAR") // Transaction currency (e.g., SAR, KWD, USD)
put("supportedCurrencies", "ALL") // Allow all currencies supported by Tap
/**
* GATEWAY CONFIGURATION:
* Identifies the merchant account. The `publicKey` is mandatory,
* and `merchantId` is optional for sub-merchants or marketplace setups.
*/
// Gateway
put("gateway", JSONObject().apply {
put("publicKey", "pk_test_gznOhsfdL0QMV8AW7tSN2wKP")
put("merchantId", "")
})
/**
* CUSTOMER DETAILS:
* Pass customer info for better tracking and security checks.
*/
// Customer
put("customer", JSONObject().apply {
put("firstName", "First Android")
put("lastName", "Test")
put("email", "[email protected]")
put("phone", JSONObject().apply {
put("countryCode", "966")
put("number", "55567890")
})
})
/**
* TRANSACTION CONFIGURATION:
* Defines how the payment will be processed (charge or authorize).
*/
// Transaction
put("transaction", JSONObject().apply {
put("mode", "charge") // Other option: "authorize"
// Charge details
put("charge", JSONObject().apply {
put("saveCard", true) // Save the card for future use
put("threeDSecure", true) // Enable 3D Secure for fraud prevention
// Auto actions: e.g., auto-void if payment not captured within time
put("auto", JSONObject().apply {
put("type", "VOID")
put("time", 100)
})
// URL to redirect after checkout is completed
put("redirect", JSONObject().apply {
put("url", "https://demo.staging.tap.company/v2/sdk/checkout")
})
// Example subscription setup
put("subscription", JSONObject().apply {
put("type", "SCHEDULED")
put("amount_variability", "FIXED")
put("txn_count", 0)
})
put("airline", JSONObject().apply {
put("reference", JSONObject().apply {
put("booking", "")
})
})
})
})
// Amount
put("amount", "1")
/**
* ORDER DETAILS:
* Defines the items and amounts in this checkout session.
*/
put("order", JSONObject().apply {
put("id", "")// Pass an order ID from your backend if available
put("currency", "SAR")
put("amount", "1")
put("items", JSONArray().apply {
put(JSONObject().apply {
put("amount", "1")
put("currency", "SAR")
put("name", "Item Title 1")
put("quantity", 1)
put("description", "item description 1")
})
})
})
/**
* CARD OPTIONS:
* Controls card UI behavior and allowed input methods.
*/
put("cardOptions", JSONObject().apply {
put("showBrands", true) // Show card brand logos
put("showLoadingState", false) // Show loading spinner
put("collectHolderName", true) // Ask for cardholder's name
put("preLoadCardName", "")
put("cardNameEditable", true) // Allow user to edit cardholder name
put("cardFundingSource", "all") // Allow all funding sources
put("saveCardOption", "all") // Show save card option
put("forceLtr", false) // Force left-to-right layout
// Enable additional card input options (scanner, NFC)
put("alternativeCardInputs", JSONObject().apply {
put("cardScanner", true)
put("cardNFC", true)
})
})
// Enable Apple Pay (only relevant for iOS, here for compatibility)
put("isApplePayAvailableOnClient", true)
}
/**
* INITIALIZE THE TAP CHECKOUT SDK:
* This attaches the checkout view to the specified layout element.
*/
CheckoutConfiguration.configureWithTapCheckoutDictionary(
this,
publicKey, // Public key
findViewById(R.id.checkout_pay),
configuration, // Full configuration map
this
)
}
/**
* CALLBACKS:
* Handle payment flow events.
*/
override fun onCheckoutReady() {
// Called when the checkout interface is ready to be displayed
}
override fun onCheckoutcancel() {
// Called when the user cancels the checkout
}
override fun onCheckoutSuccess(data: String) {
// Called when the payment is successful.
// `data` contains payment info in JSON format
}
override fun onCheckoutError(error: String) {
// Called when an error occurs during checkout
}
}
That's it! You now have a working payment system.
Basic Usage
Understanding the Flow
sequenceDiagram participant App as Your App participant SDK as Checkout SDK participant UI as Payment UI participant Server as Payment Server App->>SDK: startCheckout(config, listener) SDK->>UI: Present checkout interface UI->>App: onCheckoutReady() Note over UI: User enters payment details UI->>Server: Process payment Server->>UI: Payment result alt Payment Success UI->>App: onCheckoutSuccess(data) else Payment Failed UI->>App: onCheckoutError(data) end UI->>App: onCheckoutClose()
Step-by-Step Integration
Step 1: Configure Your Payment
val config = LinkedHashMap<String, Any>().apply {
// Core settings
put("open", true) // Automatically open checkout on init
put("hashString", "") // Hash for security (can be generated server-side)
put("checkoutMode", "page")
put("language", "en") // Language: "en" or "ar"
put("themeMode", "dark") // Theme: "dark" or "light"
// Supported payment options
put("supportedPaymentMethods", "ALL") // Allow all payment methods
put("paymentType", "ALL") // Allow all payment types
put("selectedCurrency", "SAR") // Transaction currency (e.g., SAR, KWD, USD)
put("supportedCurrencies", "ALL") // Allow all currencies supported by Tap
/**
* GATEWAY CONFIGURATION:
* Identifies the merchant account. The `publicKey` is mandatory,
* and `merchantId` is optional for sub-merchants or marketplace setups.
*/
// Gateway
put("gateway", JSONObject().apply {
put("publicKey", "pk_test_gznOhsfdL0QMV8AW7tSN2wKP")
put("merchantId", "")
})
/**
* CUSTOMER DETAILS:
* Pass customer info for better tracking and security checks.
*/
// Customer
put("customer", JSONObject().apply {
put("firstName", "First Android")
put("lastName", "Test")
put("email", "[email protected]")
put("phone", JSONObject().apply {
put("countryCode", "966")
put("number", "55567890")
})
})
/**
* TRANSACTION CONFIGURATION:
* Defines how the payment will be processed (charge or authorize).
*/
// Transaction
put("transaction", JSONObject().apply {
put("mode", "charge") // Other option: "authorize"
// Charge details
put("charge", JSONObject().apply {
put("saveCard", true) // Save the card for future use
put("threeDSecure", true) // Enable 3D Secure for fraud prevention
// Auto actions: e.g., auto-void if payment not captured within time
put("auto", JSONObject().apply {
put("type", "VOID")
put("time", 100)
})
// URL to redirect after checkout is completed
put("redirect", JSONObject().apply {
put("url", "https://demo.staging.tap.company/v2/sdk/checkout")
})
// Example subscription setup
put("subscription", JSONObject().apply {
put("type", "SCHEDULED")
put("amount_variability", "FIXED")
put("txn_count", 0)
})
put("airline", JSONObject().apply {
put("reference", JSONObject().apply {
put("booking", "")
})
})
})
})
// Amount
put("amount", "1")
/**
* ORDER DETAILS:
* Defines the items and amounts in this checkout session.
*/
put("order", JSONObject().apply {
put("id", "")// Pass an order ID from your backend if available
put("currency", "SAR")
put("amount", "1")
put("items", JSONArray().apply {
put(JSONObject().apply {
put("amount", "1")
put("currency", "SAR")
put("name", "Item Title 1")
put("quantity", 1)
put("description", "item description 1")
})
})
})
/**
* CARD OPTIONS:
* Controls card UI behavior and allowed input methods.
*/
put("cardOptions", JSONObject().apply {
put("showBrands", true) // Show card brand logos
put("showLoadingState", false) // Show loading spinner
put("collectHolderName", true) // Ask for cardholder's name
put("preLoadCardName", "")
put("cardNameEditable", true) // Allow user to edit cardholder name
put("cardFundingSource", "all") // Allow all funding sources
put("saveCardOption", "all") // Show save card option
put("forceLtr", false) // Force left-to-right layout
// Enable additional card input options (scanner, NFC)
put("alternativeCardInputs", JSONObject().apply {
put("cardScanner", true)
put("cardNFC", true)
})
})
// Enable Apple Pay (only relevant for iOS, here for compatibility)
put("isApplePayAvailableOnClient", true)
}
Step 2: Start the Checkout
CheckoutConfiguration.configureWithTapCheckoutDictionary(
this,
publicKey,
findViewById(R.id.checkout_pay),
configuration,
this
)
Step 3: Handle Results
override fun onCheckoutReady() {
// Called when the checkout interface is ready to be displayed
}
override fun onCheckoutcancel() {
// Called when the user cancels the checkout
}
override fun onCheckoutSuccess(data: String) {
// Called when the payment is successful.
// `data` contains payment info in JSON format
}
override fun onCheckoutError(error: String) {
// Called when an error occurs during checkout
}
Configuration
Required Configuration
val config = LinkedHashMap<String, Any>().apply {
// Amount
put("amount", "1")
// Gateway
put("gateway", JSONObject().apply {
put("publicKey", "pk_test_gznOhsfdL0QMV8AW7tSN2wKP")
put("merchantId", "")
})
// Customer
put("customer", JSONObject().apply {
put("firstName", "First Android")
put("lastName", "Test")
put("email", "[email protected]")
put("phone", JSONObject().apply {
put("countryCode", "966")
put("number", "55567890")
})
})
// Order
put("order", JSONObject().apply {
put("id", "") // Pass an order ID from your backend if available
put("currency", "SAR")
put("amount", "1")
put("items", JSONArray().apply {
put(JSONObject().apply {
put("amount", "1")
put("currency", "SAR")
put("name", "Item Title 1")
put("quantity", 1)
put("description", "item description 1")
})
})
})
Optional Configuration
val config = LinkedHashMap<String, Any>().apply {
put("language", "en") // Language: "en" or "ar"
put("themeMode", "light") // Theme: "light", "dark", "dynamic"
put("supportedPaymentMethods", "ALL") // Allow all payment methods
put("paymentType", "ALL") // Allow all payment types
put("cardOptions", JSONObject().apply {
put("showBrands", true) // Show card brand logos
put("collectHolderName", true) // Ask for cardholder's name
put("cardNameEditable", true) // Allow editing cardholder name
put("saveCardOption", "all") // Allow saving card for future use
put("alternativeCardInputs", JSONObject().apply {
put("cardScanner", true) // Enable card scanner
put("cardNFC", true) // Enable NFC input
})
})
put("transaction", JSONObject().apply {
put("mode", "charge") // Transaction mode: charge or authorize
put("saveCard", true) // Save card for future use
put("threeDSecure", true) // Enable 3D Secure for fraud prevention
})
}
Gateway Configuration
// ---------- Test Environment ----------
val gateway = JSONObject().apply {
put("publicKey", "pk_test_your_test_key") // Your Test public key
put("merchantId", "your_test_merchant_id") // Your Test merchant ID
}
// ---------- Production Environment ----------
val gateway = JSONObject().apply {
put("publicKey", "pk_live_your_live_key") // Your Live public key
put("merchantId", "your_live_merchant_id") // Your Live merchant ID
}
β οΈ Important: Use pk_test_
for testing and pk_live_
for production.
Customer Configuration
val customer = JSONObject().apply {
put("firstName", "John") // Customer's first name
put("lastName", "Doe") // Customer's last name
put("email", "[email protected]") // Customer's email
put("phone", JSONObject().apply {
put("countryCode", "+1") // Country code
put("number", "1234567890") // Phone number
})
put("id", "cus_123") // Optional: Customer ID
}
Order Configuration
val order = JSONObject().apply {
put("id", "order_123") // Optional: Your order ID
put("currency", "KWD") // Currency code
put("amount", "25.99") // Order amount
// Items array
put("items", JSONArray().apply {
put(JSONObject().apply {
put("name", "Product Name")
put("amount", "25.99")
put("currency", "KWD")
put("quantity", 1)
put("description", "Product description")
})
})
}
Callbacks
Understanding what each callback means and how to handle them:
onCheckoutReady()
override fun onCheckoutReady() {
// The checkout interface has loaded and is ready for user interaction
// This is a good place to:
// - Hide loading indicators
// - Log analytics events
// - Update UI state
hideLoadingIndicator()
logAnalyticsEvent("checkout_ready")
}
onCheckoutSuccess(data: String)
override fun onCheckoutSuccess(data: String) {
// Payment was processed successfully
// The 'data' parameter contains payment details in JSON format
try {
val jsonObject = JSONObject(data)
val transactionId = jsonObject.getString("id")
Log.d("Checkout", "Transaction ID: $transactionId")
} catch (e: Exception) {
Log.e("Checkout", "Failed to parse payment data", e)
showErrorMessage("Payment completed but failed to process details")
}
}
onCheckoutError(data: String)
override fun onCheckoutError(data: String) {
// Payment failed or encountered an error
// The 'data' parameter contains error details
Log.e("Checkout", "Payment error: $data")
// Common error handling:
when {
data.contains("cancelled") -> {
Log.d("Checkout", "Payment was cancelled by user")
showMessage("Payment was cancelled")
}
data.contains("declined") -> {
Log.w("Checkout", "Payment was declined")
showAlert("Payment Declined", "Please check your card details and try again")
}
data.contains("network") -> {
Log.e("Checkout", "Network error")
showAlert("Network Error", "Please check your internet connection and try again")
}
else -> {
Log.e("Checkout", "Unknown payment error")
showAlert("Error", "Something went wrong. Please try again.")
}
}
}
onCheckoutClose()
override fun onCheckoutClose() {
// The checkout interface was closed
// This is called after onCheckoutSuccess, onCheckoutError, or when user manually closes
Log.d("Checkout", "Checkout interface closed")
}
Advanced Features
Theme Customization
// ---------- Light Theme ----------
put("themeMode", "light")
// ---------- Dark Theme ----------
put("themeMode", "dark")
// ---------- Dynamic Theme ----------
put("themeMode", "dynamic")
Payment Method Selection
// ---------- Allow All Payment Methods ----------
put("supportedPaymentMethods", "ALL")
// ---------- Specify Payment Methods ----------
put("supportedPaymentMethods", JSONArray().apply {
put("VISA")
put("MASTERCARD")
put("AMERICAN_EXPRESS")
put("MADA")
put("APPLE_PAY")
put("GOOGLE_PAY")
put("OMANNET")
put("BENEFIT")
put("FAWRY")
put("KNET")
put("STC_PAY")
put("TABBY")
put("DEEMA")
put("SAMSUNGPAY")
put("PAYPAL")
put("NAPS")
put("BENEFIT_PAY")
})
Card Options
val cardOptions = JSONObject().apply {
put("showBrands", true) // Show card brand logos
put("collectHolderName", true) // Ask for cardholder's name
put("cardNameEditable", true) // Allow editing cardholder name
put("saveCardOption", "all") // Show save card option (all cards)
// Alternative card inputs (scanner, NFC)
put("alternativeCardInputs", JSONObject().apply {
put("cardScanner", true) // Enable card scanner
put("cardNFC", true) // Enable NFC reading
})
}
Multi-language Support
val language = "en"
val language = "ar"
Transaction Options
val transaction = JSONObject().apply {
put("mode", "charge") // charge or "authorize"
put("threeDSecure", true) // Enable 3D Secure
// Auto actions: e.g. auto-void if payment not captured in time
put("auto", JSONObject().apply {
put("type", "VOID") // AutoType.VOID
put("time", 100) // Time in minutes
})
// Redirect URL after checkout
put("redirect", JSONObject().apply {
put("url", "https://your-app.com/checkout/result")
})
}
Example App
The following example app demonstrates all SDK features:
Running the Example
- Clone the repository
- Open the project in Android Studio
- Add your test API keys in
MainActivity.kt
- Run the app on emulator or device
Key Features Demonstrated
- Basic Integration: Simple payment flow
- Configuration Options: All customization options
- Callback Handling: Proper response handling
- UI Customization: Theme and language options
Example App Structure
CheckoutExample/
βββ MainActivity.kt # Main example implementation
βββ CheckoutSettingsActivity.kt # Configuration options
βββ layouts/ # UI layouts
βββ values/ # Resources
Troubleshooting
Common Issues
1. SDK Not Starting
Problem: Nothing happens when calling startCheckout()
Solution:
- Check that all required fields are provided
- Verify your public key is correct
- Ensure the listener is properly implemented
- Check internet connectivity
2. Payment Fails Immediately
Problem: onCheckoutError
is called immediately
Solution:
- Verify your API keys are correct
- Check network connectivity
- Ensure amount is properly formatted
- Verify merchant ID is registered
3. UI Not Displaying Properly
Problem: Checkout interface looks broken
Solution:
- Check Android API level compatibility
- Verify theme mode settings
- Test on different devices
- Check for conflicting styles
4. Callbacks Not Working
Problem: Listener methods not being called
Solution:
- Ensure your class implements
TapCheckoutStatusDelegate
- Check that listener is set before calling
startCheckout()
- Verify activity lifecycle management
Testing
- Use test API keys for development
- Test with different card numbers
- Verify error handling with invalid data
- Test on different Android versions
Architecture
SDK Structure Overview
graph TB A[Your App] --> B[CheckoutSDK] B --> C[CheckoutActivity] C --> D[WebView Payment Interface] C --> E[Network Layer] C --> F[Security Layer] B --> G[CheckoutSDKListener] G --> H[onCheckoutReady] G --> I[onCheckoutSuccess] G --> J[onCheckoutError] G --> K[onCheckoutClose] E --> L[Payment Gateway] F --> M[Encryption/Security]
Key Components
- CheckoutSDK: Main entry point for the SDK
- CheckoutConfiguration: Holds all required checkout settings
- TapCheckout: Handles the payment UI
- TapCheckoutStatusDelegate: Callback interface for results
- Network Layer: Handles API communication
- Security Layer: Manages encryption and security
API Reference
CheckoutSDK
Methods
fun initialize(context: Context)
Initializes the SDK with the application context.
CheckoutConfiguration.configureWithTapCheckoutDictionary(
this,
publicKey,
findViewById(R.id.checkout_pay),
configuration,
this
)
Starts the checkout process with the given configuration.
TapCheckoutStatusDelegate
Required interface for handling checkout events.
Methods
fun onCheckoutReady()
Called when the checkout interface is ready for user interaction.
fun onCheckoutSuccess(data: String)
Called when payment is processed successfully.
fun onCheckoutcancel(){}
Called when checkout is canceled.
- data`: JSON string containing payment details
fun onCheckoutError(data: String)
Called when payment fails or encounters an error.
data
: String containing error information
fun onCheckoutClose()
Called when the checkout interface is closed.
Advanced Features
ThemeMode
class ThemeMode {
LIGHT, // Light theme
DARK, // Dark theme
Dynamic, // Dynamic theme
}
PaymentMethod
class PaymentMethod {
ALL,
MADA,
KNET,
VISA,
MASTERCARD,
AMERICAN_EXPRESS,
OMANNET,
GOOGLE_PAY,
SAMSUNGPAY,
FAWRY,
TABBY,
PAYPAL,
DEEMA,
STC_PAY,
NAPS,
BENEFIT,
BENEFIT_PAY
}
PaymentType
class PaymentType {
ALL, // All payment types
WEB, // Web payments
CARD, // Card payments
DEVICE // Device payments
}
Scope
class Scope {
Charge : This means you will get charge objects.
Authorize This means you will get an authenticated Tap token to use in our charge api right away.
}
Support
For questions, issues, or feature requests:
- π§ Email: [email protected]
- π Documentation: https://developers.tap.company/
Updated 2 days ago