> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.coinflow.cash/guides/checkout/implementation-overview/mobile-app-payments/android-sdk/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.coinflow.cash/_mcp/server. # Android SDK ## Overview `coinflow-card-form` is a Jetpack Compose SDK that embeds Coinflow's card tokenization form directly into Android apps. The user enters their card inside your app, the SDK returns a payment token, and your backend charges the card via the standard Coinflow checkout API. * **Package:** [`cash.coinflow:coinflow-card-form`](https://central.sonatype.com/artifact/cash.coinflow/coinflow-card-form) * **Distribution:** Maven Central * **Current version:** `0.2.0` ## Requirements * Android `minSdk` 24+ * Kotlin 1.9+ * Jetpack Compose ## Installation ```kotlin // settings.gradle.kts dependencyResolutionManagement { repositories { google() mavenCentral() } } // app/build.gradle.kts dependencies { implementation("cash.coinflow:coinflow-card-form:0.2.0") } ``` ## Integration #### Add the card form composable Drop `CoinflowCardFormView` into your Compose layout and pass a `CoinflowCardFormController` you'll use to trigger tokenization. ```kotlin import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import cash.coinflow.cardform.* import kotlinx.coroutines.launch @Composable fun PaymentScreen() { val controller = remember { CoinflowCardFormController() } val scope = rememberCoroutineScope() Column { CoinflowCardFormView( variant = CardFormVariant.CARD_FORM, merchantId = "your-merchant-id", env = CoinflowEnv.SANDBOX, controller = controller, modifier = Modifier.fillMaxWidth().height(52.dp) ) Button(onClick = { scope.launch { try { val response = controller.tokenize() println("Token: ${response.token}") } catch (e: Exception) { // surface error to user } } }) { Text("Pay") } } } ``` > **Info** > > `your-merchant-id` is an **example placeholder**. Use your actual merchant ID from the merchant dashboard, or contact the Coinflow integrations team. Typically read from a `BuildConfig` field, not hard-coded. #### Configure the environment ```kotlin val env = if (BuildConfig.DEBUG) CoinflowEnv.SANDBOX else CoinflowEnv.PROD ``` * `CoinflowEnv.SANDBOX` — test cards, no real money * `CoinflowEnv.PROD` — live cards, real money #### Charge the token server-side `controller.tokenize()` is a `suspend` function. It returns a `TokenizeResponse`: * `token: String` — payment token to send to your backend * `expMonth: String?`, `expYear: String?` — populated only for variants that collect expiry Send the token to your server and call Coinflow's checkout API to charge it. See the [Checkout API reference](/api-reference/api-reference/checkout/card-checkout) for the full request shape. ## Variants | Variant | Captures | Use case | | ---------------------------------- | ------------------- | ------------------------------------------ | | `CardFormVariant.CARD_FORM` | Number, expiry, CVV | Standard one-shot capture | | `CardFormVariant.CARD_NUMBER_FORM` | Number + expiry | First step of a two-step flow | | `CardFormVariant.CVV_FORM` | CVV only | Re-collecting CVV for a card-on-file token | ## Theming `MerchantTheme` styles the rendered form. All fields optional. ```kotlin val theme = MerchantTheme( primary = "#165DFB", background = "#ffffff", textColor = "#05092E", ctaColor = "#165DFB", font = "Red Hat Display", style = MerchantStyle.ROUNDED ) CoinflowCardFormView(theme = theme, /* ... */) ``` #### All theme fields | Field | Purpose | | ------------------------------------------------------------------ | --------------------------------------------------- | | `primary`, `ctaColor` | Accent / action colors (hex strings) | | `background`, `backgroundAccent`, `backgroundAccent2` | Form background tones | | `textColor`, `textColorAccent`, `textColorAction` | Input and label text colors | | `font`, `fontSize`, `fontWeight` | Typography. `font` must be available on the device. | | `style` | Input shape: `ROUNDED`, `SHARP`, `PILL` | | `cardNumberPlaceholder`, `cvvPlaceholder`, `expirationPlaceholder` | Override input placeholder text | | `showCardIcon` | Toggle the card brand icon (Visa/Mastercard/Amex) | ## Dynamic height The hosted form reflows responsively — at narrow widths the inputs wrap to multiple rows. To keep your Compose container fitted, listen for height changes via the `onHeightChange` callback: ```kotlin var formHeight by remember { mutableStateOf(52.dp) } CoinflowCardFormView( merchantId = "your-merchant-id", controller = controller, modifier = Modifier .fillMaxWidth() .height(formHeight), onHeightChange = { formHeight = it.dp } ) ``` The callback receives the rendered content height in CSS pixels (1:1 with `dp` at default WebView density). Without this wiring the form may be clipped if it wraps. ## Resources * **Source:** [github.com/coinflow-labs-us/coinflow-android](https://github.com/coinflow-labs-us/coinflow-android) * **Maven Central:** [cash.coinflow:coinflow-card-form](https://central.sonatype.com/artifact/cash.coinflow/coinflow-card-form) * **License:** Apache 2.0 * **Checkout API:** [Card Checkout endpoint](/api-reference/api-reference/checkout/card-checkout)