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.
PrimerVaultedPaymentMethods renders the customer’s saved (vaulted) payment methods as a list, composed from three slots: a header, a per-method row, and a submit button. Tapping a row selects that method; the submit button pays with the currently selected vaulted method. The view resolves its PrimerSelectionSession from the environment. Selection, deletion, and CVV recapture are all driven through that session — PrimerVaultedPaymentMethods only composes the UI.
This view reads its session from the environment injected by the .primerCheckoutSession(_:onCompletion:) modifier. Place it inside a view hierarchy that applies that modifier. When no session is present it renders an empty placeholder.

PrimerVaultedPaymentMethods

@available(iOS 15.0, *)
public struct PrimerVaultedPaymentMethods: View {

  public typealias VaultedMethod = PrimerHeadlessUniversalCheckout.VaultedPaymentMethod

  public init(
    header: @escaping (PrimerSelectionSession) -> AnyView
      = { AnyView(VaultedPaymentMethodsDefaults.header($0)) },
    item: @escaping (VaultedMethod, _ isSelected: Bool, _ onSelect: @escaping () -> Void) -> AnyView
      = { AnyView(VaultedPaymentMethodsDefaults.item($0, isSelected: $1, onSelect: $2)) },
    submitButton: @escaping (_ isLoading: Bool, _ isEnabled: Bool, _ onSubmit: @escaping () -> Void) -> AnyView
      = { AnyView(VaultedPaymentMethodsDefaults.submitButton(isLoading: $0, isEnabled: $1, onSubmit: $2)) }
  )
}
ParameterTypeDefaultDescription
header(PrimerSelectionSession) -> AnyViewVaultedPaymentMethodsDefaults.header($0)Header shown above the list. Receives the session so custom headers can read state or trigger session actions.
item(VaultedMethod, _ isSelected: Bool, _ onSelect: @escaping () -> Void) -> AnyViewVaultedPaymentMethodsDefaults.item(...)Row for each vaulted method. Receives the method, whether it is currently selected, and a callback to select it.
submitButton(_ isLoading: Bool, _ isEnabled: Bool, _ onSubmit: @escaping () -> Void) -> AnyViewVaultedPaymentMethodsDefaults.submitButton(...)Submit button below the list. Receives loading state, enabled state, and a callback that pays with the selected method.
Slots are type-erased to AnyView rather than using opaque return types. The three-argument item and submitButton builders hit Swift’s generic-default inference limits, so this view trades the opaque-return ergonomics of PrimerCardForm for guaranteed composition. Wrap any custom slot content in AnyView.

VaultedMethod typealias

public typealias VaultedMethod = PrimerHeadlessUniversalCheckout.VaultedPaymentMethod
VaultedMethod is a convenience alias for PrimerHeadlessUniversalCheckout.VaultedPaymentMethod, the model passed to the item slot.
public final class VaultedPaymentMethod: Codable {
  public let id: String
  public let paymentMethodType: String
  public let paymentInstrumentType: PaymentInstrumentType
  public let paymentInstrumentData: Response.Body.Tokenization.PaymentInstrumentData
  public let analyticsId: String
}
PropertyTypeDescription
idStringUnique identifier for this vaulted method. Use it to drive selection and deletion.
paymentMethodTypeStringPayment method type (e.g. "PAYMENT_CARD", "PAYPAL").
paymentInstrumentTypePaymentInstrumentTypeType of payment instrument (e.g. card, bank account).
paymentInstrumentDataResponse.Body.Tokenization.PaymentInstrumentDataDetailed instrument data: card network, masked digits, expiry, external payer info, BIN data.
analyticsIdStringIdentifier used for analytics tracking.

Usage

The default slots produce a complete, themed vaulted list — no slot arguments are required:
import SwiftUI
import PrimerSDK

@available(iOS 15.0, *)
struct SavedMethodsView: View {
  var body: some View {
    PrimerVaultedPaymentMethods()
  }
}
Wrap the view in a hierarchy that injects a checkout session:
import SwiftUI
import PrimerSDK

@available(iOS 15.0, *)
struct CheckoutScreen: View {
  let clientToken: String

  var body: some View {
    ScrollView {
      PrimerVaultedPaymentMethods()
        .padding()
    }
    .primerCheckoutSession(clientToken) { result in
      // Handle the payment result
    }
  }
}

Customizing slots

Provide any combination of slots; omitted slots fall back to their defaults. Custom content must be wrapped in AnyView.
import SwiftUI
import PrimerSDK

