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

# PrimerSelectionSession

> Observable payment-method selection session backing the list and vaulted views

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

`PrimerSelectionSession` is the observable session that drives payment-method selection. It exposes the available methods, the current selection, search and filtering state, and vaulted-card actions (including CVV recapture) as a single `@Published` state value, and provides the methods that mutate that state.

A single `PrimerSelectionSession` backs **both** [`PrimerPaymentMethods`](/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/primer-payment-methods) (the list of available methods) and [`PrimerVaultedPaymentMethods`](/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/vaulted-payment-methods) (saved methods). Both views resolve the same session from the environment supplied by the `.primerCheckoutSession(_:)` modifier, so you rarely construct or hold it yourself — you read it from the slots those views hand you.

<Info>
  `PrimerSelectionSession` is a `@MainActor`, `ObservableObject` final class available on iOS 15.0 and later (`@available(iOS 15.0, *)`). Observe it with `@ObservedObject` and call its methods from the main actor.
</Info>

## Declaration

```swift theme={"dark"}
@available(iOS 15.0, *)
@MainActor
public final class PrimerSelectionSession: ObservableObject {
  @Published public private(set) var state: PrimerPaymentMethodSelectionState
  public var vaultedPaymentMethods: [PrimerHeadlessUniversalCheckout.VaultedPaymentMethod] { get }
}
```

The session is created and injected by the SDK. The slots of `PrimerPaymentMethods` and `PrimerVaultedPaymentMethods` receive it directly, so you do not initialize it yourself.

## Properties

| Property                | Type                                                     | Description                                                                                                                                                                           |
| ----------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `state`                 | `PrimerPaymentMethodSelectionState`                      | The latest selection state, bridged from the underlying selection scope. Read-only (`@Published public private(set)`) — drive UI from it and call the session's methods to change it. |
| `vaultedPaymentMethods` | `[PrimerHeadlessUniversalCheckout.VaultedPaymentMethod]` | Get-only. Saved (vaulted) payment methods, loaded once during checkout initialization. Returns an empty array when none are available.                                                |

<Note>
  `state` is the snapshot you render from; `vaultedPaymentMethods` is the raw list of saved cards. Selection of a vaulted method is reflected back through `state.selectedVaultedPaymentMethod`.
</Note>

## Methods

| Method                                                                          | Description                                                                                                                                          |
| ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `select(_ method: CheckoutPaymentMethod)`                                       | Selects a payment method, starting its flow (card form, redirect, native wallet, etc.).                                                              |
| `cancel()`                                                                      | Cancels the current selection flow.                                                                                                                  |
| `selectVaulted(_ method: PrimerHeadlessUniversalCheckout.VaultedPaymentMethod)` | Marks a vaulted method as selected so a subsequent submit targets it.                                                                                |
| `delete(_ method: PrimerHeadlessUniversalCheckout.VaultedPaymentMethod)`        | Routes to the delete-confirmation screen for a vaulted method.                                                                                       |
| `showAll()`                                                                     | Navigates to the full list of saved payment methods.                                                                                                 |
| `updateCvvInput(_ cvv: String)`                                                 | Updates and validates the CVV for the selected vaulted card during CVV recapture. Drives `state.cvvInput`, `state.isCvvValid`, and `state.cvvError`. |

### select(\_:)

```swift theme={"dark"}
public func select(_ method: CheckoutPaymentMethod)
```

Selects a payment method to begin its payment flow. Call this from a method row's tap handler. The selected method is reflected in `state.selectedPaymentMethod`.

| Parameter | Type                    | Description                                                                                                     |
| --------- | ----------------------- | --------------------------------------------------------------------------------------------------------------- |
| `method`  | `CheckoutPaymentMethod` | The payment method the user chose. Typically the value passed into the `method` slot of `PrimerPaymentMethods`. |

### cancel()

```swift theme={"dark"}
public func cancel()
```

Cancels the in-progress selection flow.

### selectVaulted(\_:)

```swift theme={"dark"}
public func selectVaulted(_ method: PrimerHeadlessUniversalCheckout.VaultedPaymentMethod)
```

