purchases-flutter
purchases-flutter copied to clipboard
Paid User status is lost after migrating from Legacy API Key to the new API Keys until calling restorePurchases()
SDK purchases_flutter 4.2.1 flutter 3.3.2
I'm migrating my apps from Legacy API Key to the New API Keys (Android and iOS) and I noticed that when a Paid Used updates to the new app version which uses de New API Keys, Revenue Cat does not recognize that user as a Paid User anymore. Only when I call Purchases.restorePurchases() the user is recognized as a Paid User again.
Example code, right after migrating from Legacy API Key to New API Keys:
CustomerInfo purchaserInfo = await Purchases.getCustomerInfo();
if (purchaserInfo.entitlements.active.isNotEmpty) {
print("@@@ paid user");
} else {
print("@@@ free user");
}
CustomerInfo restoredInfo = await Purchases.restorePurchases();
if (restoredInfo.entitlements.active.isNotEmpty) {
print("@@@ paid user (restored)");
} else {
print("@@@ free user (restored)");
}
Running the above code the first time gives me in the console:
@@@ free user
@@@ paid user (restored)
Running for the second time:
@@@ paid user
@@@ paid user (restored)
I don't know if its an intended behavior or just a bug, but it took me 3 days to figure it out, luckily before production. I've fully tested this code on Android and tonight I'm testing it on a physical iPhone device.
👀 SDKONCALL-124 We've just linked this issue to our internal tracker and notified the team. Thank you for reporting, we're checking this out!
@danieeelfc Hey! 👋 This is definitely a weird behavior that I don't think we would have expected 🤔
Question 1
Are you able to share you code around where you are configuring Purchases with the API keys both before and after your migration? I just want to make sure I'm seeing the whole picture 😇
Question 2 Do you know if you go from "new API Key" to "legacy API Key" if you observe the same behavior?
Thanks!
hey @joshdholtz ! Thanks for your reply!
Answer 1 Sure. This is the code before de migration:
await Purchases.setDebugLogsEnabled(true);
await Purchases.setup(kRevenueCatApiKey); //legacy
CustomerInfo purchaserInfo = await Purchases.getCustomerInfo();
if (purchaserInfo.entitlements.active.isNotEmpty) {
print("@@@ paid user");
setPaidUserStatus(true);
} else {
print("@@@ free user");
setPaidUserStatus(false);
}
After the migration:
await Purchases.setDebugLogsEnabled(true);
PurchasesConfiguration configuration;
if (Platform.isAndroid) {
configuration = PurchasesConfiguration(kRevenueCatGoogleApiKey);
} else if (Platform.isIOS) {
configuration = PurchasesConfiguration(kRevenueCatAppleApiKey);
}
await Purchases.configure(configuration);
CustomerInfo purchaserInfo = await Purchases.getCustomerInfo();
if (purchaserInfo.entitlements.active.isNotEmpty) {
print("@@@ paid user");
setPaidUserStatus(true);
} else {
print("@@@ free user");
setPaidUserStatus(false);
}
Answer 2
I've just tested it here to answer the question and the answer is no. If go from the new to the old API key, paid user status is kept.
Bonus Answer 😁
I've just run the code on an iPhone and the result is the same as Android.
@danieeelfc Thank you for doing all those tests! I tested going from legacy API key to new API key on native iOS and I was not able to replicate that behavior so it sounds like it may be something on the Flutter side but I haven't been able to replicate yet 🤔 I'll ask some questions to the rest of the team on Monday to see if anybody has any ideas!
@joshdholtz thanks for your effort!
Could it be something with my implementation?
Revenuecat docs are very straight-forward, but maybe I could be missing something.
I've tested migrating keys for one of my other apps and I get the same console output.
First time code is run:
@@@ free user
@@@ paid user (restored)
Second time:
@@@ paid user
@@@ paid user (restored)
@joshdholtz Any updates on this from your side?
@danieeelfc I have checked the same scenario in my app and looks like purchase previously made with legacy API key, was successfully recognized in the app with new Android API key. BTW, as a side note restorePurchases shouldn't be called during app launch according to Apple recommendations. User should initiate this operations manually - https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/restoring_purchased_products
Got the same issue after updating to the new API keys and migrating to version 4. Using the same code as @danieeelfc and my product is a non-subscription one (if that helps).
I have only gotten complaints from Android users until now. Restoring purchases seems to work, but it is still not optimal to have this issue.
RevenueCat dev team, looks like it requires your attention. Probably I haven't done thoughtful testing from my side. Taking into account that we have 2 incidents, we should investigate the root cause. Probably it is combination of migrating from old to new key together with updating flutter SDK from old version to the latest one?
I believe we are also experiencing this issue and hoping for a fix after updating to 4.X.X from 3.X.X .
We have reached out to RC support for a definitive answer but the most likely answer is probably going to be in this thread
can you reproduce this consistently?
I'm inclined to believe that issues here are either due to caching or to the migration path itself, but not to the API key, since the SDK is fairly agnostic of API keys - they're not stored, they just live in memory as a property, and aren't used to compare with previous values.
If you can reproduce this consistently, could you share debug logs? They'll likely tell us what's happening here (i.e.: is the SDK returning an out-of-date cached value, identifying the user to be a different user, etc)
@aboedo In my case, I wasn't able to reproduce it on my test devices. The 2 users who complained about it finally got it resolved after closing the app and using Restore Purchases again.
@whiplashoo thanks for the quick turnaround! In that case, any chance that these were users who haven't used the app in a while? If that's the case, perhaps they were getting an outdated cached value for customerInfo, and then when either reopening or using restore purchases they got an updated value.
If this is the case, the best way to protect against it is to use the customer info listener to know when there's a new version of customerInfo available.
When calling getCustomerInfo(), if there's a cached value, that one will be returned, and if it's outdated, the SDK will fetch a new version from the backend and send an update through the listener.
@aboedo we did a fresh install with the app so any cached values would be wiped out. We were still having the problem
We have started an RC support ticket #22469 and have not yet received a response.
That support ticket describes in detail the issue that we are experiencing (from a dev perspective)
I am a product manager and have asked the dev team to investigate further.
They are going to respond to the support ticket first and I have asked them to respond here if that does not help them.
They do not believe it to be a caching issue as they would have experienced before upgrading to flutter 4.X.X but that is an anecdotal summary of our previous discussion regarding the issue. It is also experienced whether they uninstall the app or not (and "clear cache" before uninstall does not have an impact).
Restore purchases does, in fact, restore purchases. However, there are many cases in which restore purchases cannot fix the issue including cross-platform purchases (purchase on Android and use on iOS) and customers that have purchased on STRIPE as restore purchases only works when they are on a platform device that made a purchase on the platform not for Android/iOS customers that purchased on STRIPE.
- It appears that syncpurchases being called on app open does not sync purchases at all after upgrading to 4.X.X
- Manually restoring purchases for every customer is not ideal, even if it worked in all cases (it doesn't).
- Restore purchases does not work in cross-platform cases. ~33% of our customers paid on STRIPE and we are unable to give them access after upgrading to 4.X.X. Customers that paid on Android and use the app on iOS are edge cases but also will be impacted.