Get help with your SDK implementation.
Recently active
I am trying to keep track of which consumables have been awarded to the player and need to track it with a unique identifier for each purchase. In the Unity SDK, the StoreTransactions that I get in the CustomerInfo.NonSubscriptionsTransactions have a property called TransactionIdentifier. However, this does not match the transaction_id I see online in RevenueCats front end.Question 1: Why does the TransactionIdentifier not match the tranaction_id that i see in RevenueCat online?Question 2: Since I cannot access the tranaction_id in Unity, is the TransactionIdentifer that right way to uniquely track a consumable purchase and will this value persist for the lifetime of the user?
About ¼ of our users’ attempted subscription purchases on iOS are failing with errorcode 2 (store problem). There are no underlying errors that we can see, but this error message in the logs is present for almost all of them (PID is different each time):Product purchase for 'pro_plan_quarterly_24' failed with error: systemError(Error Domain=NSCocoaErrorDomain Code=4097 "connection to service with pid 13290 named com.apple.storekitd" UserInfo={NSDebugDescription=connection to service with pid 13290 named com.apple.storekitd})We’ve found this difficult to reproduce on our own devices. We’ve found that when it does happen, then if we press the button to start the subscription purchase again then it does usually work the second time.Our integration involves AppsFlyer, Superwall, and Amplitude.We put in additional logging to try to catch whatever the problem is. Since then we are seeing this happening across iOS 18.3.1 and 18.1.1, but it’s happened on other versions before then.
I am upgrading to use the RevenueCat’s own configurable paywall (most likely going to use V2 so I dont have to upgrade later). I am currently using custom hardcoded UI for various versions of the paywall in my app.I am wanting to use slightly different messaging on my paywall depending on where in the app it is opened from - for example one when you initially introduce a premium offer, vs one where someone is trying to access content that is only available in the premium offer. I have one offering. Is this possible?
I'm integrating the RevenueCat Web Billing SDK into my web app, and I'm experiencing an issue where the Stripe checkout iframe does not fully display.Issue Details:When I click "Start Free Trial", the RevenueCat paywall opens as expected. After entering my email, the next screen (where Stripe should load the secure checkout UI) only shows the title and a grayed-out "Start Trial" button—but no credit card form appears. The Stripe iframe is present in the DOM, but its height remains 2px, and its opacity stays 0. I tried putting height at auto, didn’t change anything. (see screenshots below)What I’ve Tried:Verified that the user appears in the RevenueCat dashboard after authentication. Ensured that the correct offering and products are configured in RevenueCat. Checked browser console logs—no specific errors related to Stripe, but I randomly get 400 Bad Request errors from https://e.revenue.cat/v1/events. Confirmed that RevenueCat properly initializes and fetches offerings before triggeri
Hi team, I saw there are new templates for Paywalls v2, so what templates are good for one-time-purchase (Non-Consumable IAP)?
How do I create a footer-only v2 Paywall and display it in native Android below another @Composable?
I’ve integrated RevenueCat into my Flutter app, and subscriptions are working perfectly in local development (tested on a real device using StoreKit). However, when testing the same build on TestFlight and Production, in-app purchases fail.What I Have Tried:✅ Verified that the same bundle ID is used across development, TestFlight, and production. ✅ Checked that RevenueCat is correctly initialized with the right API key. ✅ Ensured that the App Store "Paid Apps Agreement" is accepted in App Store Connect > Agreements, Tax, and Banking. ✅ Created and assigned sandbox accounts (iOS 18 moved this to Settings > Developer > Sandbox Account). ✅ Removed the StoreKit configuration file from the Release Scheme in Xcode to ensure real App Store purchases. ✅ Checked that my in-app purchase products are approved and in "Ready to Submit" or "Waiting for Review" state in App Store Connect. ✅ Ensured the App-Specific Shared Secret is added to RevenueCat.✅ Tried waiting a few hours in case purc
I’m unable to get the onPurchaseCompleted handler working while testing the purchase. This handler manages the post-purchase UI updates. I am using paywall version 2 PaywallView().onPurchaseStarted{ _ inprint("onPurhaseStarted: ")}.onPurchaseCompleted{ _ inprint("onPurchaseCompleted: ")isPaywallPresented = false}.onRestoreStarted {print("onRestoreStarted: ")}.onRestoreCompleted{ _ inprint("onRestoreCompleted: ")isPaywallPresented = false}.onPurchaseFailure { error inprint("purchase error \(error)")isPaywallPresented = false}.onRequestedDismissal {print("onRequestedDismissal: ")isPaywallPresented = false}.onDisappear {print("ModalView dismissed") // Action when dismissed}
Hello,The question is about Flutter SDK on iOS.I noticed the following behaviour for RevenueCatUI.presentPaywallIfNeeded and RevenueCatUI.presentPaywall:- If the app was in the background, and I call “await RevenueCatUI.presentPaywall(...)” right after the app is resumed, the call never returns (awaiting forever).- Everything works if I add 500-1000 ms delay after the app is resumed.Could someone explain why is this happening? How can I wait for the SDK to be ready to show the paywall without adding an explicite delay?I tried:- await Purchases.getCustomerInfo();- await Purchases.getProducts();- await Purchases.getOfferings();Nothing from this list helps, only the actual delay does.Thank you.
Hello,We have started using Revenue Cat to manage in-app purchases, but we are having trouble recovering purchases that were not made via RevenueCat on Android. We login the user via SDK using Purchases.sharedInstance.logInWith("our-custom-user-id"). We wait for a successful response and if the user is logged in for the first time, we call Purchases.sharedInstance.syncPurchases() to sync the purchases not made via RevenueCat. The problem is the "timeline" of events. See screenshot.The webhook for the purchase was sent with an anonymous user ID because an alias was not created at the time. We are unable to sync purchases on our backend with an anonymous user id. Since the "SUBSCRIBER_ALIAS" webhook is deprecated, we are unable to wait for this webhook and sync purchases after that. Please help. Do you have any solution for this?Thank you in advance for your reply.
Hi,How can I check if a user has canceled a subscription or trial?If a user has canceled a subscription, his status is active until its expiration date. It's the same with the trial period. Is it possible to determine it was canceled, but at the same time it is still valid? Thanks
Hi!The product (Flutter) I’m currently building has users both on a web app and in a mobile app.One use case I’m struggling with currently is that a user might buy a premium subscription from the web app through Stripe and then open the mobile app which might have cached the CustomerInfo object for at ~5 minutes.Due to the caching, the user will not immediately see the subscription in the app which is not ideal as it can cause confusion. What are the best practices to deal with something like this?Edit:I know about the invalidateCustomerInfoCache() function. I’m interested to know if there is a recommended way to use that function. Any help and tips are appreciated!
I have the following code, but only the paywallViewControllerWasDismissed method is being called. Other PaywallViewControllerDelegate methods are not triggered. Any solution for this? import Foundationimport RevenueCatUIimport RevenueCatimport UIKit class RevenueCatManager: NSObject { static let shared = RevenueCatManager() private override init() {} func presentPaywall(from viewController: UIViewController, offeringID: String) { Purchases.shared.getOfferings { (offerings, error) in guard let offering = offerings?.offering(identifier: offeringID) else { print("⚠️ Error fetching offering with ID: \(offeringID) - \(error?.localizedDescription ?? "Unknown error")") return } DispatchQueue.main.async { let paywallVC = PaywallViewController(offering: offering) paywallVC.delegate = self paywallVC.modalPresentationStyle = .fullScreen viewController.p
I'm using getCustomerInfo on the splash screen to check the subscription status when the app is opened for the first time (where the cache is empty). However, I’ve noticed that getCustomerInfo sometimes takes 10-20 seconds to fetch data, which is too long for a smooth user experience.Since I’m not using a server-side solution, what are the best practices to speed up this process purely on the client side? Would pre-fetching, background loading, or specific configurations help reduce the delay?Any insights or recommendations would be greatly appreciated!
I am only using ios products currently. The information pulled is incorrect and there are multiple errors. For example, one product is a yearly subscription of $12.99, but the price is $11.88 and there are prices for monthly and weekly subscriptions. I can’t complete testing with the inaccurate data, but I have found no issues in the xcode files or apple store.
Hello, We are seeing a weird behavior for some of our users: after purchasing a subscription they are not premium. To actually become premium, they need to do a restore of the purchase. Do you know what could be the issue? Thanks!
When using purchases_ui_flutter I get the following errors when trying to run a debug build:Could not resolve all files for configuration ':app:debugRuntimeClasspath'. > Failed to transform lifecycle-livedata-core-2.8.3.aar (androidx.lifecycle:lifecycle-livedata-core:2.8.3) to match attributes {artifactType=android-dex, asm-transformed-variant=NONE, dexing-enable-desugaring=true, dexing-enable-jacoco-instrumentation=false, dexing-is-debuggable=true, dexing-min-sdk=26, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.libraryelements=aar, org.gradle.status=release, org.gradle.usage=java-runtime}. > Execution failed for DexingNoClasspathTransform: C:\Users\porta\.gradle\caches\8.9\transforms\02266809379a8c0cb61126b0d331cfeb\transformed\lifecycle-livedata-core-2.8.3-runtime.jar. > Error while dexing. > Failed to transform constraintlayout-core-1.1.0.jar (androidx.constraintlayout:constraintlayout-core:1.1.0) to match attributes {
I have tried to hit the https://api.revenuecat.com/v1/subscribers/{userId} endpoint and I receive data back, as the https://www.revenuecat.com/reference/subscribers api docs show: Get OR create a subscriberIf the provided app_user_id doesn't exists, a new subscriber will be created with the App User Id. However, when I go to my customers page I do not see that customer having been created. How can I achieve this? What I’m ultimately trying to achieve is to provide a user with access to my app without them needing to make a purchase, however in order to set a promotional entitlement it would appear the user needs to already be created.Any ideas?
Just testing Paywalls v2 on react-native. iOS works perfectly, Android is showing the fallback - standard paywall. "react-native-purchases": "^8.7.0", "react-native-purchases-ui": "^8.7.0",react-native: ^0.76.1The logs don’t seem to show any errors: ℹ️ Debug logging enabledℹ️ SDK Version - 8.13.0ℹ️ Package name - XXXXXXXXXXXXXXXX👤 Initial App User ID - nullℹ️ Purchases configured with response verification: DISABLED👤 Identifying App User ID: $RCAnonymousID:XXXXXXXXXXXXXXXXℹ️ Deleting old synced subscriber attributes that don't belong to $RCAnonymousID:XXXXXXXXXXXXXXXXℹ️ Listener setℹ️ Sending latest CustomerInfo to listener.ℹ️ setAttributes calledRetrieving customer info with policy: CACHED_OR_FETCHEDℹ️ Vending CustomerInfo from cache.ℹ️ Checking if cache is stale AppInBackground trueℹ️ Starting connection for com.android.billingclient.api.BillingClientImpl@aXXXXXXXℹ️ App foregroundedℹ️ CustomerInfo cache is stale, updating from network in foreground.Retrieving customer info wi
Error purchasing: Error Domain=RevenueCat.ErrorCode Code=8 "The receipt is not valid. The purchased product was missing in the receipt. This is typically due to a bug in StoreKit." UserInfo={NSLocalizedDescription=The receipt is not valid. The purchased product was missing in the receipt. This is typically due to a bug in StoreKit., rc_backend_error_code=7712, rc_response_status_code=422, NSUnderlyingError=0x301610a80 {Error Domain=RevenueCat.BackendErrorCode Code=7712 "The purchased product was missing in the receipt. This is typically due to a bug in StoreKit." UserInfo={NSLocalizedDescription=The purchased product was missing in the receipt. This is typically due to a bug in StoreKit., rc_backend_error_code=7712}}, source_function=parseUnsuccessfulResponse(), source_file=RevenueCat/HTTPClient.swift:890, readable_error_code=INVALID_RECEIPT}Until a couple of days back Lifetime plan used to work. Not sure what happened since 2 days I am unable to purchase this is sandbox mode - I am u
I recently launched a monthly and annual subscription for my app. Both don’t have a free trial, because the product already has a built in free trial (it’s a golf app, users get 5 free rounds a year and then can do either subscription to get unlimited rounds).I’d like to offer promo codes to new users that either give them a free trial or a discount.I built something using offer codes, but tbh offer codes are just so janky on apple’s end that the experience is pretty rough. I’d really love to use introductory offers and build something like so1) I have my own promo code table in my backend that maps a promo code to a SKProductDiscount id2) By default on my paywall screen I only show my products (no introductory offers)3) Users can enter a promo code and if it’s valid, the endpoint will return the SKProductDiscount id4) If the id matches an introductory offer of one of the products, I either update the UI or just trigger the purchase(package:discount:) call automaticallyI know this flow
We've recently upgraded to RevenueCat SDK 8.6.1 in our React Native app and noticed a change in how the paywall events are triggered, for both our old Paywall v1 and new Paywall v2.Previously, when a user subscribed, the onPurchaseCompleted method was called as expected. However, in the latest version, users who start a trial now first trigger onPurchaseStarted and then onDismiss, without onPurchaseCompleted being called.Here’s our implementation: const handlePurchaseStarted = useCallback(({ packageBeingPurchased }: { packageBeingPurchased: PurchasesPackage }) => { posthog.capture("onboarding_paywall_purchase_started", { packageIdentifier: packageBeingPurchased.identifier, });}, [posthog]);const handlePurchaseCompleted = useCallback(async ({ storeTransaction }: { storeTransaction: PurchasesStoreTransaction }) => { posthog.capture("onboarding_paywall_purchase_completed", { transactionId: storeTransaction.transactionIdentifier, productIdentifier: storeTransaction.produc
Sorry if it was asked before, I searched but couldn’t find anything :(What is the best way to calculate the price for annual subscription per month/week? I want to show user, how much he/she will pay for an annual subscription each month or week.An app already implementing this, is Snapchat. I checked all over revenuecat documentation but didn’t find this feature.
I’m encountering an issue where payments made using a slow test card are eventually refunded because they aren’t acknowledged in time. Environment:Google Sandbox environment and slow test card Android SDK 8.11.0 Real-time Developer Notifications have been configured as described hereSTR:Purchase a non-consumable (lifetime subscription) using a slow test card While the transaction remains pending, close the app and wait approximately 7 minutes Reopen the appExpected Result: The user has the non-consumable (lifetime subscription), and the payment completes successfullyActual Result: The user does not have the non-consumable (lifetime subscription), and the payment is refunded. Also, there is an email from Google indicating the purchase was cancelled due to lack of acknowledgment:This test purchase was cancelled because it was not acknowledged. You should ensure that all purchases are acknowledged so that they are not subject to refunds. For more information, see https://developer.android
I’ve implemented Customer Center (works fine on iOS). On Android the dark mode doesn’t work properly. Using default color settings in the Customer Center Appearance config. "react-native-purchases": "^8.7.0","react-native-purchases-ui": "^8.7.0"
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.