Skip to content

fix: attribute presented offering to queue-synced active purchases#3627

Open
ajpallares wants to merge 2 commits into
mainfrom
pallares/sdk-4373-cache-purchase-attribution-for-queue
Open

fix: attribute presented offering to queue-synced active purchases#3627
ajpallares wants to merge 2 commits into
mainfrom
pallares/sdk-4373-cache-purchase-attribution-for-queue

Conversation

@ajpallares

@ajpallares ajpallares commented Jun 18, 2026

Copy link
Copy Markdown
Member

Part of SDK-4373.

Motivation

When a just-purchased transaction is discovered via queryPurchases (synced as an unsynced active purchase) before or instead of the BillingClient purchase callback, its receipt is POSTed without the presented offering, showing up as "Unknown" offerings in charts.

Description

  • makePurchaseAsync stamps the in-memory PurchaseContext with an initiationDate.
  • queryPurchases results pass through a new attachCachedPurchaseContext helper that back-fills the cached presented offering context onto transactions missing one, guarded by purchaseTime >= initiationDate.

Limitation: the context cache is in-memory, so this only recovers attribution for the same-session race, not purchases synced in a later session.


Note

Medium Risk
Touches purchase/receipt attribution on the Google billing path; wrong time gating could mis-attribute offerings, but scope is narrow and guarded by initiation date and existing context checks.

Overview
Fixes Unknown offering attribution when a new Google Play purchase is synced via queryPurchases (unsynced active purchases) before the BillingClient purchase callback runs.

makePurchaseAsync now records initiationDate on the in-memory PurchaseContext. queryPurchases passes results through attachCachedPurchaseContext, which copies the cached context (including presented offering) onto transactions that lack it, only when purchaseTime >= initiationDate so older purchases are not mis-tagged.

Recovery is same-session only because the cache is in-memory.

Reviewed by Cursor Bugbot for commit 2501a1c. Bugbot is set up for automated code reviews on this repo. Configure here.

…hases

When a purchase is initiated through the SDK, the pending-purchase sync
path (queryPurchases) could post the transaction with
`unsynced_active_purchases` and no presented offering context before the
normal purchase-completion path ran, causing "Unknown" offerings in
charts (SDK-4373). PurchaseContext now records the purchase-intent date,
and queryPurchases attaches the cached presented offering context to a
returned transaction when its product id matches and its purchase time is
at or after the intent date.

Co-authored-by: Cursor <cursoragent@cursor.com>
@ajpallares ajpallares added the pr:fix A bug fix label Jun 18, 2026
@ajpallares
ajpallares marked this pull request as ready for review June 19, 2026 11:49
@ajpallares
ajpallares requested a review from a team as a code owner June 19, 2026 11:49
@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.66667% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.24%. Comparing base (354ae2e) to head (2501a1c).
⚠️ Report is 22 commits behind head on main.

Files with missing lines Patch % Lines
.../com/revenuecat/purchases/google/BillingWrapper.kt 64.28% 2 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3627      +/-   ##
==========================================
- Coverage   80.25%   80.24%   -0.02%     
==========================================
  Files         379      379              
  Lines       15530    15544      +14     
  Branches     2163     2167       +4     
==========================================
+ Hits        12464    12473       +9     
- Misses       2202     2204       +2     
- Partials      864      867       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ajpallares
ajpallares requested review from a team and tonidero June 19, 2026 11:50
@ajpallares

ajpallares commented Jun 19, 2026

Copy link
Copy Markdown
Member Author

I'm thinking that in order not to introduce misattributions with this PR, we need to merge #3165 first. This other PR wasn't really needed by itself, but this PR makes it important to avoid adding the attribution from a cancelled purchase. WDYT @RevenueCat/coresdk?

@tonidero tonidero left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks good! Just a possible missing test.

Regarding the other PR. I think it wouldn't be bad to add it indeed... We've confirmed the behavior correct? If so I think it makes sense. I would just see if we need to address the existing comment (I've lost context on that PR TBH)

}

@Test
fun `queryPurchases does not attach cached presented offering context when purchase time is before initiation date`() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also have a test for when there is a cached context for a different productId? (Shouldn't attach I think)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh true. Good call!

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