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

# Android

> Öppna Dodo Payments hosted checkout från en Android-app i en Chrome Custom Tab och få tillbaka ett typat resultat i ett enda anrop.

<Info>
  Detta är det officiella Android checkout SDK (`com.dodopayments.api:checkout-android`),
  för att öppna Dodos hosted checkout. Det skiljer sig från
  [backend Kotlin SDK](/developer-resources/sdks/kotlin), som anropar Dodo
  Payments API från din server.
</Info>

<CardGroup cols={2}>
  <Card title="Checkout Sessions API" icon="cart-shopping" href="/developer-resources/checkout-session">
    Skapa `checkout_url` som detta SDK öppnar
  </Card>

  <Card title="Mobile Integration Guide" icon="mobile" href="/developer-resources/mobile-integration">
    Bästa praxis för mobila checkout-flöden
  </Card>
</CardGroup>

Android SDK öppnar Dodos hosted checkout i en Chrome Custom Tab med `androidx.browser.customtabs`. Det innehåller ingen nätverkskod och lagrar ingen API key. Du skickar en `checkoutUrl` från checkout session på din backend, och SDK:t returnerar en typad `CheckoutResult` när användaren slutför eller avbryter flödet.

**Krav:** `minSdk` 23, Kotlin, Java 17.

## Installation

<Steps>
  <Step title="Add the Dependency">
    ```kotlin build.gradle.kts theme={null}
    dependencies {
        implementation("com.dodopayments.api:checkout-android:1.0.0")
    }
    ```
  </Step>

  <Step title="Register a Callback URL Scheme">
    Ange ditt callback scheme som en Gradle manifest placeholder. Bibliotekets eget
    manifest deklarerar redan redirect activity:s intent filter med token `${dodoCallbackScheme}`, så den här enda egenskapen är hela konfigurationen —
    du behöver inte lägga till någon manifest-XML:

    ```kotlin build.gradle.kts theme={null}
    android {
        defaultConfig {
            manifestPlaceholders["dodoCallbackScheme"] = "myapp"
        }
    }
    ```

    Värdet måste matcha schemat i `CheckoutParams.returnUrl` (t.ex.
    `myapp://checkout/return`).

    <Note>
      Om du utelämnar placeholder helt misslyckas bygget omedelbart med ett fel om
      olöst placeholder, i stället för att misslyckas tyst vid checkout. Om du anger den men den inte matchar schemat för `returnUrl`, kastar `DodoCheckout.start`
      `PLATFORM_ERROR` innan något visas.
    </Note>
  </Step>
</Steps>

## Användning

SDK:t stöder två sätt att anropa det.

<Tabs>
  <Tab title="Launcher (Recommended)">
    Registrera kontraktet med `registerForActivityResult` och starta det sedan:

    ```kotlin theme={null}
    import com.dodopayments.checkout.CheckoutParams
    import com.dodopayments.checkout.CheckoutStatus
    import com.dodopayments.checkout.DodoCheckout

    private val checkoutLauncher =
        registerForActivityResult(DodoCheckout.contract()) { result ->
            when (result.status) {
                CheckoutStatus.SUCCEEDED -> showSuccess(result.paymentId)
                CheckoutStatus.FAILED -> showFailure()
                CheckoutStatus.CANCELLED -> dismiss()
                CheckoutStatus.PENDING -> showPending()
                CheckoutStatus.EXPIRED -> showExpired()
            }
        }

    checkoutLauncher.launch(
        CheckoutParams(
            checkoutUrl = checkoutUrl, // from your backend's checkout session
            returnUrl = "myapp://checkout/return"
        )
    )
    ```

    <Tip>
      Föredra detta sätt. Resultatet levereras via Androids OS-hanterade
      `ActivityResultRegistry`, så det överlever om processen avslutas.
    </Tip>
  </Tab>

  <Tab title="Suspend Function">
    Anropa `DodoCheckout.start` från en coroutine scope:

    ```kotlin theme={null}
    import com.dodopayments.checkout.CheckoutParams
    import com.dodopayments.checkout.CheckoutStatus
    import com.dodopayments.checkout.DodoCheckout

    lifecycleScope.launch {
        val result = DodoCheckout.start(
            activity = this@MyActivity,
            params = CheckoutParams(
                checkoutUrl = checkoutUrl, // from your backend's checkout session
                returnUrl = "myapp://checkout/return"
            ),
            onEvent = { event -> println(event.name) } // logging only
        )

        when (result.status) {
            CheckoutStatus.SUCCEEDED -> showSuccess(result.paymentId)
            CheckoutStatus.FAILED -> showFailure()
            CheckoutStatus.CANCELLED -> dismiss()
            CheckoutStatus.PENDING -> showPending()
            CheckoutStatus.EXPIRED -> showExpired()
        }
    }
    ```

    <Warning>
      Detta sätt löser en `CompletableDeferred` i minnet, så det överlever **inte**
      om processen avslutas. `onEvent` är endast tillgänglig här, inte på kontraktet.
    </Warning>
  </Tab>
</Tabs>

## Vad resultatet betyder

<Warning>
  Fältet `status` är en UI-hint, inte ett bevis på betalning. Verifiera alltid betalningen på din backend med webhooks eller endpointen Get Payment Detail innan du beviljar åtkomst.
</Warning>

<ParamField body="status" type="CheckoutStatus" required>
  En av `SUCCEEDED`, `FAILED`, `CANCELLED`, `PENDING`, `EXPIRED`.
</ParamField>

<ParamField body="paymentId" type="String?">
  Anges när return URL innehöll en sådan. Visa den i UI:t, men använd den inte för att bevilja åtkomst. Se Verify the Payment nedan.
</ParamField>

<ParamField body="subscriptionId" type="String?">
  Anges för subscription checkouts.
</ParamField>

<ParamField body="licenseKeys" type="List<String>?">
  Anges när checkouten innehåller license key-produkter.
</ParamField>

<ParamField body="customerEmail" type="String?">
  Anges när checkouten samlar in en e-postadress.
</ParamField>

<ParamField body="raw" type="Map<String, String>">
  Varje query parameter från return URL, ordagrant.
</ParamField>

## Verifiera betalningen

<CardGroup cols={2}>
  <Card title="Webhooks" icon="webhook" href="/developer-resources/webhooks">
    Lyssna på betalningshändelser i realtid
  </Card>

  <Card title="Get Payment Detail" icon="magnifying-glass" href="/api-reference/payments/get-payments-1">
    Fråga efter betalningsstatus vid behov
  </Card>
</CardGroup>

Bevilja användaren åtkomst först efter att något av dessa har bekräftat betalningen. Förlita dig inte enbart på `CheckoutResult.status`.

## Fel

`DodoCheckout.start` kastar `CheckoutError` endast vid felaktig användning eller ett plattformsfel. Läs koden från `CheckoutError.code`:

* `INVALID_CHECKOUT_URL`: inte en `checkout.dodopayments.com` session URL.
* `INVALID_RETURN_URL`: inte en giltig absolut URL.
* `ALREADY_IN_PROGRESS`: en checkout körs redan.
* `PLATFORM_ERROR`: oväntat plattformsfel, inklusive en `returnUrl` vars
  schema inte matchar din `dodoCallbackScheme` placeholder.

Om en användare avbryter eller en betalning nekas är resultatet alltid ett resultat (`CANCELLED` eller
`FAILED`), aldrig ett kastat fel. Med launcher-sättet kastas valideringsfel ut från `launcher.launch(...)`.

## Övergivna sessioner

Om appen avslutas eller användaren tvångsstoppar den under checkout lagrar SDK:t sessionen lokalt. Nästa gång appen startas kontrollerar du om det finns en övergiven session och synkroniserar den med din backend:

```kotlin theme={null}
DodoCheckout.getAbandonedSession(context)?.let { abandoned ->
    // reconcile abandoned.sessionId with your backend, then:
    DodoCheckout.clearAbandonedSession(context)
}
```

`abandoned.createdAt` är en epoch-tidsstämpel i millisekunder.

## Relaterat

<CardGroup cols={2}>
  <Card title="Mobile Integration Guide" icon="mobile" href="/developer-resources/mobile-integration">
    Bästa praxis för mobila checkout-flöden
  </Card>

  <Card title="Kotlin SDK" icon="code" href="/developer-resources/sdks/kotlin">
    Backend SDK för server-side-operationer
  </Card>
</CardGroup>
