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.
PrimerCheckout is the prebuilt, fully managed SwiftUI flow. Drop it into your view hierarchy with a client token and it renders Primer’s default screens end to end — splash, payment method selection, card form, processing, and the success and error results — including 3DS and redirect handling. This is the fastest way to integrate. You do not compose any screens or wire up sessions yourself; the view manages its own lifecycle and reports the outcome through onCompletion.
PrimerCheckout renders the SDK’s default screens and does not expose the composable views or their @ViewBuilder slots. For full UI customization, embed views such as PrimerCardForm and PrimerPaymentMethods in your own layout and wire them up with PrimerCheckoutSession.

Declaration

@available(iOS 15.0, *)
@MainActor
public struct PrimerCheckout: View

Initializer

public init(
  clientToken: String,
  primerSettings: PrimerSettings = PrimerSettings(),
  primerTheme: PrimerCheckoutTheme = PrimerCheckoutTheme(),
  onCompletion: ((PrimerCheckoutState) -> Void)? = nil
)

Parameters

ParameterTypeDefaultDescription
clientTokenStringRequiredThe client token obtained from your backend. See Client session.
primerSettingsPrimerSettingsPrimerSettings()Configuration settings including payment options and UI preferences.
primerThemePrimerCheckoutThemePrimerCheckoutTheme()Theme configuration for design tokens applied across all default screens.
onCompletion((PrimerCheckoutState) -> Void)?nilOptional completion callback invoked when checkout completes with the final state (success, failure, or dismissed). See PrimerCheckoutState.
PrimerCheckout requires iOS 15.0 or later and must be used on the main actor, like any SwiftUI View.

Usage

Minimal

Present the managed flow with just a client token. All other parameters use their defaults.
import SwiftUI
import PrimerSDK

struct CheckoutView: View {
  let clientToken: String

  var body: some View {
    PrimerCheckout(clientToken: clientToken)
  }
}

With settings and theme

Customize payment options and design tokens by passing primerSettings and primerTheme.
import SwiftUI
import PrimerSDK

struct CheckoutView: View {
  let clientToken: String

  var body: some View {
    PrimerCheckout(
      clientToken: clientToken,
      primerSettings: PrimerSettings(),
      primerTheme: PrimerCheckoutTheme()
    )
  }
}

Handling the result

Pass an onCompletion closure and switch over the terminal PrimerCheckoutState to react to the outcome.
import SwiftUI
import PrimerSDK

struct CheckoutView: View {
  let clientToken: String
  @Environment(\.dismiss) private var dismiss

  var body: some View {
    PrimerCheckout(clientToken: clientToken) { state in
      switch state {
      case let .success(result):
        print("Payment succeeded: \(result.paymentId)")
        dismiss()
      case let .failure(error):
        print("Payment failed: \(error.localizedDescription)")
      case .dismissed:
        dismiss()
      default:
        // .initializing and .ready are lifecycle states and are
        // never delivered to onCompletion.
        break
      }
    }
  }
}
See Handle the payment result for a full walkthrough of consuming each PrimerCheckoutState case.

Presenting modally

PrimerCheckout is an ordinary SwiftUI View, so present it however your navigation pattern prefers — for example, in a .sheet.
import SwiftUI
import PrimerSDK

struct StorefrontView: View {
  @State private var isCheckoutPresented = false
  let clientToken: String

  var body: some View {
    Button("Pay") { isCheckoutPresented = true }
      .sheet(isPresented: $isCheckoutPresented) {
        PrimerCheckout(clientToken: clientToken) { state in
          if case .dismissed = state { isCheckoutPresented = false }
          if case .success = state { isCheckoutPresented = false }
        }
      }
  }
}

Customizing the UI

PrimerCheckout does not accept screen slots. When you need to control layout, styling, or which fields appear, build your own UI from the composable views and drive them with a session instead.
GoalUse
Fastest integration, default screensPrimerCheckout (this page)
Custom SwiftUI layout and slotsPrimerCheckoutSession + PrimerCardForm / PrimerPaymentMethods
UIKit appsPrimerCheckoutPresenter
For the composable approach, create a PrimerCheckoutSession as a @StateObject, place the composable views in your layout, and attach the .primerCheckoutSession(_:onCompletion:) modifier. The modifier injects the session that those views resolve from the environment.
import SwiftUI
import PrimerSDK

struct CustomCheckoutView: View {
  @StateObject private var session: PrimerCheckoutSession

  init(clientToken: String) {
    _session = StateObject(wrappedValue: PrimerCheckoutSession(clientToken: clientToken))
  }

  var body: some View {
    ScrollView {
      PrimerPaymentMethods()
      PrimerCardForm()
    }
    .primerCheckoutSession(session) { state in
      handle(state)
    }
  }

  private func handle(_ state: PrimerCheckoutState) {
    // React to the terminal state.
  }
}

See also

PrimerCheckoutSession

Compose custom UI from the SwiftUI views.

PrimerCheckoutPresenter

Present the managed flow from UIKit.

PrimerCheckoutState

The terminal states delivered to onCompletion.

PrimerCheckoutTheme

Style the default screens with design tokens.