Configure Checkout Drop-in once with unified settings for all payment methods, callbacks, and transaction data.
Checkout Drop-in uses a single, unified configuration at initialisation. Instead of configuring individual payment components, you configure Drop-in once and it automatically handles all payment methods.
All configuration happens at initialisation via CheckoutDropIn(config:):
import SwiftUI
import PXPCheckoutSDK
let config = CheckoutDropInConfig(
// REQUIRED
environment: .test,
session: sessionData,
transactionData: DropInTransactionData(
amount: Decimal(string: "99.99") ?? 0,
currency: "USD",
entryType: .ecom,
intent: DropInTransactionIntentData(
card: .authorisation,
paypal: .purchase,
aeropay: .authorisation
),
merchantTransactionId: UUID().uuidString,
merchantTransactionDate: { Date() }
),
merchantShopperId: "shopper-123",
ownerId: "MERCHANT_GROUP_1", // Merchant group ID from Unity Portal
// OPTIONAL: Fraud detection
kountDisabled: false,
// Recommended: always implement success and error handlers
onSuccess: { result in
// Handle success
},
onError: { paymentMethod, error in
// Handle error
},
// Optional callbacks
onGetShippingAddress: {
// Return ShippingAddress? for billing prefill / PayPal setProvidedAddress
nil
},
onGetShopper: {
TransactionShopper(id: "shopper-123")
},
onBeforeSubmit: { paymentMethod async in
// Return true to proceed
return true
},
onSubmit: { paymentMethod in
// Payment started (card, Apple Pay, and Aeropay; not PayPal)
},
analyticsEvent: { event in
// Track analytics
}
)
// Initialise and create Drop-in
let dropIn = try CheckoutDropIn(config: config)
await dropIn.create()
// Render in SwiftUI
dropIn.buildContent()Specifies which Unity environment to connect to:
.test: sandbox environment. Use this for development, testing, and staging..live: live environment. Use this for production deployments.
environment: .test // or .liveSession data is retrieved from your backend and contains payment configuration:
// Backend endpoint
let sessionData = try await fetchSessionFromBackend()
// Pass to Drop-in
session: sessionDataSession data includes:
sessionId: Unique session identifier.hmacKey: HMAC authentication key.encryptionKey: Encryption key.allowedFundingTypes: Which payment methods are enabled.sessionExpiry: Optional session expiry timestamp from your backend (respect when creating new sessions).restrictions: Optional session-level card restrictions merged with checkout config.
For session creation details, including optional customerProfileId, see the implementation guide.
Identifies who owns this transaction:
merchantShopperId: "shopper-123", // Required — your shopper identifier
ownerId: "MERCHANT_GROUP_1" // Required — merchant group ID from the Unity PortalDrop-in sets ownerType to "MerchantGroup" automatically. You don't pass it in CheckoutDropInConfig. Supply the merchant group identifier, not a site merchant ID.
Defines the payment amount, currency, and intent:
transactionData: DropInTransactionData(
amount: Decimal(string: "99.99") ?? 0,
currency: "USD",
entryType: .ecom,
intent: DropInTransactionIntentData(
card: .authorisation,
paypal: .purchase,
aeropay: .authorisation
),
merchantTransactionId: UUID().uuidString,
merchantTransactionDate: { Date() }
)The following table describes each DropInTransactionData property:
| Property | Description |
|---|---|
amountDecimal required | The transaction amount shown and submitted by the drop-in. |
currencyString required | The currency code, in ISO 4217 format. Aeropay requires "USD". |
entryTypeEntryType required | The transaction entry type. Aeropay requires .ecom. |
intentDropInTransactionIntentData required | Card, PayPal, and Aeropay intent configuration. Each intent property is optional — set only methods present in session.allowedFundingTypes.card: CardIntentType (for example .authorisation, .purchase, .verification, .estimatedAuthorisation).paypal: DropInPayPalIntentType — .authorisation or .purchase only.aeropay: DropInAeropayIntentType — .authorisation, .purchase, or .estimatedAuthorisation.PayPal and Aeropay payout are not available in Drop-in (excluded at the type level). See Aeropay. |
merchantTransactionIdString required | A merchant-generated transaction ID. Use a UUID or order ID to ensure uniqueness. |
merchantTransactionDate() -> Date required | Closure returning the transaction date. Typically { Date() }. |
cardAcceptorNameString? | Optional card acceptor name shown on card statements. |
recurringRecurringType? | Optional recurring payment configuration for subscriptions. Example:RecurringType(frequencyInDays: 30, frequencyExpiration: "2026-12-31") |
linkIdString? | Optional link ID when linking transactions together. |
Your unique identifier for the transaction:
merchantTransactionId: UUID().uuidString
// Or use your own format
merchantTransactionId: "order-\(orderId)"Drop-in provides unified callbacks for payment success, failure, and processing. onSuccess and onError are optional in the Swift initializer but should always be implemented. Without them, completed or failed payments are not handled.
Callback coverage differs by method. See the notes below and Events.
CheckoutDropInConfig(
// OPTIONAL: Get shopper information
onGetShopper: {
TransactionShopper(id: "shopper-123")
},
// Recommended: called when payment succeeds
onSuccess: { result in
print("Payment successful: \(result.systemTransactionId)")
// CRITICAL: Always verify on backend before fulfilling the order
verifyPaymentOnBackend(result)
},
// Recommended: called when payment fails
onError: { paymentMethod, error in
print("Payment failed: \(error.errorCode) - \(error.errorMessage)")
},
// OPTIONAL: Called before payment submission
onBeforeSubmit: { paymentMethod async in
print("Payment method: \(paymentMethod.rawValue)")
// Return true to proceed. Return false to block submission without calling onCancel or onError.
return true
},
// OPTIONAL: Called when payment starts processing (card, Apple Pay, and Aeropay)
onSubmit: { paymentMethod in
print("Processing payment...")
}
)Card-on-file UI is created only when onGetShopper returns TransactionShopper(id:) with a non-empty id (and the session allows cards). See Card display properties.
onSubmit is called when payment processing starts for card, Apple Pay, and Aeropay. PayPal doesn't invoke onSubmit. For Aeropay, onSubmit(.aeropay) fires after bank-account confirmation, not when the Pay by bank button is first tapped. Use onBeforeSubmit or Drop-in's processing state for PayPal loading UI. See onSubmit.
For detailed callback documentation, see Events.
Use onGetShippingAddress to supply a shipping address for billing prefill and for PayPal when shippingPreference is .setProvidedAddress. Card and PayPal transaction builders can consume this callback.
onGetShippingAddress: {
ShippingAddress(
// Populate from your checkout form / order record
countryCode: "GB",
postalCode: "NW1 6XE",
address: "221B Baker Street",
city: "London"
)
}For PayPal shipping preference details, see PayPal configuration.
Track payment flow events:
analyticsEvent: { event in
print("Event: \(event.eventName)")
// Send to your analytics platform
sendToFirebaseAnalytics(event)
}For detailed analytics documentation, see Analytics.
Configure payment-method-specific settings:
methodConfig: DropInMethodConfig(
global: DropInGlobalConfig(
acceptedCardNetworks: [.visa, .mastercard, .amex],
allowedIssuerCountryCodes: ["US", "GB"],
transactionInfo: DropInTransactionInfo(
countryCode: "US",
totalLabel: "Total"
),
riskScreeningData: RiskScreeningData(
performRiskScreening: true,
userIp: "203.0.113.10",
transaction: RiskScreeningTransaction(subtotal: 149.99)
)
),
card: DropInCardConfig(
showCOF: true,
showNewCard: true
),
paypal: DropInPaypalConfig(
fundingSources: [.paypal, .paylater],
shippingPreference: .getFromFile
),
applePay: DropInApplePayConfig(
shippingContactConfiguration: DropInApplePayShippingContactConfiguration(
requireShippingContactFields: [.postalAddress, .name]
)
),
aeropay: DropInAeropayConfig(
// userId: "existing-aeropay-user-id",
// skipConsumerDataCollection: true, // all four onGetShopper fields required and valid (phone +1 + 10 digits); editable fields nil/empty
// editableConsumerDataFields: [.email],
// excludedBankAccountIds: ["12345"]
)
)Use DropInCardConfig to show or hide card-on-file and new card entry. Both flags default to true when omitted. When both are false, Drop-in hides the entire card payment method panel.
For detailed payment method configuration, see:
Configure Aeropay through methodConfig.aeropay (DropInAeropayConfig). All properties are optional:
userId— returning Aeropay user ID (skips consumer data and OTP).skipConsumerDataCollection— skip the data screen whenonGetShopperreturns all four non-empty fields and editable fields arenilor empty. All four values must be valid (phone:+14155550123— US E.164,+1plus 10 digits). Invalid non-empty values triggeronErrorwithSDK1300at create or button tap instead of skipping.editableConsumerDataFields— which prefilled fields stay editable (.firstName,.lastName,.email,.phoneNumber).excludedBankAccountIds— bank account IDs to hide from bank selection.
methodConfig.global.onCancel applies when the shopper closes the Aeropay popup (paymentMethod == .aeropay, payload nil). methodConfig.global.onGetConsent doesn't apply to Aeropay (Card, PayPal, and Apple Pay only).
For the full property reference, decision tree, and skip-consistent examples, see Aeropay.
Customise text displayed in the Drop-in interface by implementing the Localisation protocol. Override Drop-in-specific keys to replace default labels, messages, and accessibility strings. Unset properties fall back to the built-in strings for your configured locale.
The following table lists the main Drop-in localisation keys:
| Property | Description |
|---|---|
submitTextString? | Text for the submit or pay button in card and related flows. |
checkoutDropInHeaderTextString? | Header text shown at the top of Drop-in. |
checkoutDropInCardLabelString? | Label for the card payment method row. |
checkoutDropInPaypalLabelString? | Label for the PayPal payment method row. |
checkoutDropInApplePayLabelString? | Label for the Apple Pay payment method row. |
checkoutDropInAeropayLabelString? | Label for the Aeropay payment method row (default: Pay by bank via Aeropay). |
checkoutDropInGooglePayLabelString? | Label for Google Pay (reserved for future use). |
checkoutDropInCardOnFileTitleString? | Title for the saved cards section. |
checkoutDropInNewCardTitleString? | Title for the new card entry section. |
checkoutDropInBillingAddressTitleString? | Title for the billing address section. |
checkoutDropInSecuredByTextString? | “Secured by” branding text shown in Drop-in. |
checkoutDropInPxpBrandingTextString? | PXP branding text shown in Drop-in. |
checkoutDropInLoadingTextString? | Loading message shown while Drop-in initialises or processes payment. |
checkoutDropInNoPaymentMethodsErrorString? | Error message when no payment methods are available. |
checkoutDropInCheckoutPaymentSelectionAccessibilityLabelString? | VoiceOver label for the checkout payment selection region. |
checkoutDropInQuickPaymentMethodsAccessibilityLabelString? | VoiceOver label for the quick payment methods section. |
checkoutDropInPaymentMethodsAccessibilityLabelString? | VoiceOver label for the main payment methods list. |
checkoutDropInA11yPaymentMethodPrefixString? | VoiceOver prefix for payment method rows (accessibility). |
checkoutDropInA11yExpandedStateString? | VoiceOver label when a payment method panel is expanded. |
checkoutDropInA11yCollapsedStateString? | VoiceOver label when a payment method panel is collapsed. |
checkoutDropInA11yExpandedHintString? | VoiceOver hint when a panel is expanded. |
checkoutDropInA11yCollapsedHintString? | VoiceOver hint when a panel is collapsed. |
checkoutDropInA11yErrorPrefixString? | VoiceOver prefix for inline error messages. |
checkoutDropInA11yCheckoutReadyString? | VoiceOver announcement when checkout is ready. |
checkoutDropInA11yPaymentFailedString? | VoiceOver announcement when payment fails. |
checkoutDropInA11yLoadingPaymentMethodString? | VoiceOver announcement while a payment method is loading. |
// Localisation has no default implementations. Copy DefaultLocalisation (or wrap it and
// forward every property), then override the Drop-in keys you need.
struct MyDropInLocalisation: Localisation {
private let base = DefaultLocalisation()
var submitText: String? { "Pay Now" }
var checkoutDropInHeaderText: String? { "Choose Payment Method" }
var checkoutDropInAeropayLabel: String? { "Pay by bank via Aeropay" }
var cardConsentLabel: String? { base.cardConsentLabel }
// Forward every other Localisation requirement to `base` the same way.
// A type that declares only a few properties will not compile.
}
// Pass to Drop-in config
localisation: MyDropInLocalisation()Localisation is a large protocol shared across checkout components. There are no protocol extensions with defaults. Every required property must be implemented (typically by forwarding to DefaultLocalisation). Overriding only Drop-in keys without the rest will not compile.
When locale is omitted, Drop-in defaults to "en-US". It does not automatically follow the device language.
Set an explicit locale to control built-in SDK strings:
locale: "en-US" // or "es-ES", "el-GR"Drop-in ships built-in string bundles for the following locales:
| Locale | Language |
|---|---|
"en-US" | English (United States). Used when locale is omitted or unrecognised. |
"es-ES" | Spanish (Spain). |
"el-GR" | Greek (Greece). |
Any other locale value falls back to "en-US" strings. Custom Localisation overrides apply on top of the selected bundle.
Pass hyphenated locale values to CheckoutDropInConfig.locale (for example "en-US"). PayPal validation may use underscore format internally (en_US); you do not need to convert values in app code.
Limit accepted card types by owner segment and funding source at checkout. Restrictions apply during card submission after BIN lookup: they filter which cards customers can pay with.
Set restrictions on CheckoutDropInConfig or in session data. When both are present, the SDK merges them as a union (session values first, then config values not already present).
restrictions: Restrictions(
card: Restrictions.Card(
ownerTypes: [.consumer], // Consumer cards only
fundingSources: [.credit, .debit] // Exclude prepaid
)
)The following table describes restriction properties:
| Property | Description |
|---|---|
restrictionsRestrictions? | Optional checkout-level card restrictions on CheckoutDropInConfig. Merged with session.restrictions when both are set. |
restrictions.card.ownerTypes[CardOwnerType]? | Allowed card owner segments. Omit to allow all owner types configured in the merged restriction set. Possible values:
|
restrictions.card.fundingSources[CardFundingSource]? | Allowed funding sources. Omit to allow all funding sources in the merged restriction set. Possible values:
|
methodConfig.global.allowedCardFundingSource is separate from restrictions. It controls Apple Pay merchant capabilities (.credit and .debit only) and does not replace session or checkout card restrictions for manual card entry.
Control Kount device data collection:
kountDisabled: false // Set to true to disable KountDefaults to false (Kount enabled).
To pass transaction risk screening data to the payment flow, use methodConfig.global.riskScreeningData:
methodConfig: DropInMethodConfig(
global: DropInGlobalConfig(
riskScreeningData: RiskScreeningData(
performRiskScreening: true,
userIp: "203.0.113.10",
transaction: RiskScreeningTransaction(subtotal: 149.99)
)
)
)The difference between these two settings:
kountDisabled: controls whether Kount device data is collected during the checkout flow.methodConfig.global.riskScreeningData: provides transaction-level risk data that is sent with card, Apple Pay, and PayPal Drop-in payment requests.
When Kount is enabled, the SDK injects the device session ID at authorisation time. You don't pass it in RiskScreeningData.
Fetch a session from your backend, then initialise Drop-in with required fields and core callbacks:
import SwiftUI
import PXPCheckoutSDK
// Get session from backend
let sessionData = try await fetchSessionFromBackend()
let config = CheckoutDropInConfig(
environment: .test,
session: sessionData,
transactionData: DropInTransactionData(
amount: Decimal(string: "99.99") ?? 0,
currency: "USD",
entryType: .ecom,
intent: DropInTransactionIntentData(
card: .authorisation,
paypal: .purchase,
aeropay: .authorisation
),
merchantTransactionId: UUID().uuidString,
merchantTransactionDate: { Date() }
),
merchantShopperId: "shopper-123",
ownerId: "MERCHANT_GROUP_1", // Merchant group ID from Unity Portal
onGetShopper: {
TransactionShopper(id: "shopper-123")
},
onSuccess: { result in
Task {
await verifyPaymentOnBackend(result)
}
},
onError: { paymentMethod, error in
print("Payment failed: \(error.errorMessage)")
}
)
let dropIn = try CheckoutDropIn(config: config)
await dropIn.create()Render in SwiftUI with dropIn.buildContent().
Use this pattern when you need validation gates, loading state, analytics, and detailed error handling:
import SwiftUI
import PXPCheckoutSDK
let sessionData = try await fetchSessionFromBackend()
let orderId = "order-12345"
let config = CheckoutDropInConfig(
// REQUIRED
environment: .live,
session: sessionData,
transactionData: DropInTransactionData(
amount: Decimal(string: "149.99") ?? 0,
currency: "USD",
entryType: .ecom,
intent: DropInTransactionIntentData(
card: .authorisation,
paypal: .purchase,
aeropay: .authorisation
),
merchantTransactionId: "order-\(orderId)",
merchantTransactionDate: { Date() }
),
merchantShopperId: "shopper-456",
ownerId: "MERCHANT_GROUP_1", // Merchant group ID from Unity Portal
locale: "en-US",
kountDisabled: false,
// CALLBACKS
onGetShippingAddress: {
ShippingAddress(
countryCode: "US",
postalCode: "10001",
address: "123 Main St",
city: "New York",
state: "NY"
)
},
onGetShopper: {
TransactionShopper(
id: "shopper-456",
email: "customer@example.com"
)
},
onBeforeSubmit: { paymentMethod async in
print("Payment method selected: \(paymentMethod.rawValue)")
// Custom validation — return false to block submission (does not call onCancel or onError)
guard await validateOrder(orderId) else {
return false
}
guard await checkInventory(orderId) else {
return false
}
return true
},
onSubmit: { paymentMethod in
// Card, Apple Pay, and Aeropay — PayPal does not call onSubmit
print("Payment processing started for: \(paymentMethod.rawValue)")
showLoadingIndicator()
},
onSuccess: { result in
hideLoadingIndicator()
// CRITICAL: Verify on backend before fulfilling the order
Task {
do {
let verified = try await verifyPaymentOnBackend(
systemTransactionId: result.systemTransactionId,
merchantTransactionId: result.merchantTransactionId ?? "",
orderId: orderId
)
if verified.success {
navigateToOrderConfirmation(orderId: verified.orderId)
} else {
showError("Payment verification failed. Please contact support.")
}
} catch {
showError("Unable to verify payment. Please contact support.")
}
}
},
onError: { paymentMethod, error in
hideLoadingIndicator()
let userMessage: String
switch error.errorCode {
case "SDK1114":
userMessage = "Authentication failed. Please try again or use a different card."
case "SDK0500":
userMessage = "Connection error. Check your internet connection."
case "SDK1116":
// Generic card-payment failure when no more specific code was preserved
userMessage = "Card payment failed. Please try another payment method."
case "SDK0113", "SDK0115", "SDK1125":
userMessage = "Pay by Bank is unavailable. Please choose another payment method."
case "SDK1126":
userMessage = "Pay by Bank payment failed. Please try again."
default:
if error.errorMessage.localizedCaseInsensitiveContains("session") ||
error.errorMessage.localizedCaseInsensitiveContains("expired") {
userMessage = "Session expired. Please refresh checkout."
} else {
userMessage = "Payment failed: \(error.errorMessage)"
}
}
showError(userMessage)
},
analyticsEvent: { event in
print("Analytics: \(event.eventName)")
sendToAnalyticsPlatform(event)
}
)
let dropIn = try CheckoutDropIn(config: config)
await dropIn.create()For payment-method-specific settings (methodConfig, restrictions, Apple Pay shipping handlers, and similar), see Payment method configuration above and the linked method guides.
Drop-in method configuration values are optional overrides. When you omit an optional value, the SDK derives the effective component configuration from the checkout session, Unity site configuration, or SDK defaults.
When global or card config values are omitted, the SDK falls back as follows:
| Config value | Fallback behaviour |
|---|---|
methodConfig.global.acceptedCardNetworks | Falls back to session cardSchemes, then cards. If neither is present, no card networks are applied. |
methodConfig.global.allowedCardFundingSource | Falls back to [.credit, .debit] for Apple Pay merchant capabilities. Does not read session restrictions. |
methodConfig.global.allowedIssuerCountryCodes | Falls back to nil. No issuer country filter is applied to Apple Pay supportedCountries. |
methodConfig.global.transactionInfo | Falls back to a basic Apple Pay total using transaction amount and currency (totalLabel defaults to "TOTAL"). |
methodConfig.global.shippingOptions | Falls back to empty list (no shipping options displayed). |
methodConfig.global.couponInfo | Falls back to nil (no coupon information displayed). |
methodConfig.global.onGetConsent | Falls back to omitted. Drop-in uses built-in consent UI where configured (card storage checkbox when site storeCardConsent is Ask; PayPal consent when consentComponent is enabled). Doesn't apply to Aeropay. |
methodConfig.global.onCancel | Falls back to no-op (cancel events are not captured). When set, Aeropay fires this with .aeropay and a nil payload when the shopper closes the popup. |
methodConfig.card | Falls back to both card-on-file and new card sections enabled when methodConfig or card is omitted. |
methodConfig.card.showCOF | Falls back to true. Card-on-file is created only when the session allows cards and onGetShopper returns a non-empty shopper id. |
methodConfig.card.showNewCard | Falls back to true. When both showCOF and showNewCard resolve to false, the Card payment method panel is hidden. |
When Apple Pay config values are omitted, the SDK falls back as follows:
| Config value | Fallback behaviour |
|---|---|
methodConfig.applePay.shippingContactConfiguration | Falls back to no required shipping fields. |
methodConfig.applePay.billingContactConfiguration | Falls back to no required billing fields. |
methodConfig.applePay.onShippingContactSelected | Falls back to no shipping contact update (original transaction info used). |
methodConfig.applePay.onShippingMethodSelected | Falls back to no shipping method update (original transaction info used). |
methodConfig.applePay.onPaymentMethodSelected | Falls back to no payment method update (original transaction info used). |
methodConfig.applePay.onCouponCodeChanged | Falls back to no coupon code processing. |
When PayPal config values are omitted, the SDK falls back as follows:
| Config value | Fallback behaviour |
|---|---|
methodConfig.paypal.fundingSources | Falls back to session allowedFundingTypes.wallets.paypal.allowedFundingOptions. If neither merchant config nor session lists options, no PayPal buttons are rendered. |
methodConfig.paypal.shippingPreference | Falls back to .noShipping (no shipping address collected by PayPal). |
methodConfig.paypal.payeeEmailAddress | Falls back to nil (no payee email displayed). |
methodConfig.paypal.paymentDescription | Falls back to nil (PayPal uses its default order description behaviour). |
methodConfig.paypal.consentComponent | Falls back to true (PayPal consent component shown when PayPal is enabled). |
When Aeropay config values are omitted, the SDK falls back as follows:
| Config value | Fallback behaviour |
|---|---|
methodConfig.aeropay | Falls back to default DropInAeropayConfig values (userId nil, skipConsumerDataCollection false, editable fields nil, excluded bank IDs nil). Aeropay still appears when session funding and transaction eligibility allow it. |
methodConfig.aeropay.userId | Falls back to nil. New-shopper flow uses onGetShopper and may show consumer data collection and OTP. |
methodConfig.aeropay.skipConsumerDataCollection | Falls back to false. Consumer data screen is shown unless userId is set. |
methodConfig.aeropay.editableConsumerDataFields | Falls back to nil (prefilled fields are read-only). |
methodConfig.aeropay.excludedBankAccountIds | Falls back to nil (all linked accounts are shown). |
When integrating Checkout Drop-in at scale:
- Session management: Cache session data appropriately but respect the
sessionExpirytimestamp. Create new sessions for new checkout attempts. - Error handling: Implement comprehensive error handling for all callbacks. Log errors with sufficient context for debugging.
- Backend verification: Always verify payment results on your backend before fulfilling the order. Frontend callbacks can be manipulated.
- Analytics: Implement
analyticsEventto monitor drop-in performance, conversion rates, and error patterns. - Testing: Test with all enabled payment methods in both test and live environments before going to production.
Continue with these guides: