# Custom Checkout

> Build a custom checkout experience using the Bolt iOS SDK's payment flow and authorization APIs.

Source: https://help.boltapp.com/developers/sdks/ios-swift/custom-checkout

## Overview [#overview]

If you need more control over the checkout experience than the [managed checkout flow](/developers/sdks/ios-swift/checkout/) provides, you can use the SDK's **payment flow** and **payment authorization** APIs independently. This lets you:

1. **Collect a payment method**: Present the Bolt payment UI to tokenize a credit/debit card.
2. **Authorize the payment**: Charge the tokenized card against an order token on your terms.

This approach is useful when you want to tokenize and store a card for later use, or build a fully custom checkout UI around Bolt's payment infrastructure.

## Complete Example [#complete-example]

```swift title="Swift"
import BoltCheckoutSDK

class CustomCheckoutViewController: UIViewController,
    BoltPaymentFlowDelegate,
    BoltPaymentAuthorizationDelegate {

    func onAddPaymentTapped() {
        BoltCheckout.shared.startPaymentFlow(delegate: self)
    }

    // --- BoltPaymentFlowDelegate ---

    func onPaymentFlowSuccess(paymentMethod: BoltPaymentMethod, creditCard: BoltCreditCard?) {
        // Card is now tokenized: show card summary in your UI, then authorize when ready
    }

    func onPaymentFlowError(errorReason: String) {
        showError(errorReason)
    }

    func onPaymentFlowCancel() {
        // User backed out
    }

    // Called when the user confirms the order in your custom UI
    func onConfirmOrder(orderToken: String) {
        BoltCheckout.shared.authorizePayment(
            userInfo: BoltUserInfo(
                firstName: "Jane",
                lastName: "Doe",
                email: "jane@example.com",
                phone: "+15551234567"
            ),
            orderToken: orderToken,
            delegate: self
        )
    }

    // --- BoltPaymentAuthorizationDelegate ---

    func onPaymentAuthorizationSuccess(orderReference: String) {
        navigateToConfirmation(orderReference)
    }

    func onPaymentAuthorizationFail(status: String, reason: String) {
        showDeclinedMessage(reason)
    }

    func onPaymentAuthorizationError(errorReason: String) {
        showError(errorReason)
    }
}
```

## Step-by-Step Breakdown [#step-by-step-breakdown]

### 1. Launch the Payment Flow [#1-launch-the-payment-flow]

Present the Bolt payment UI to collect and tokenize a card:

```swift title="Swift"
BoltCheckout.shared.startPaymentFlow(delegate: self)
```

On success, `onPaymentFlowSuccess` is called with a `BoltCreditCard` containing the tokenized card details (token, last4, network, expiration, postal code).

### 2. Authorize the Payment [#2-authorize-the-payment]

Once the user confirms in your custom UI, authorize the charge:

```swift title="Swift"
BoltCheckout.shared.authorizePayment(
    userInfo: BoltUserInfo(
        firstName: "Jane",
        lastName: "Doe",
        email: "jane@example.com",
        phone: "+15551234567"
    ),
    orderToken: orderToken,
    delegate: self
)
```

<Warning>
  If `authorizePayment()` is called before a card has been tokenized via the payment flow, `onPaymentAuthorizationError` fires immediately with an explanatory message.
</Warning>

## Payment Flow Callbacks [#payment-flow-callbacks]

See the full [BoltPaymentFlowDelegate reference](/developers/sdks/ios-swift/api-reference/#boltpaymentflowdelegate).

| Callback                                          | Description                                                                                            |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `onPaymentFlowSuccess(paymentMethod:creditCard:)` | Card successfully tokenized. `creditCard` contains token, last4, network, expiration, and postal code. |
| `onPaymentFlowError(errorReason:)`                | Tokenization or network failure.                                                                       |
| `onPaymentFlowCancel()`                           | User dismissed the payment screen.                                                                     |

## Payment Authorization Callbacks [#payment-authorization-callbacks]

See the full [BoltPaymentAuthorizationDelegate reference](/developers/sdks/ios-swift/api-reference/#boltpaymentauthorizationdelegate).

| Callback                                         | Description                                                            |
| ------------------------------------------------ | ---------------------------------------------------------------------- |
| `onPaymentAuthorizationSuccess(orderReference:)` | Payment authorized. Use `orderReference` to confirm with your backend. |
| `onPaymentAuthorizationFail(status:reason:)`     | Authorization declined by the processor (e.g. insufficient funds).     |
| `onPaymentAuthorizationError(errorReason:)`      | Request failed before reaching the processor (e.g. network timeout).   |
