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

# Android SDK

> How to integrate and manage payments through the lite Android SDK.

Accept card payments in your Android app with lite's Payment Sheet or embeddable payment form.

## Overview

The lite Android SDK lets customers pay without leaving your app. It provides two integration options:

* **Payment Sheet:** a complete checkout presented over your existing interface.
* **Embeddable payment form:** the same lite-managed checkout UI placed inside your Jetpack Compose layout.

The SDK collects and validates card details, encrypts them on the device, tokenizes the payment method, and submits the payment to lite. Raw card details are not sent to your server.

Individual card elements are not part of the supported payment SDK. Use the Payment Sheet for the quickest integration, or the embeddable form when you need control over where checkout appears inside your checkout page.

The Android SDK supports card payments, saved cards, and 3D Secure.

## How it works

1. Your server creates a checkout session with the lite API and receives a session secret.
2. Your app gives the session secret to the SDK.
3. The SDK loads the session and displays the payment methods enabled for it.
4. The customer enters a new card or selects a saved card.
5. The SDK encrypts new card data, tokenizes it, and submits the payment.
6. If required, the SDK presents and completes 3D Secure automatically.
7. Your server confirms the final payment result before fulfilling the order.

## Before you begin

You need:

* A lite account with a configured channel.
* Valid lite API keys on your server.
* A backend endpoint that creates lite checkout sessions.
* An Android app using API 26 or later.
* `compileSdk` 35 or later and Java 17.

Never place lite API keys in your Android app. Create checkout sessions on your server and send only the session secret to the app.

## Integrate the SDK

### 1. Install the SDK

Make sure Maven Central is available in your dependency repositories:

```kotlin theme={null}
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
    }
}
```

Add the SDK to your app module:

```kotlin theme={null}
dependencies {
    implementation("sa.lite:lite-android:0.0.1")
}
```

The SDK declares the Android internet permission in its manifest, so it is merged into your application automatically. Check your final merged manifest if your build removes library permissions.

### 2. Create a checkout session

Your server must create a checkout session using your lite API credentials and return its session secret to the app.

Do not generate the session secret in the app and do not include your lite API keys in application resources or `BuildConfig`.

```bash theme={null}
curl https://api.lite.sa/api/v1/checkout/sessions \
  -H "x-api-key: $LITE_API_KEY" \
  -H "x-correlation-id: $(uuidgen)" \
  -H "x-idempotency-key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "channel_id": "550e8400-e29b-41d4-a716-446655440000",
    "amount": 4999,
    "currency": "SAR",
    "customer": {
      "email": "john.doe@email.com",
      "first_name": "John",
      "last_name": "Doe"
    },
    "order": { "reference": "ORD-123456" },
    "redirect_urls": {
      "success": "https://example.com/return?session_id={SESSION_ID}",
      "failure": "https://example.com/checkout"
    },
    "expiry": 1800
  }'
```

```json theme={null}
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "client_secret": "cs_a1b2c3d4e5f6",
  "status": "Pending",
  "expires_on": "2026-06-01T12:30:00.000Z",
  "order_id": "ORD-123456",
  "amount": 4999,
  "currency": "SAR"
}
```

Return `client_secret` to your app, where the SDK takes it as `clientSecret`. Keep the session `id` on your server so you can confirm the payment afterwards.

The session determines the amount, currency, enabled card networks, and eligible saved cards. Create a new session for each checkout attempt.

### 3. Present the Payment Sheet

The Payment Sheet is the recommended integration. It manages its own checkout UI and 3D Secure lifecycle:

```kotlin theme={null}
import sa.lite.checkout.core.PaymentOperationStatus
import sa.lite.checkout.ui.LiteCardLayout
import sa.lite.checkout.ui.LitePaymentSheet

LitePaymentSheet.present(
    activity = this,
    clientSecret = sessionSecret,
    configuration = LitePaymentSheet.Configuration(
        cardLayout = LiteCardLayout.COMPACT,
        showResultBeforeDismiss = true,
        privacyPolicyUrl = "https://merchant.example/privacy",
    ),
) { result ->
    when (result.status) {
        PaymentOperationStatus.SUCCESS -> {
            // Show success, then confirm result.paymentId from your server.
        }
        PaymentOperationStatus.FAILURE -> {
            // Show result.error and allow the customer to retry when appropriate.
        }
        PaymentOperationStatus.PROCESSING -> {
            // Keep the order pending and confirm the result from your server.
        }
        PaymentOperationStatus.CANCELLED -> {
            // The customer dismissed checkout or cancelled authentication.
        }
        PaymentOperationStatus.ALREADY_COMPLETED -> {
            // This session had already completed. Confirm it from your server.
        }
    }
}
```

Call `present` from an `Activity`. The SDK attaches its 3D Secure presenter for the duration of the Payment Sheet and removes its UI when checkout finishes.

Only one Payment Sheet can be presented at a time. A second presentation attempt returns a failure with the error code `already_presenting`.

The available card layouts are:

