> ## Documentation Index
> Fetch the complete documentation index at: https://docs.y.uno/llms.txt
> Use this file to discover all available pages before exploring further.

# Android Payments

The Android SDK makes it easy to integrate payment flows into your Android app.

## Additional resources

* Access the [Release notes](/changelog/android) or the [Yuno Android SDK repository](https://github.com/yuno-payments/yuno-sdk-android) to verify the latest SDK version available.

## Requirements

* **Minimum SDK Version**: `minSdkVersion` 21 or above
* **Java**: Java 8 enabled
* **AndroidX**: Use AndroidX instead of older support libraries
* **Android Gradle Plugin**: 4.0.0 or above
* **ProGuard**: 6.2.2 or above
* **Kotlin Gradle Plugin**: 1.4.0 or above
* **ELF Page Size Support**: Compliant with Google's 16 KB ELF page alignment requirements (Android 15 / ARMv9 ready)

### ProGuard / R8 Configuration

If your project has `minifyEnabled = true`, add these rules to your `proguard-rules.pro` file to ensure the SDK works correctly, especially with **AGP 8.x+ R8 full mode**.

<Accordion title="Official Yuno ProGuard / R8 rules">
  ```proguard theme={"theme":{"light":"github-dark","dark":"github-dark"}}
  # Preserve generic type signatures and annotations
  -keepattributes Signature
  -keepattributes *Annotation*

  # Yuno SDK
  -keep class com.yuno.** { *; }
  -dontwarn com.yuno.**

  # Gson — R8 full mode compatibility
  -keep class com.google.gson.** { *; }
  -keep,allowobfuscation,allowshrinking,allowoptimization class * extends com.google.gson.reflect.TypeToken
  -dontwarn com.google.gson.**

  # Retrofit — R8 full mode compatibility
  -keep,allowobfuscation,allowshrinking interface retrofit2.Call
  -keep,allowobfuscation,allowshrinking class retrofit2.Response
  -keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
  -dontwarn retrofit2.**

  # OkHttp + Okio — Suppress warnings
  -dontwarn okhttp3.**
  -dontwarn okio.**
  ```

  ### Why are these rules necessary?

  AGP 8.x+ enables **R8 full mode** by default, which aggressively strips generic type signatures. Without `-keepattributes Signature`, Gson’s `TypeToken<T>` can fail at runtime with `java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType`.
</Accordion>

## Include the library in your project

The first step is including the library in your project. Add the Yuno Android SDK to your project through Gradle. Add the repository source and dependency:

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
maven { url "https://yunopayments.jfrog.io/artifactory/snapshots-libs-release" }
```

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
dependencies {
    implementation 'com.yuno.payments:android-sdk:2.11.0'
}
```

Once Step 1 is complete, continue with the full-checkout integration.

## Parameters

For the full list of parameters and YunoConfig details, see the [Android SDK Common Reference](/docs/sdks/resources/references/android).

| Parameter                 | Description                                                                    |
| ------------------------- | ------------------------------------------------------------------------------ |
| `checkoutSession`         | Checkout session ID from your backend (Create checkout session API). Required. |
| `countryCode`             | ISO country code (e.g. `US`). Required.                                        |
| `callbackPaymentState`    | Callback: payment state (e.g. SUCCEEDED, FAIL, PROCESSING, REJECT).            |
| `merchantSessionId`       | Optional merchant session identifier.                                          |
| `YunoConfig` (initialize) | Optional: saveCardEnabled, keepLoader, language, styles. See Common Reference. |

## full-checkout

Implement Full (Android): customizable UI, payment method management, fraud prevention, and checkout flows. More feature-rich than Headless, which focuses on core payment processing. See [Requirements](#requirements) above.

### Step 1: Include the library in your project

Follow the steps in [Include the library in your project](#include-the-library-in-your-project) above.

### Step 2: Initialize SDK with the public key

Retrieve your public API keys from the [Yuno Dashboard](https://dashboard.y.uno/).

If you haven't implemented a custom application, create one. In the `onCreate()` method of your application class, call the initialize function (`Yuno.initialize`):

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
class CustomApplication : Application() {
  override fun onCreate() {
    super.onCreate()
    Yuno.initialize(
      this,
      "<your-public-api-key>",
      config = YunoConfig(
        keepLoader = true,
      ),
    )
  }
}
```

See the [credentials page](/reference/getting-started/authentication) for more information. Use the data class `YunoConfig` to customize the SDK's behavior. Include this configuration when calling `Yuno.initialize()`. The available options are:

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
data class YunoConfig(
    val saveCardEnabled: Boolean = false,
    val keepLoader: Boolean = false,
    val language: YunoLanguage? = null,
    val styles: YunoStyles? = null
)
```

<Warning>
  **cardFlow removed from YunoConfig**

  Starting from version **2.11.0**, `cardFlow` is no longer part of `YunoConfig`. Card flow configuration is now handled exclusively through the **CheckoutBuilder**. If you are migrating from an earlier version, remove `cardFlow` from your `YunoConfig` and configure it in the CheckoutBuilder instead.
</Warning>

### YunoConfig options

Customization options:

| customization option | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `saveCardEnabled`    | Enables the Save card checkbox on card flows. Check the Save card section for more information.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `keepLoader`         | When `true`, the SDK loader persists from OTT generation until `continuePayment()` is called. For details, see [keepLoader Parameter](/docs/sdks/resources/references/android#keeploader-parameter).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `language`           | Defines the language to be used in the payment forms. You can set it to one of the available language options: <ul><li>ar (Arabic)</li><li>es (Spanish)</li><li>en (English)</li><li>pt (Portuguese)</li><li>fil (Filipino)</li><li>id (Indonesian)</li><li>ms (Malay)</li><li>th (Thai)</li><li>zh-TW (Chinese (Traditional, Taiwan))</li><li>zh-CN (Chinese (Simplified, China))</li><li>vi (Vietnamese)</li><li>fr (French)</li><li>pl (Polish)</li><li>it (Italian)</li><li>de (German)</li><li>ru (Russian)</li><li>tr (Turkish)</li><li>nl (Dutch)</li><li>sv (Swedish)</li><li>ko (Korean)</li><li>ja (Japanese)</li><li>hi (Hindi)</li><li>bn (Bengali)</li><li>ml (Malayalam)</li><li>ur (Urdu)</li></ul> |
| `styles`             | Enables SDK-wide UI customization. Use it to define global visual styles like font family and button appearance (color, padding, radius, typography) through a `YunoStyles` object. For more information, check the styles section.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |

Update your manifest to use your application:

```xml theme={"theme":{"light":"github-dark","dark":"github-dark"}}
<application android:name=".CustomApplication"></application>
```

### Step 3: Create the checkout session

Each payment requires a new `checkout_session`. Use the [Create checkout session](/reference/checkout-sessions/create-checkout-session) endpoint to create one; use that session to initiate the payment.

If your payment flow sends users to an external browser (e.g., for 3DS authentication or bank redirects), set the `callback_url` when creating your checkout session. See [Handle external browser return (callback\_url)](#step-3-create-the-checkout-session) for details.

### Step 4: Start the checkout process

Call the `startCheckout` method inside the `onCreate()` function of the activity that initializes the SDK to start a new payment process with Full (Android):

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
startCheckout(
  checkoutSession: "checkout_session",
  countryCode: "country_code_iso",
  callbackPaymentState: ((String?) -> Unit)?,
  merchantSessionId: String? = null
)
```

See [Parameters](#parameters). The following are the possible states returned by the `callbackPaymentState`:

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
const val PAYMENT_STATE_SUCCEEDED = "SUCCEEDED"
const val PAYMENT_STATE_FAIL = "FAIL"
const val PAYMENT_STATE_PROCESSING = "PROCESSING"
const val PAYMENT_STATE_REJECT = "REJECT"
const val PAYMENT_STATE_INTERNAL_ERROR = "INTERNAL_ERROR"
const val PAYMENT_STATE_STATE_CANCELED_BY_USER = "CANCELED"
```

Possible states:

| **State**        | **Description**                                                                                                                 | **Additional action required**                                                                                |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `SUCCEEDED`      | The transaction or payment process was successfully completed without any errors.                                               | No.                                                                                                           |
| `FAIL`           | The transaction failed due to errors such as data validation issues, server connection failures, or technical/network problems. | Yes. Investigate the cause of failure (validation, network, server) and take corrective measures.             |
| `PROCESSING`     | The transaction is currently in progress, awaiting approval or verification.                                                    | No.                                                                                                           |
| `REJECT`         | The transaction was rejected due to reasons like insufficient funds or suspected fraudulent activity.                           | Yes. Inform the user of the rejection, provide the reason if possible, and suggest actions.                   |
| `INTERNAL_ERROR` | An unexpected internal error occurred within the system handling the payment process.                                           | Yes. Requires technical intervention to review the system, fix internal issues, and retry or inform the user. |
| `CANCELED`       | The user voluntarily canceled the transaction or abandoned the payment process.                                                 | No.                                                                                                           |

#### Payment status validation

This section explains how the SDK handles payment status when users cancel or leave payment flows, and how the SDK status relates to the backend payment status in these scenarios.

##### Sync payment methods (Google Pay)

For synchronous payment methods like Google Pay, when a user cancels or closes the wallet UI before a payment service provider (PSP) response is received:

* **SDK Status**: Returns `CANCELED` (CANCELLED\_BY\_USER)
* **Backend payment status**: Remains `PENDING` until PSP timeout or merchant cancellation
* **Important**: The SDK will not return `REJECT` or `PROCESSING` in this scenario

This ensures that the backend payment remains in a pending state and can be properly handled by the merchant's system.

##### Async payment methods (PIX and QR-based methods)

For asynchronous payment methods like PIX, when a user closes the QR code window (clicks X) before completing the payment:

* **SDK Status**: Returns `PROCESSING`, optionally with a sub-status such as `CLOSED_BY_USER`
* **Backend payment status**: Remains `PENDING` and the QR code remains valid until expiry
* **Checkout session reuse**: Re-opening the same checkout session can display the same valid QR code
* **No Automatic Cancellation**: The PIX payment is not automatically cancelled when the user closes the QR window

This behavior allows users to return to the payment flow and complete the transaction using the same QR code before it expires.

##### Expired async payments

If a PIX QR code expires naturally:

* **Backend Status**: Updated to `EXPIRED`
* **SDK Status**: SDK callbacks and polling endpoints return `EXPIRED` consistently

This ensures merchants receive accurate status information when a payment method has expired.

### Step 5: Add the SDK view to the checkout

Use the `PaymentMethodListViewComponent` to display the available payment methods when implementing Full (Android) with Jetpack Compose. This component provides callbacks to notify your app when to enable or disable the pay button, and when an enrolled payment method is successfully removed.

#### Component signature

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
@Composable
fun PaymentMethodListViewComponent(
    activity: Activity,
    modifier: Modifier? = null,
    onPaymentSelected: (Boolean) -> Unit,
    onUnEnrollSuccess: (Boolean) -> Unit = {}
)
```

#### Component options

* `activity: Activity`: Current `Activity` where the component is hosted. Required for payment flows.
* `modifier: Modifier?` (optional): Layout and appearance (e.g. padding, spacing). Defaults to `null`.
* `onPaymentSelected: (Boolean) -> Unit`: Invoked when a payment method is selected or deselected (`true` = method selected, enable pay button; `false` = none selected).
* `onUnEnrollSuccess: (Boolean) -> Unit` (optional): Invoked when a stored payment method is successfully removed.

#### Example

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
val coroutineScope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
var paymentMethodIsSelected by remember { mutableStateOf(false) }

Column(
    modifier = Modifier
        .weight(1f)
        .verticalScroll(rememberScrollState())
) {
    PaymentMethodListViewComponent(
        activity = activity,
        onPaymentSelected = { isSelected ->
            paymentMethodIsSelected = isSelected
        },
        onUnEnrollSuccess = { success ->
            if (success) {
                coroutineScope.launch {
                    snackbarHostState.showSnackbar(
                        message = "Your payment method has been removed",
                    )
                }
            }
        },
    )
}
```

<Danger>
  **Important**

  Always wrap the component in a `Column` with `.verticalScroll(rememberScrollState())`. Without this, the list of payment methods may not render or scroll properly when there are multiple methods available.
</Danger>

### Step 6: Initiate the payment process

Call the `startPayment()` method to start a payment process:

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
startPayment(
    showStatusYuno: Boolean,
    callbackOTT: (String?) -> Unit = this::onTokenUpdated,
    callBackTokenWithInformation: (OneTimeTokenModel?) -> Unit = this::onTokenComplete
)

```

#### Options

Configure the payment with the following options:

| Parameter                      | Description                                                                                                                                                            |
| :----------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `showStatusYuno`               | A boolean that specifies whether the payment status should be displayed within the Yuno interface.                                                                     |
| `callbackOTT`                  | A required function that returns the updated one-time token (OTT) needed to complete the payment process. This token is required to complete the payment.              |
| `callBackTokenWithInformation` | A function that supplies detailed information about the one-time token, wrapped in a `OneTimeTokenModel` object, allowing for comprehensive handling of token details. |

#### OneTimeTokenModel

The `callBackTokenWithInformation` callback provides detailed information about the one-time token through the `OneTimeTokenModel` object:

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
@Parcelize
data class OneTimeTokenModel(
    val token: String? = null,
    val vaultedToken: String? = null,
    val vaultOnSuccess: Boolean? = null,
    val type: String? = null,
    val cardData: CardInformationModel? = null,
    val customer: CustomerPayerInformationModel? = null,
) : Parcelable
```

**Card Information Model**

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
@Parcelize
data class CardInformationModel(
    val holderName: String? = null,
    val iin: String? = null,
    val lfd: String? = null,
    val numberLength: Int? = null,
    val securityCodeLength: Int? = null,
    val brand: String? = null,
    val type: String? = null,
    val category: String? = null,
    val issuerName: String? = null,
    val issuerCode: String? = null,
    val countryCode: String? = null,
) : Parcelable
```

**Customer Payer Information Model**

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
@Parcelize
data class CustomerPayerInformationModel(
    val name: String? = null,
    val lastName: String? = null,
    val email: String? = null,
    val document: Document? = null,
    val phone: Phone? = null,
    val address: Address? = null,
    val deviceFingerPrint: String? = null,
    val thirdPartySessionId: String? = null,
) : Parcelable
```

**Supporting Models**

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
@Parcelize
data class Document(
    val documentNumber: String? = null,
    val documentType: String? = null,
) : Parcelable

@Parcelize
data class Phone(
    val number: String,
    val countryCode: String,
) : Parcelable

@Parcelize
data class Address(
    val addressLine1: String? = null,
    val addressLine2: String? = null,
    val country: String? = null,
    val city: String? = null,
    val state: String? = null,
    val zipCode: String? = null,
    val neighborhood: String? = null,
) : Parcelable
```

### Step 7: Get the one-time token (OTT)

After the customer fills out the requested data in Yuno's payment forms, you will obtain the one-time token, a required parameter to create a payment using the Yuno API.

The one-time token will be shared by Yuno using the `callbackOTT` function you provided in Step 6 when initiating the payment. The one-time token will be available in the `onActivityResult`.

A loader can be shown while the one-time token is generated. Use Yuno's default or implement your own with the required configuration.

### Step 8: Create the payment

After receiving the one-time token from [Step 7](#step-7-get-the-one-time-token-ott), create the payment using the [Create payment endpoint](/reference/payments/create-payment). Use the `checkout_session` from [Step 3](#step-3-create-the-checkout-session) and the one-time token to create the payment.

The response from the Create payment endpoint will include the parameter `sdk_action_required`, which defines if additional actions are required to finish the payment based on the payment type.

<Warning>
  **Continue Payment Method Integration**

  Yuno **requires** you integrate the `continuePayment` method of the SDK after the payment is created because certain asynchronous payment methods require additional customer actions to complete. The API will inform you of this scenario via the `sdk_action_required` field of the response, which will be returned as true. The `yuno.continuePayment()` function will display additional screens to customers, where they can carry out the necessary actions to complete the payment without you needing to handle every scenario.
</Warning>

### Step 9: Continue payment

Yuno requires integrating the SDK's `continuePayment` method after the payment is created, as certain asynchronous payment methods require additional customer actions to complete. The response from the [Create payment endpoint](/reference/payments/create-payment), from Step 8, will include an `sdk_action_required` field. If it returns `TRUE`, you need to call the `continuePayment()` function to show additional screens that allow the customer to complete the payment. Otherwise, this step is not necessary. Call the `continuePayment` method:

```kotlin theme={"theme":{"light":"github-dark","dark":"github-dark"}}
continuePayment(
    showPaymentStatus: Boolean = true,
    checkoutSession: String? = null,
    countryCode: String? = null,
    callbackPaymentState: ((String?) -> Unit)? = null
)
```

To show your payment status screens, send `FALSE` in the `showPaymentStatus` parameter. Then, get the payment state by callback.

## Common reference

For full parameter and customization details, see the [Android SDK Common Reference](/docs/sdks/resources/references/android).
