Skip to content

fix(ios): send one _makePurchase message per purchase attempt - #1020

Closed
vegaro wants to merge 1 commit into
mainfrom
cesar/fix-duplicate-purchase-error-message
Closed

fix(ios): send one _makePurchase message per purchase attempt#1020
vegaro wants to merge 1 commit into
mainfrom
cesar/fix-duplicate-purchase-error-message

Conversation

@vegaro

@vegaro vegaro commented Jul 28, 2026

Copy link
Copy Markdown
Member

What changed

purchaseProduct and purchasePackage sent the response to _makePurchase twice on failure — once inside the error branch, and again from the unconditional send after the if/else:

if (error) {
    ...
    [self sendJSONObject:response toMethod:MAKE_PURCHASE];   // first
} else {
    ...
}
[self sendJSONObject:response toMethod:MAKE_PURCHASE];       // second, always runs

Only the first delivery reaches the caller today, because _makePurchase clears MakePurchaseCallback before invoking it, so the duplicate is dropped by the null guard. The extra UnitySendMessage is still wasted work on the wrong contract. The two win-back offer handlers already had the correct single-send shape; this makes all four consistent.

Also in this PR

response[@"userCancelled"] = false appeared in three places. false is 0, so it boxes to nil, and assigning nil through an NSMutableDictionary subscript removes the key rather than storing it — the success payload shipped with no userCancelled field at all. Unity reads the missing key as false via SimpleJSON, so the behaviour was correct by accident. Replaced with @NO so the payload matches what PurchaseResult expects. purchasePackage already used @NO, which is what made the inconsistency visible.

Overlaps with #1008

#1008 rewrites these same lines for request-ID correlation and carries the double send unchanged. It will conflict with this PR, and the duplicate matters more there: once callbacks are consumed by request ID, the second message arrives as an unrecognised request rather than being dropped by a null check.

Verification

  • Compiles: archive-ios, archive-ios-cocoapods, build-integration-tests-ios and build-subtester-ios all pass on CI, so the plugin builds and links.
  • Runtime behaviour of a failed purchase — not covered.

No test in this repo exercises PurchasesUnityHelper.m at runtime, and Edit Mode tests do not compile the iOS plugin, so the single-send behaviour on a failed purchase is unverified. Worth a manual check in Subtester (cancel a purchase, confirm one _makePurchase log line) before this leaves draft.

🤖 Generated with Claude Code

purchaseProduct and purchasePackage sent the response twice when the purchase
failed: once inside the error branch and once from the unconditional send that
follows the if/else. Only the first delivery reached the caller, because
_makePurchase clears MakePurchaseCallback before invoking it, so the second
message was silently dropped. The win-back offer handlers already had the
correct single-send shape; this makes all four consistent.

Also replaces `response[@"userCancelled"] = false` with `@NO` in the three
places that used it. `false` is 0, so it boxed to nil, and assigning nil through
an NSMutableDictionary subscript removes the key instead of storing it — the
success payload was shipping without userCancelled at all. Unity read the
missing key as false, so the effect was invisible, but the payload did not match
what PurchaseResult expects.

Co-Authored-By: Claude <noreply@anthropic.com>
@RevenueCat-Danger-Bot

Copy link
Copy Markdown
1 Error
🚫 Label the PR using one of the change type labels. If you are not sure which label to use, choose pr:other.
Label Description
pr:feat A new feature. Use along with pr:breaking to force a major release.
pr:fix A bug fix. Use along with pr:force_minor to force a minor release.
pr:other Other changes. Catch-all for anything that doesn't fit the above categories. Releases that only contain this label will not be released. Use along with pr:force_patch, or pr:force_minor to force a patch or minor release.
pr:RevenueCatUI Use along any other tag to mark a PR that only contains RevenueCatUI changes
pr:next_release Preparing a new release
pr:dependencies Updating a dependency
pr:phc_dependencies Updating purchases-hybrid-common dependency
pr:changelog_ignore The PR will not be included in the changelog. This label doesn't determine the type of bump of the version and must be combined with pr:feat, pr:fix or pr:other.

Generated by 🚫 Danger

@vegaro

vegaro commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

closing in favor of #1042

@vegaro vegaro closed this Aug 6, 2026
@vegaro
vegaro deleted the cesar/fix-duplicate-purchase-error-message branch August 6, 2026 10:53
@vegaro vegaro added the pr:fix A bug fix label Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:fix A bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants