Question

Offerings are empty in developer build, but all new identifiers match up

  • 21 February 2023
  • 10 replies
  • 351 views

Badge +3

This seems to be a common ask for help, but Purchases.getOfferings() is not working for me with the error `None of the products registered in the RevenueCat dashboard could be fetched from App Store Connect`. It’s a situation like this other thread (among others), but I think I’ve double-checked all the things to watch out for.

Specifically, I had RevenueCat working with my app, which right now is in beta so at most some folks are testing it via Testflight - RevenueCat could retrieve the products then. I then decided to create a dev version of my app using a different bundle ID so that I could simultaneously have the Testflight version and the Expo development build on my phone.

Now, Purchases.getOfferings() is working fine on the Testflight version (which has my original bundle ID) but not on my development version (with the new bundle ID). Things I’ve checked:

  • The development build of my app has the new bundle ID
  • I have created a new app in App Store Connect using that new bundle ID
  • I have registered a new app in RevenueCat using that new bundle ID
  • The new app in App Store Connect has the corresponding (new) subscription in a subscription group
  • That new subscription has all the information filled out such that it is “Ready to Submit”
  • I have registered that new subscription in RevenueCat as a new product, and it is attached to a new Offering (though it is not marked as the “Current” one)

Is there anything else I should be checking?


10 replies

Badge +3

Just calling out some things which I know to be different, in case it makes a difference:

  1. I haven’t tried to upload any version of my development build under the new bundle ID yet, ie no version of the app with the new bundle ID is available on Testflight
  2. In the App Store Connect interface for the new (development) version of my app, in the settings page “App information”, the Bundle ID field has a dropdown for me to choose from, whereas in my original app, the Bundle ID field just shows me the bundle ID and doesn’t allow me to edit it at all
Badge +3

An interesting observation from my attempted debugging:

On the screen I’m screenshotting below, that’s where I’m getting the RevenueCat error about not being able to fetch any products. That screen shows the bundleID (`{Constants.expoConfig.ios.bundleIdentifier}`) and, if it can fetch offerings info, shows that.

When I build the app using Expo’s `npx expo run:ios` command, the app runs on my computer in iOS Simulator, and the RevenueCat call DOES work, ie fetches the offerings without an error. 

 

But when I run it on my physical phone using an Expo development build and `npx expo start --dev-client` on my computer, it still fails:

 

This suggests to me that something is different behind-the-scenes between the two build methods. The one on the simulator might be reading the bundleID from my app.config.js but still using the working bundleID from my production app?

Badge +3

Following up from the above - found out that the version of my app running `npx expo run:ios` is actually still using the old (production) bundleID, and thus is still working for RevenueCat, whereas the development version is using the new bundleID, which doesn’t seem to be picked up by RevenueCat.

I’ve tried creating a new app/bundleID in App Store Connect - a new development build is confirmed to be using that new bundleID. I set that bundleID up in RevenueCat and the corresponding subscriptions up in ASC, but again I’m getting the same error and RevenueCat can’t fetch any of the products.

It’s been more than 24hr since I created the first new bundleID, so it’s becoming increasingly unlikely it’s a propagation issue.

 

Here’s what the newest app looks like in ASC:

With this subscription:

Here’s the app’s setup in RevenueCat:

(The App Store Connect App-Specific Shared Secret is set as well)

 

Here’s my setup of the Products in RevenueCat:

 

That should be all the setup I need, right?

Userlevel 4
Badge +6

Hi @apotheonlabs,

Thanks for all the detailed info! With the amount of bundle ID switching going on, it’s definitely still worth quadruple checking that the current dev bundle id you’re using is the same across: RevenueCat, App Store Connect, and your app. 

Can you try putting the product for your dev build into the current offering and see if that allows the offerings to successfully fetch?

Badge +3

Hi @apotheonlabs,

Thanks for all the detailed info! With the amount of bundle ID switching going on, it’s definitely still worth quadruple checking that the current dev bundle id you’re using is the same across: RevenueCat, App Store Connect, and your app. 

Can you try putting the product for your dev build into the current offering and see if that allows the offerings to successfully fetch?

 

Thanks for your time and attention! I’ve just re-verified that I’m using the new bundleID consistently across my app, RevenueCat (it’s one of the 3 apps registered under this Project) and ASC (where the app shows “1.0 Prepare for Submission” and there is no TestFlight build yet - I’m testing this using an Expo development build).

Unfortunately adding the dev product to the current offering did not fix the issue. Here is a screenshot showing my current offering:

It has 1 package, “Monthly”, which has these 2 products attached to it now:

I just added the notomedev.premium.v1 product.

 

Is there anything else I can try? Alternatively, are there any API calls I can make to ASC to see if I can retrieve the products directly, just to try that?

Badge +3

