# Handling Storefront & Price Changes

A purchase can be enqueued in one storefront but execute in another — for example, a logged-out user starts a purchase with their device region, then logs into an account registered in a different country, where the price or availability differs.

OnsideKit does **not** silently charge the new price. Before processing such a purchase, it asks your **payment queue delegate** whether to continue, so you can confirm the change with the user or cancel it.

## The delegate

```swift
protocol OnsidePaymentQueueDelegate: AnyObject {
    @MainActor func onsidePaymentQueue(
        _ queue: OnsidePaymentQueue,
        shouldContinue transaction: OnsidePaymentTransaction,
        in storefront: OnsideStorefront
    ) -> Bool

    @MainActor func onsidePaymentQueue(
        _ queue: OnsidePaymentQueue,
        shouldContinue transaction: OnsidePaymentTransaction,
        in storefront: OnsideStorefront
    ) async -> Bool
}
```

Both a synchronous and an asynchronous variant are available — implement whichever fits. The default implementation returns `true` (always continue), and the async default forwards to the sync one.

{% hint style="info" %}
The gate fires **only** when a queued transaction would execute in a storefront different from the one it was enqueued in. Same-storefront purchases proceed without calling the delegate.
{% endhint %}

* Return `true` — the transaction proceeds in the new storefront.
* Return `false` — the transaction is discarded.

## Implement the gate

Assign a delegate to the queue (keep a strong reference — the delegate is held weakly):

```swift
Onside.defaultPaymentQueue().delegate = self
```

Use the `async` variant to confirm with the user before continuing:

```swift
extension StoreCoordinator: OnsidePaymentQueueDelegate {
    func onsidePaymentQueue(
        _ queue: OnsidePaymentQueue,
        shouldContinue transaction: OnsidePaymentTransaction,
        in storefront: OnsideStorefront
    ) async -> Bool {
        let newPrice = transaction.payment.product.price
        return await confirmPriceChange(
            to: newPrice,
            region: storefront.countryCode
        )
    }

    @MainActor
    private func confirmPriceChange(to price: OnsidePrice, region: String) async -> Bool {
        // Present an alert: "The price is now \(price.value) \(price.currencyCode)
        // for region \(region). Continue?" and return the user's choice.
        return await withCheckedContinuation { continuation in
            // ... present UI, resume with true/false ...
        }
    }
}
```

If you don't set a delegate, OnsideKit continues by default (as if you returned `true`).

## Related

* [Regions & Storefronts](/sdk/products-and-subscriptions/regions-and-storefronts.md) — how the region is resolved and why it can change
* [The Payment Queue & Transactions](/sdk/core-concepts/payment-queue.md) — the queue resets and notifies `onsidePaymentQueueDidChangeStorefront` when the storefront changes


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.onside.io/sdk/purchasing/storefront-price-changes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
