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

# iOS

> Öffne den gehosteten Checkout von Dodo Payments aus einer iOS-App in SFSafariViewController und erhalte mit einem Aufruf ein typisiertes Ergebnis zurück.

<Info>
  Dies ist das offizielle iOS-Checkout-SDK von Dodo Payments für Swift. Es öffnet den gehosteten Checkout von Dodo in einer nativen Browseransicht und gibt ein typisiertes Ergebnis zurück.
</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>

Das iOS SDK öffnet den gehosteten Checkout von Dodo in `SFSafariViewController`, enthält keinen API-Schlüssel und ruft die Dodo API niemals direkt auf. Die gesamte Checkout-Logik läuft im Browser; das SDK verwaltet lediglich den Lebenszyklus der Ansicht und erfasst die Rückgabe-URL.

Erfordert iOS 16+ und Swift 6.

## Installation

<Steps>
  <Step title="Add the Package">
    Gehe in Xcode zu **File → Add Package Dependencies** und gib Folgendes ein:

    ```
    https://github.com/dodopayments/dodopayments-mobile-sdk-ios
    ```

    Wähle Version 1.0.0 oder höher aus.

    Alternativ kannst du es zu deinem `Package.swift` hinzufügen:

    ```swift Package.swift theme={null}
    .package(url: "https://github.com/dodopayments/dodopayments-mobile-sdk-ios", from: "1.0.0")
    ```
  </Step>

  <Step title="Register a Callback URL Scheme">
    Deine App muss ein URL-Schema registrieren, um die Rückgabe-URL vom Checkout zu empfangen. Füge dies zu deinem `Info.plist` hinzu:

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

    Du kannst dies auch über die Xcode-Oberfläche **Info → URL Types** hinzufügen.
  </Step>
</Steps>

## Verwendung

```swift theme={null}
import DodoCheckout

let result = try await DodoCheckout.start(
    checkoutUrl: checkoutUrl,   // from your backend's checkout session
    returnUrl: URL(string: "myapp://checkout/return")!,
    onEvent: { event in print(event.name) }  // logging only
)

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

## Weiterleiten der Rückgabe-URL

`SFSafariViewController` kann seine eigene Rückgabe-URL nicht innerhalb des Prozesses abfangen. Deine App muss eingehende URLs an das SDK weiterleiten.

<Tabs>
  <Tab title="SwiftUI">
    ```swift theme={null}
    .onOpenURL { url in
        DodoCheckout.handleOpenURL(url)
    }
    ```
  </Tab>

  <Tab title="SceneDelegate">
    ```swift SceneDelegate.swift theme={null}
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        guard let url = URLContexts.first?.url else { return }
        DodoCheckout.handleOpenURL(url)
    }
    ```
  </Tab>
</Tabs>

<Note>
  Es ist sicher, hier jede URL weiterzuleiten. `handleOpenURL` reagiert nur auf URLs, die deinem registrierten `returnUrl` entsprechen, und gibt für alles andere `false` zurück.
</Note>

## Bedeutung des Ergebnisses

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

<ParamField body="status" type="CheckoutStatus" required>
  Eines von `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 zur Zugriffserteilung. Siehe unten unter „Zahlung verifizieren“.
</ParamField>

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

<ParamField body="licenseKeys" type="[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="[String: String]">
  Jeder Query-Parameter aus der Rückgabe-URL, unverändert.
</ParamField>

## Zahlung verifizieren

<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 Subscription 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 prüfen.
  </Card>
</CardGroup>

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

## Fehler

`start` löst `CheckoutError` nur bei fehlerhafter Verwendung oder einem Plattformfehler aus. Eine stornierte oder abgelehnte Zahlung ist immer ein Ergebnis, niemals eine Ausnahme.

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

## Abgebrochene Sessions

<Info>
  Wenn die App während des Checkouts beendet wird, stelle die Session beim nächsten Start wieder her und gleiche sie mit deinem Backend ab.
</Info>

```swift theme={null}
import DodoCheckout

if let abandoned = DodoCheckout.getAbandonedSession() {
    // reconcile abandoned.sessionId with your backend, then:
    DodoCheckout.clearAbandonedSession()
}
```

## Verwandte Themen

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

  <Card title="React Native SDK" icon="react" href="/developer-resources/sdks/react-native">
    Umschließt denselben Swift-Kern unter iOS.
  </Card>
</CardGroup>
