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

> Öffne den gehosteten Checkout von Dodo Payments aus Flutter in einem Systembrowser-Tab und erhalte das typisierte Ergebnis mit einem einzigen Aufruf zurück.

<Info>
  Dies ist das offizielle Dodo Payments Flutter-Paket (`dodopayments_checkout`
  auf pub.dev). Es gibt außerdem ein separates, von der Community entwickeltes Paket; siehe
  [Community-Projekte](/community/projects).
</Info>

<CardGroup cols={2}>
  <Card title="Checkout Sessions API" icon="cart-shopping" href="/developer-resources/checkout-session">
    Erstelle die checkout\_url, die dieses SDK öffnet, in deinem Backend.
  </Card>

  <Card title="Mobile Integration Guide" icon="mobile" href="/developer-resources/mobile-integration">
    Erfahre, wie dies in den vollständigen mobilen Zahlungsablauf passt.
  </Card>
</CardGroup>

`dodopayments_checkout` öffnet den gehosteten Checkout von Dodo in
`SFSafariViewController` unter iOS und einem Chrome Custom Tab unter Android – dieselben
nativen Kernkomponenten, die auch von den eigenständigen [iOS](/developer-resources/sdks/ios)- und
[Android](/developer-resources/sdks/android)-SDKs verwendet werden. Die gesamte Checkout-Logik befindet sich in
diesen nativen Kernkomponenten; die Dart-Schicht leitet den Aufruf über einen typisierten
[Pigeon](https://pub.dev/packages/pigeon)-Kanal weiter. Sie enthält keinen API-Schlüssel und
ruft niemals die Dodo Payments API auf.

Erfordert Flutter 3.44+ / Dart 3.12+, iOS 16+ und 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">
        Füge in `ios/Runner/Info.plist` einen URL-Typ für dein Schema hinzu:

        ```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>
        ```

        Leite eingehende URLs anschließend (z. B. über
        [`app_links`](https://pub.dev/packages/app_links)) an das SDK weiter, da
        `SFSafariViewController` seine eigene Rückgabe-URL nicht abfangen kann:

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

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

        <Note>
          Es ist sicher, hier jede URL weiterzuleiten. `handleOpenURL` reagiert nur auf URLs,
          die zu deinem registrierten `returnUrl` passen, und löst für alles
          andere `false` auf.
        </Note>
      </Tab>

      <Tab title="Android">
        Lege dein Callback-Schema als Gradle-Manifest-Platzhalter fest:

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

        <Warning>
          Wenn `MainActivity` `android:taskAffinity=""` festlegt (den standardmäßigen Wert von `flutter
                    create`), entferne ihn oder gib den Activities des SDKs dieselbe
          affinity. Andernfalls können einige OEM-Android-Builds den laufenden
          Checkout verlieren und `PLATFORM_ERROR` zurückgeben.
        </Warning>
      </Tab>
    </Tabs>
  </Step>
</Steps>

## Verwendung

```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();
}
```

## Bedeutung des Ergebnisses

<Warning>
  `result.status` ist ein UI-Hinweis und kein Zahlungsnachweis. Bestätige jede Zahlung
  über dein Backend mithilfe des `payment.succeeded`-/`subscription.active`-
  Webhooks.
</Warning>

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

<ParamField body="paymentId" type="String?">
  Wird gesetzt, wenn die Rückgabe-URL einen solchen Wert enthielt. Zeige ihn in der UI an, verwende ihn jedoch nicht,
  um Zugriff zu gewähren. Siehe unten unter „Zahlung überprüfen“.
</ParamField>

<ParamField body="subscriptionId" type="String?">
  Wird für Abonnement-Checkouts gesetzt.
</ParamField>

<ParamField body="licenseKeys" type="List<String>?">
  Wird gesetzt, wenn der Checkout Produkte mit Lizenzschlüsseln enthält.
</ParamField>

<ParamField body="customerEmail" type="String?">
  Wird gesetzt, wenn der Checkout eine E-Mail-Adresse erfasst.
</ParamField>

<ParamField body="raw" type="Map<String, String>">
  Jeder Query-Parameter aus der Rückgabe-URL, unverändert.
</ParamField>

## Zahlung überprüfen

<CardGroup cols={2}>
  <Card title="Webhooks" icon="webhook" href="/developer-resources/webhooks">
    Dodo Payments ruft dein Backend auf, wenn eine Zahlung erfolgreich ist oder ein Abonnement aktiviert wird.
  </Card>

  <Card title="Get Payment Detail" icon="magnifying-glass" href="/api-reference/payments/get-payments-1">
    Rufe `paymentId` mit deinem geheimen Schlüssel ab, um den Status direkt zu überprüfen.
  </Card>
</CardGroup>

Gewähre Zugriff erst, nachdem eine dieser Methoden die Zahlung bestätigt hat, niemals allein aufgrund von
`result.status`.

## Fehler

`start` löst `CheckoutException` nur bei falscher Verwendung oder einem Plattformfehler aus.
Eine stornierte oder abgelehnte Zahlung wird immer als Ergebnis und niemals als Exception zurückgegeben.

* `invalidCheckoutUrl` (`INVALID_CHECKOUT_URL`): keine `checkout.dodopayments.com`-Sitzungs-URL.
* `invalidReturnUrl` (`INVALID_RETURN_URL`): keine gültige absolute URL.
* `alreadyInProgress` (`ALREADY_IN_PROGRESS`): Ein Checkout läuft bereits.
* `platformError` (`PLATFORM_ERROR`): unerwarteter Plattformfehler.

## Verlassene Sitzungen

<Info>
  Wenn die App während des Checkouts beendet wird, stelle die Sitzung beim nächsten Start wieder her und
  stimme sie mit deinem Backend ab.
</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();
}
```

## Verwandte Inhalte

<CardGroup cols={2}>
  <Card title="Mobile Integration Guide" icon="mobile" href="/developer-resources/mobile-integration">
    Derselbe Vertrag für Android, iOS und React Native.
  </Card>

  <Card title="Community Projects" icon="users" href="/community/projects">
    Es gibt außerdem ein separates, von der Community entwickeltes Flutter-Paket.
  </Card>
</CardGroup>
