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

> Abra o checkout hospedado do Dodo Payments a partir de um app iOS em SFSafariViewController com o SDK oficial para Swift e obtenha um resultado de checkout tipado a partir de uma única chamada.

> [!NOTE]
>
> Esta página aborda o SDK oficial de checkout do Dodo Payments para iOS e Swift. Ele abre o checkout hospedado do Dodo Payments em uma visualização de navegador nativa e retorna um resultado tipado.

> **[Checkout Sessions API](https://docs.dodopayments.com/developer-resources/checkout-session.md)**
>
> Crie o `checkout_url` que este SDK abre a partir do seu backend.

> **[Mobile Integration Guide](https://docs.dodopayments.com/developer-resources/mobile-integration.md)**
>
> Veja como este SDK se encaixa no fluxo completo de pagamentos móveis.

O SDK para iOS abre o checkout hospedado do Dodo Payments em `SFSafariViewController` e retorna um `CheckoutResult` tipado quando o cliente conclui ou sai do checkout. Ele não armazena nenhuma API key e não contém código de rede, portanto nunca chama a API do Dodo Payments. O checkout é executado na visualização do navegador. O SDK apresenta e fecha essa visualização e lê o resultado da URL de retorno.

**Requisitos:** iOS 16 ou posterior e Swift 6.2 ou posterior (o pacote declara `swift-tools-version: 6.2`). O SDK não tem dependências de terceiros.

## Instalação

**1. Add the Package**

No Xcode, acesse **File → Add Package Dependencies** e insira a URL do pacote:

```text theme={null}
https://github.com/dodopayments/dodopayments-mobile-sdk-ios
```

Selecione a versão 1.1.0 ou posterior. A [personalização da aparência](#appearance-customization) requer a versão 1.1.0.

Para adicionar o pacote em `Package.swift`, em vez disso, adicione esta dependência:

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

O produto da biblioteca é `DodoCheckout`.

**2. Register a Callback URL Scheme**

Registre um esquema de URL para que o iOS encaminhe a URL de retorno do checkout de volta ao seu app. Adicione um tipo de URL ao seu `Info.plist`:

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

Você também pode adicionar o tipo de URL no Xcode em **Info → URL Types**.

Use este esquema no `returnUrl` que você passa ao SDK, por exemplo `myapp://checkout/return`, e defina a mesma URL como `return_url` da sessão de checkout quando o seu backend criar a sessão. O SDK compara a URL de retorno pelo esquema, host e caminho. A URL não precisa carregar uma página real.

## Uso

`DodoCheckout.start` é uma função `async` que é executada no ator principal. Passe `checkoutUrl` como um `URL` criado a partir do `checkout_url` retornado pelo seu backend:

```swift theme={null}
import DodoCheckout

// showSuccess(_:), showFailure(), showExpired(), and reconcileAbandonedSession()
// are your own functions. See Abandoned Sessions for what to reconcile.
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: await reconcileAbandonedSession()  // outcome unknown, not a failure
case .pending:   await reconcileAbandonedSession()
case .expired:   showExpired()
}
```

`onEvent` recebe eventos `.opened`, `.returnReceived` e `.closed`. Seus valores `name` são `checkout.opened`, `checkout.return_received` e `checkout.closed`. Use os eventos apenas para logging, nunca para decidir o resultado.

## Encaminhamento da URL de retorno

`SFSafariViewController` não pode capturar sua própria URL de retorno, então o iOS abre a URL no seu app. Encaminhe cada URL recebida para `DodoCheckout.handleOpenURL(_:)`. Em um app sem cenas, chame-o a partir do `application(_:open:options:)` do app delegate.

**SwiftUI**

```swift theme={null}
.onOpenURL { url in
    DodoCheckout.handleOpenURL(url)
}
```

**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)
}
```

> [!NOTE]
>
> Você pode encaminhar todas as URLs. `handleOpenURL` atua apenas em uma URL que corresponde ao `returnUrl` do checkout em andamento e retorna `true` para ela. Para qualquer outra URL, ele retorna `false`; portanto, trate essa URL por conta própria.

## O significado do resultado

O SDK cria `CheckoutResult` a partir dos parâmetros de consulta na URL de retorno.

> [!WARNING]
>
> `result.status` é uma indicação para a UI, não uma prova de pagamento. Confirme cada pagamento a partir do seu backend, usando o webhook `payment.succeeded` ou `subscription.active`.

**status** `CheckoutStatus` *required*

Um dos cinco valores:

* `succeeded`: a URL de retorno tem `status=succeeded` (pagamento único) ou `status=active` (assinatura).
* `failed`: o pagamento foi recusado (`status=failed`).
* `cancelled`: o cliente fechou a sheet antes que a URL de retorno chegasse. O SDK não conhece o resultado, e o pagamento pode ter sido bem-sucedido; portanto, não exiba uma tela de falha. Em vez disso, faça a reconciliação da [sessão abandonada](#abandoned-sessions).
* `pending`: o pagamento é liquidado posteriormente (`status=processing` ou qualquer valor `requires_*`), ou o parâmetro `status` estava ausente ou não foi reconhecido. Faça a reconciliação como em `cancelled`.
* `expired`: a sessão de checkout expirou (`status=expired`).

**paymentId** `String?`

O parâmetro de consulta `payment_id`, quando a URL de retorno inclui um. Mostre-o na sua UI, mas não o use para conceder acesso. Consulte [Verificar o pagamento](#verify-the-payment).

**subscriptionId** `String?`

O parâmetro de consulta `subscription_id`. Definido para checkouts de assinatura.

**licenseKeys** `[String]?`

O parâmetro de consulta `license_key`. Definido quando o checkout inclui produtos com chaves de licença.

**customerEmail** `String?`

O parâmetro de consulta `email`. Definido quando o checkout captura um endereço de e-mail.

**raw** `[String: String]`

Cada parâmetro de consulta da URL de retorno, literalmente.

## Verificar o pagamento

> **[Webhooks](https://docs.dodopayments.com/developer-resources/webhooks.md)**
>
> O Dodo Payments chama o seu backend quando um pagamento é bem-sucedido ou uma assinatura é ativada.

> **[Get Payment Detail](https://docs.dodopayments.com/api-reference/payments/get-payments-1.md)**
>
> Consulte `paymentId` com sua secret key para verificar o status.

Conceda acesso somente depois que uma dessas opções confirmar o pagamento. Não dependa apenas de `result.status`.

## Personalização da aparência

Para alterar o botão de fechamento da sheet, o estilo de apresentação e o esquema de cores, passe um `BrowserCustomization` como `customization` para `start(...)`. Todos os campos são opcionais. Para um campo `nil`, o SDK não define essa opção e o iOS aplica seu próprio padrão. A exceção é `presentationStyle`, em que `nil` significa `pageSheet`.

**dismissButtonStyle** `DismissButtonStyle?`

Estilo do botão de fechamento: `done`, `close` ou `cancel`. O iOS decide se ele será renderizado como um rótulo ou um ícone.

**presentationStyle** `PresentationStyle?`

`pageSheet` (o padrão) apresenta um cartão que o cliente pode deslizar para baixo para fechar. `fullScreen` cobre a tela inteira e não tem gesto de fechamento.

**barCollapsingEnabled** `Bool?`

Permite que a barra de ferramentas seja recolhida conforme a página rola. Ela só tem efeito visível quando `presentationStyle` é `fullScreen`. Com `pageSheet`, as barras permanecem fixas independentemente desta configuração.

**colorScheme** `ColorScheme?`

`light` ou `dark` força essa aparência independentemente da configuração do sistema do dispositivo. `system` segue a configuração do sistema. Esta opção aplica o tema somente aos controles nativos ao redor da página. O modo claro ou escuro da própria página de checkout vem de `customization.theme` na sessão de checkout, e suas cores vêm de `customization.theme_config`.

O iOS não tem uma opção de cor da barra de ferramentas. As propriedades de tonalidade do `SFSafariViewController` subjacente estão obsoletas a partir do iOS 26.

```swift theme={null}
let result = try await DodoCheckout.start(
    checkoutUrl: checkoutUrl,
    returnUrl: URL(string: "myapp://checkout/return")!,
    customization: BrowserCustomization(
        dismissButtonStyle: .close,
        presentationStyle: .fullScreen,
        colorScheme: .dark
    )
)
```

## Erros

`start` lança `CheckoutError` somente em caso de uso incorreto ou falha da plataforma. Leia o motivo em `error.code`. O cancelamento por parte do cliente ou um pagamento recusado sempre é um resultado, nunca um erro lançado.

* `invalidCheckoutUrl` (`INVALID_CHECKOUT_URL`): `checkoutUrl` não é uma URL de sessão de checkout `https` (caminho começando com `/session/`) em `checkout.dodopayments.com` ou `test.checkout.dodopayments.com`.
* `invalidReturnUrl` (`INVALID_RETURN_URL`): `returnUrl` não é uma URL absoluta com esquema e host.
* `alreadyInProgress` (`ALREADY_IN_PROGRESS`): outro checkout está em execução. Apenas um checkout pode ser executado por vez.
* `platformError` (`PLATFORM_ERROR`): falha inesperada da plataforma, como a ausência de um view controller a partir do qual apresentar.

Depois de um erro lançado, verifique também se há uma sessão abandonada. Se a sheet não tiver confirmado que apareceu, o SDK mantém a sessão registrada porque o checkout ainda pode estar aberto. A exceção é `alreadyInProgress`: um registro encontrado nesse momento pertence ao checkout que ainda está em execução.

## Sessões abandonadas

> [!NOTE]
>
> O SDK registra a sessão de checkout quando apresenta o checkout e limpa o registro somente quando o checkout termina com `succeeded`, `failed` ou `expired`. O registro permanece quando o app é encerrado durante o checkout e após um resultado `cancelled` ou `pending`. Verifique se há um registro na próxima inicialização e após cada resultado `cancelled` ou `pending`.

```swift theme={null}
import DodoCheckout

if let abandoned = DodoCheckout.getAbandonedSession() {
    // Ask your backend for the outcome of abandoned.sessionId, and show it.
    // Clear the record only after the outcome is final:
    DodoCheckout.clearAbandonedSession()
}
```

`abandoned.sessionId` é o ID da sessão de checkout, que começa com `cks_`. `abandoned.createdAt` é o checkout `Date` iniciado. Seu backend pode consultar a sessão com [Obter sessão de checkout](https://docs.dodopayments.com/api-reference/checkout-sessions/get-checkouts.md), que retorna `payment_id` e `payment_status`. Até que o pagamento alcance um status final, trate-o como pendente, não como falho.

## Relacionado

> **[Mobile Integration Guide](https://docs.dodopayments.com/developer-resources/mobile-integration.md)**
>
> O mesmo contrato para Android, React Native e Flutter.

> **[React Native SDK](https://docs.dodopayments.com/developer-resources/sdks/react-native.md)**
>
> Encapsula este mesmo núcleo Swift no iOS.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.