Skip to main content
Question

GetCustomerInfo is returning old data, unless called twice?


Forum|alt.badge.img+4

Hi,

While testing my subscriptions on IOS with a sandbox account i found a strange behaviour of getCustomerInfo(), needing to call it twice in order to get the correct data.

The way i’ve set my app is to call getCustomerInfo on appLaunch and on appResume, to check for updates. The scenario is the following:

I purchase a subscription and get back info that the entitlement is active and my expirationDate is 5min from now (because of the sandbox account). Then i minimize the app and wait 6 mins, after which i can see the sub renewal transaction appearing in rc dashboard and in the customer details screen. I open the app, which triggers getCustomerInfo, but it’s returning the same data i got from when i first purchased the sub. Then when i minimize the app and open it again, triggering getCustomerInfo for the 2nd time, it return the correct updated data with the new expirationDate.

Is this the expected behaviour? Is this because of Sandbox? Or am i doing something wrong?

P.S. it’s a flutter app, if it makes any difference.

18 replies

imougy
Forum|alt.badge.img+9
  • Active Helper
  • 94 replies
  • September 16, 2022

Where do you init the SDK?  My recommendation is to init the SDK a bit late, not on appLaunch (btw, I am not familiar with Flutter).  In my app, I init the SDK when I create the tab controller (viewDidLoad).  I used to init the SDK on didFinishLaunchingWithOptions and that caused all kind of random issues, thanks to Apple recent iOS startup change in iOS 15.  

Please try and let us know.

Thanks,


Forum|alt.badge.img+4
  • Author
  • New Member
  • 2 replies
  • September 23, 2022

Hi @imougy ,

I tried to initialize it late in the app after everything else is loaded and the initial screen is rendered, but i still get the same issue.. I am not sure if this has to do something with the flutter SDK or the caching thats done for getCustomerInfo() or because of sandbox, but it’s really making it unreliable. Easiest way to reproduce is:

  1. Purchase a subscription
  2. Minimize app
  3. Cancel the purchased subscription from the app store manage subs page
  4. Wait for the subscription to expire (in my case for ios sandbox monthly sub is 5 mins)
  5. Open the app,
  6. Call getCustomerInfo() - nothing is changed user’s subscription is still active
  7. Minimize the app
  8. Open it again
  9. Call getCustomerInfo() again - this time correct information is retrieved and user sub is not active

 


Forum|alt.badge.img+1
  • New Member
  • 2 replies
  • October 28, 2022

Was there ever a true solution to this, the exact same thing is happening for me (build is in apples sandbox environment for storekit). Calling ‘get customer info’ ‘later’ isn’t really going to cut it. Surely the update of stale cache data needs to be within a closure or something similar so we can update our users subscription status following the asynchronous call by revenue cat on initial app load.

I’ve outlined a timeline of how I see it from a mixture of revenue cat debug logs and my own print statements

  1. Revenue cat config and debug settings are applied via appDelegate and initial Revenue cat pull is initiated as stated in debug messages:

2022-10-28 15:45:35.134382+0200 Vocable[26790:2040491] [Purchases] - DEBUG: 👤 Identifying App User ID

<NON RELEVANT DEBUG LOGS REMOVED FOR BREVITY>


