RevenueCat / purchases-ios

In-app purchases and subscriptions made easy. Support for iOS, watchOS, tvOS, macOS, and visionOS.
https://www.revenuecat.com/
MIT License
2.36k stars 319 forks source link

Rounding error in pricePerYear, pricePerMonth and similar variants #4246

Closed wilfredbtan closed 1 month ago

wilfredbtan commented 2 months ago

Describe the bug There seems to be a rounding issue for prices such as $19.99 and $1.99. Furthermore, there is inconsistent formatting between localizedPriceString and the localizedPricePerYear variants.

  1. Environment
    1. Platform: iOS
    2. SDK version: 5.3.2
    3. StoreKit version:
      • [] StoreKit 1
      • [x] StoreKit 2 (enabled with usesStoreKit2IfAvailable(true))
    4. OS version: 17.6.1
    5. Xcode version: 15.1
    6. Device and/or simulator:
      • [x] Device
      • [ ] Simulator
    7. Environment:
      • [x] Sandbox
      • [ ] TestFlight
      • [ ] Production
    8. How widespread is the issue. Percentage of devices affected.
  2. Debug logs that reproduce the issue. Complete logs with Purchases.logLevel = .verbose will help us debug this issue.
Logs here
  1. Steps to reproduce, with a description of expected vs. actual behavior

I have an annual subscription priced at $19.99/year, when using localizedPriceString (e.g. yearlyPackage.storeProduct.localizedPriceString), it is displayed as "S $19.99" (with the S infront). However, when I use localizedPricePerYear, the displayed string is "$19.98" (without the S and a rounding error in the last cent).

The same issue occurs for my monthly subscription priced at $2.99. That is, using localizedPricePerYear on my monthly package is displayed as "$2.98" (with the last cent rounded wrongly)

I can't simply use localizedPriceString for all my products because I intend to show the localizedPricePerMonth for my annual subscription to aid the user in comparing my annual and monthly prices.

Thus it's a bit inconvenient if both are formatted differently.

  1. Other information (e.g. stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, etc.)

I suspect this may be due to the way that pricePerYear is calculated, particularly the rounding down behaviour here: https://github.com/RevenueCat/purchases-ios/blob/0d112d084e13faea89160577dfa086124a7504aa/Sources/Purchasing/StoreKitAbstractions/SubscriptionPeriod.swift#L154

  1. Additional context So far I've only noticed this in the Singapore locale in SGD but I have yet to test other locales.

I also tried this workaround but it doesn't work as well:

let localizedMonthlyPriceString = yearlyPackage.storeProduct.priceFormatter?.string(from: yearlyPackage.storeProduct.pricePerMonth)
RCGitBot commented 2 months ago

👀 We've just linked this issue to our internal tracker and notified the team. Thank you for reporting, we're checking this out!

Br1tBreaker commented 2 months ago

Right, sounds like you've stumbled across a bit of a wonky glitch in the Purchases SDK, mate. Inconsistent formatting and rounding errors? That's a proper nuisance when you're trying to give your users a clear picture of your pricing.

It's smart that you're looking into the pricePerYear calculation in the SDK's code. That rounding down behaviour could definitely be the culprit behind those pesky cent discrepancies.

You're spot on about not being able to rely solely on localizedPriceString for everything. Showing the localizedPricePerMonth for annual subscriptions is a crucial bit of transparency for users.

The Singapore locale issue is interesting, but don't assume it's isolated. Definitely test other locales and see if the problem crops up elsewhere.

As for that workaround... yeah, sometimes those quick fixes don't quite hit the mark. It's good you tried, though.

Here's the deal: you've done your due diligence, mate. You've updated the SDK, checked the docs, scoured the community, and even poked around in the code. This bug deserves some attention from the RevenueCat crew.

Hit up their support team or submit a detailed bug report on GitHub. Include all the info you've got here: environment details, steps to reproduce, expected vs. actual behaviour, and those insightful code snippets. The more info you provide, the quicker they can get to the bottom of it and roll out a fix.

In the meantime, you might have to get a bit creative with your UI or consider temporarily tweaking your pricing display to avoid confusion for your users.

Keep your chin up, bruv. You'll get this sorted.

tonidero commented 1 month ago

Hi @wilfredbtan, many thanks for reporting this!

We've worked on a fix in #4275, which should have been released in 5.3.4? Please let us know if that works!

wilfredbtan commented 1 month ago

Thanks for fixing this. It works perfectly now :D

tonidero commented 1 month ago

Nice! Thanks for letting us know! Will close this issue but feel free to reopen if needed