Get help with your SDK implementation.
Recently active
Hi,Our app is a subscription streaming with Monthly and Yearly package.The current flow we want to use with RC are:1) . Subscription Purchase but the user not login yet to the app. So still as a guestGuest > Purchase > Successful Is it correct if we use this const { customerInfo, created } = await Purchases.logIn(guest_id); ?Then we will force them to login before can use the full features of the app.Login > successfulBecause its already logged in, then we can get the actual subscriber_id for that user,Is it correct if we use this const { customerInfo, created } = await Purchases.logIn(subscriber_id); ?So in RC, the app_user_id will be updated with the latest one which is subscriber_id, whilst the original_app_user_id is still the original Anonyomous ID.Then later, this user can login to any device / platform and still can get the same status of the subscription.Is it my understanding on how to implement is correct?Thank you
testing
Hello, I’ve added `Purchases.addCustomerInfoUpdateListener` to listen for changes to `CustomerInfo`. Now, I know it works because it gets fired when I make a subscription purchase with Purchases.purchasePackage.However, I do not see it firing when a user cancels their subscription from Google Play or when it automatically expires. I have Google Developer Real-time notifications set up, tested and working. I can also see the RevenueCat Customer History Dashboard get updated with the cancellation/expiration event, but it never propagates back to the listener. If I call `getCustomerInfo()` directly though, I can see the changes.Curious if this broken, or expected behavior? By the looks of it it says it should fire when it detects any changes to CustomerInfo, so in theory it should fire, but it doesn't. Using Capacitor SDK v7.4.0 Thanks!
Hello RevenueCat team and community!I’m trying to integrate Stripe with RC and so far i’ve been following the steps of this documentationAfter receiving both checkout events in my backend server: customer.subscription.created and checkout.session.completed I send a POST request to the receipts endpoints. Every time I send a request the response I get is the following:{ "code":7103, "message":"The receipt is not valid."}Even if I try to send manual requests from the terminal using cURL i will get the same response. Here is an example:curl -X POST \ https://api.revenuecat.com/v1/receipts \ -H 'Content-Type: application/json' \ -H 'X-Platform: stripe' \ -H 'Authorization: Bearer strp_xxxxx' \ -d '{ "app_user_id": "my_app_user_id", "fetch_token": "sub_xxxxx" }'I took the Authorization token from the Stripe App Public API KEY created in the RC dashboardSome additional info:I’m not the owner of the RC project, neither the Stripe account. Yet I have admin privileges in both accou
Hi.I left an inquiry on the ticket, but I also wrote it here.Since November 2023, we have been using this service well and there have been no problems.However, there is a problem that the webbook is not called when some Android users call Pursances.purchaseStoreProduct api from about 10 to 15 days ago.Fortunately, we also got a device that had the problem and checked the log with the device that was working normally, and found that only one log was differentIn the normal log, there is "CustomerInfoUpgraded, sending to listener," but the above log does not appear in the log of the problematic device.I wonder if there were any similar tickets or inquiries like this, and if you already know, I wonder how to fix it.Thank you.
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?
Hello,I recently explored the guide on transitioning a paid iOS app to a subscription model as outlined in your article at RevenueCat. While insightful, it doesn't entirely address our specific requirements.Our application is initially free to download, offering in-app purchases (IAP) to access additional functionalities. We're considering introducing a paid version in select markets to evaluate its performance. For this purpose, I'm seeking an effective method to verify whether a user has made a purchase to download the app (not based on the app version).I've come across the possibility of locating a receipt within the app bundle that could potentially provide this information. Could you advise on the reliability of this approach and how to implement it effectively?Thanks for your help.
Please tell the specific gradle version for revenuecat version 7.5.2.
following the docs but react native with expo doesn’t recognize purchaseshttps://www.revenuecat.com/docs/getting-started/quickstart#4-using-revenuecats-purchases-sdk ERROR ReferenceError: Property 'Purchases' doesn't existThis error is located at: in App (at withDevTools.js:18) in withDevTools(App) (at renderApplication.js:57) in RCTView (at View.js:116) in View (at AppContainer.js:127) in RCTView (at View.js:116) in View (at AppContainer.js:155) in AppContainer (at renderApplication.js:50) in main(RootComponent) (at renderApplication.js:67), js engine: hermes ERROR ReferenceError: Property 'Purchases' doesn't exist
I am successfully making a purchase in IOS sandbox environment and returning the customerInfo object shown below. However once the user is automatically logged in i check their subscription status and it is empty.The user does not show up in my sandbox customer list in revenue cat and the only way i can find them is by manually searching their user ID. When i call the login function there is no active purchases so my app will not authenticate them once they try to re login, or if they want to view their active subscriptions. I am not sure why I am returning a successful purchase object but their account has no record of a purchase?Here is the customerInfo object after making the subscription purchase 'customer INFO: ', { firstSeen: '2024-02-16T03:51:30Z', entitlements: { active: { pro: { willRenew: true, ownershipType: 'PURCHASED', productIdentifier: 'sportyMonthly899', originalPurchaseDateMillis: 1708095600000, latestPurchaseD
I have a paywall in my new flutter app and it has processed two payments so far, so seems to be workign well. But I noticed a crash in my Android Developers Console and when I went through it I saw this line: Caused by ga.i0: There is no singleton instance. Make sure you configure Purchases before trying to get the default instance. More info here: https://errors.rev.cat/configuring-sdk Do we need to configure the purchase beforehand? I would think yes, and maybe I am configurign mine in an odd way which is why its been working. But maybe I need to clean up my code a little. I created a revenuecat provider with: class RevenueCatProvider with ChangeNotifier { CustomerInfo? _customerInfo; CustomerInfo? get customerInfo => _customerInfo; RevenueCatProvider() { initPlatformPurchaseStateRevenueCat(); } Future<void> refreshCustomerInfo() async { try { _customerInfo = await Purchases.getCustomerInfo(); notifyListeners(); } on PlatformException catch (e) {
I am super disappointed to find that this expected functionality (at least for iOS) is not available in Revenue Cat. This has caused us a huge issue - we’re almost finished migrating to RC for payments as we add a new platform to our stack (Web) with the last part of our migration being updating the iOS app - ALL of the backend work has been completed for this and only now are we finding out that this basic functionality is not available. It’s not exactly sign-posted either and so not picked up during initial investigation of RC - mainly because this doesn’t seem like something you’d need to actively validate is possible! Surely this is on your roadmap? I can see many people have been asking for this - if there’s a timeline for this please let me know or it seems impossible that we can move forward with RC as a solution.
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
I’m new to React Native, Expo, and RevenueCat so this is likely very basic but can’t find an answer to this anywhere. I’m following this guide.I’m not familiar with the lingo yet but I’m pretty sure I’m using the “managed workflow” version of Expo. In terms of development and testing, the only setup I’m currently familiar with is Expo Go -- in other words, running “npm start” on my dev machine, opening Expo Go on my device and connecting, then updating/editing code. This is the only way I know how to write code for my app. Then when I’m ready for full testing on a device, I run an EAS build and download it to my device, but at this point I have absolutely no more visibility into the code, it’s a complete black box -- it’s just a standalone running app on my phone.My understanding is that the RevenueCat modules do not work with Expo Go. If I try to include them I get a “Invariant Violation: Your JavaScript code tried to access a native module that doesn't exist” error. First question is
Hello,So I have my app set up and working very nicely using revenueCat, however there is one tiny issue that I hope someone here can help with.I have a subscription management page where I am displaying some details, where ‘next billed amount’ is one of them, that is displaying the amount billed string that I can only find in the offerings object.So far I have been fine with just comparing the productId found in the offering object with the id in the active subscriptions from the customer info object. The thing is, if the user purchases that product on an android device but then switches to iPhone, then I can’t currently get the billed amount, because the offering is now returning the product Id of the iPhone product which is different to the android one. So comparing the two returns falsy and therefor an undefined amount. So I am wondering how others may have gone around this. One solution I do have in mind is naming the identifiers for android and iOS products exactly the same, but w
Hello,I have followed official revenue cat react native facebook ads tracking integration tutorial.It seems like I am setting the facebook anonymous ID to the customer:But when I actually make a purchase from my sandbox account, I see no events being triggered. Here is how I am implementing my code: useEffect(() => { const configurePurchases = async () => { Purchases.setLogLevel(Purchases.LOG_LEVEL.VERBOSE); if (Platform.OS === "ios") { await Purchases.configure({ apiKey: APIKeys.apple, }); // Automatically collect the $idfa, $idfv, and $ip values Purchases.collectDeviceIdentifiers(); const anonymousId = await AppEventsLogger.getAnonymousID(); Purchases.setFBAnonymousID(anonymousId); } if (Platform.OS === "android") { await Purchases.configure({ apiKey: APIKeys.google, }); } }; configurePurchases().catch((error) => { console.error({ configurePurchasesError:
When I open the app everything works fine but when i close it and reopen it from the home screen it crashes on TestFlight.Here's the crash log of the thread its crashing on:Thread 0 name:Thread 0 Crashed:0 libswiftCore.dylib 0x00000001847363fc _assertionFailure(_:_:file:line:flags:) + 264 (AssertCommon.swift:144)1 PurchasesHybridCommon 0x00000001019af1a4 closure #1 in variable initialization expression of static FatalErrorUtil.defaultFatalErrorClosure + 64 (FatalErrorUtil.swift:15)2 PurchasesHybridCommon 0x00000001019a73a0 fatalError(_:file:line:) + 60 (FatalErrorUtil.swift:27)3 PurchasesHybridCommon 0x00000001019a73a0 static CommonFunctionality.sharedInstance.getter + 84 (CommonFunctionality.swift:21)4 PurchasesHybridCommon 0x00000001019a73a0 static CommonFunctionality.customerInfo(fetchPolicy:completion:) + 84 (<compiler-generated>:405)5 PurchasesHybridCommon 0x00000001019a73a0 specialized static CommonFunctio
Hello,I’m building an Ionic mobile app with the Capacitor plugin and testing payments for IOS and Android in sandbox mode. I have the Google Play store payment working properly in sandbox mode but with IOS I am having an issue with the purchasePackage method.I am receiving offerings and packages properly, using the IOS key, but when I pass in a package into the purchasePackage method, a TCP timeout occurs. I assume this is because it is reaching out to an API and waiting for a response that it isn’t getting. How can we get past this or is this a known issue with developing with Ionic Capacitor and IOS payment subscriptions? I want to test this in a production environment but that would need Apple’s approval with broken authentication. Any guidance or input would be greatly appreciated Steps taken to debug: Make sure IOS and Android keys are working properly Purposely passing broken data into purchasePackage to see what it returns Console logging and follow the trail of data until it re
Hi, I’m working on creating a native paywall with SwiftUI because we have a paywall design that deviates from the templates. (it’s mainly sizes and margin - footer paywalls are too tall for our use. Hope this is configurable in the future) While creating a custom paywall, I wish we could still use some of the variables and localization RC offers with paywall templates. e.g., I tried to access periodName (e.g. “Annual”) via package.periodNameOrIdentifier(.current)This gives “'periodNameOrIdentifier' is inaccessible due to 'internal' protection level" It seems that making ‘extension Package: VariableDataProvider’ public might allow this. Can RC support this? At a high level, the pain here is that as soon as we try to do anything custom that deviates from the template, we face reimplementing many of the conveniences RC provides. Wish there was a middle ground somehow.
My request to `https://api.revenuecat.com/v2/projects/:projectId/customers` is returning a 404 error which doesn’t really make sense. Full error object below: ```{ "doc_url": "https://errors.rev.cat/resource-missing", "message": "Resource not found", "object": "error", "retryable": false, "type": "resource_missing"}```I am using the projectId returned from calling GET Projects in the v2 API.I am using a V2 API key. The permissions look like: One thing I noticed is that the API key permissions has a “Customer information permissions” section, but there’s nothing there.I know the v2 API is in Beta… is something not finished here?
Hello, my client would like to slightly customize a template, beyond what's possible with the no-code editor, but not enough to warrant creating a new one from scratch. The modifications desired are as follows:Adding a 'chip overlay' around a price card labeled 'Recommended.' Adding a strikethrough text displaying a higher price tag near the effective price.Do you provide such customization services? We would be willing to pay for this. Thank you.
For customer P7JhJ9xGhJeZq1zhrxRptq52Kmb2, I am trying to determine when to remove extra entitlements.The EXPIRATION event seems to have triggered exactly 3 days after when renewal would have happened. Which is what I expect since grace period i set at 3 days.But the RC dashboard seems to show that there is still time until expiration. Maybe this matches the “Grace period ends” timestamp 1707470032885 on the BILLING_ISSUE event.So should entitlement be removed now when I’ve received the EXPIRATION event, or later when grace period ends?
I’m using StoreKit 2 with an automatically synced StoreKit Configuration file in Xcode which is an amazing tool to use in development. Unfortunately, even though I uploaded the public certificate for StoreKit testing, I always get the “ERROR: 😿‼️ The receipt is not valid.” message during development.I’ve read in other threads that this is a common issue. Also, I’ve read somewhere to use StoreKit 1 or to not provide a StoreKit configuration file. But I’m not willing to use older APIs and features when there are shiny new tools that make development much more fun. Please don’t try to convince me that StoreKit 1 is more stable. I’ve used StoreKit 2 directly, and it was an awesome development experience. I’m just using RevenueCat for the Live Data, Experiments, and for the Paywall UI. But my development experience has degraded since I made the switch.To improve this, I would like to simply turn off receipt validation when I run my app in DEBUG mode. In other words, I’m looking for somethi
I am testing purchasing my subscriptions in sandbox. My device has purchased a subscription before, and it has expired.When I go in to purchase again, `Purchases.shared.purchasePackage` returns immediately with the `purchaserInfo` and the default entitlement shows my previous purchase, with an isActive status of false. I was never presented with the purchase modal. When I `restoreTransactions`, the `purcahserInfo` shows the same, an expired entitlement. Why can’t I re-purchase an expired subscription?
Is there any reason _not_ to call `syncPurchases` on every fresh install? That way if a user has a pre-existing subscription, we’ll know right away.The RevenueCat documentation lists these considerations:https://www.revenuecat.com/docs/restoring-purchases#considerationsBut if the user has an anonymous ID, calling syncSubscriptions will just discard that anonymous ID the user does in fact have a subscription (I believe).I don’t see any downsides to it, but I could be missing something.
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.