> This page is for Afterpay.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.cash.app/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.cash.app/_mcp/server.

# Checkout V1 (Deprecated) on iOS

> **Deprecated**
>
> Checkout V1 is deprecated. Use [Checkout V2](/cash-app-afterpay/guides/sdk/ios-sdk/implementation-guide) for new integrations. Checkout V2 supports standard and express checkout, and it shows a loading screen while your app gets the checkout token. Checkout V1 supports standard checkout only. The SDK still includes it, so existing integrations keep working. Use it in a new integration only if your app needs its SwiftUI or Objective-C API.

With Checkout V1, your server creates a checkout and returns its redirect URL to your app. The SDK loads the URL in a web view inside your app and watches for checkout to redirect to your confirm or cancel URL. The customer never leaves your app. When the customer confirms, the SDK returns the order token, and your server completes the payment.

Checkout V1 supports Swift with UIKit, SwiftUI, and Objective-C.

## Step 1: Create a checkout on your server

When the customer starts checkout, your server calls [Create Checkout](/cash-app-afterpay/api-reference/reference/checkouts/create-checkout-1) and returns the `redirectCheckoutUrl` from the response to your app.

```json
{
  "amount": { "amount": "100.00", "currency": "USD" },
  "consumer": { "email": "test@example.com" },
  "merchant": {
    "redirectConfirmUrl": "https://example.com/checkout/confirm",
    "redirectCancelUrl": "https://example.com/checkout/cancel"
  },
  "merchantReference": "merchant-order-123"
}
```

> **Warning**
>
> Set both `merchant.redirectConfirmUrl` and `merchant.redirectCancelUrl`. The SDK uses them to detect the result. They can be any URLs; by default, the SDK doesn't load them.

## Step 2: Present the checkout

Pass the checkout URL to the SDK. The SDK checks that the URL is an Afterpay checkout URL before it loads it.

#### Swift (UIKit)

```swift
Afterpay.presentCheckoutModally(
  over: self,
  loading: checkoutURL
) { result in
  switch result {
  case .success(let token):
    // Send the token to your server to complete the order.
    break
  case .cancelled(let reason):
    // Handle the cancellation.
    break
  }
}
```

#### SwiftUI

```swift
struct CheckoutView: View {
  // Setting this to a checkout URL presents the Afterpay checkout.
  @State private var checkoutURL: URL?

  var body: some View {
    CartView()
      .afterpayCheckout(url: $checkoutURL) { result in
        switch result {
        case .success(let token):
          // Send the token to your server.
          break
        case .cancelled(let reason):
          // Handle the cancellation.
          break
        }
      }
  }
}
```

#### Objective-C

```objc
void (^completion)(APCheckoutResult *) = ^(APCheckoutResult *result) {
  if ([result isKindOfClass:[APCheckoutResultSuccess class]]) {
    // Send [(APCheckoutResultSuccess *)result token] to your server.
  } else {
    // Handle [(APCheckoutResultCancelled *)result reason].
  }
};

[APAfterpay presentCheckoutModallyOverViewController:self
                                  loadingCheckoutURL:self.checkoutURL
                                            animated:YES
                                          completion:completion];
```

If you haven't set the configuration, or the customer's language isn't supported in your region, `Afterpay.enabled` is `false`. `presentCheckoutModally` then returns without presenting checkout or calling the completion handler. The SwiftUI modifier doesn't check `Afterpay.enabled`, so don't show your payment button when it's `false`. For details, see [Payment button visibility](/cash-app-afterpay/guides/sdk/ios-sdk/ui-components/payment-button#visibility).

### Load the redirect URLs

By default, the SDK stops at the redirect and doesn't load your confirm or cancel URL. To load the redirect URL and read the result from its response instead, pass `shouldLoadRedirectUrls: true` to `presentCheckoutModally`. The SwiftUI `afterpayCheckout` modifier accepts this parameter but ignores it in SDK 5.9.0.

## Step 3: Handle the result

A successful result contains the order token. A canceled result contains a `CancellationReason`:

| Reason                | Meaning                                                                                                              |
| --------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `userInitiated`       | The customer closed or canceled checkout.                                                                            |
| `networkError(Error)` | The checkout page failed to load, the SDK showed a retry dialog, and the customer chose to cancel.                   |
| `unretrievableUrl`    | The SDK couldn't read the redirect URL from the response. This happens only when `shouldLoadRedirectUrls` is `true`. |
| `invalidURL(URL)`     | The URL you passed isn't an Afterpay checkout URL.                                                                   |

## Step 4: Complete the order

Send the order token to your server. To capture the full amount immediately, your server calls [Capture Full Payment](/cash-app-afterpay/api-reference/reference/payments/capture-full-payment) with the token. To capture later, call [Auth](/cash-app-afterpay/api-reference/reference/payments/auth) and then [Capture Payment](/cash-app-afterpay/api-reference/reference/payments/capture-payment).

For the full server flow, see the [Mobile SDK quickstart](/cash-app-afterpay/guides/sdk/quickstart).