RevenueCat setup with Expo for in-app purchases and subscriptions. Covers configuration, products, paywalls, sandbox testing, and Firebase Extension sync. Use when adding mobile payments or subscriptions.
You can't use Stripe or Polar.sh for digital goods in mobile apps. Apple and Google require their native billing systems. RevenueCat wraps both into one API.
npx expo install react-native-purchases
Requires a development build (not Expo Go). In development, the SDK enters mock mode.
Go to app.revenuecat.com and create a project.
import Purchases from 'react-native-purchases';
import { Platform } from 'react-native';
export async function initializePurchases() {
Purchases.configure({
apiKey: Platform.select({
ios: 'appl_your_ios_key',
android: 'goog_your_android_key',
})!,
});
}
Call this in your app's root component or entry file.
const offerings = await Purchases.getOfferings();
if (offerings.current) {
const packages = offerings.current.availablePackages;
// packages[0].product.title - "Premium Monthly"
// packages[0].product.priceString - "$9.99"
// packages[0].product.description - "Unlimited generations"
}
async function purchase(pkg: PurchasesPackage) {
try {
const { customerInfo } = await Purchases.purchasePackage(pkg);
if (customerInfo.entitlements.active['premium']) {
// User now has premium access!
navigation.navigate('Home');
}
} catch (e: any) {
if (!e.userCancelled) {
Alert.alert('Error', 'Purchase failed. Please try again.');
}
}
}
async function checkPremiumAccess(): Promise<boolean> {
const customerInfo = await Purchases.getCustomerInfo();
return !!customerInfo.entitlements.active['premium'];
}
Required by App Store guidelines:
async function restorePurchases() {
try {
const customerInfo = await Purchases.restorePurchases();
if (customerInfo.entitlements.active['premium']) {
Alert.alert('Restored', 'Your premium access has been restored!');
} else {
Alert.alert('No purchases found', 'No active subscriptions to restore.');
}
} catch (e) {
Alert.alert('Error', 'Could not restore purchases.');
}
}
Install the RevenueCat Firebase Extension to automatically sync purchase data:
customers/{userId}/ in FirestoreNow you can read subscription status directly from Firestore:
const customerDoc = await firestore()
.collection('customers')
.doc(userId)
.get();
const isActive = customerDoc.data()?.activeEntitlements?.includes('premium');
function Paywall() {
const [packages, setPackages] = useState([]);
useEffect(() => {
async function load() {
const offerings = await Purchases.getOfferings();
setPackages(offerings.current?.availablePackages || []);
}
load();
}, []);
return (
<View>
<Text>Upgrade to Premium</Text>
{packages.map((pkg) => (
<TouchableOpacity key={pkg.identifier} onPress={() => purchase(pkg)}>
<Text>{pkg.product.title}</Text>
<Text>{pkg.product.priceString}/month</Text>
</TouchableOpacity>
))}
<TouchableOpacity onPress={restorePurchases}>
<Text>Restore Purchases</Text>
</TouchableOpacity>
</View>
);
}
RevenueCat is free up to $2,500 monthly tracked revenue. After that, 1% of MTR.