Discussion and help from anything related to RevenueCat.
Recently active
When I get a test customer’s CustomerInfo while offline it looks exactly the same as if the user simply had no entitlements. How can we tell the difference - how can we know if a user has NOT made a purchase or if they are simply offline? If there anything in the CustomerInfo that can tell us? I feel like we can’t know for sure if a purchase has NOT been made.
What are the best practices to implement offline use-case?One of the main features of our subscription is to use our outdoor app with poor internet reception or no reception with maps and other information downloaded before. can we check the subscription status while the device is offline? what happens when the reception is very bad but not offline, is it still good to call “Purchases.shared.purchaserInfo” or will it make the UI feel non-responsive?
Hi. I granted a sandbox user access to an entitlement, but I see this action only on on the “Overview” (“Sandbox data” disabled) tab.Going to tab “Customers” > “Sandbox”, I see an older grant in the “Last Purchase”, but not the last one.Analyzing the “Customer Profile”, I also don’t see my last grant.What do I miss?
Hi, We have an internal statistics tools which collects various statistics each day, which are then used in various internal reports.I would like to add some data available in RC dashboard to those reports, for example the number of active subscription (ideally per app), and the MRR (ideally per app as well).Is it a way to easily get those informations from RevenueCat? I would probably use the API to get all subscriptions and compute those myself, but it would be much more efficient to use the data calculated by RC. Thanks,
My Flutter app’s Firebase Crashlytics keeps catching a platform exception from RevenueCat on Android. It’s being caught for the majority of my userbase.SDK versions:purchases_flutter: 8.1.0purchases_ui_flutter: 8.1.0Exception details (look for “revenuecat-events-thread”):Fatal Exception: io.flutter.plugins.firebase.crashlytics.FlutterError: WebSocketChannelException: Instance of 'WebSocketException' at FirebaseCrashlytics.recordError(firebase_crashlytics.dart:119) at main.<fn>(main.dart:101)pool-10-thread-9: at sun.misc.Unsafe.park(Unsafe.java) at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:230) at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:461) at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:362) at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:937) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolE
I made a sandbox purchase but after the subscription expired ReveneCat is now seeing my non-sandbox subscription which is still active so it never expires in the app. Am I doing something wrong here?The customerInfo dictionary is showing non-sandbox:2024-08-17 17:48:36.722499-0600 BackcountrySkiReporter[3714:868874] [network] DEBUG: ℹ️ GetOfferingsOperation: StartedPrinting description of purchaserInfo:<CustomerInfo:originalApplicationVersion=1.0,latestExpirationDate=Optional(2024-08-26 21:26:33 +0000),activeEntitlements=["pro": "<EntitlementInfo: \"\nidentifier=pro,\nisActive=true,\nwillRenew=true,\nperiodType=PeriodType(rawValue: 0),\nlatestPurchaseDate=Optional(2023-08-26 21:26:33 +0000),\noriginalPurchaseDate=Optional(2018-08-19 21:26:34 +0000),\nexpirationDate=Optional(2024-08-26 21:26:33 +0000),\nstore=Store(rawValue: 0),\nproductIdentifier=com.bcski.pro.annual,\nproductPlanIdentifier=null,\nisSandbox=false,\nunsubscribeDetectedAt=nil,\nbillingIssueDetectedAt=nil,\nownershi
Hello, We export RevenueCat data to Metabase via a Webhook. We'd like to reproduce the main tables we have on RevenueCat to cross-reference them with our other collected user data, but we can't find the same data between our Metabase and RevenueCat tables. We've tried to follow the instructions on this article, but the names of the columns we have are different from those indicated on this article. Do you have more precise documentation that would enable us to reproduce your tables using the three tables provided below this email? Maybe it would be easier to do a visio to see it together?Thanks a lot for your help,Louis Table 1 : RevenueCat Subscription Event : - ID- Event ID- Type- App User ID- Original App User ID- Date - Store - Cancel Reason- Expiration Reason- Usd Price - Eur Price- Price- Currency- Tax Percentage- Comission Percentage- Transaction ID- Original Transaction ID- Country Code- Offer Code- Device ID Attr- Product IDTable 2 : Revenuecat Subscription- ID- Subscriber ID
Hi everyone, We have a Subscription page developed in Flutter that displays 3 Tiers of subscription - LITE, PRO (Monthly & Annual) and ULTRA (Monthly and Annual). RevenueCat’s single paywall only supports a single offering - current. And hence, the way that we’ve configured is that there are 2 offerings - PRO (with its PRO paywall) and Ultra (with its ULTRA paywall).When the page is loaded, in the initState() - we call:if (Platform.isAndroid) {await Purchases.configure(PurchasesConfiguration("xxx")..appUserID = userId);} else if (Platform.isIOS) {await Purchases.configure(PurchasesConfiguration("yyyy")..appUserID = userId);} To show 2 different Paywalls, there is a function that gets the respective offerings in initState():var _offerings = await Purchases.getOfferings();var _proOffering = await _offerings.getOffering('Pro')!;var _ultraOffering = await _offerings.getOffering('Ultra')!;setState(() {offerings = _offerings;proOffering = _proOffering;ultraOffering = _ultraOffering;}); I
sdk: 5.3.2 [RCPurchases configureWithAPIKey:]
This might be related to this threadI used the Stripe test mode to purchase a subscription. It's shown in Sandbox mode on the RC website for that customer. The customer has the attached entitlement granted. But when I call the REST API like this:https://api.revenuecat.com/v2/projects/${revenue_cat_project_id}/customers/${user_id}/subscriptions?environment=sandboxIt returns an empty list.I don't see the documentation mentioning anything about the subscriptions endpoint still being in beta, so I assume it should work for Stripe subscriptions as well. The goal I'm trying to achieve is for my Flutter app to determine which store a user's current subscription was purchased with on the web. I need this information to provide them with the correct management URL.I'm using the SDK for mobile platforms, and a Firebase Function to call the REST API on web, because I believe the Flutter SDK does not work on Flutter web. Correct me if I'm wrong. I'm open for any suggestions on improving this flow
When I submitted my app for review on the Play Store, it was rejected due to a "Broken functionality policy violation." The email included a screenshot that shows "The item that you were attempting to purchase could not be found." After investigating this error, I found that it occurs when the app is used with the non-License Tester. Therefore, I attached the License Tester account information to the app submission details and explained to the reviewer how to log in with the License Tester account. However, the app was rejected for the same reason again. In this case, how can I pass the review?It seems that the reviewer is not logging in with an account registered with the License Tester, so I looked for other methods. In one article, it was reported that it was possible to pass the review by ensuring that the error dialog would not appear, even if the purchase could not actually be completed.So, I ran the app locally using an Android device logged in with a non-License Tester account
Hello,We have a huge rate of “Payment Pending”, “Payment Decline”, and “Canceled” on our subscriptions in Google Play Store, after the end of one-week trial.We tried contacting Google several times, but they say everything is normal and don’t give us any helpful answer. :-/Since some of the payments go through, we believe it shouldn’t be a general technical issue. So, we are wondering if anyone has any idea, thoughts, or experience that can help us. Here is one page of our “Order management.” We have 8 pages like this in August. Further Notes:We are in the US, and running Google Ads in the US. (Most these users are US-Based.) We have a registered LLC in California, operate in California, have got a D-U-N-S number and Tax Registration numbers and we have put all of them in the Developer profile and Google has validated them. We tried switching from $59.99/yr to $7.99/mo (with one week trial) to reduce the transaction amount, but we still see a lot of these Payment Pending/Declined/Can
When a user purchases a subscription we run the code that calls purchase():const getInfo = useCallback(async () => { try { const info = await Purchases.getCustomerInfo(); packageRef.current = info?.entitlements?.active?.[entitlementName]?.productIdentifier; const { isActive: isEntitled } = info?.entitlements?.active?.[entitlementName] || {}; setIsActive(!!isEntitled); if (isEntitled) { setSawPaywall(true); } return info; } catch (e) { throw new Error((e as Error).message); } }, [setIsActive]);const purchase = async (purchasePackage: PurchasesPackage) => { try { await Purchases.purchasePackage(purchasePackage); await getInfo(); } catch (e) { if ((e as Error).message !== 'Purchase was cancelled.') { throw new Error((e as Error).message); } } };After the subscription is successful, the app runs correctly, which navigates to the sign in page and after the user signs in, goes to
For my product, users frequently download the app after subscribing by first redeeming a promo code.Sometimes, on a fresh install, RevenueCat automatically syncs a user’s subscription. Other time, it does not and the user has to tap our “restore” button, calling restorePurchases, making for a confusing UX. After much testing, I cannot explain this discrepancy.What is the best way to ensure that the user’s subscription restores/syncs preemptively, so I can present the correct onboarding process? Calling syncPurchases does not seem to help at all. I’ve tried it before sign-up (anonymous user ) as well as after sign-up (after calling logIn and setting the user ID with RevCat).The docs indicate that syncPurchases should successfully sync the subscription like restore does:This method, much like restorePurchases, reactivates any content that had previously been purchased from the same store account (Apple, Google, or Amazon).This answer from the RevCat team specifies about anonymous ids: sy
I’ve setup a subscription in Google Play console that includes an offering. While the RevenueCat SDK (react native) is able to access the subscription correctly, the free trial (introPrice) is missing (set to null). Offer settings in Google Play consoleNewly created offer, user as never purchased this subscription before. Offer received on the front-end{ annual: { identifier: "$rc_annual", offeringIdentifier: "ProTrial", packageType: "ANNUAL", presentedOfferingContext: { offeringIdentifier: "ProTrial", placementIdentifier: null, targetingContext: null, }, product: { currencyCode: "AUD", defaultOption: [Object], description: "", discounts: null, identifier: "yearly_pro_trial:yearly-pro-trial", introPrice: null, presentedOfferingContext: [Object], presentedOfferingIdentifier: "ProTrial", price: 124.99, pricePerMonth: 10415833, pricePerMonthString: "A$10.42", pricePerWeek: 2397068, pricePerWeekString: "A$2.40", pricePerYear: 124990000, pricePerYe
Hello! I am trying to verify a user’s subscription on my backend, and it seems like there’s a lot of event types from the revenuecat webhook to consider.https://www.revenuecat.com/docs/integrations/webhooks/event-types-and-fieldsI want to know if i want to ensure my user’s subscription status on my backend matches with the revenuecat source of truth, do i need to necessarily implement a handler for each of these event types? It feels like alot of effort, and I am wondering if there is usually a need to implement handling for all event cases, or do most apps just need to implement for a few event types?
Hello,we used the event `in_app_purchase` to track the purchases that where made in our app. Sadly, that event has stopped firing after updating the RevenueCat and Firebase Capacitor Plugin.Does someone know if the event `in_app_purchase`, which is automatically collected by the firebase sdk, is the same as `rc_trial_start`?Firebase Events Docs: https://support.google.com/analytics/answer/9234069?hl=en&visit_id=638606024194872788-4062852051&rd=1Thanks in advance,Marius
I have a valid Android subscription and offer setup in Google Play console. When I test this, the paywall shows correctly with correct values. When I proceed to buy the subscription, both subscription and offer are show in minutes. Is this because it’s a development build or is there something wrong? SubscriptionOffer
I want to present the Paywall, if needed, on every 4th launch of the app. I can track the launch count, but can’t seem to figure out how to couple this with .presentPaywallIfNeeded in the ContentView. // Show paywall every 4th launch if launchCount % 4 == 0 { // Present RevenueCat Paywall presentPaywall() }import Foundationimport RevenueCatclass SubscriptionManager: ObservableObject { @Published var hasPro: Bool = false init() { checkSubscriptionStatus() } func checkSubscriptionStatus() { Purchases.shared.getCustomerInfo { (customerInfo, error) in if let error = error { print("Error fetching customer info: \(error.localizedDescription)") return } print("checkSubscriptionStatus") DispatchQueue.main.async { self.hasPro = customerInfo?.entitlements["pro"]?.isActive == true print("hasPro: \(self.hasPro))") } }
Similar to this post I have a iOS RevenueCat pricing experiment. Separate from that, I have offer codes that users can use to purchase the subscription (standard Apple offer codes). Will the experiment accurately exclude purchases made through offer codes?
I have set up an integration between OneSignal and RevenueCat, checked over the App ID and API key, both are correct. I recently found out that our app was not setting the OneSignal ID and on the Purchases SDK for flutter (8.0.1). We fixed this and checked that the user does indeed have a valid OneSignal ID and it should be sending the given data tags to OneSignal. however it seems that when i look through the integration logs that RevenueCat sends empty body to OneSignal and in turn gets a 404 reply with the given error below (the webhook to our backend sends the update correctly so theres no issue there). Note: i have not change any of the tag names so they are default{"errors":[{"code":"subscription-0","title":"Subscription not found"}]} Any idea why this is happening? EDIT: seems flutter SDK still only supports old device centric (9.0) version of RevenueCat, does this mean the integration does not work at all in that case unless we set it manually?
kkkk
Summary: App Store in-app purchases not pulling correctly with promotional offer (free trial)Description:I am trying to offer users a free trial using RevenueCat and in-app purchases. The line of code throwing the error is:const selectedPackage = offering.availablePackages[0]; // This is the package objectconst product = selectedPackage.product; // Extract the product from the packagelet discount: any = null;if (product.discounts) {await Purchases.restorePurchases().then((res) => {console.log('Restore purchases:', res);});discount = await Purchases.getPromotionalOffer(product, product.discounts[0]).catch((error) => {Alert.alert('Error','An error occurred while fetching the subscription details. Please try again.');console.log('Error getting discount:', error);setLoading(false);return null;});}Specifically, the Purchases.getPromotionalOffer() is throwing the error:Possible Unhandled Promise Rejection (id: 0): Error: The receipt is not valid.The debug logs are showing the following
The RC Flutter SDK offers the .logIn method, which allows the current user to log in using only the appUserID.Since the appUserID is exposed on the client side, a malicious user could potentially obtain someone else's appUserID (e.g., through reverse engineering the app or intercepting network requests) and use it to impersonate that user. This could allow unauthorized access to premium content or features, etc..
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.