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

# PrimerCheckoutPresenter

> UIKit entry point for presenting the managed checkout and receiving delegate callbacks

<Warning>
  Primer Checkout iOS SDK is currently in **beta** (v3.0.0-beta.1).
  The API is subject to change before the stable release.
</Warning>

`PrimerCheckoutPresenter` is the UIKit entry point for the managed checkout. It presents the
CheckoutComponents UI from a `UIViewController` and delivers results through a delegate, acting as a
bridge between UIKit apps and the underlying SwiftUI implementation.

<Info>
  For pure SwiftUI apps, use [`PrimerCheckout`](/docs/sdk/ios-checkout/v3.0.0-beta/api/primer-checkout)
  directly instead of this class. `PrimerCheckoutPresenter` exists for view-controller based
  navigation and Objective-C interoperability.
</Info>

## Declaration

```swift theme={"dark"}
@available(iOS 15.0, *)
@MainActor
@objc public final class PrimerCheckoutPresenter: NSObject
```

The presenter is a `@MainActor` singleton: call its static methods from the main thread (the
default for UIKit lifecycle callbacks). It is also exposed to Objective-C via `@objc`.

## Properties

| Property       | Type                               | Description                                                                             |
| -------------- | ---------------------------------- | --------------------------------------------------------------------------------------- |
| `shared`       | `PrimerCheckoutPresenter`          | The shared singleton instance. Use it to assign the `delegate`. Exposed to Objective-C. |
| `delegate`     | `PrimerCheckoutPresenterDelegate?` | The object that receives checkout result and lifecycle callbacks. Held weakly.          |
| `isAvailable`  | `Bool`                             | `static`. `true` when CheckoutComponents can be presented on the current OS version.    |
| `isPresenting` | `Bool`                             | `static`. `true` while a checkout is being presented or is currently on screen.         |

```swift theme={"dark"}
@objc public static let shared = PrimerCheckoutPresenter()

public weak var delegate: PrimerCheckoutPresenterDelegate?

@objc public static var isAvailable: Bool
@objc public static var isPresenting: Bool
```

<Note>
  `delegate` is a `weak` reference. Retain the object you assign (for example the presenting view
  controller) for as long as checkout is on screen, otherwise callbacks will not fire.
</Note>

## Presenting checkout

`presentCheckout` has four overloads. They differ only in how much you configure and whether you
supply the presenting view controller yourself. All overloads accept an optional trailing
`completion` closure that runs once the checkout UI has finished presenting.

None of these parameters have Swift defaults. The overloads that omit settings or theme apply the
SDK's current global `PrimerSettings` and a default `PrimerCheckoutTheme()` internally.

### From an explicit view controller

```swift theme={"dark"}
@objc public static func presentCheckout(
    clientToken: String,
    from viewController: UIViewController,
    completion: (() -> Void)? = nil
)

public static func presentCheckout(
    clientToken: String,
    from viewController: UIViewController,
    primerSettings: PrimerSettings,
    completion: (() -> Void)? = nil
)

public static func presentCheckout(
    clientToken: String,
    from viewController: UIViewController,
    primerSettings: PrimerSettings,
    primerTheme: PrimerCheckoutTheme,
    completion: (() -> Void)? = nil
)
```

### With automatic view controller detection

These overloads locate the top-most presenting view controller for you, which is convenient when
you do not have a view controller reference at hand.

```swift theme={"dark"}
@objc public static func presentCheckout(
    clientToken: String,
    completion: (() -> Void)? = nil
)

public static func presentCheckout(
    clientToken: String,
    primerSettings: PrimerSettings,
    completion: (() -> Void)? = nil
)
```

<Warning>
  If no presenting view controller can be found, the automatic overloads report a
  [`PrimerError`](/docs/sdk/ios-checkout/v3.0.0-beta/api/common/primer-error) through
  `primerCheckoutPresenterDidFailWithError(_:)`. Assign the `delegate` before calling these methods.
</Warning>

### Parameters

| Parameter        | Type                  | Default | Description                                                                                                                                                                                             |
| ---------------- | --------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientToken`    | `String`              | —       | The client token for the session. Generate it from your backend with the [client session](/docs/checkout/client-session) API.                                                                                |
| `viewController` | `UIViewController`    | —       | The view controller to present from. Omitted in the automatic-detection overloads.                                                                                                                      |
| `primerSettings` | `PrimerSettings`      | —       | Configuration applied to this checkout session. Overloads that omit it use the SDK's current global `PrimerSettings`. See [`PrimerSettings`](/docs/sdk/ios-checkout/v3.0.0-beta/api/common/primer-settings). |
| `primerTheme`    | `PrimerCheckoutTheme` | —       | Theme configuration for the [design tokens](/docs/sdk/ios-checkout/v3.0.0-beta/api/theming/primer-theme). Overloads that omit it use a default `PrimerCheckoutTheme()`.                                      |
| `completion`     | `(() -> Void)?`       | `nil`   | Optional closure invoked once the checkout UI has finished presenting.                                                                                                                                  |

<Note>
  The overloads that take `primerSettings` or `primerTheme` are **not** `@objc` compatible because of
  those Swift-only parameter types. From Objective-C, use the `clientToken` /
  `clientToken:from:` overloads, or configure settings globally via `PrimerSettings`.
</Note>

## Dismissing checkout

```swift theme={"dark"}
@objc public static func dismiss(
    animated: Bool = true,
    completion: (() -> Void)? = nil
)
```

| Parameter    | Type            | Default | Description                                         |
| ------------ | --------------- | ------- | --------------------------------------------------- |
| `animated`   | `Bool`          | `true`  | Whether to animate the dismissal.                   |
| `completion` | `(() -> Void)?` | `nil`   | Optional closure invoked after dismissal completes. |

Calling `dismiss` triggers `primerCheckoutPresenterDidDismiss()` on the delegate. The checkout also
dismisses itself automatically when a payment succeeds or fails.

## PrimerCheckoutPresenterDelegate

```swift theme={"dark"}
@available(iOS 15.0, *)
public protocol PrimerCheckoutPresenterDelegate: AnyObject
```

Conform to this protocol to receive checkout results and lifecycle events. The result methods are
required; the 3DS lifecycle methods are optional thanks to default implementations in a protocol
extension.

### Required methods

| Method                                              | Description                                                                                               |
| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `primerCheckoutPresenterDidCompleteWithSuccess(_:)` | Called when payment is successful, with the [`PaymentResult`](#paymentresult).                            |
| `primerCheckoutPresenterDidFailWithError(_:)`       | Called when payment fails, with a [`PrimerError`](/docs/sdk/ios-checkout/v3.0.0-beta/api/common/primer-error). |
| `primerCheckoutPresenterDidDismiss()`               | Called when checkout is dismissed without completion.                                                     |

```swift theme={"dark"}
func primerCheckoutPresenterDidCompleteWithSuccess(_ result: PaymentResult)
func primerCheckoutPresenterDidFailWithError(_ error: PrimerError)
func primerCheckoutPresenterDidDismiss()
```

### Optional 3DS lifecycle methods

Implement these only if you need to observe the 3-D Secure challenge lifecycle. Each has a default
empty implementation, so you can omit any you do not need.

| Method                                                                       | Description                                                                                                                  |
| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `primerCheckoutPresenterWillPresent3DSChallenge(_:)`                         | Called when a 3DS challenge is about to be presented, with the `PrimerPaymentMethodTokenData` requiring 3DS.                 |
| `primerCheckoutPresenterDidDismiss3DSChallenge()`                            | Called when the 3DS challenge UI is dismissed.                                                                               |
| `primerCheckoutPresenterDidComplete3DSChallenge(success:resumeToken:error:)` | Called when the 3DS challenge completes, indicating success, the resume token (when successful), or the error (when failed). |

```swift theme={"dark"}
func primerCheckoutPresenterWillPresent3DSChallenge(
    _ paymentMethodTokenData: PrimerPaymentMethodTokenData
)
func primerCheckoutPresenterDidDismiss3DSChallenge()
func primerCheckoutPresenterDidComplete3DSChallenge(
    success: Bool,
    resumeToken: String?,
    error: Error?
)
```

## PaymentResult

The success callback delivers a `PaymentResult` value.

```swift theme={"dark"}
public struct PaymentResult: Sendable, Equatable {
    public let paymentId: String
    public let status: PaymentStatus
    public let token: String?
    public let redirectUrl: String?
    public let errorMessage: String?
    public let amount: Int?
    public let currencyCode: String?
    public let paymentMethodType: String?
}
```

| Property            | Type            | Description                                     |
| ------------------- | --------------- | ----------------------------------------------- |
| `paymentId`         | `String`        | The unique identifier of the payment.           |
| `status`            | `PaymentStatus` | The final status of the payment.                |
| `token`             | `String?`       | The payment token, when available.              |
| `redirectUrl`       | `String?`       | A redirect URL, when the flow involved one.     |
| `errorMessage`      | `String?`       | A human-readable error message, when available. |
| `amount`            | `Int?`          | The payment amount in minor units.              |
| `currencyCode`      | `String?`       | The ISO 4217 currency code.                     |
| `paymentMethodType` | `String?`       | The payment method type used for the payment.   |

### PaymentStatus

```swift theme={"dark"}
public enum PaymentStatus: Sendable {
    case pending
    case success
    case failed
}
```

| Case      | Description                           |
| --------- | ------------------------------------- |
| `pending` | The payment is still being processed. |
| `success` | The payment completed successfully.   |
| `failed`  | The payment failed.                   |

<Tip>
  When switching on `PaymentStatus`, always include a `default` case so your code stays
  forward-compatible with future status values.
</Tip>

## UIKit usage example

```swift theme={"dark"}
import PrimerSDK
import UIKit

final class CheckoutViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        PrimerCheckoutPresenter.shared.delegate = self
    }

    @IBAction func payButtonTapped(_ sender: UIButton) {
        PrimerCheckoutPresenter.presentCheckout(
            clientToken: clientToken,
            from: self
        )
    }
}

extension CheckoutViewController: PrimerCheckoutPresenterDelegate {
    func primerCheckoutPresenterDidCompleteWithSuccess(_ result: PaymentResult) {
        switch result.status {
        case .success:
            showReceipt(paymentId: result.paymentId)
        case .pending:
            showPendingState(paymentId: result.paymentId)
        case .failed:
            showError(message: result.errorMessage)
        default:
            break
        }
    }

    func primerCheckoutPresenterDidFailWithError(_ error: PrimerError) {
        showError(message: error.errorDescription)
    }

    func primerCheckoutPresenterDidDismiss() {
        // The shopper closed checkout without completing a payment.
    }
}
```

To apply custom settings or theming, use the richer overload:

```swift theme={"dark"}
PrimerCheckoutPresenter.presentCheckout(
    clientToken: clientToken,
    from: self,
    primerSettings: settings,
    primerTheme: theme
)
```

<Note>
  `PrimerCheckoutPresenter.shared.delegate` is `weak`. Keep the conforming object (here, the view
  controller) alive for the duration of checkout so the callbacks are delivered.
</Note>

## See also

<CardGroup cols={2}>
  <Card title="PrimerCheckout" icon="swift" href="/docs/sdk/ios-checkout/v3.0.0-beta/api/primer-checkout">
    The SwiftUI view for embedding checkout directly in a SwiftUI hierarchy.
  </Card>

  <Card title="PrimerCheckoutState" icon="diagram-project" href="/docs/sdk/ios-checkout/v3.0.0-beta/api/primer-checkout-state">
    The state model that drives the managed checkout flow.
  </Card>

  <Card title="PrimerError" icon="triangle-exclamation" href="/docs/sdk/ios-checkout/v3.0.0-beta/api/common/primer-error">
    The error type delivered to the failure callback.
  </Card>

  <Card title="UIKit integration" icon="mobile" href="/docs/sdk/ios-checkout/v3.0.0-beta/guides/uikit-integration">
    A guide to integrating the managed checkout in UIKit apps.
  </Card>
</CardGroup>