Marks a saved payment method as selected. The selection is reflected in `state.selectedVaultedPaymentMethod`; a subsequent submit pays with this method. If the card requires CVV recapture, `state.requiresCvvInput` becomes `true`.

| Parameter | Type                                                   | Description                 |
| --------- | ------------------------------------------------------ | --------------------------- |
| `method`  | `PrimerHeadlessUniversalCheckout.VaultedPaymentMethod` | The saved method to select. |

### delete(\_:)

```swift theme={"dark"}
public func delete(_ method: PrimerHeadlessUniversalCheckout.VaultedPaymentMethod)
```

Routes to the delete-confirmation screen for a saved payment method.

| Parameter | Type                                                   | Description                 |
| --------- | ------------------------------------------------------ | --------------------------- |
| `method`  | `PrimerHeadlessUniversalCheckout.VaultedPaymentMethod` | The saved method to remove. |

### showAll()

```swift theme={"dark"}
public func showAll()
```

Navigates to the full list of saved payment methods (the "show all saved methods" action).

### updateCvvInput(\_:)

```swift theme={"dark"}
public func updateCvvInput(_ cvv: String)
```

Updates and validates the CVV entered for the selected vaulted card during CVV recapture. The result is published through `state.cvvInput`, `state.isCvvValid`, and `state.cvvError`.

| Parameter | Type     | Description                                 |
| --------- | -------- | ------------------------------------------- |
| `cvv`     | `String` | The current CVV text from your input field. |

## PrimerPaymentMethodSelectionState

`PrimerPaymentMethodSelectionState` is the immutable snapshot published by `state`. It conforms to `Equatable`. Every stored property is `public internal(set)` — readable from your code but mutated only by the SDK, so treat it as read-only and call the session's methods to change selection.

```swift theme={"dark"}
@available(iOS 15.0, *)
public struct PrimerPaymentMethodSelectionState: Equatable {
  public internal(set) var paymentMethods: [CheckoutPaymentMethod]
  public internal(set) var isLoading: Bool
  public internal(set) var selectedPaymentMethod: CheckoutPaymentMethod?
  public internal(set) var searchQuery: String
  public internal(set) var filteredPaymentMethods: [CheckoutPaymentMethod]
  public internal(set) var error: String?
  public internal(set) var selectedVaultedPaymentMethod: PrimerHeadlessUniversalCheckout.VaultedPaymentMethod?
  public internal(set) var isVaultPaymentLoading: Bool
  public internal(set) var requiresCvvInput: Bool
  public internal(set) var cvvInput: String
  public internal(set) var isCvvValid: Bool
  public internal(set) var cvvError: String?
  public internal(set) var isPaymentMethodsExpanded: Bool
}
```

### Properties

| Property                       | Type                                                    | Description                                                                                                                                                           |
| ------------------------------ | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `paymentMethods`               | `[CheckoutPaymentMethod]`                               | All available payment methods for the current session.                                                                                                                |
| `isLoading`                    | `Bool`                                                  | Whether the available payment methods are still loading.                                                                                                              |
| `selectedPaymentMethod`        | `CheckoutPaymentMethod?`                                | The currently selected available method, or `nil`.                                                                                                                    |
| `searchQuery`                  | `String`                                                | The current search text applied to the method list.                                                                                                                   |
| `filteredPaymentMethods`       | `[CheckoutPaymentMethod]`                               | The methods matching `searchQuery`.                                                                                                                                   |
| `error`                        | `String?`                                               | An error message for the selection flow, or `nil`.                                                                                                                    |
| `selectedVaultedPaymentMethod` | `PrimerHeadlessUniversalCheckout.VaultedPaymentMethod?` | The currently selected saved method, or `nil`.                                                                                                                        |
| `isVaultPaymentLoading`        | `Bool`                                                  | Whether a payment with the selected vaulted method is in progress.                                                                                                    |
| `requiresCvvInput`             | `Bool`                                                  | Whether CVV input is required for the selected vaulted card.                                                                                                          |
| `cvvInput`                     | `String`                                                | The CVV value entered by the user.                                                                                                                                    |
| `isCvvValid`                   | `Bool`                                                  | Whether the entered CVV is valid.                                                                                                                                     |
| `cvvError`                     | `String?`                                               | CVV validation error message, or `nil`.                                                                                                                               |
| `isPaymentMethodsExpanded`     | `Bool`                                                  | Whether the payment methods section is expanded (showing all methods). Defaults to `true`; becomes `false` when the user selects a vaulted method or CVV input opens. |

