> 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 widget

`WidgetView` shows the customer's Afterpay payment schedule. Show it when the order total can change after the customer finishes the Afterpay checkout, for example because of shipping costs or promo codes. The widget also tells the customer about anything that blocks the purchase, such as going over their Afterpay limit.

`WidgetView` is a `UIView` that renders the Afterpay web widget in a web view. Its height adjusts to fit the widget, and the widget fits any container at least 300 points wide.

## Create the widget

Set the merchant configuration first. Both initializers throw `WidgetView.WidgetError.noConfiguration` if you haven't set one.

#### After checkout

After a checkout, create the widget with the order token from the checkout result. The widget looks up the order and shows its schedule.

```swift
let widgetView = try WidgetView(token: token)
```

#### Before checkout

Before the customer checks out, create the widget with the order total. Use the same currency as your configuration.

```swift
let widgetView = try WidgetView(amount: "200.00")
```

Both initializers take an optional `style` parameter. Set `logo` and `heading` to `true` to show the Afterpay logo and heading. Both default to `false`.

```swift
let widgetView = try WidgetView(
  amount: "200.00",
  style: WidgetView.Style(logo: false, heading: true)
)
```

The widget has a border and rounded corners on its layer. Change them to match your app:

```swift
widgetView.layer.cornerRadius = 4
widgetView.layer.borderColor = UIColor.systemGray4.cgColor
```

## Update the order total

When the order total changes, send the new total to the widget. Use the same currency as your configuration.

```swift
try widgetView.sendUpdate(amount: "50.00")
```

## Get the widget status

Before you capture the payment, check that the widget is valid. The completion handler runs on the main thread.

```swift
widgetView.getStatus { result in
  switch result {
  case .success(.valid(let amountDueToday, let checksum)):
    // Send the checksum to your server with the capture request.
    break
  case .success(.invalid(let errorCode, let message)):
    // Don't let the customer complete the order.
    break
  case .failure(let error):
    // Handle the error.
    break
  }
}
```

When the widget is valid, its status includes the amount due today and the payment schedule checksum. The checksum identifies the payment schedule that the customer saw. It's available only for a widget created with a checkout token. Pass it as `paymentScheduleChecksum` when you [capture the payment](/cash-app-afterpay/api-reference/reference/payments/capture-full-payment).

## Respond to widget events

To be notified when the widget changes, implement `WidgetHandler` and register it with `Afterpay.setWidgetHandler(_:)`. The SDK holds the handler weakly, so keep a strong reference to it.

```swift
final class CheckoutWidgetHandler: WidgetHandler {
  func onReady(
    isValid: Bool,
    amountDueToday: Money,
    paymentScheduleChecksum: String?
  ) {
    // The widget is ready to accept updates.
  }

  func onChanged(status: WidgetStatus) {
    // The widget's status changed.
  }

  func onError(errorCode: String?, message: String?) {
    // The widget reported an error.
  }

  func onFailure(error: Error) {
    // An error occurred in the SDK.
  }
}

// Keep the handler in a stored property, for example on your view controller.
private let widgetHandler = CheckoutWidgetHandler()

override func viewDidLoad() {
  super.viewDidLoad()
  Afterpay.setWidgetHandler(widgetHandler)
}
```

If your app uses Combine, use `WidgetEventPublisher` as the handler. It publishes the same events as `ready`, `changed`, `errors`, and `failures`:

```swift
private let eventPublisher = WidgetEventPublisher()
private var cancellables = Set<AnyCancellable>()

override func viewDidLoad() {
  super.viewDidLoad()
  Afterpay.setWidgetHandler(eventPublisher)

  eventPublisher.changed
    .sink { status in
      // Respond to the status.
    }
    .store(in: &cancellables)
}
```