Learn how to configure the new card component.
The new card component provides a complete payment form with card number, expiry date, CVC, and cardholder name fields. At minimum, you need to configure it with card submit callbacks:
import SwiftUI
import PXPCheckoutSDK
var submitConfig = CardSubmitComponentConfig()
submitConfig.onPreAuthorisation = { _ async in TransactionInitiationData() }
submitConfig.onPostAuthorisation = { _ in }
let newCardConfig = NewCardComponentConfig(submit: submitConfig)
let newCard = try pxpCheckout.create(.newCard, componentConfig: newCardConfig) as! NewCardComponent
newCard.buildContent()Add a live card preview that updates as the customer types:
let dynConfig = DynamicCardImageComponentConfig()
let dynamicCardImage = try pxpCheckout.create(.dynamicCardImage, componentConfig: dynConfig) as! DynamicCardImageComponent
var submitConfig = CardSubmitComponentConfig()
submitConfig.onPreAuthorisation = { _ async in TransactionInitiationData() }
submitConfig.onPostAuthorisation = { _ in }
let newCardConfig = NewCardComponentConfig(
dynamicCardImageComponent: dynamicCardImage,
submit: submitConfig
)
let newCard = try pxpCheckout.create(.newCard, componentConfig: newCardConfig) as! NewCardComponent
VStack(alignment: .leading, spacing: 16) {
dynamicCardImage.buildContent()
newCard.buildContent()
}The new card component automatically wires the card input fields to the dynamic card image. You just need to include both in your view hierarchy.
Customise field labels, styling, and which fields to display:
var fields = NewCardComponentFields(
cardNumber: CardNumberComponentConfig(
label: "Card number",
acceptedCardBrands: [.visa, .mastercard, .amex]
),
expiryDate: CardExpiryDateComponentConfig(label: "Expiry", formatOptions: .mmYY),
cvc: NewCardOptionalField(config: CardCvcComponentConfig(label: "CVC", isRequired: true), isShown: true),
holderName: NewCardOptionalField(config: CardHolderNameComponentConfig(label: "Name on card"), isShown: true),
cardBrandSelector: CardBrandSelectorComponentConfig(),
cardConsent: NewCardOptionalField(config: CardConsentComponentConfig(), isShown: true)
)
var submitConfig = CardSubmitComponentConfig()
submitConfig.onPreAuthorisation = { _ async in TransactionInitiationData() }
submitConfig.onPostAuthorisation = { _ in }
submitConfig.onPostTokenisation = { result in
if let success = result as? CardTokenizationResultSuccess {
print("Token ID: \(success.gatewayTokenId)")
}
}
let newCardConfig = NewCardComponentConfig(
styles: ContainerStyle(
cornerRadius: 12,
padding: EdgeInsets(top: 16, leading: 16, bottom: 16, trailing: 16),
spacing: 12
),
inputStyles: FieldInputStateStyles(
base: FieldInputStyle(cornerRadius: 8, borderWidth: 1, borderColor: Color(.separator))
),
fields: fields,
submit: submitConfig,
displayRequiredIcon: true
)
let newCard = try pxpCheckout.create(.newCard, componentConfig: newCardConfig) as! NewCardComponentYou can customise the overall styling and nested field configurations:
| Property | Description |
|---|---|
stylesContainerStyle? | The container styling for the entire form. Controls spacing between fields, padding, border, background, shadow, and corner radius. Properties: backgroundColor, borderColor, borderWidth, cornerRadius, padding, margin, opacity, shadow (ShadowStyle), spacing (vertical space between fields), horizontalSpacing (horizontal space between fields). Defaults to nil. |
inputStylesFieldInputStateStyles? | The input styling applied to all fields (card number, expiry, CVC, cardholder name). Overrides individual field inputStyles if set. States: base, active, valid, invalid. Each state supports: color, placeholderColor, fontWeight, fontSize, backgroundColor, borderColor, borderWidth, cornerRadius, padding, minHeight. Defaults to nil. |
labelStylesFieldLabelStateStyles? | The label styling applied to all fields. Overrides individual field labelStyles if set. States: base, active, valid, invalid. Each state supports: color, font. Additional property: minWidth (CGFloat? - default: 80). Defaults to nil. |
fieldsNewCardComponentFields? | The individual field configurations for card number, expiry date, CVC, cardholder name, card brand selector, and consent checkbox. Controls which fields are displayed and their specific settings. Defaults to nil. |
submitCardSubmitComponentConfig? | The card submit configuration. Controls payment flow, authentication, callbacks, button styling, and linked billing address components. See Card submit. Defaults to nil. |
dynamicCardImageComponentDynamicCardImageComponent? | The optional dynamic card image component. When provided, the component automatically wires the card input fields to display live updates on the card image. Defaults to nil. |
displayRequiredIconBool? | Whether to display required field indicators. When true, shows visual markers (e.g., asterisks) next to required fields. Defaults to nil. |
onChange((NewCardComponentState) -> Void)? | Callback triggered when the component state changes. Receives the updated component state with field values and validation status. Defaults to nil. |
onBlur(() -> Void)? | Callback triggered when the component loses focus. Defaults to nil. |
onFocus(() -> Void)? | Callback triggered when the component gains focus. Defaults to nil. |
onValidation(([ValidationResult]) -> Void)? | Callback triggered when validation is performed on the component. Receives an array of validation results for all fields. Defaults to nil. |
onPostTokenisation((CardTokenizationResult) -> Void)? | Callback triggered after card tokenisation completes. Receives the tokenisation result (success or failure). Defaults to nil. |
You can control which fields to display and how they're configured:
| Property | Description |
|---|---|
cardNumberCardNumberComponentConfig? | The card number field configuration. Controls label, placeholder, accepted card brands, validation messages, styling, and event handlers. Defaults to nil. |
expiryDateCardExpiryDateComponentConfig? | The expiry date field configuration. Controls label, placeholder, format options (MM/YY or MM/YYYY), validation messages, styling, and event handlers. Defaults to nil. |
cvcNewCardOptionalField<CardCvcComponentConfig>? | The CVC field configuration and visibility. Controls label, placeholder, requirement status, validation messages, styling, and whether the field is displayed in the form. Defaults to shown. |
holderNameNewCardOptionalField<CardHolderNameComponentConfig>? | The cardholder name field configuration and visibility. Controls label, placeholder, requirement status, auto-capitalisation, validation messages, styling, and whether the field is displayed. Defaults to shown. |
cardBrandSelectorCardBrandSelectorComponentConfig? | The card brand selector configuration. Displays accepted card brands and highlights the detected brand as the user types the card number. Defaults to nil. |
cardConsentNewCardOptionalField<CardConsentComponentConfig>? | The consent checkbox configuration and visibility. Controls label, requirement status, checked/unchecked styling, and whether the checkbox is displayed. Used for obtaining user consent to save card details. Defaults to hidden. |
| Property | Description |
|---|---|
configConfig? | The field-specific configuration object. Type depends on the field (e.g., CardCvcComponentConfig for CVC, CardHolderNameComponentConfig for cardholder name, CardConsentComponentConfig for consent). Defaults to nil. |
isShownBool? | Whether the field is displayed in the form. When false, the field is completely hidden. Defaults to nil. |
Returns SwiftUI content for the new card form:
newCard.buildContent()A simple new card payment form with default settings:
var submitConfig = CardSubmitComponentConfig()
submitConfig.onPreAuthorisation = { _ async in TransactionInitiationData() }
submitConfig.onPostAuthorisation = { result in
// Handle payment result
}
let newCardConfig = NewCardComponentConfig(submit: submitConfig)
let newCard = try pxpCheckout.create(.newCard, componentConfig: newCardConfig) as! NewCardComponentDisplay accepted card brands and highlight the detected brand:
var fields = NewCardComponentFields(
cardNumber: CardNumberComponentConfig(
label: "Card number",
acceptedCardBrands: [.visa, .mastercard, .amex, .discover]
),
cardBrandSelector: CardBrandSelectorComponentConfig()
)
var submitConfig = CardSubmitComponentConfig()
submitConfig.onPreAuthorisation = { _ async in TransactionInitiationData() }
submitConfig.onPostAuthorisation = { _ in }
let newCardConfig = NewCardComponentConfig(
fields: fields,
submit: submitConfig
)
let newCard = try pxpCheckout.create(.newCard, componentConfig: newCardConfig) as! NewCardComponentApply custom styling to the form and fields:
var fields = NewCardComponentFields(
cardNumber: CardNumberComponentConfig(label: "Card number"),
expiryDate: CardExpiryDateComponentConfig(label: "Expiry"),
cvc: NewCardOptionalField(
config: CardCvcComponentConfig(label: "CVC", isRequired: true),
isShown: true
),
holderName: NewCardOptionalField(
config: CardHolderNameComponentConfig(label: "Name on card"),
isShown: true
)
)
var submitConfig = CardSubmitComponentConfig()
submitConfig.onPreAuthorisation = { _ async in TransactionInitiationData() }
submitConfig.onPostAuthorisation = { _ in }
let newCardConfig = NewCardComponentConfig(
styles: ContainerStyle(
backgroundColor: .white,
cornerRadius: 12,
borderWidth: 1,
borderColor: Color(.separator),
padding: EdgeInsets(top: 20, leading: 16, bottom: 20, trailing: 16),
spacing: 16
),
inputStyles: FieldInputStateStyles(
base: FieldInputStyle(
cornerRadius: 8,
borderWidth: 1,
borderColor: Color(.separator),
padding: EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12)
)
),
fields: fields,
submit: submitConfig
)
let newCard = try pxpCheckout.create(.newCard, componentConfig: newCardConfig) as! NewCardComponentInclude a consent checkbox for saving the card:
var fields = NewCardComponentFields(
cardConsent: NewCardOptionalField(
config: CardConsentComponentConfig(
label: "Save card for future purchases",
isRequired: false
),
isShown: true
)
)
var submitConfig = CardSubmitComponentConfig()
submitConfig.onPreAuthorisation = { _ async in TransactionInitiationData() }
submitConfig.onPostAuthorisation = { _ in }
submitConfig.onPostTokenisation = { result in
if let success = result as? CardTokenizationResultSuccess {
print("Card saved with token: \(success.gatewayTokenId)")
}
}
let newCardConfig = NewCardComponentConfig(
fields: fields,
submit: submitConfig
)
let newCard = try pxpCheckout.create(.newCard, componentConfig: newCardConfig) as! NewCardComponentEnable 3DS authentication for the payment:
var submitConfig = CardSubmitComponentConfig()
submitConfig.useUnityAuthenticationStrategy = true
submitConfig.onPreInitiateAuthentication = { async in
PreInitiateIntegratedAuthenticationData(providerId: "pxpfinancial", timeout: 120)
}
submitConfig.onPreAuthentication = { async in
InitiateIntegratedAuthenticationData(
merchantCountryNumericCode: "826",
merchantLegalName: "Example Ltd",
challengeWindowSize: .size1,
requestorChallengeIndicator: .challengeRequestedMandate,
timeout: 180
)
}
submitConfig.onPreAuthorisation = { _ async in TransactionInitiationData() }
submitConfig.onPostAuthorisation = { _ in }
let newCardConfig = NewCardComponentConfig(submit: submitConfig)
let newCard = try pxpCheckout.create(.newCard, componentConfig: newCardConfig) as! NewCardComponentA comprehensive new card form with all features:
let dynConfig = DynamicCardImageComponentConfig(
frontDynamicCardImageBackground: Image("CardFront"),
backDynamicCardImageBackground: Image("CardBack")
)
let dynamicCardImage = try pxpCheckout.create(.dynamicCardImage, componentConfig: dynConfig) as! DynamicCardImageComponent
var fields = NewCardComponentFields(
cardNumber: CardNumberComponentConfig(
label: "Card number",
acceptedCardBrands: [.visa, .mastercard, .amex]
),
expiryDate: CardExpiryDateComponentConfig(
label: "Expiry",
formatOptions: .mmYY
),
cvc: NewCardOptionalField(
config: CardCvcComponentConfig(label: "CVC", isRequired: true),
isShown: true
),
holderName: NewCardOptionalField(
config: CardHolderNameComponentConfig(label: "Name on card"),
isShown: true
),
cardBrandSelector: CardBrandSelectorComponentConfig(),
cardConsent: NewCardOptionalField(
config: CardConsentComponentConfig(label: "Save card for future use"),
isShown: true
)
)
var submitConfig = CardSubmitComponentConfig()
submitConfig.useUnityAuthenticationStrategy = true
submitConfig.onPreInitiateAuthentication = { async in
PreInitiateIntegratedAuthenticationData(providerId: "pxpfinancial", timeout: 120)
}
submitConfig.onPreAuthentication = { async in
InitiateIntegratedAuthenticationData(
merchantCountryNumericCode: "826",
merchantLegalName: "Example Ltd",
challengeWindowSize: .size1,
requestorChallengeIndicator: .challengeRequestedMandate,
timeout: 180
)
}
submitConfig.onPreAuthorisation = { _ async in TransactionInitiationData() }
submitConfig.onPostAuthorisation = { result in
// Handle payment result
}
submitConfig.onPostTokenisation = { result in
if let success = result as? CardTokenizationResultSuccess {
print("Token created: \(success.gatewayTokenId)")
}
}
let newCardConfig = NewCardComponentConfig(
styles: ContainerStyle(
backgroundColor: .white,
cornerRadius: 12,
borderWidth: 1,
borderColor: Color(.separator),
padding: EdgeInsets(top: 20, leading: 16, bottom: 20, trailing: 16),
spacing: 16
),
inputStyles: FieldInputStateStyles(
base: FieldInputStyle(
cornerRadius: 8,
borderWidth: 1,
borderColor: Color(.separator)
)
),
fields: fields,
submit: submitConfig,
dynamicCardImageComponent: dynamicCardImage,
displayRequiredIcon: true
)
let newCard = try pxpCheckout.create(.newCard, componentConfig: newCardConfig) as! NewCardComponent
VStack(alignment: .leading, spacing: 16) {
dynamicCardImage.buildContent()
newCard.buildContent()
}For more information about payment flows and validation, see Card submit, 3DS transactions, and Data validation.