A Kotlin Android sample application demonstrating integration with the Gr4vy Kotlin Android SDK. This app provides a testing interface for the SDK endpoints with persistent configuration management using Jetpack Compose, including comprehensive 3DS authentication support with customizable UI themes.
- Kotlin Client App for Gr4vy Kotlin SDK
The app uses modern Android patterns with Kotlin Coroutines for async API calls, calling the Gr4vy Android SDK directly and DataStore for persistent configuration across app sessions.
- Home Tab: Main navigation to API endpoint screens
- Admin Tab: Configuration management panel
-
Payment Options -
POST /payment-options- Configure metadata, country, currency, amount, locale, and cart items
- Dynamic metadata key-value pairs
- Cart items with detailed product information
-
Card Details -
GET /card-details- Test card BIN lookup and payment method validation
- Supports intent, subsequent payments, and merchant-initiated transactions
-
Payment Methods -
GET /buyers/{buyer_id}/payment-methods- Retrieve stored payment methods for buyers
- Sorting and filtering options
- Buyer identification by ID or external identifier
-
Tokenize -
PUT /tokenize- Tokenize payment methods (card or stored payment method ID)
- 3DS authentication support
- Test card selection for frictionless and challenge flows
- Customizable 3DS UI themes (light/dark mode support)
- SDK timeout configuration
- Secure payment method storage
The Admin tab provides centralized configuration for all API calls:
- gr4vyId - Your Gr4vy merchant identifier
- token - API authentication token
- server - Environment selection (sandbox/production)
- timeout - Request timeout in seconds (optional)
- merchantId - Used in payment options requests
- All settings persist across app restarts using DataStore Preferences
- Empty timeout field uses SDK default timeout
- Configuration is shared across all API screens
- Switch between sandbox and production environments instantly
The Tokenize screen includes comprehensive 3DS authentication features:
- Authentication Toggle: Enable/disable 3DS authentication
- Test Cards: Pre-configured test cards for both flows:
- Frictionless Flow: Cards that complete authentication without challenge (4242 4242 4242 4242)
- Challenge Flow: Cards that trigger authentication challenge screens (4916 9940 6425 2017, 5100 0000 0000 0010)
- UI Customization: Three built-in themes for 3DS challenge screens:
- Red/Blue theme
- Orange/Purple theme
- Green/Yellow theme
- Each theme supports both light and dark modes
- Timeout Configuration: Configurable SDK max timeout (in minutes)
- Response Data: Returns authentication details including:
tokenized: Whether the payment method was successfully tokenizedauthentication.attempted: Whether 3DS authentication was attemptedauthentication.user_cancelled: Whether the user cancelled the authenticationauthentication.timed_out: Whether the authentication timed outauthentication.type: The type of authentication performedauthentication.transaction_status: The final status of the 3DS transaction
All API calls use Kotlin Coroutines:
Button(onClick = {
scope.launch {
sendRequest()
}
}) {
Text("GET")
}- SDK error type handling including 3DS-specific errors:
threeDSError: 3DS authentication failuresuiContextError: UI context-related issues
- Network error detection and visual messages
- HTTP status code display with detailed error responses
- Expandable error messages show full JSON error details
- Pretty-printed JSON responses
- Copy/share functionality for debugging
- Separate navigation for success and error responses
- Form data persists between app launches using DataStore
- Admin settings stored securely in encrypted preferences
- Complex data structures (metadata, cart items) serialized with Kotlinx Serialization
- Open the Admin tab
- Enter your
gr4vyIdand optionaltoken - Select environment
- Optionally set custom timeout
- Navigate through the Home tab to each API screen
- Fill in required fields (marked with validation)
- For Tokenize: Select test cards for 3DS testing (frictionless or challenge flows), choose a theme, and configure authentication settings
- Tap the action button (GET/POST/PUT) to make requests
- View responses with authentication details (for 3DS-enabled requests)
- Use as reference implementation for SDK integration
- Test various parameter combinations
- Debug API responses with detailed error information
- Create new Composable following existing patterns
- Add admin settings storage with DataStore
- Implement suspend request function with error handling
- Add navigation route in
MainActivity.kt
- All screens use Jetpack Compose with Material 3 design
- Consistent styling with custom theme
- Error states handled with Material error colors
- Loading states with CircularProgressIndicator
The app demonstrates comprehensive 3DS UI theming capabilities:
private fun buildRedBlueTheme(): Gr4vyThreeDSUiCustomizationMap {
val light = Gr4vyThreeDSUiCustomization(
label = Gr4vyThreeDSLabelCustomization(
textFontName = "sans-serif",
textFontSize = 16,
textColorHex = "#1c1c1e",
headingTextFontName = "sans-serif-medium",
headingTextFontSize = 24,
headingTextColorHex = "#0a0a0a"
),
toolbar = Gr4vyThreeDSToolbarCustomization(
textFontName = "sans-serif-medium",
textFontSize = 17,
textColorHex = "#ffffff",
backgroundColorHex = "#007aff",
headerText = "Secure Checkout",
buttonText = "Cancel"
),
// ... additional customizations
)
// Separate dark mode customization
val dark = Gr4vyThreeDSUiCustomization(...)
return Gr4vyThreeDSUiCustomizationMap(default = light, dark = dark)
}Customizable elements include:
- Labels (text font, size, color for both body and heading)
- Toolbar (font, colors, button text, header text)
- Text boxes (font, colors, border width, corner radius)
- View backgrounds (challenge and progress views)
- Buttons (submit, continue, next, resend, etc. - each with individual styling)
Basic SDK initialization:
val server: Gr4vyServer = if (serverEnvironment == "production") {
Gr4vyServer.Production
} else {
Gr4vyServer.Sandbox
}
val gr4vy = try {
Gr4vy(
gr4vyId = gr4vyID,
token = trimmedToken,
server = server,
timeout = timeoutInterval
)
} catch (e: Exception) {
errorMessage = "Failed to configure Gr4vy SDK: ${e.message}"
return
}Tokenize with 3DS authentication:
gr4vy.tokenize(
checkoutSessionId = checkoutSessionId,
cardData = cardRequest,
activity = activity, // Activity context required
sdkMaxTimeoutMinutes = timeoutMinutes,
authenticate = true,
uiCustomization = buildRedBlueTheme() // Optional theme
) { result ->
when (result) {
is Gr4vyResult.Success -> {
val tokenizeResult = result.data
// Access tokenizeResult.tokenized and tokenizeResult.authentication
}
is Gr4vyResult.Error -> {
// Handle error
}
}
}- Jetpack Compose - Modern Android UI toolkit
- Kotlin Coroutines - Asynchronous programming
- DataStore Preferences - Settings persistence
- Navigation Compose - Screen navigation
- Kotlinx Serialization - JSON handling
- OkHttp - HTTP client for networking
- Gr4vy Android SDK - Payment processing
- Android 8.0+ (API level 26)
- Kotlin 2.0+
- Android Studio Koala+ (2024.1.1+)
- Gradle 8.0+
- Gr4vy Android SDK
- Clone the repository
- Open in Android Studio
- Sync Gradle dependencies
- Run on device or emulator
# Build debug APK
./gradlew assembleDebug
# Run tests
./gradlew test
# Install on connected device
./gradlew installDebugThe project includes a simplified GitHub Actions workflow (.github/workflows/android.yml) that:
- Validates Gradle wrapper integrity
- Builds the sample app with
./gradlew assemble - Runs Android Lint for code quality checks
This sample app is provided as-is for demonstration purposes.