fix(mobile): stop matching entitlement by hardcoded identifier string
RevenueCat's entitlement identifier contains U+2024 (ONE DOT LEADER), not a plain period — "Menul.io Pro" never matched the real "Menul⁚io Pro" key, so isProActive() stayed false even after a real purchase (confirmed via a genuine sandbox trial that RevenueCat recorded as active while the app kept showing "Ücretsiz plan"). RevenueCat's API doesn't allow renaming an entitlement's lookup_key after creation (405), so fixed on our side instead: this app only ever grants one entitlement, so "any active entitlement" == Pro, no identifier string needed.
This commit is contained in:
@@ -6,7 +6,7 @@ import { Ionicons } from "@expo/vector-icons";
|
|||||||
import type { CustomerInfo, PurchasesOffering, PurchasesPackage } from "react-native-purchases";
|
import type { CustomerInfo, PurchasesOffering, PurchasesPackage } from "react-native-purchases";
|
||||||
import Purchases from "react-native-purchases";
|
import Purchases from "react-native-purchases";
|
||||||
import { getActiveRestaurant } from "@/lib/active-restaurant";
|
import { getActiveRestaurant } from "@/lib/active-restaurant";
|
||||||
import { configurePurchases, getCurrentOffering, getCustomerInfo, isProActive, PRO_ENTITLEMENT_ID } from "@/lib/purchases";
|
import { configurePurchases, getActiveEntitlement, getCurrentOffering, getCustomerInfo, isProActive } from "@/lib/purchases";
|
||||||
|
|
||||||
export default function SubscriptionScreen() {
|
export default function SubscriptionScreen() {
|
||||||
const insets = useSafeAreaInsets();
|
const insets = useSafeAreaInsets();
|
||||||
@@ -74,7 +74,7 @@ export default function SubscriptionScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isPro = customerInfo ? isProActive(customerInfo) : false;
|
const isPro = customerInfo ? isProActive(customerInfo) : false;
|
||||||
const expiresAt = customerInfo?.entitlements.active[PRO_ENTITLEMENT_ID]?.expirationDate;
|
const expiresAt = customerInfo ? getActiveEntitlement(customerInfo)?.expirationDate : null;
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { Platform } from "react-native";
|
|||||||
import Purchases, { type CustomerInfo, type PurchasesOffering } from "react-native-purchases";
|
import Purchases, { type CustomerInfo, type PurchasesOffering } from "react-native-purchases";
|
||||||
|
|
||||||
const API_KEY = process.env.EXPO_PUBLIC_REVENUECAT_API_KEY;
|
const API_KEY = process.env.EXPO_PUBLIC_REVENUECAT_API_KEY;
|
||||||
export const PRO_ENTITLEMENT_ID = "Menul.io Pro";
|
|
||||||
|
|
||||||
let configuredForRestaurantId: string | null = null;
|
let configuredForRestaurantId: string | null = null;
|
||||||
|
|
||||||
@@ -32,6 +31,16 @@ export async function getCustomerInfo(): Promise<CustomerInfo> {
|
|||||||
return Purchases.getCustomerInfo();
|
return Purchases.getCustomerInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checking by exact entitlement identifier is fragile — RevenueCat's
|
||||||
|
// dashboard let the identifier get created with a non-ASCII character
|
||||||
|
// ("Menul⁚io Pro" uses U+2024, not a plain period), which silently never
|
||||||
|
// matched a hardcoded string. This app only ever grants one entitlement,
|
||||||
|
// so "any active entitlement" is Pro and doesn't depend on that string.
|
||||||
export function isProActive(info: CustomerInfo): boolean {
|
export function isProActive(info: CustomerInfo): boolean {
|
||||||
return info.entitlements.active[PRO_ENTITLEMENT_ID] !== undefined;
|
return Object.keys(info.entitlements.active).length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getActiveEntitlement(info: CustomerInfo) {
|
||||||
|
const [first] = Object.values(info.entitlements.active);
|
||||||
|
return first ?? null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user