Going to production
Switch VoltCheckout from sandbox to production and avoid the most common integration mistakes.
Sandbox vs production
Change .sandbox to .production in your configuration when you ship to users:
// Sandbox - no real money changes hands
let config = VoltCheckout.Configuration.sandbox(
customerId: "sandbox-customer-id",
tokenProvider: { try await YourAuth.fetchSandboxToken() }
)
// Production
let config = VoltCheckout.Configuration.production(
customerId: "your-production-customer-id",
tokenProvider: { try await YourAuth.fetchToken() }
)
let checkout = VoltCheckout(configuration: config)The sandbox connects to gateway.sandbox.volt.io. The production build connects to gateway.volt.io. No other code changes are needed.
Common mistakes
Create the instance once and reuse it. Recreating it tears down and rebuilds the internal state machine.
// Do this once — in an @StateObject or app root object
let checkout = VoltCheckout(configuration: config)If the modifier is missing, calling checkout.payment(with:) will suspend indefinitely — the sheet has nowhere to present.
ContentView()
.voltCheckoutSheet(using: checkout) // requiredAttach it to a view in the main navigation hierarchy, not inside a modal that might be dismissed before the payment flow ends.
Amount(currency:minorUnits:) returns nil for minorUnits == 0. Unwrapping it will crash. Always validate amounts before building a PaymentIntent.
guard minorUnits > 0, let amount = Amount(currency: .EUR, minorUnits: minorUnits) else {
return
}nil means the user cancelled — it is expected behaviour. Only treat .paymentCreated statuses like failed or refusedByBank as payment errors.
switch result {
case .paymentCreated(let id, let status, _):
// handle payment status
case nil:
// user cancelled — not an error
break
default:
break
}How is this guide?
Last updated on