<Tip>
  Because the state is `Equatable`, SwiftUI only re-renders observers when a meaningful field changes. Drive your custom rows and empty states directly from these properties rather than caching copies.
</Tip>

## CheckoutPaymentMethod

`paymentMethods` and `filteredPaymentMethods` are arrays of `CheckoutPaymentMethod`, the model describing a single selectable method. It is documented in full on the [`PrimerPaymentMethods`](/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/primer-payment-methods) page; the key fields are `id`, `type`, `name`, `icon`, and the surcharge and styling properties.

## Usage

### Reading state and selecting a method

`PrimerPaymentMethods` hands each `method` slot a `CheckoutPaymentMethod` and an `onSelect` closure that calls `select(_:)` for you. To select outside a slot — for example from a custom header — call `select(_:)` on the session directly.

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

struct CheckoutScreen: View {
  @StateObject private var session = PrimerCheckoutSession(clientToken: clientToken)

  var body: some View {
    ScrollView {
      PrimerPaymentMethods(
        method: { paymentMethod, onSelect in
          Button(action: onSelect) {
            HStack {
              if let icon = paymentMethod.icon {
                Image(uiImage: icon)
                  .resizable()
                  .scaledToFit()
                  .frame(width: 28, height: 28)
              }
              Text(paymentMethod.buttonText ?? paymentMethod.name)
              Spacer()
              if let surcharge = paymentMethod.formattedSurcharge {
                Text(surcharge).foregroundColor(.secondary)
              }
            }
            .padding()
          }
          .buttonStyle(.plain)
        }
      )
    }
    .primerCheckoutSession(session) { state in
      handle(state)
    }
  }
}
```

### Working with vaulted methods and CVV recapture

When rendering saved methods, drive the UI from `state` and call the vaulted helpers on the session. If the selected card requires CVV recapture, `state.requiresCvvInput` is `true`; feed your CVV field through `updateCvvInput(_:)` and read `state.isCvvValid` / `state.cvvError` for validation feedback.

```swift theme={"dark"}
struct SavedMethodRow: View {
  @ObservedObject var session: PrimerSelectionSession
  let method: PrimerHeadlessUniversalCheckout.VaultedPaymentMethod

  var body: some View {
    VStack(alignment: .leading, spacing: 8) {
      HStack {
        Text(method.paymentMethodType)
        Spacer()
        Button("Use") { session.selectVaulted(method) }
        Button("Delete", role: .destructive) { session.delete(method) }
      }

      if session.state.requiresCvvInput,
         session.state.selectedVaultedPaymentMethod?.id == method.id {
        SecureField("CVV", text: Binding(
          get: { session.state.cvvInput },
          set: { session.updateCvvInput($0) }
        ))
        if let cvvError = session.state.cvvError {
          Text(cvvError).foregroundColor(.red).font(.caption)
        }
      }
    }
  }
}
```

<Warning>
  Never mutate `state` directly — every property is `internal(set)`. Change selection only through `select(_:)`, `selectVaulted(_:)`, `delete(_:)`, `showAll()`, `updateCvvInput(_:)`, and `cancel()`.
</Warning>

## See also

<CardGroup cols={2}>
  <Card title="PrimerPaymentMethods" icon="list" href="/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/primer-payment-methods">
    The slot-based view that renders the available payment methods.
  </Card>

  <Card title="PrimerVaultedPaymentMethods" icon="vault" href="/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/vaulted-payment-methods">
    Render and select saved (vaulted) payment methods.
  </Card>

  <Card title="PaymentMethodsDefaults" icon="puzzle-piece" href="/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/payment-methods-defaults">
    Default slot bodies used by the payment-method views.
  </Card>

  <Card title="PrimerCheckoutSession" icon="circle-play" href="/docs/sdk/ios-checkout/v3.0.0-beta/api/primer-checkout-session">
    The top-level session injected via .primerCheckoutSession(\_:).
  </Card>
</CardGroup>
