# Kustom Checkout in an Android app

Add Kustom Checkout to an Android app with KustomMobileSDK — add the Gradle dependency, create a KustomCheckoutView in XML or code and handle its events.

This guide adds Kustom Checkout to an Android app with the Kustom Mobile SDK. You create a
`KustomCheckoutView`, set the checkout snippet your server returns on it, and handle the
events it dispatches. [Kustom Checkout in a mobile app](/checkout/mobile-sdk/) explains what's
common to every platform.

## Before you start

You need:

- **A server endpoint that returns a checkout snippet.** Your backend, not the app, creates
  the order with your API credentials and returns its `html_snippet`. See [Create and update
  an order](/checkout/integrate/create-order/). This guide calls the endpoint `<YOUR-URL>`.
- **A return URL.** A custom URL scheme your app is registered for, such as `myapp://`. It
  brings the customer back after a payment method sends them to a third-party app. See [the
  return URL](/checkout/mobile-sdk/#the-return-url).

## Step by step

### 1. Add the SDK

Add the KustomMobileSDK Maven repositories and the dependency to your Gradle build:

```kotlin
repositories {
  maven("https://x.kustomcdn.co/mobile-sdk/android/")
  maven("https://x.klarnacdn.net/mobile-sdk/")
}

dependencies {
  implementation("com.kustom.mobile.sdk:kustom-mobile-sdk:1.x.x")
}
```

The second repository is required because KustomMobileSDK still resolves shared artifacts
from the Klarna Mobile SDK's Maven host. Keep it until Kustom says otherwise.

### 2. Create the checkout view

The checkout view is `KustomCheckoutView`. Declare it in your layout or build it in code.

**In XML.** Declare the view with its environment, region and return URL:

```xml
<com.kustom.mobile.sdk.api.checkout.KustomCheckoutView
    android:id="@+id/checkoutView"
    app:kustomEnvironment="production"
    app:kustomRegion="eu"
    app:kustomReturnUrl="myapp://" />
```

Then look it up in your activity and attach an event handler (step 4):

```kotlin
val checkoutView: KustomCheckoutView = findViewById(R.id.checkoutView)
checkoutView.eventHandler = myEventHandler
```

**In code.** Build the view with everything at once. This is also where you set the theme:

```kotlin
val checkoutView = KustomCheckoutView(
    activity = this,
    returnURL = "myapp://",
    eventHandler = myEventHandler,
    environment = KustomEnvironment.PRODUCTION,
    region = KustomRegion.EU,
    theme = KustomTheme.LIGHT
)
```

### 3. Set the snippet

Fetch the `html_snippet` from `<YOUR-URL>` and set it on the view. This is what renders the
checkout:

```kotlin
checkoutView.setSnippet(snippet)
```

### 4. Handle events and errors

The event handler implements `KustomEventHandler`: `onEvent` receives product events and
`onError` receives SDK errors. Act on each event by its `action`:

```kotlin
checkoutView.eventHandler = object : KustomEventHandler {
    override fun onEvent(component: KustomComponent, event: KustomProductEvent) {
        when (event.action) {
            "complete" -> loadConfirmationSnippet(event.params["uri"])
            "external" -> openExternalPayment(event.params["uri"])
            "validation_error" -> handleValidationError(
                event.params["error_type"],
                event.params["error_text"],
            )
        }
    }

    override fun onError(component: KustomComponent, error: KustomMobileSDKError) {
        Log.e(TAG, "Received error: ${error.name}. Message: ${error.message}")
    }
}
```

The `complete` action means the customer has paid, and `params["uri"]` is the confirmation
URL to load next. `external` carries the URL of an external payment method to send the
customer to, and `validation_error` carries the error's type and text. [Events and
errors](/checkout/mobile-sdk/#events-and-errors) lists every action and error field.

## Check that it works

Point the app at a Playground order and run the flow end to end:

1. The checkout renders in the view after `setSnippet`, rather than staying blank.
2. Paying with [Playground test data](/basics/test-data/) dispatches a `complete` event carrying a `uri`.
3. Your confirmation screen loads from that `uri`.
4. Turning off the network mid-checkout produces an error in `onError`, with `isFatal` telling you whether to recover or bail out.

A blank view almost always means the snippet never arrived. Check the response from
`<YOUR-URL>` before suspecting the SDK.

## Variations

**Pausing the checkout while you update the order.** `suspend()` stops the customer from
interacting with the checkout and `resume()` lets them continue. Suspend before you change the
order and resume afterwards, so the customer never sees stale totals:

```kotlin
checkoutView.suspend()
checkoutView.resume()
```

## Troubleshooting

**The customer is left in the bank app after BankID.** BankID may not return the customer
automatically after authentication. They might have to switch back to your app themselves.

## Related

- [Confirmation and push](/checkout/integrate/confirmation-and-push/) — what your server must do once `complete` fires
- [Create and update an order](/checkout/integrate/create-order/) — the call behind `<YOUR-URL>`
- [Kustom Checkout in a mobile app](/checkout/mobile-sdk/) — native or hybrid, the return URL and migrating from the Klarna Mobile SDK
- [iOS](/checkout/mobile-sdk/ios/) and [React Native](/checkout/mobile-sdk/react-native/) — the same integration on the other platforms
- [Test data](/basics/test-data/) — Playground customers and cards to pay with