@available(iOS 15.0, *)
struct CustomVaultedMethods: View {
  var body: some View {
    PrimerVaultedPaymentMethods(
      header: { _ in
        AnyView(
          Text("Pay faster with a saved card")
            .font(.headline)
            .frame(maxWidth: .infinity, alignment: .leading)
        )
      },
      item: { method, isSelected, onSelect in
        AnyView(
          Button(action: onSelect) {
            HStack {
              Text(method.paymentMethodType)
              Spacer()
              if isSelected {
                Image(systemName: "checkmark.circle.fill")
              }
            }
            .padding()
          }
          .buttonStyle(.plain)
        )
      }
    )
  }
}
Use the isSelected flag the item slot receives to render selection affordances (checkmarks, borders, highlights). Calling onSelect marks the row’s method as the active vaulted method so the next submit targets it.

Driving selection, deletion, and CVV

PrimerVaultedPaymentMethods delegates all behavior to PrimerSelectionSession. Read vaultedPaymentMethods and call the session methods directly from custom slots.
MemberSignatureDescription
vaultedPaymentMethodsvar vaultedPaymentMethods: [PrimerHeadlessUniversalCheckout.VaultedPaymentMethod] { get }Saved methods for the current customer, loaded once during checkout initialization. Empty while loading or when none exist.
selectVaulted(_:)func selectVaulted(_ method: PrimerHeadlessUniversalCheckout.VaultedPaymentMethod)Marks a vaulted method as selected so a subsequent submit targets it. Backing the item slot’s onSelect.
delete(_:)func delete(_ method: PrimerHeadlessUniversalCheckout.VaultedPaymentMethod)Routes to the delete-confirmation screen for a vaulted method.
showAll()func showAll()Navigates to the full list of saved payment methods.
updateCvvInput(_:)func updateCvvInput(_ cvv: String)Updates and validates the CVV during CVV recapture, driving state.cvvInput, state.isCvvValid, and state.cvvError.
The selection state read by the slots lives on session.state (PrimerPaymentMethodSelectionState):
PropertyTypeDescription
selectedVaultedPaymentMethodPrimerHeadlessUniversalCheckout.VaultedPaymentMethod?The currently selected vaulted method, or nil. Compare its id to highlight the selected row.
isVaultPaymentLoadingBooltrue while a vaulted payment is in flight. Backs the submit slot’s isLoading.
requiresCvvInputBooltrue when the selected card requires CVV recapture before submitting.
cvvInputStringThe CVV value entered during recapture.
isCvvValidBooltrue when the entered CVV passes validation.
cvvErrorString?CVV validation error message, if any.
CVV recapture is handled by the SDK and is not a customizable slot. When the selected vaulted card requires a CVV, the view inserts a managed CVV field between the rows and the submit button, wired to updateCvvInput(_:). The submit button stays disabled until a method is selected and — when CVV recapture is required — until a valid CVV is entered.

VaultedPaymentMethodsDefaults

The default slot content. Because PrimerVaultedPaymentMethods erases its slots to AnyView, these helpers return some View. Compose them inside custom slots to keep the default look while overriding only part of the layout.
@available(iOS 15.0, *)
public enum VaultedPaymentMethodsDefaults {

  public static func header(_ session: PrimerSelectionSession) -> some View

  public static func item(
    _ method: PrimerHeadlessUniversalCheckout.VaultedPaymentMethod,
    isSelected: Bool,
    onSelect: @escaping () -> Void
  ) -> some View

  public static func submitButton(
    isLoading: Bool,
    isEnabled: Bool,
    onSubmit: @escaping () -> Void
  ) -> some View

  @MainActor
  @ViewBuilder
  public static func cvvInput(_ session: PrimerSelectionSession) -> some View

  public static func unavailable() -> some View
}
MethodDescription
header(_:)Default section header (“All saved payment methods”). The session argument is accepted only to match the slot signature; the header is static.
item(_:isSelected:onSelect:)Default vaulted method row with brand icon, label, and a selection checkmark.
submitButton(isLoading:isEnabled:onSubmit:)Default pay button. Shows a progress spinner while isLoading and dims while disabled.
cvvInput(_:)SDK-managed CVV recapture field, shown only when session.state.requiresCvvInput is true. Rendered automatically by the view — not a slot you pass in.
unavailable()Empty placeholder rendered when no PrimerSelectionSession is available in the environment.
Reuse a default while customizing a sibling slot:
PrimerVaultedPaymentMethods(
  submitButton: { isLoading, isEnabled, onSubmit in
    AnyView(VaultedPaymentMethodsDefaults.submitButton(
      isLoading: isLoading,
      isEnabled: isEnabled,
      onSubmit: onSubmit
    ))
  }
)

See also

PrimerSelectionSession

Selection, deletion, and CVV actions for payment methods and vaulted methods.

PrimerPaymentMethods

Slot-based list of available (non-vaulted) payment methods.

PaymentMethodsDefaults

Default slot content for the payment methods list.

PrimerCardForm

Slot-based card entry form for new cards.