Registers a handler invoked when Encore’s offer flow completes and a purchase is needed. The handler receives a PurchaseRequest containing the product ID, placement ID, and optional promotional offer ID. Use it to trigger the purchase via your subscription manager (e.g. StoreKit, RevenueCat).
Set onPurchaseRequest before calling placement().show(). If not set, Encore will fall back to a native StoreKit purchase automatically. For best results with 3P subscription managers, set this handler to purchase through your provider directly.
Signature
public func onPurchaseRequest(_ handler: @escaping (PurchaseRequest) async throws -> Void) -> Encore
Parameters
| Name | Type | Description |
|---|
handler | (PurchaseRequest) async throws -> Void | Async throwing callback receiving a PurchaseRequest. Trigger your purchase flow here. |
PurchaseRequest Properties
| Property | Type | Description |
|---|
productId | String | The App Store product identifier to purchase |
placementId | String? | Which placement triggered this purchase, if any |
promoOfferId | String? | Promotional offer identifier to apply, or nil for standard purchases |
Returns
Returns the Encore instance for chaining.
When It Fires
| Scenario | Fires? |
|---|
| User accepts an offer | Yes |
| User dismisses without purchasing | No — see onPassthrough() |
| No offer available for this user | No — see onPassthrough() |
Usage
StoreKit
RevenueCat
Adapty
Qonversion
Custom
Encore.shared.onPurchaseRequest { purchaseRequest in
guard let product = try await Product.products(for: [purchaseRequest.productId]).first else { return }
let result = try await product.purchase()
// StoreKit 2 handles the rest
}
Encore.shared.onPurchaseRequest { purchaseRequest in
let products = try await Purchases.shared.products([purchaseRequest.productId])
guard let product = products.first else { return }
try await Purchases.shared.purchase(product: product)
}
Encore.shared.onPurchaseRequest { purchaseRequest in
let products = try await Adapty.getPaywallProducts(paywall: paywall)
guard let product = products.first(where: { $0.vendorProductId == purchaseRequest.productId }) else { return }
try await Adapty.makePurchase(product: product)
}
Encore.shared.onPurchaseRequest { purchaseRequest in
try await Qonversion.shared().purchaseProduct(productId: purchaseRequest.productId)
}
Encore.shared.onPurchaseRequest { purchaseRequest in
// purchaseRequest.productId — App Store product ID to purchase
// purchaseRequest.placementId — which placement triggered this (optional)
// purchaseRequest.promoOfferId — promotional offer to apply (optional)
try await yourManager.purchase(purchaseRequest.productId)
}
Chained with onPassthrough
Encore.shared
.onPurchaseRequest { purchaseRequest in
guard let product = try await Product.products(for: [purchaseRequest.productId]).first else { return }
let result = try await product.purchase()
}
.onPassthrough { placementId in
// User didn't purchase — continue original flow
proceedWithCancellation()
}
The handler is an async throws function, so you can call other async APIs (like StoreKit or network requests) directly inside it.
When no onPurchaseRequest handler is set, Encore handles purchases via native StoreKit 2 automatically.
Use onPurchaseComplete to sync these transactions with providers that don’t auto-detect StoreKit transactions (e.g., Adapty, Qonversion).