2022-10-28 15:45:35.240780+0200 Vocable[26790:2040491] [Purchases] - DEBUG: ℹ️ Vending CustomerInfo from cache.

  1. Below two lines are printing from my landing VC model from which the users subscription status is set using method :- Purchases.shared.getCustomerInfo { (customerInfo, error) in

YEARLY SUB EXPIRATION 28 Oct 2022 at 14:41:07
MONTHLY SUB EXPIRATION 28 Oct 2022 at 15:25:21

**Following these print statements (print statements formatted by myself and not RC’s debug logs) my users subscription status is set and the user advances.

  1. Revenue cat completes update of stale data and updates cache:

<NON RELEVANT DEBUG LOGS REMOVED FOR BREVITY>

2022-10-28 15:45:42.576591+0200 Vocable[26790:2040724] [Purchases] - DEBUG: ℹ️ API request completed: GET /v1/subscribers/$RCAnonymousID:edc791d7aa324f34a3fe54122c96d71f 304
2022-10-28 15:45:42.623087+0200 Vocable[26790:2040724] [Purchases] - DEBUG: ℹ️ Sending latest CustomerInfo to delegate.
2022-10-28 15:45:42.623206+0200 Vocable[26790:2040724] [Purchases] - DEBUG: 😻 CustomerInfo updated from network.
2022-10-28 15:45:42.625030+0200 Vocable[26790:2040724] [Purchases] - DEBUG: 😻 CustomerInfo updated from network.

 

Unfortunately by the time the local cache has been updated my user is logged in and has access to premium features even though their subscription has expired (upon close and open of app or another get status the correct subscription status is offered from the cache).

It would be far better if we could utilize a closure on the initial update of stale cached data before allowing the user to advance.

Hopefully there is a simple solution to this that I’m missing.


imougy
Forum|alt.badge.img+9
  • Active Helper
  • 94 replies
  • October 28, 2022

This seems an issue and solution is not delaying the init unfortunately. 
the good news is of course things settle down after a while. I understand you want instant reflection of the purchase status but it seems a lower status bug in the SDK.


Forum|alt.badge.img+1
  • New Member
  • 2 replies
  • October 28, 2022

Is there a ways to initiate an observer for successful completion of data update, I could at least update the UI if needed?


imougy
Forum|alt.badge.img+9
  • Active Helper
  • 94 replies
  • October 28, 2022

Since we are talking about workarounds, have you tried calling the getCustomerInfo twice, put a delay so the second call is executed after 1 second or so?

I don’t like workarounds like this but if it works, well!


Chris-29
Forum|alt.badge.img+5
  • Dedicated Member
  • 19 replies
  • February 6, 2023
LeonLabs wrote:

Is there a ways to initiate an observer for successful completion of data update, I could at least update the UI if needed?

 

So I was hitting this exact scenario. When the app was launched after the sub had expired I saw RC realize it and start a network request:

[Purchases] - DEBUG: ℹ️ applicationDidBecomeActive

BEFORE the network request is complete my code in the onAppear calls Purchases.shared.getCustomerInfo and gets back cached data.

[Purchases] - DEBUG: ℹ️ Vending CustomerInfo from cache.

Then the network request completes with the updated data (that nothing was using yet). When I minimized my app again and launched it for the second time the onAppear saw this new data instead of the old cached data.

The way I got around this was by adding more logic to the didSet for the customerInfo in UserViewModel. I was looking specifically for the expiration date so I had my logic do its magic with the newest value when customerInfo changes.


Forum|alt.badge.img+2
  • New Member
  • 2 replies
  • February 21, 2023

I am having the same issue in flutter: even after waiting more than 5 minutes after the subscription has expired (manually cancelling the test subscription in Google Play, then wait e.g. 10 minutes), the first call to getCustomerInfo still returns that the subscrition is active. Only the second attempt makes it work… What are we missing here?

Thanks!


@Bence Blaske I am having the exact same issue in Flutter. No matter how many times I delete and reinstall the app, whenever I install my app from Google Play Store, First run is active no matter what I do. I couldn’t check if this issue is also happening for other users or not. But basically, 5 min cache is kinda dangerous for my app, reaching the premium once in my app is worst thing ever because then they would probably delete the app.


Forum|alt.badge.img

@user_v431f41 @Bence Blaske I was the same issue for a while and even the workarounds didn’t help, after searching in the flutter plugin I found this

Purchases.invalidateCustomerInfoCache();

it basically makes the customer info cache invalid so on the next getCustomerInfo call it is certain that the latest object is retrieved from RC backend, I think this is the optimal solution


vic-a563d7
Forum|alt.badge.img+6
  • Dedicated Member
  • 44 replies
  • November 20, 2023

Running into the same issue with react native and invalidateCustomerInfoCache() just does not resolve. And relaunching the app just makes everything stop working (cant even call getCustomerInfo() anymore).

Has anyone found a better solution? Or is there a way NOT to use the cache? I am ok to have getCustomerInfo() call the servers each time since I have my own “cache” based on back-end + webhooks.


Forum|alt.badge.img+3
  • Active Member
  • 13 replies
  • November 23, 2023

@vic-a563d7 I encountered the same issue on Android and this solved it for me:

Purchases.sharedInstance.getCustomerInfoWith(    onSuccess = {            },    onError = {            },    fetchPolicy = CacheFetchPolicy.FETCH_CURRENT)

 

The default behavior is CACHED_OR_FETCHED - returns the cached data if available (even if stale). If not available, fetches up-to-date data. If cached data is stale, it initiates a fetch in the background.

 

(Thanks to my colleague Laurentiu for the tip)


vic-a563d7
Forum|alt.badge.img+6
  • Dedicated Member
  • 44 replies
  • November 25, 2023

Thanks @Radu S , which SDK is this? I am using the react native one and I don’t see a way to force the fetch to be “current”.. I assume this means get it from network always and avoid the cache?


Forum|alt.badge.img+3
  • Active Member
  • 13 replies
  • November 28, 2023
vic-a563d7 wrote:

Thanks @Radu S , which SDK is this? I am using the react native one and I don’t see a way to force the fetch to be “current”.. 

Android SDK. Sorry, I assumed the option is available for react native too.

 

vic-a563d7 wrote:

I assume this means get it from network always and avoid the cache?

Yes


vic-a563d7
Forum|alt.badge.img+6
  • Dedicated Member
  • 44 replies
  • November 28, 2023

Got it. I don’t think this is available in the react native SDK.. Not sure who can confirm..


  • New Member
  • 1 reply
  • August 1, 2024
fethi-hamdani wrote:

@user_v431f41 @Bence Blaske I was the same issue for a while and even the workarounds didn’t help, after searching in the flutter plugin I found this

Purchases.invalidateCustomerInfoCache();

it basically makes the customer info cache invalid so on the next getCustomerInfo call it is certain that the latest object is retrieved from RC backend, I think this is the optimal solution

Damn this fixed the issue! Right after some payment change you just call this and it will get the correct customer info right away, no delay. Thanks!


Forum|alt.badge.img+3
  • Helper
  • 4 replies
  • October 10, 2024
myboy wrote:
fethi-hamdani wrote:

@user_v431f41 @Bence Blaske I was the same issue for a while and even the workarounds didn’t help, after searching in the flutter plugin I found this

Purchases.invalidateCustomerInfoCache();

it basically makes the customer info cache invalid so on the next getCustomerInfo call it is certain that the latest object is retrieved from RC backend, I think this is the optimal solution

Damn this fixed the issue! Right after some payment change you just call this and it will get the correct customer info right away, no delay. Thanks!



Fixed my issue as well! Especially when needing to refresh the user cache after a receipt post from stripe that grants them the entitlement. Thanks!


Forum|alt.badge.img+2
  • New Member
  • 1 reply
  • November 5, 2024
fethi-hamdani wrote:

@user_v431f41 @Bence Blaske I was the same issue for a while and even the workarounds didn’t help, after searching in the flutter plugin I found this

Purchases.invalidateCustomerInfoCache();

it basically makes the customer info cache invalid so on the next getCustomerInfo call it is certain that the latest object is retrieved from RC backend, I think this is the optimal solution

this fixed the issue! Right after some payment change you just call this and it will get the correct customer info right away Thanks!


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings