feat(mobile): integrate react-native-purchases (RevenueCat)
- Purchases.configure() runs with appUserID = restaurantId at every point the id becomes known (login resolve, cold-start rehydration, onboarding restaurant creation) — this must match what the backend webhook expects (see apps/api/src/routes/subscription.ts). - New account/subscription.tsx paywall: current entitlement status, offering packages with real store prices, purchase, restore. - Linked from the account screen. Native module — requires an EAS/dev-client build, not plain Expo Go.
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { Platform } from "react-native";
|
||||
import Purchases, { type CustomerInfo, type PurchasesOffering } from "react-native-purchases";
|
||||
|
||||
const API_KEY = process.env.EXPO_PUBLIC_REVENUECAT_API_KEY;
|
||||
export const PRO_ENTITLEMENT_ID = "Menul.io Pro";
|
||||
|
||||
let configuredForRestaurantId: string | null = null;
|
||||
|
||||
// appUserID is the restaurant id — the backend webhook (POST
|
||||
// /subscription/webhook) maps RevenueCat's app_user_id straight to
|
||||
// subscriptions.restaurant_id, so these must always match.
|
||||
export function configurePurchases(restaurantId: string) {
|
||||
if (!API_KEY) {
|
||||
console.warn("EXPO_PUBLIC_REVENUECAT_API_KEY missing — purchases disabled");
|
||||
return;
|
||||
}
|
||||
if (configuredForRestaurantId === restaurantId) return;
|
||||
|
||||
Purchases.configure({ apiKey: API_KEY, appUserID: restaurantId });
|
||||
if (Platform.OS !== "web") {
|
||||
Purchases.setLogLevel(__DEV__ ? Purchases.LOG_LEVEL.DEBUG : Purchases.LOG_LEVEL.WARN);
|
||||
}
|
||||
configuredForRestaurantId = restaurantId;
|
||||
}
|
||||
|
||||
export async function getCurrentOffering(): Promise<PurchasesOffering | null> {
|
||||
const offerings = await Purchases.getOfferings();
|
||||
return offerings.current;
|
||||
}
|
||||
|
||||
export async function getCustomerInfo(): Promise<CustomerInfo> {
|
||||
return Purchases.getCustomerInfo();
|
||||
}
|
||||
|
||||
export function isProActive(info: CustomerInfo): boolean {
|
||||
return info.entitlements.active[PRO_ENTITLEMENT_ID] !== undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user