| Layout                   | Behavior                                                           |
| ------------------------ | ------------------------------------------------------------------ |
| `LiteCardLayout.COMPACT` | A grouped, compact card-information form. This is the default.     |
| `LiteCardLayout.FORM`    | Separate card number, expiry, CVV, and optional cardholder fields. |
| `LiteCardLayout.LINE`    | A condensed single-row card entry.                                 |

### 4. Embed the payment form

Use `LitePaymentForm` when checkout must appear inside your own Compose screen. Own `Lite` as an Activity `ViewModel` and wrap the form in `LiteHost`:

```kotlin theme={null}
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import sa.lite.checkout.ui.Lite
import sa.lite.checkout.ui.LiteCardLayout
import sa.lite.checkout.ui.LiteHost
import sa.lite.checkout.ui.LitePaymentForm

class CheckoutActivity : ComponentActivity() {
    private val lite: Lite by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            LiteHost(lite) {
                LitePaymentForm(
                    lite = lite,
                    cardLayout = LiteCardLayout.COMPACT,
                    clientSecret = sessionSecret,
                    privacyPolicyUrl = "https://merchant.example/privacy",
                    onPayResult = { result ->
                        handlePaymentResult(result)
                    },
                )
            }
        }
    }

    private fun handlePaymentResult(result: Lite.PayResult) {
        // Handle every result status and confirm the payment from your server.
    }
}
```

Passing `clientSecret` starts the SDK automatically. `LiteHost` attaches the built-in 3D Secure presenter while its content is composed and detaches it when the content is removed.

If you do not use `LiteHost`, attach and detach the same `Lite` instance manually:

```kotlin theme={null}
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    lite.attach(this)
}

override fun onDestroy() {
    lite.detach(this)
    super.onDestroy()
}
```

Do not use `LiteHost` and manual `attach`/`detach` together for the same instance.

You can observe initialization and payment state through `StateFlow`:

```kotlin theme={null}
val phase by lite.phase.collectAsState()

when (val current = phase) {
    Lite.Phase.Idle,
    Lite.Phase.LoadingSession,
    Lite.Phase.Ready,
    Lite.Phase.Paying -> Unit
    is Lite.Phase.Failed -> {
        // Show current.message.
    }
}
```

### 5. Save and reuse cards

When the session contains eligible saved cards, the Payment Sheet and embeddable form display them automatically. The customer can select a saved card or enter a new one.

For a new card, the form includes a **Save card for future purchase** control. Saved cards are available only when the customer and checkout session are eligible for them. Your server remains responsible for creating the session with the correct customer context.

### 6. Handle 3D Secure

No separate 3D Secure implementation is required. The SDK presents the issuer challenge in a secured in-app WebView and resumes payment processing after it closes.

For the Payment Sheet, attachment is automatic. For the embeddable form, use `LiteHost` or call `lite.attach(activity)` as shown above. If no Activity is attached when 3D Secure is required, the payment fails instead of waiting indefinitely.

Keep the Activity and checkout screen alive until the result callback runs. Do not fulfill the order from the 3D Secure callback or redirect alone; wait for the lite payment result and verify it from your server.

### 7. Handle the result

The callback receives a `Lite.PayResult`:

```kotlin theme={null}
data class PayResult(
    val status: PaymentOperationStatus,
    val paymentId: String?,
    val error: String?,
    val errorCode: String?,
)
```

| Status              | Meaning                                                                                            |
| ------------------- | -------------------------------------------------------------------------------------------------- |
| `SUCCESS`           | The payment was authorized or captured. `paymentId` identifies the payment.                        |
| `FAILURE`           | The payment failed or was rejected. Display `error` and use `errorCode` for programmatic handling. |
| `PROCESSING`        | The payment has not reached a final state. Keep the order pending and check it from your server.   |
| `CANCELLED`         | The customer dismissed checkout or cancelled authentication.                                       |
| `ALREADY_COMPLETED` | The opened session already had a completed payment. This is not a new payment attempt.             |

The built-in form disables its pay button while a payment is in progress. Keep your checkout screen mounted until the result callback runs.

### 8. Confirm the payment on your server

A client-side success result is not sufficient for order fulfillment. The app can close, lose connectivity, or be modified.

Always retrieve the checkout session or payment from your server and verify its final state before fulfilling the order.

## Clean up

The Payment Sheet clears card fields when it closes.

For an embeddable integration, the Activity `ViewModel` owns `Lite`. Reset it when the customer abandons checkout or when you intentionally restart the flow:

```kotlin theme={null}
lite.reset()
```

`reset()` cancels the active SDK payment job and removes the loaded session, collected card fields, selected saved card, and previous result.

## Test your integration

Use lite test API keys and test cards to verify:

* Successful card payments.
* Declined and unsupported cards.
* 3D Secure success, failure, and cancellation.
* Processing payments.
* Saved-card display and payment.
* Saving a new card for future use.
* Payment Sheet dismissal.
* Activity recreation and rotation.
* Reopening a completed session.

Test that your server confirms the final payment state before your system fulfills an order.
