RevenueCat / purchases-capacitor

Capacitor in-app purchases and subscriptions made easy.
MIT License
155 stars 15 forks source link

Calling getCustomerInfo directly after a purchase is made returns pre-purchase cached data #265

Open benmarsh opened 6 months ago

benmarsh commented 6 months ago

Hi,

In our app we have a "boot sequence" which, amongst other things, checks that they have an active subscription. After a purchase is made, we run through the sequence again, the expectation being that it should now see the granted entitlement.

The active subscription check is based on a Purchases.getCustomerInfo() call and does not directly use the MakePurchaseResult data returned from the successful Purchases.purchaseStoreProduct() call.

It appears that the cached CustomerInfo isn't being updated/invalidated after the purchase has been made so when we run through the boot sequence again the cached CustomerInfo doesn't show the entitlement it should.

We've added a Purchases.invalidateCustomerInfoCache() call after the purchase has been made but this doesn't always appear to be successful (or maybe have completed?) before we check again for the entitlement via Purchases.getCustomerInfo().

We could add a workaround to this; skip any entitlement check for the rest of the app session after a purchase has been made, or cache the CustomerInfo ourselves (again possibly for 5 minutes) until we know that the cached data should have expired.

Happy to run up a demo of this if required, but maybe the above is enough of a description of the issue.

Thanks.

RCGitBot commented 6 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!

mshmoustafa commented 6 months ago

Hey @benmarsh, Some debug logs that reproduce this would be helpful because the customer info should be updated as soon as the purchase goes through. That being said, maybe there is a delay in the purchase process itself. I have two suggestions:

  1. When you call purchaseStoreProduct, even if you don't use the result, you can use it as a notification that the purchase has completed and check the customerinfo at that time. Are you already doing that, and if so, are you still running into a stale cache?
  2. Try calling getCustomerInfo a couple times. If the cache is stale, the first call returns the stale cache and updates it. The second call should give you the fresh cache. What happens when you do this?
  3. You may want to implement a listener so you'll get notified as soon as the customerinfo is updated: https://www.revenuecat.com/docs/getting-started/configuring-sdk#android
WesleyClarkRC commented 6 months ago

Hi @benmarsh, Just wanted to follow up to see if this is still impacting you and if you were able to retrieve the debug logs from when you recreate it

benmarsh commented 6 months ago

Hi, so yes we're still seeing issues with this - I'm still working on getting some debug logs with various examples of our workflow.

What appears to be causing our problem is that calling Purchases.getCustomerInfo() returns the older stale version of the object whilst in the background requesting a newer version. Previously however our experience of the behaviour has been that (if caching existed?) that a stale object wouldn't be immediately returned and instead we'd just wait for a fresh version from the server via a promise.

One scenario where we notice this is when a subscription expires outside of the app. Starting up the app after this time (incorrectly?) allows the user access to our app - as we're getting the stale "subscribed" customerInfo. In the background it appears to get updated after this point as if you then quit the app and reopen it then correctly goes to our paywall.

Our biggest problem here though is with purchasing of subscriptions - in some cases what was happening is that a user would purchase a subscription, the app would then check entitlements via Purchases.getCustomerInfo() which would return a stale cached version with the new entitlements missing, and as such the user wouldn't navigate forward from the paywall. Quitting the app and relaunching at this point allowed the users in, but in some cases users mistakenly purchased an additional subscription as they believed the first hadn't been successful.

For now I've added functionality that bypasses the subscription check when a new purchase is made, this gets new users correctly into the app whist the customerInfo is updated from the server.

I need to look into where this change began appearing in our app - we started off with the Cordova version of the SDK and moved to the Capacitor one, and we've been more frequent in updating the Capacitor SDK to the latest, most recently from 7.5.2 to 7.5.10.

If you have any comments on the above it would be great to hear them, otherwise I'll see if I can get some scenarios to replicate with debug logs enabled and will post those back here when I have them.

WesleyClarkRC commented 5 months ago

Hi, thank you for the further context. I am glad to hear that you have a workaround currently. The debug logs would be best in terms of us identifying the issue. Just for my clarification, in your current workflow, are you using the returning of the result as a notification in order to call the getCustomerInfo?