This guide covers the v6 checkout entry points and the shared concepts used by all payment method docs.
For card-specific configuration and flow guides, see card.md, card-session-flow.md, and card-advanced-flow.md. For theme customization, see theme.md. For migration notes, see ../../MIGRATION.md.
The public integration surface is centered around four concepts:
Checkout.setup(...)is the entry point for checkout flows.CheckoutConfigurationis the shared configuration container.- Flow callbacks are configured with closures.
- Payment components are created from
SessionCheckoutorAdvancedCheckout.
Import the modules used by these examples:
import Adyen
import AdyenActions
import AdyenCard
import AdyenCheckout
import AdyenUI
import UIKitAdyenCheckout provides the setup APIs for session, advanced, and action-only flows.
CheckoutConfiguration is the checkout-wide container for:
- environment, amount, and client key
- component-specific configuration objects
- checkout-wide options such as
showsSubmitButton(_:) - theming and localization configured through
CheckoutConfiguration
let configuration = try CheckoutConfiguration(
environment: .test,
amount: amount,
clientKey: clientKey
) {
CardConfiguration()
AuthenticationConfiguration()
.requestorAppURL(URL(string: "https://your-domain.example/adyen")!)
}Use the builder closure to register component configuration objects that should apply to the flow.
Use the session flow when your backend starts checkout with /sessions.
let configuration = try CheckoutConfiguration(
environment: .test,
amount: amount,
clientKey: clientKey
) {
CardConfiguration()
AuthenticationConfiguration()
.requestorAppURL(URL(string: "https://your-domain.example/adyen")!)
}
let checkout = try await Checkout.setup(
with: sessionResponse,
configuration: configuration,
presentationDelegate: self
)
.onBeforeSubmit { data in
.proceed(data: data, sessionData: nil)
}
.onComplete { result in
print(result.resultCode)
}
.onFailure { error in
print(error.localizedDescription)
}
let component = try checkout.createPaymentComponent(for: .scheme)In session flow, the effective amount comes from the /sessions response. A client-side amount on CheckoutConfiguration does not override it. For card-specific session-controlled settings such as showStorePaymentMethod(_:), installmentConfiguration(_:), and showInstallmentAmount, see card-session-flow.md.
SessionCheckout can:
- create an individual payment component with
createPaymentComponent(for:) - let you inspect or patch shopper data before submit with
onBeforeSubmit(_:)
Use the advanced flow when your backend starts checkout with /paymentMethods and handles /payments and /payments/details.
let configuration = try CheckoutConfiguration(
environment: .test,
amount: amount,
clientKey: clientKey
) {
CardConfiguration()
}
let checkout = try await Checkout.setup(
with: paymentMethods,
configuration: configuration,
presentationDelegate: self
)
.onSubmit { data in
try await callPayments(with: data)
}
.onAdditionalDetails { data in
try await callDetails(with: data)
}
.onComplete { result in
print(result.resultCode)
}
.onFailure { error in
print(error.localizedDescription)
}
let component = try checkout.createPaymentComponent(for: .scheme)callPayments(with:) should return SubmitResult, and callDetails(with:) should return AdditionalDetailsResult.
AdvancedCheckout can:
- create an individual payment component with
createPaymentComponent(for:) - expose
onSubmit(_:)for/payments - expose
onAdditionalDetails(_:)for/payments/details
If your app only needs to handle actions, you can set up checkout without PaymentMethods or SessionResponse:
let checkout = try await Checkout.setup(
configuration: configuration,
presentationDelegate: self
)
.onAdditionalDetails { data in
try await callDetails(with: data)
}
.onComplete { result in
print(result.resultCode)
}
.onFailure { error in
print(error.localizedDescription)
}callDetails(with:) should return AdditionalDetailsResult.
Call checkout.handle(action:) when your backend returns an action.
Pass a PresentationDelegate if you want checkout to present action components from your own UI layer:
extension CheckoutViewController: PresentationDelegate {
func present(viewController: UIViewController) {
present(viewController, animated: true)
}
}createPaymentComponent(for:) returns CheckoutPaymentComponent. Use its viewController for presentation.
guard let viewController = component.viewController else { return }
let navigationController = UINavigationController(rootViewController: viewController)
viewController.navigationItem.leftBarButtonItem = .init(
barButtonSystemItem: .cancel,
target: self,
action: #selector(cancelPressed)
)
present(navigationController, animated: true)For the full CheckoutTheme guide and the supported color overrides, see theme.md.
Use localizationProvider(_:) on CheckoutConfiguration for programmatic string overrides across the checkout flow:
struct DemoLocalizationProvider: CheckoutLocalizationProvider {
func localizedString(_ key: CheckoutLocalizationKey, locale: Locale) -> String? {
switch (key, locale.languageCode) {
case (.cardNumber, "en"):
return "Custom Card Number"
case (.cardSecurityCode, "en"):
return "Custom CVC"
default:
return nil
}
}
}
let configuration = try CheckoutConfiguration(
environment: .test,
amount: amount,
clientKey: clientKey
) {
CardConfiguration()
}
.localizationProvider(DemoLocalizationProvider())Use app-bundle .strings or .xcstrings files when you want to add a fully new language. Use localizationProvider(_:) when you want targeted runtime overrides.
Pass incoming URLs to the SDK so active redirect actions can resume after the shopper returns from a browser or external app.
UIKit - AppDelegate:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
Checkout.handleReturn(url: url)
return true
}UIKit - SceneDelegate:
func scene(_ scene: UIScene, openURLContexts contexts: Set<UIOpenURLContext>) {
guard let url = contexts.first?.url else { return }
Checkout.handleReturn(url: url)
}SwiftUI:
ContentView()
.onOpenURL { url in Checkout.handleReturn(url: url) }It is safe to pass all incoming URLs; any URL not belonging to an active checkout redirect is ignored.