Fix exit offer crash in MY_APP mode with PurchaseLogic#6391
Merged
Conversation
When `purchasesAreCompletedBy` is set to `.myApp`, the PaywallView requires `performPurchase` and `performRestore` handlers to be provided. The exit offer PaywallViewController was being created with `nil` for both handlers, causing a fatal error when the user dismissed the paywall and an exit offer was configured. This change captures the parent controller's handlers from its PurchaseHandler and passes them through to the exit offer controller, following the same pattern already used for delegate, dismiss handler, fonts, and touch blocking configuration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5 tasks
rickvdl
reviewed
Mar 4, 2026
rickvdl
left a comment
Member
There was a problem hiding this comment.
Fix itself looks good to me, but I don't really understand how this could cause a crash? Maybe an assertion that checked if the custom logic was provided when PACB: myApp?
Contributor
Author
@rickvdl That's pretty much it... Basically it threw an error that displayed a DebugErrorView, that actually crashes on release: |
rickvdl
approved these changes
Mar 4, 2026
tonidero
added a commit
to RevenueCat/purchases-unity
that referenced
this pull request
Mar 11, 2026
…CompletedBy.MyApp` (#842) ## Summary - Add `PurchaseLogic` parameter to paywall presentation, allowing customers in `PurchasesAreCompletedBy.MyApp` mode to handle purchases and restores themselves through the paywall UI - New public types: `PurchaseLogic` (with `PerformPurchaseHandler` and `PerformRestoreHandler` delegates) and `PurchaseLogicResult` enum - Optional `purchaseLogic` parameter added to all `PaywallOptions` constructors - Uses existing `HybridPurchaseLogicBridge` from purchases-hybrid-common on both platforms - Subtester: adds a "Paywall w/ PurchaseLogic" button that calls `PurchasePackage` within the handler ### Android-specific - Dialog uses `FLAG_NOT_FOCUSABLE` to prevent Unity's message processing from breaking after `ProxyBillingActivity` (Google Play billing) lifecycle transitions - `AndroidJavaProxy.Invoke` override handles method dispatch as Unity's proxy matching doesn't always resolve direct C# methods - `SynchronizationContext` captured at setup time to ensure async continuations run on the main thread ### iOS-specific - Uses `PaywallProxy.presentPaywall(options:purchaseLogicBridge:paywallResultHandler:)` - Updated non-PurchaseLogic path to use the non-deprecated API with `nil` bridge ### Related PRs - RevenueCat/purchases-ios#6391 — Fix exit offer crash in MY_APP mode (required for exit offers to work with PurchaseLogic) ## Test plan - [ ] Present paywall with `PurchaseLogic` on Android — purchase, cancel, and error flows - [ ] Present paywall with `PurchaseLogic` on iOS — purchase, cancel, and error flows - [ ] Present paywall WITHOUT `PurchaseLogic` — verify no regression on both platforms - [ ] Verify back button / dismiss works on both platforms - [ ] Test with exit offers (requires purchases-ios#6391) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
purchasesAreCompletedByis set to.myAppPaywallViewControllerwas created withperformPurchase: nilandperformRestore: nil, but in MY_APP mode these handlers are required otherwise, it fails to display with a crash.performPurchase/performRestorehandlers to the exit offer controllerTest plan
purchasesAreCompletedByto.myAppperformPurchaseandperformRestorehandlers🤖 Generated with Claude Code
Note
Medium Risk
Touches paywall dismissal/exit-offer presentation and purchase execution closures; a small change but it affects the purchase flow in
.myAppmode and could impact exit-offer behavior if the wrong handlers are propagated.Overview
Fixes an exit-offer presentation crash when
Purchasesis configured with.myApppurchase completion by passing through the existingperformPurchase/performRestoreclosures to the exit-offerPaywallViewControllerinstead of constructing it withnilhandlers.This ensures the exit-offer paywall can initiate purchases/restores using the same app-provided logic as the original paywall.
Written by Cursor Bugbot for commit f7e777b. This will update automatically on new commits. Configure here.