> For the complete documentation index, see [llms.txt](https://docs.onside.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.onside.io/sdk/purchasing/storefront-price-changes.md).

# Handling Storefront & Price Changes

Approve or cancel a queued purchase when the storefront or price changes between enqueue and execution, using OnsidePaymentQueueDelegate.

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
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
