Skip to content

Conversation

tonidero
Copy link
Contributor

@tonidero tonidero commented Jul 15, 2025

Description

Upgrades/downgrades were not working after the changes in #2506. This fixes the issue and adds some tests to the relevant code to avoid it from happening again.

This should deal with #2531

@tonidero tonidero requested a review from a team July 15, 2025 17:41
@tonidero tonidero added the pr:fix A bug fix label Jul 15, 2025
Copy link
Member

@JayShortway JayShortway left a comment

Choose a reason for hiding this comment

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

Looks good! Just 2 questions.

Comment on lines +470 to +472
val purchasesRecordWrapper = purchasesByHashedToken.values.firstOrNull {
it.productIds.firstOrNull() == productId
}
Copy link
Member

Choose a reason for hiding this comment

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

2 questions:

  • How big can purchasesByHashedToken get?
  • Can multiple active purchases have the same product ID? Maybe not, because for that to happen the IAP has to be consumed, and if it's consumed, it's no longer active?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How big can purchasesByHashedToken get?

Shouldn't be big. It will be a map of every active subscription basically, but don't expect users to have more than 2-3 at most usually?

Can multiple active purchases have the same product ID? Maybe not, because for that to happen the IAP has to be consumed, and if it's consumed, it's no longer active?

Just answered in a different comment that I hadn't sent, but no, you can only have one active subs for each product, so this should be unique, if any is found.

@@ -1646,6 +1647,62 @@ class BillingWrapperTest {
assertThat(receivedError!!.code).isEqualTo(PurchasesErrorCode.StoreProblemError)
}

// region findPurchaseInActivePurchases
Copy link
Member

Choose a reason for hiding this comment

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

❤️

{ purchasesByProductId ->
val purchasesRecordWrapper = purchasesByProductId[productId]
{ purchasesByHashedToken ->
val purchasesRecordWrapper = purchasesByHashedToken.values.firstOrNull {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note this structure should only have at most one transaction per product Id. Google won't allow multiple active subs for the same product Id.

Copy link

codecov bot commented Jul 15, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 78.10%. Comparing base (370838c) to head (f6b88e2).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2532      +/-   ##
==========================================
+ Coverage   77.93%   78.10%   +0.17%     
==========================================
  Files         286      286              
  Lines       10572    10573       +1     
  Branches     1485     1485              
==========================================
+ Hits         8239     8258      +19     
+ Misses       1687     1668      -19     
- Partials      646      647       +1     

☔ View full report in Codecov by Sentry.
📢 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.

@tonidero tonidero merged commit 7b27dc4 into main Jul 15, 2025
14 checks passed
@tonidero tonidero deleted the fix-upgrades branch July 15, 2025 18:12
tonidero pushed a commit that referenced this pull request Jul 15, 2025
**This is an automatic release.**

## RevenueCat SDK
### 🐞 Bugfixes
* Fix upgrades/downgrades after BC8 update (#2532) via Toni Rico
(@tonidero)
### 📦 Dependency Updates
* [RENOVATE] Update build-dependencies (#2515) via RevenueCat Git Bot
(@RCGitBot)
* [RENOVATE] Update build-dependencies (#2472) via RevenueCat Git Bot
(@RCGitBot)

## RevenueCatUI SDK
### Paywallv2
#### 🐞 Bugfixes
* Make PaywallActivity not consume insets in Android 16+ (#2520) via
Toni Rico (@tonidero)

### 🔄 Other Changes
* Add CLAUDE.md (#2522) via Cesar de la Vega (@vegaro)
* Update kotlin version in README (#2524) via Cesar de la Vega (@vegaro)
* Increase compile/target SDK version to 35 (#2525) via Toni Rico
(@tonidero)
* Fix snapshot deployment (#2526) via Toni Rico (@tonidero)
* Update CircleCI android orb (#2521) via Toni Rico (@tonidero)
* [AUTOMATIC][Paywalls V2] Updates paywall-preview-resources submodule
(#2517) via RevenueCat Git Bot (@RCGitBot)
* Improve v9 migration docs (#2514) via Toni Rico (@tonidero)
* Bump AGP to 8.10.1 and Gradle to 8.14.2 (#2440) via Jaewoong Eum
(@skydoves)
* Fixes compilation of the CEC sample app. (#2512) via JayShortway
(@JayShortway)

Co-authored-by: revenuecat-ops <ops@revenuecat.com>
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