> ## 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.

# Flutter

> Öppna Dodo Payments' hostade checkout från Flutter i en systemwebbläsarflik och få tillbaka ett typat resultat i ett enda anrop.

<Info>
  Detta är det officiella Flutter-paketet för Dodo Payments (`dodopayments_checkout`
  på pub.dev). Det finns även ett separat, community-byggt paket, se
  [Community Projects](/community/projects).
</Info>

<CardGroup cols={2}>
  <Card title="Checkout Sessions API" icon="cart-shopping" href="/developer-resources/checkout-session">
    Skapa checkout\_url som detta SDK öppnar, från din backend.
  </Card>

  <Card title="Mobile Integration Guide" icon="mobile" href="/developer-resources/mobile-integration">
    Se hur detta passar in i det fullständiga mobila betalningsflödet.
  </Card>
</CardGroup>

`dodopayments_checkout` öppnar Dodos hostade checkout i
`SFSafariViewController` på iOS och i en Chrome Custom Tab på Android — samma
inbyggda kärnor som används av de fristående [iOS](/developer-resources/sdks/ios)- och
[Android](/developer-resources/sdks/android)-SDK:erna. All checkoutlogik finns i
dessa inbyggda kärnor; Dart-lagret vidarebefordrar anropet via en typad
[Pigeon](https://pub.dev/packages/pigeon)-kanal. Det innehåller ingen API-nyckel och
anropar aldrig Dodo Payments API.

Kräver Flutter 3.44+ / Dart 3.12+, iOS 16+ och Android `minSdk` 23.

## Installation

<Steps>
  <Step title="Add the Dependency">
    ```yaml pubspec.yaml theme={null}
    dependencies:
      dodopayments_checkout: ^1.0.0
    ```
  </Step>

  <Step title="Register a Callback URL Scheme">
    <Tabs>
      <Tab title="iOS">
        Lägg till en URL-typ för ditt schema i `ios/Runner/Info.plist`:

        ```xml ios/Runner/Info.plist theme={null}
        <key>CFBundleURLTypes</key>
        <array>
          <dict>
            <key>CFBundleURLName</key>
            <string>myapp</string>
            <key>CFBundleURLSchemes</key>
            <array>
              <string>myapp</string>
            </array>
          </dict>
        </array>
        ```

        Vidarebefordra sedan inkommande URL:er (till exempel via
        [`app_links`](https://pub.dev/packages/app_links)) till SDK:t, eftersom
        `SFSafariViewController` inte kan fånga sin egen retur-URL:

        ```dart theme={null}
        import 'package:dodopayments_checkout/dodopayments_checkout.dart';

        DodoCheckout.instance.handleOpenURL(url);
        ```

        <Note>
          Det är säkert att vidarebefordra alla URL:er här. `handleOpenURL` agerar endast på URL:er
          som matchar ditt registrerade `returnUrl` och löser `false` för allt
          annat.
        </Note>
      </Tab>

      <Tab title="Android">
        Ange ditt callback-schema som en manifest-placeholder i Gradle:

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

        <Warning>
          Om `MainActivity` anger `android:taskAffinity=""` (standardvärdet för `flutter
                    create`), ta bort det eller ge SDK:ts activities samma
          affinitet. Annars kan vissa OEM Android-byggen förlora den pågående
          checkout-sessionen och returnera `PLATFORM_ERROR`.
        </Warning>
      </Tab>
    </Tabs>
  </Step>
</Steps>

## Användning

```dart theme={null}
import 'package:dodopayments_checkout/dodopayments_checkout.dart';

final result = await DodoCheckout.instance.start(
  CheckoutParams(
    checkoutUrl: Uri.parse(checkoutUrl), // from your backend's checkout session
    returnUrl: Uri.parse('myapp://checkout/return'), // scheme must be registered (see Setup)
    onEvent: (event) => print(event.type), // logging only
  ),
);

switch (result.status) {
  case CheckoutStatus.succeeded: showSuccess(result.paymentId);
  case CheckoutStatus.failed:    showFailure();
  case CheckoutStatus.cancelled: dismiss();
  case CheckoutStatus.pending:   showPending();
  case CheckoutStatus.expired:   showExpired();
}
```

## Vad resultatet betyder

<Warning>
  `result.status` är en UI-hint, inte ett bevis på betalning. Bekräfta varje betalning
  från din backend via `payment.succeeded` / `subscription.active`
  webhook.
</Warning>

<ParamField body="status" type="CheckoutStatus" required>
  En av `succeeded`, `failed`, `cancelled`, `pending`, `expired`.
</ParamField>

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

<ParamField body="subscriptionId" type="String?">
  Anges för prenumerations-checkouter.
</ParamField>

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

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

<ParamField body="raw" type="Map<String, String>">
  Varje frågeparameter från retur-URL:en, ordagrant.
</ParamField>

## Verifiera betalningen

<CardGroup cols={2}>
  <Card title="Webhooks" icon="webhook" href="/developer-resources/webhooks">
    Dodo Payments anropar din backend när en betalning lyckas eller en prenumeration aktiveras.
  </Card>

  <Card title="Get Payment Detail" icon="magnifying-glass" href="/api-reference/payments/get-payments-1">
    Slå upp `paymentId` med din hemliga nyckel för att kontrollera dess status direkt.
  </Card>
</CardGroup>

Bevilja åtkomst efter att något av dessa har bekräftat betalningen, aldrig enbart från
`result.status`.

## Fel

`start` kastar `CheckoutException` endast vid felaktig användning eller ett plattformsfel.
En avbruten eller nekad betalning är alltid ett resultat, aldrig ett undantag.

* `invalidCheckoutUrl` (`INVALID_CHECKOUT_URL`): inte en `checkout.dodopayments.com` sessions-URL.
* `invalidReturnUrl` (`INVALID_RETURN_URL`): inte en giltig absolut URL.
* `alreadyInProgress` (`ALREADY_IN_PROGRESS`): en checkout körs redan.
* `platformError` (`PLATFORM_ERROR`): oväntat plattformsfel.

## Övergivna sessioner

<Info>
  Om appen avslutas mitt under checkouten återställer du sessionen vid nästa start och
  synkroniserar den med din backend.
</Info>

```dart theme={null}
import 'package:dodopayments_checkout/dodopayments_checkout.dart';

final abandoned = await DodoCheckout.instance.getAbandonedSession();
if (abandoned != null) {
  // reconcile abandoned.sessionId with your backend, then:
  await DodoCheckout.instance.clearAbandonedSession();
}
```

## Relaterat

<CardGroup cols={2}>
  <Card title="Mobile Integration Guide" icon="mobile" href="/developer-resources/mobile-integration">
    Samma kontrakt för Android, iOS och React Native.
  </Card>

  <Card title="Community Projects" icon="users" href="/community/projects">
    Det finns även ett separat, community-byggt Flutter-paket.
  </Card>
</CardGroup>
