purchaseUpdatedListener
Fired when a purchase is successful or when a pending purchase is completed.
Duplicate Transaction Replays on iOS
StoreKit can replay the same unfinished transaction through more than one native path during a single connection session. By default, OpenIAP delivers one purchaseUpdated event per iOS transaction ID to purchase-success listeners, while still keeping distinct transactions separate. This prevents entitlement delivery from running twice for the same purchase.
For diagnostics, register the purchase update listener with dedupeTransactionIOS: false. The flag belongs to the purchase update listener only; purchase error listeners do not receive successful StoreKit transactions. Android ignores this iOS-only option.
Listener Setup
let subscription = OpenIapModule.shared.purchaseUpdatedListener(
{ purchase in
print("Purchase updated: \(purchase.productId)")
},
options: nil
)Registers a listener for successful purchase events.
Opt In to iOS StoreKit Replays
let subscription = OpenIapModule.shared.purchaseUpdatedListener(
{ purchase in
print("StoreKit replay or first delivery: \(purchase.id)")
},
options: PurchaseUpdatedListenerOptions(
dedupeTransactionIOS: false
)
)import OpenIap
let subscription = OpenIapModule.shared.purchaseUpdatedListener { purchase in
Task {
print("Purchase updated: \(purchase.productId)")
// Verify and deliver
if await verifyPurchaseOnServer(purchase) {
await deliverProduct(purchase.productId)
try await OpenIapModule.shared.finishTransaction(
purchase: purchase,
isConsumable: false
)
}
}
}
// Cleanup when done
OpenIapModule.shared.removeListener(subscription)Event Payload
The purchase event delivers a Purchase object containing transaction details.
Purchase Update Flow
- Receive Purchase object via listener
- Validate receipt with backend service
- Deliver purchased content to user
- Finish transaction with finishTransaction (handles acknowledgment on both platforms)
- Update application state