Finally got it to work by creating a new Project for my development version (which has the side effect of creating a new API key that I use in `Purchase.configure()`, instead of adding my development version as another app within the same Project that houses my live version.

Don’t know if this is fully expected behavior or not - perhaps just my own misunderstanding about what a Project vs App should be - but at least I’m unblocked now.

Badge +1

This thread was incredibly helpful for me; thank you @apotheonlabs for all the details!

 

Did you need to have a build uploaded to ASC for this to work? I’m using Expo development builds and am still getting the same errors you were getting. I’ve put this under a separate Project in RevenueCat, but that doesn’t seem to solve the problem.

Badge +3

@Stevie Clifton In RevenueCat, I have 2 projects as I mentioned above - one for prod, one for dev. For my app, I have different bundleIDs for the prod vs dev versions, so that I can have the latest TestFlight Beta version (the “prod” version) and a RN development build (the “dev” version) simultaneously on my phone.

I did technically create a new app (not sure if that’s the right term) in ASC for the dev version’s bundleID, but I haven’t had to upload the dev version to ASC ever (there are no builds under that app for me in ASC).

How this looks in practice is that in my app.config.js, I have a boolean at the top of the file for const IS_DEV = true (which I flip to false to make a production build). Then in the exported config JSON, I have various key/values like…

"ios": {

"buildNumber": "16",

"bundleIdentifier": IS_DEV ? "dev bundle id here" : "prod bundle id here",

},

"extra": {

"ENV_NAME": IS_DEV ? "dev" : "prod",

"REVENUECAT_APPLE_KEY": IS_DEV ? 'dev revcat project key' : 'prod revcat project key',

"REVCAT_SUBSCRIPTION_NAME": IS_DEV ? 'dev subscription’s name' : 'prod subscription’s name',

},

 

Hope that helps!

Badge +1

Oh my gosh, I finally got it working. So stupid. I needed to fully setup my bank account in Apple. The IOS guide is really lacking here; it says:


Make sure Paid Applications Agreement is signed

Before you set up your products, make sure you have the latest Paid Applications Agreement signed in in the "Agreements, Tax, and Banking" module in App Store Connect. You will not be able to test in-app purchases until the latest version of this agreement is signed with Apple.

I had done that, but it’s not sufficient. You have to fully fill out the tax forms and add a bank account that is then validated by Apple. 

@apotheonlabs: I have an approach to configs that I think you might like; here’s how I have it setup in case it works for you! I found an easy way to define all my variables in one place and not have to use conditionals all over the place and not have to set and then unset things based on the environment.
 

At the top of my app.config.ts I have something like this:

let Config;
if (process.env.APP_ENV === 'production') {
Config = {
backendApiDomain: 'REDACTED',
customerIoSiteIdApiKey: 'REDACTED',
appId: 'REDACTED',
appName: 'REDACTED',
stage: 'REDACTED',
sentryDsn:
'REDACTED',
mixpanelToken: 'REDACTED',
revenueCatApiKey: 'REDACTED',
};
} else if (process.env.APP_ENV === 'development') {
Config = {
backendApiDomain: 'REDACTED',
customerIoSiteIdApiKey: 'REDACTED',
appId: 'REDACTED',
appName: 'REDACTED',
stage: 'REDACTED',
sentryDsn:
'REDACTED',
mixpanelToken: 'REDACTED',
revenueCatApiKey: 'REDACTED',
};
} else {
throw new Error(
'Could not find an APP_ENV environment variable. Set with `export APP_ENV=development` if developing locally.',
);
}

And then I can reference that config without having conditionals all throughout my code in the config, e.g.
 

export default ({ config }) => ({
...config,
name: Config.appName,
ios: {
supportsTablet: false,
bundleIdentifier: Config.appId,
},
android: {
package: Config.appId,
},
extra: {
...Config,
});

 

And in my eas.json, I have this, which automatically passes the right APP_ENV for builds:

{
"cli": {
"version": ">= 2.3.0",
"appVersionSource": "remote"
},
"build": {
"development": {
"env": {
"APP_ENV": "development"
},
"developmentClient": true,
"distribution": "internal",
},
"production": {
"env": {
"APP_ENV": "production"
},
"channel": "production",
"autoIncrement": true,
}
},
"submit": {
"production": {
"ios": {
"companyName": "REDACTED",
"ascAppId": "REDACTED"
}
}
}
}

And then I can reference all my Config vars in my code with this little library (you can rip out the Typescript stuff if you’re not using it)

// Config.ts
//
// Simple helper to re-export the environment variables we set
// in the app config
import Constants from 'expo-constants';

export interface AppConfig {
backendApiDomain: string;
appId: string;
appName: string;
stage: string;
customerIoSiteIdApiKey: string;
mixpanelToken: string;
sentryDsn: string;
revenueCatApiKey: string;
}

export default Constants.expoConfig?.extra as AppConfig;

 

And then all over my code I can import that helper library and use it like this:
 

import Config from 'constants/Config';

console.log("Here's my bundle identifier!", Config.appId);

 

Badge +1

I also just posted this request to fix the documentation to make it more clear that the tax/banking information needs to be filled out.

 

Reply