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.
PrimerCardForm is a SwiftUI View that renders a complete card payment form, composed from three section slots: card details, billing address, and submit button. Each section is a @ViewBuilder slot you can replace. The form resolves its PrimerCardFormSession from the environment (provided by the .primerCheckoutSession(_:onCompletion:) modifier), so it can be embedded anywhere — inside the modal PrimerCheckout or inline in your own layout.
Requires iOS 15.0+. PrimerCardForm is @available(iOS 15.0, *).

Signature

@available(iOS 15.0, *)
public struct PrimerCardForm<CardDetails: View, Billing: View, Submit: View>: View {

  public init(
    @ViewBuilder cardDetails: @escaping (PrimerCardFormSession) -> CardDetails = { CardFormDefaults.cardDetails($0) },
    @ViewBuilder billingAddress: @escaping (PrimerCardFormSession) -> Billing = { CardFormDefaults.billingAddress($0) },
    @ViewBuilder submitButton: @escaping (PrimerCardFormSession) -> Submit = { CardFormDefaults.submitButton($0) }
  )
}

Parameters

ParameterTypeDefaultDescription
cardDetails(PrimerCardFormSession) -> CardDetails{ CardFormDefaults.cardDetails($0) }Slot for the card input fields (number, expiry, CVV, cardholder name).
billingAddress(PrimerCardFormSession) -> Billing{ CardFormDefaults.billingAddress($0) }Slot for the billing address fields. Only rendered when required by the session.
submitButton(PrimerCardFormSession) -> Submit{ CardFormDefaults.submitButton($0) }Slot for the submit/pay button.
Each slot receives the active PrimerCardFormSession, which exposes the published state and the field-update and submit() methods you need to drive custom UI.
Every slot is generic and defaults to a CardFormDefaults builder. Because the defaults are supplied per-parameter, you can override any single slot and leave the rest at their default styling — you never have to re-implement the whole form.

Default layout

The default form stacks the three slots vertically:
OrderSlotDefault content
1cardDetailsCardFormDefaults.cardDetails — card number, expiry, CVV, cardholder name
2billingAddressCardFormDefaults.billingAddress — billing address fields, rendered only when the session requires them
3submitButtonCardFormDefaults.submitButton — the pay button
If no session is available in the environment, the form renders CardFormDefaults.unavailable() instead.

Usage

Default form

Render the fully styled default card form with no arguments:
import SwiftUI
import PrimerSDK

struct CardPaymentScreen: View {
  var body: some View {
    PrimerCardForm()
  }
}
Place PrimerCardForm() inside a view that has the .primerCheckoutSession(_:onCompletion:) modifier applied, so the form can resolve its PrimerCardFormSession from the environment.

Overriding a single slot

To customize one section, pass a labeled argument and leave the others at their defaults. Here only the submit button is replaced — cardDetails and billingAddress keep the default styling:
PrimerCardForm(submitButton: { session in
  MyPayButton(isLoading: session.state.isLoading) {
    session.submit()
  }
})
A bare trailing closure binds to the last slot — submitButton. To override cardDetails or billingAddress, always use the labeled argument form (cardDetails: / billingAddress:). For example, PrimerCardForm { session in ... } customizes the submit button, not the card fields.

Recomposing the card section from building blocks

You don’t have to discard the default fields when customizing a slot. Compose the default content with your own views using the per-field builders on CardFormDefaults:
PrimerCardForm(cardDetails: { session in
  VStack {
    CardFormDefaults.cardDetails(session)
    MyPromoBanner()
  }
})
You can also assemble the card section from the individual field building blocks — CardFormDefaults.cardNumber, expiryDate, cvv, and cardholderName:
PrimerCardForm(cardDetails: { session in
  VStack(spacing: 16) {
    CardFormDefaults.cardNumber(session)
    HStack(spacing: 16) {
      CardFormDefaults.expiryDate(session)
      CardFormDefaults.cvv(session)
    }
    CardFormDefaults.cardholderName(session)
  }
})
See Card field components for the full set of field building blocks.

See also

PrimerCardFormSession

State, field-update methods, and submit() passed into every slot.

CardFormDefaults

Default section and field builders used by each slot.

Card field components

Individual field building blocks for recomposing the card section.

PrimerPaymentMethods

Render the list of available payment methods alongside the card form.