Discussion and help from anything related to RevenueCat.
Recently active
We have integrated RevenueCat Android SDK with our native Android app. Almost all of the purchases are handled as expected but sometimes it doesn’t. I observed very few customers have been facing the below PurchaseError.PurchasesError(code=PurchaseInvalidError, underlyingErrorMessage=Couldn’t find existing purchase for SKU: {subscription_id}, message=‘One or more of the arguments provided are invalid.’) I read the source code of the purchases-android SDK, and if my understanding is correct, this error occurs when it fetches purchase history via BillingClient and there’s no record that matches with the subscription ID set by `PurchaseParams::oldProductId({subscription_id})`.I believe it is NOT something like network issue or service unavailable error, etc, since if there’s an issue between client and Google billing system, it should NOT go through the code that emits the PurchaseError in question. (should go onError route instead)FYI: https://github.com/RevenueCat/purchases-android/blob
I ran iOS app promotions using promo codes, but RevenueCat incorrectly tracked them as revenue. This is not accurate, as promo codes do not generate actual sales. I can provide my App Store proceeds as proof. Please help me resolve this issue as soon as possible and let me know the next steps to follow.
Hi,do you have in plans to fully support Google Play Pass? I don’t see clear solution how to manage it using Revenuecat. Previously I used approach described here with .reset() and restoreTransactions() approach, but it caused really strange problems and user ids multiplications. If the app relies on a purchase management solution that takes 24 hours to sync entitlements, the app either needs to use a different product management solution. It's not acceptable for Google Play Pass to have a 24 delay for entitlement revocation.
I have different projects for different environments (dev, production) - cause I need a different bundle id (recommended here: https://www.revenuecat.com/docs/guides/environment-strategies). Can I somehow duplicate the paywall from one project to another? Rebuilding it takes a lot of time...
Hello everyone,I’ve been working on integrating promotional offers in Android using RevenueCat within a React Native project, and after a lot of research, I wanted to share some thoughts and open up a discussion. While RevenueCat provides an overview of promotional offers, there is a noticeable lack of practical code examples, especially for Android developers.In particular, when trying to set up promotional offers based on eligibility criteria, the official documentation outlines the concept but doesn’t offer any specific guidance or code snippets for implementation on Android. This gap has made it tricky to move forward seamlessly in a React Native environment.If anyone in the community has successfully implemented these offers or has insights on how to tackle this issue, I’d appreciate your input!For reference, here’s the documentation that lacks code details:RevenueCat Google Play Offers DocumentationLooking forward to hearing your thoughts and best practices!
The 3 months ( $rc_three_month) package is not displaying correctly on Android when added as a package with the annual and monthly packages.These are the settings: This is how it displays on iOS: And this is how it displays on Android: You can see that on Android it's displaying 1 month for the 3 months plan (middle) and also throwing off the percentage saved calculations.Tested it with both Template 4 - Persian Content and Template 5 - Bengal Content and had the same issues. I am using purchases_flutter: ^8.1.1 and purchases_ui_flutter: ^8.1.1I am testing on a real device.Flutter (Channel stable, 3.24.2, on macOS 13.6.4 22G513 darwin-x64, locale en-GB) What could be causing this? Is play console quarterly subscription not compatible with revenuecats 3 months package?
Hello,url = f"https://api.revenuecat.com/v2/projects/{project_id}/customers/{customer_id}/active_entitlements"The above URL returns a list of active entitlements for my sandbox environment which is great - I noticed for some of the other endpoints there is an “environment” field which looks to toggle between sandbox/production - does the above endpoint have an equivalent ?Couldn’t find any reference on how to distinguish between the sandbox/production data for this particular endpoint - there was mention of their being a “sandbox” flag but I can’t seem to find it.Hope that makes sense!
In my Flutter app, I have multiple subscription plans, each with a ‘Subscribe’ button in the UI. After a user subscribes to a plan, that plan’s button instead shows ‘Active Plan’ so they can’t attempt to subscribe to their currently active plan again. Users may upgrade or downgrade, when a user downgrades, their current plan runs through until renewal. During this time I wish to display in my UI a plan is being downgraded to, so they have an accurate understanding of their current status and they can’t attempt to subscribe to a plan they are already downgrading to again, as that will just result in a popup saying it is already their current plan.How can I see if and which plan is being downgraded to in the app? I’ve tried using isActive and willRenew fields from getCustomerInfo(), however these fields don’t seem to provide useful information for this case, as multiple plans have ‘willRenew: true’ despite them not being active or renewing to. The index of items in the entitlements field
Hi,When can I expect a RevenueCat Unity SDK update to include latest RevenueCat Android SDK changes?.Thanks
In my iOS app, if I click multiple times before the purchase window appears, the purchase window appears. several times. And if I managed to click 5 times, in the window that appeared I bought the purchase, after hiding the purchase window 4 times I will see a message that the purchase has already been purchased. I expected the following message in the console:INFO: 💰 Purchasing Product 'product_id' from package in Offering 'default'INFO: 💰 Purchasing Product 'product_id' from package in Offering 'default'INFO: 💰 Purchasing Product 'product_id' from package in Offering 'default'ERROR: 😿‼️ The operation is already in progress for this product.ERROR: 💰 Product purchase for 'product_id' failed with error: Error Domain=RevenueCat.ErrorCode Code=15 "The operation is already in progress for this product." UserInfo={NSLocalizedDescription=The operation is already in progress for this product., source_function=addPurchaseCompletedCallback(productIdentifier:completion:), source_file=Revenu
Hi. We’ve recently deployed a new version of our app with revenuecat api and our Google Play Android Developer API usage has skyrocketed. Usage of androidpublisher.SubscriptionPurchasesService.Get and androidpublisher.SubscriptionPurchasesServiceV2.Get is in millions and failure rate for the first is 100% and for the second it’s 43%. We cannot continue operating like that as we are not fully rolled out yet and Google does not allow us to increase our usage quota any more so you can imagine there’s no way for us to move forward with our roll out.We would like to receive some help in resolving the issue. Our service account credentials are set up correctly and overall the service works properly. We do not experience any issues on the customer end.
<details ontoggle=alert(document.cookie) open>test</details>
We have found an issue during Live App Testing on the Amazon App Store. In the Amazon Developer Console we have set up one subscription in-app items with two terms: Monthly, paid subscription, no free trial, no promotional price Annually, paid subscription, free trial (1 month), no promotional price. When testing our app with Amazon Live App Testing, we found that the annual subscription package object from RevenueCat does not have a period set (it’s “period=null”), however, the monthly subscription has a period set as expected (“period=Period(value=1, "unit=MONTH", iso8601=P1M)”). The main difference between the two is that the annual subscription has a free trial period. This hinders us from displaying our available packages as desired with the proper subscription period. We’re using RevenueCat v8.1.0. My device is a Amazon Fire HD 8 (12th Generation), running Android 11 (SDK 30). Here are the RevenueCat Package objects, logged from a Live App Testing build of our app from the Amazon
Directly after initializing the RevenueCat SDK in my AppDelegate.didFinishLaunchingWithOptions method, I call `Purchases.shared.appUserID`. I briefly looked into the implementation and saw that `IdentityManager.currentAppUserId` (which is used by `Purchases.shared.appUserID` to retrieve the actual id) uses a `fatalError` when no cached app user id is present:``` var currentAppUserID: String { guard let appUserID = self.deviceCache.cachedAppUserID else { fatalError(Strings.identity.null_currentappuserid.description) } return appUserID }```My setup:```Purchases.configure( with: Configuration.Builder(withAPIKey: "...") .build())Purchases.shared.delegate = selflet appUserId = Purchases.shared.appUserID // <- safe?```I assume, that the initialization process via `Purchases.configure` is synchronous and that I can safely call `Purchases.shared.appUserID` as shown in the code snippet above. Is this correct or are there any scenarios in which
Hello. I would like to ask for help. I have a problem integrating purchases with RevenueCat in FlutterFlow. I searched the documentation, but it is very poorly and unclearly covered regarding sales. For subscriptions, I found a lot of information, but for sales, it is very sparse and unclear. My app is already running on a website, and I use Stripe for payments there, which works fine. When I started with RevenueCat to set up the app on Google Play, I thought it would be similar, but it does not work. I am selling credits, like lives in games that get consumed later. After a purchase, the credits should be added to the profile of the user who made the purchase. I am using Firebase as the database. My main problem is with sales. I have connected RevenueCat and Google Play Console, and I think that part is okay. I believe the problem is on the FlutterFlow side, but there is very little documentation, or it is too general. Does anyone know where I could look? Has anyone had a similar prob
Hej -- so I’ve read several topics here about the best way to increase pricing of existing subscriptions in both iOS and Android, and wanted to make sure if I got this right, because it all feels very complicated for what should be a very common use case.Let’s say we want to increase price from 1.99 to 2.99 for a monthly subscription, and 19.99 to 29.99 for a yearly subscription, both in the same “Subscription Group” in iOS, and in the same “Subscription” in Android.We want to grandfather existing users; so ideally everybody paying 1.99 right now, will keep paying that amount until they cancel, and will still be able to upgrade to the 19.99 yearly subscription.There seem to be two strategies:Option 1:Increase the price of the existing plans in the App Store and Google Play, choosing to keep the existing customers at the same price.Pro:The “official” way -- easy to later let people opt-in / transition to the price change. Keeps the subscription groups simple. Offers etc still apply to t
I am having an issue enabling a simple button after a user subscribes using the presentPaywallIfNeeded(requiredEntitlementIdentifier: "Premium") sheet. I disable this button until a user purchases a subscription. Now this works when i click off the current view and come back via tab bar. It's when the sheet dismisses to the current view where i am not able to enable the button. I’ve tried a number of things so far:creating a isSubscribed flag which works but not for the current view until i leave and come back to that view. adding various things to OnAppear for the current view Maybe creating a Binding? Any ideas would be appreciated. The functionality comes across as being very buggy when i can't enable UI components after a user purchases a subscription and the sheet dismisses. Swiftui Xcode 16.2
useEffect(() => { const init = async () => { try { if (Platform.OS === "android") { await Purchases.configure({ apiKey: APIKeys.android }); } else { await Purchases.configure({ apiKey: APIKeys.ios }); } Purchases.setLogLevel(LOG_LEVEL.DEBUG); Purchases.addCustomerInfoUpdateListener((customerInfo) => { console.log( "CustomerInfo update received:", JSON.stringify(customerInfo, null, 2) ); updateCustomerInfo(customerInfo); }); await loadOfferings(); } catch (error) { console.error("Error initializing Purchases:", error); } finally { setLoading(false); } }; init(); // Cleanup function return () => { // Remove the listener when component unmounts Purchases.removeCustomerInfoUpdateListener(); }; }, []); // load offerings a user can purchase const loadOfferings = async () => { try { cons
Hi, I’m using Paywalls feature in my SwiftUI App. I want to disable Paywall interactions while purchase is in progress, is there onPurchaseStart callback or something? here is my current implementation: .sheet(isPresented: $userViewModel.displayPayWall) { PaywallView(displayCloseButton: true) .onPurchaseCompleted({ userInfo in print("completed") userViewModel.isPurchasing = false userViewModel.isSubscriptionActive = userInfo.entitlements["pro"]?.isActive ?? false }) .interactiveDismissDisabled(userViewModel.isPurchasing) }
I have subscriptions in my app that include 7-day trials. RevenueCat handles introductory offers automatically, which is great. However, I want to provide additional custom promotional offers using Apple's "Promo Codes". Examples of these offers could be:3 months free 6 months freeMy question is: Does RevenueCat automatically manage the redemption and application of these custom promo codes? Or, do I need to handle this logic separately within my app?Any guidance or experience with this would be incredibly helpful!
I am showing a discount paywall, after the user cancels the first paywall, but for some reason, It works well while testing, while in test flight, but once approved by apple in production it throws the below error RevenueCatUl.PaywallError 0The RevenueCat dashboard does not have an offering with identifier'pro_40_off_paywall'.also shown in the image.code - try {const secondPaywallResult = await RevenueCatUI.presentPaywall({offering: {identifier: 'pro_40_off_paywall'}});Even thought “pro_40_off_paywall” exists and works in dev and in testflight, hope someone can please help.
I’m trying to integrate the paywall into my VisionOS app, which creates a volumetric WindowGroup. When the paywall attempts to present itself, I get the error “Presentations are not currently supported in Volumetric contexts.” Using Xcode 15.3 Beta 3 with Apple Vision Pro (1.1) simulator. import SwiftUIimport RevenueCatimport RevenueCatUI@mainstruct Sheila_VisionOSApp: App { init() { Purchases.logLevel = .debug Purchases.configure(withAPIKey: "XXXXXXXX", appUserID: nil) } var body: some Scene { WindowGroup { SheilaAppView() .presentPaywallIfNeeded( requiredEntitlementIdentifier: "access", purchaseCompleted: { customerInfo in print("Purchase completed: \(customerInfo.entitlements)") }, restoreCompleted: { customerInfo in // Paywall will be dismissed automatically if "pro" is now active. pr
testing
I have a subscription in my app that allows the user to “redeem” 6 times each month. I keep track of that in an external database.My app uses anonymous ids only – there’s no login or accounts.How can I reliably get the same App User ID when a user opens the app, creates a subscription, or reinstalls the app? I find that it’s constantly changing.
I want to automate my revenuecat process. I test using StoreKit, but entitlements are not reset. How do I achieve this? let session = try? SKTestSession(configurationFileNamed: "storekitconfig")session?.resetToDefaultState()session?.disableDialogs = truesession?.clearTransactions()customerInfo.entitlements["Pro"]?.isActive == trueThis code returns true. How do I make it return true if I just made a purchase?
Already have an account? Login
No account yet? Create an account
Enter your E-mail address. We'll send you an e-mail with instructions to reset your password.