Skip to main content
Primer Checkout iOS SDK is currently in beta (v3.0.0-beta.1). The API is subject to change before the stable release.
Every checkout ends in one of three outcomes: the payment succeeds, it fails, or the user dismisses the flow. This guide shows how to receive and react to that outcome in both SwiftUI and UIKit. The outcome is always delivered as a PrimerCheckoutState value:
The same PrimerCheckoutState also has lifecycle cases (.initializing, .ready) that you do not need to handle when reacting to the final outcome. Always include a default case when switching, so future enum additions stay source-compatible.

SwiftUI

Using PrimerCheckout

The prebuilt PrimerCheckout view accepts an onCompletion closure that fires once with the final state.

Using the .primerCheckoutSession modifier

When you embed the composable views (for example PrimerCardForm) inline in your own layout, hold a PrimerCheckoutSession as a @StateObject and receive the outcome through the onCompletion parameter of the .primerCheckoutSession(_:onCompletion:) modifier.
onCompletion is delivered exactly once. The session latches the first terminal state, so any later .dismissed produced by a view-lifecycle teardown is ignored.
Use the PaymentResult to drive navigation. PaymentResult is Equatable but not Hashable, so it cannot be appended to a NavigationPath or used with navigationDestination(for:) directly. Instead, store the result in @State and present the confirmation screen with navigationDestination(isPresented:).

UIKit

In UIKit, present the checkout with PrimerCheckoutPresenter and adopt PrimerCheckoutPresenterDelegate to receive the outcome. The presenter dismisses its own modal before calling the relevant delegate method.
Set the delegate before calling presentCheckout. If no delegate is set when checkout completes, the outcome is logged and otherwise dropped.
The delegate maps one-to-one onto the SwiftUI PrimerCheckoutState cases:

Reading the PaymentResult

On success you receive a PaymentResult. Read its properties to build your confirmation UI, send analytics, or reconcile against your backend.
status is usually .success for a .success(PaymentResult) outcome. In manual payment handling, the payment may still be .pending until your backend confirms it.

Handling the PrimerError

On failure you receive a PrimerError. The SDK already surfaces failures inside the checkout UI, so you typically use the error for logging, analytics, and support workflows rather than for displaying a message yourself.
Always log diagnosticsId. Primer support uses it to trace the exact failed request when you raise an issue.

See also

PrimerCheckoutState

The full state enum and the PaymentResult model.

PrimerError

Error categories, IDs, and diagnostics.

PrimerCheckoutPresenter

The UIKit entry point and delegate callbacks.

PrimerCheckout

The prebuilt SwiftUI checkout view.