ScaleRocket/Mobile

Configuration RevenueCat

Configurez RevenueCat pour les achats in-app et abonnements sur iOS et Android — de la création de compte aux tests sandbox.

Configuration RevenueCat

RevenueCat gère les achats in-app et les abonnements pour iOS et Android. Il encapsule le StoreKit d'Apple et Google Play Billing dans un SDK unique pour que vous n'ayez pas à gérer la validation des reçus, le suivi du statut d'abonnement ou les différences entre plateformes.

Pourquoi pas Stripe ? Apple et Google exigent que les biens numériques vendus dans les apps utilisent leurs systèmes d'achat in-app. Stripe ne peut être utilisé que pour les biens physiques ou les services effectués hors de l'app.

1. Créer un compte RevenueCat

  1. Allez sur app.revenuecat.com et inscrivez-vous
  2. Créez un nouveau Projet (ex. "Mon App")
  3. Ajoutez vos plateformes :
    • Apple App Store — vous aurez besoin de vos identifiants App Store Connect
    • Google Play Store — vous aurez besoin du compte de service Google Play Console

Configuration Apple App Store

  1. Dans RevenueCat, allez dans Project Settings > Apps > App Store App
  2. Entrez votre Bundle ID (doit correspondre à app.jsonios.bundleIdentifier)
  3. Ajoutez votre App Store Connect Shared Secret :
    • Allez sur App Store Connect → Votre App → Général > Informations de l'app > Secret partagé spécifique à l'app
    • Copiez le secret et collez-le dans RevenueCat

Configuration Google Play Store

  1. Dans RevenueCat, allez dans Project Settings > Apps > Play Store App
  2. Entrez votre Package Name (doit correspondre à app.jsonandroid.package)
  3. Uploadez votre clé JSON du compte de service :
    • Dans Google Play ConsoleConfiguration > Accès API
    • Créez un compte de service avec les permissions Données financières
    • Téléchargez la clé JSON et uploadez-la dans RevenueCat

2. Configurer les produits

Dans App Store Connect (iOS)

  1. Allez sur App Store Connect → Votre App → Monétisation > Abonnements
  2. Créez un Groupe d'abonnements (ex. "Premium")
  3. Ajoutez les produits d'abonnement :
    • Mensuel — ex. com.yourapp.monthly à 9,99$/mois
    • Annuel — ex. com.yourapp.annual à 79,99$/an
  4. Remplissez le nom d'affichage, la description et les tarifs pour chaque produit
  5. Soumettez pour review (les produits doivent être approuvés avant de fonctionner en sandbox)

Dans Google Play Console (Android)

  1. Allez sur Google Play Console → Votre App → Monétiser > Produits > Abonnements
  2. Créez les produits d'abonnement avec les mêmes IDs que sur iOS :
    • Mensuelcom.yourapp.monthly
    • Annuelcom.yourapp.annual
  3. Définissez les tarifs et la période de facturation pour chaque produit
  4. Activez les produits

3. Configurer les produits RevenueCat

De retour dans le dashboard RevenueCat :

  1. Allez dans Products et ajoutez chaque ID de produit des deux plateformes
  2. Créez un Entitlement (ex. "pro") — il représente ce que l'utilisateur débloque
  3. Attachez vos produits à l'entitlement
  4. Créez une Offering (ex. "default") — c'est ce que vous affichez aux utilisateurs
  5. Ajoutez des Packages à l'offering (Mensuel, Annuel) et liez-les à vos produits

4. Installer le SDK

npx expo install react-native-purchases

Initialiser RevenueCat

Récupérez vos clés API depuis le dashboard RevenueCat (Project Settings > Apps > API Keys) :

// lib/revenuecat.ts
import Purchases from "react-native-purchases";
import { Platform } from "react-native";

export async function initRevenueCat() {
  Purchases.configure({
    apiKey: Platform.OS === "ios"
      ? "appl_your_ios_api_key"
      : "goog_your_android_api_key",
  });
}

Appelez ceci dans votre layout racine :

// app/_layout.tsx
useEffect(() => {
  initRevenueCat();
}, []);

Identifier les utilisateurs

Liez RevenueCat à votre utilisateur authentifié pour que le statut d'abonnement se synchronise entre les appareils :

// Après une connexion réussie
const { data: { user } } = await supabase.auth.getUser();
if (user) {
  await Purchases.logIn(user.id);
}
// Après une connexion réussie
const userId = useConvexAuth().userId;
if (userId) {
  await Purchases.logIn(userId);
}

5. Configurer les webhooks

Les webhooks RevenueCat notifient votre backend quand un abonnement change (renouvellement, annulation, expiration, etc.).

  1. Créez une Edge Function Supabase pour gérer les événements webhook :
supabase functions new revenuecat-webhook
  1. Dans le dashboard RevenueCat, allez dans Integrations > Webhooks
  2. Définissez l'URL du webhook : https://your-project.supabase.co/functions/v1/revenuecat-webhook
  3. Ajoutez un header d'autorisation pour la sécurité
  4. Votre Edge Function doit mettre à jour le statut d'abonnement dans votre base de données :
// supabase/functions/revenuecat-webhook/index.ts
Deno.serve(async (req) => {
  const body = await req.json();
  const event = body.event;
  const appUserId = event.app_user_id;

  // Mettre à jour le statut d'abonnement selon le type d'événement
  // event.type: INITIAL_PURCHASE, RENEWAL, CANCELLATION, EXPIRATION, etc.
  await supabase.from("profiles").update({
    plan: event.type === "EXPIRATION" ? "free" : "pro",
    revenuecat_app_user_id: appUserId,
  }).eq("id", appUserId);

  return new Response("ok");
});
  1. Créez une action HTTP Convex pour gérer les événements webhook
  2. Dans le dashboard RevenueCat, allez dans Integrations > Webhooks
  3. Définissez l'URL du webhook : https://your-project.convex.site/revenuecat-webhook
  4. Votre action HTTP doit mettre à jour le statut d'abonnement :
// convex/http.ts
http.route({
  path: "/revenuecat-webhook",
  method: "POST",
  handler: async (ctx, req) => {
    const body = await req.json();
    const event = body.event;
    const appUserId = event.app_user_id;

    // Mettre à jour le statut d'abonnement selon le type d'événement
    await ctx.runMutation(internal.subscriptions.updateStatus, {
      userId: appUserId,
      plan: event.type === "EXPIRATION" ? "free" : "pro",
    });

    return new Response("ok");
  },
});

Types d'événements webhook

ÉvénementQuand il se déclenche
INITIAL_PURCHASEPremier achat d'abonnement
RENEWALAbonnement renouvelé
CANCELLATIONUtilisateur a annulé (toujours actif jusqu'à la fin de la période)
EXPIRATIONAbonnement expiré
BILLING_ISSUEÉchec de paiement
PRODUCT_CHANGEUtilisateur a changé de plan (upgrade/downgrade)

6. Tester en mode sandbox

Tests sandbox iOS

  1. Dans App Store Connect, allez dans Utilisateurs et accès > Sandbox > Comptes de test
  2. Créez un compte testeur sandbox (utilisez un vrai email auquel vous avez accès)
  3. Sur votre appareil de test : Réglages > App Store > Compte Sandbox — connectez-vous avec le compte sandbox
  4. Lancez votre build de développement — les achats utiliseront automatiquement l'environnement sandbox
  5. Les abonnements sandbox se renouvellent à un rythme accéléré :
    • 1 semaine → 3 minutes
    • 1 mois → 5 minutes
    • 1 an → 1 heure

Tests sandbox Android

  1. Dans Google Play Console, allez dans Configuration > Tests de licence
  2. Ajoutez les adresses Gmail des testeurs
  3. Uploadez un APK/AAB sur n'importe quel track (le test interne fonctionne)
  4. Les testeurs peuvent effectuer des achats sans être facturés

Vérifier dans RevenueCat

  1. Effectuez un achat test sur votre appareil
  2. Vérifiez le dashboard RevenueCat → Customers pour voir l'achat
  3. Vérifiez que votre endpoint webhook a reçu l'événement
  4. Confirmez que votre base de données a été mise à jour avec le bon statut d'abonnement

RevenueCat Paywall

Construisez un écran paywall pour afficher vos offres :

function PaywallScreen() {
  const [offerings, setOfferings] = useState<PurchasesOfferings | null>(null);

  useEffect(() => {
    Purchases.getOfferings().then(setOfferings);
  }, []);

  return (
    <ScreenLayout>
      <Text style={styles.title}>Upgrade to Pro</Text>
      <Text style={styles.subtitle}>Unlock all features</Text>

      {offerings?.current?.availablePackages.map((pkg) => (
        <TouchableOpacity key={pkg.identifier} onPress={() => purchaseSubscription(pkg)}>
          <Text>{pkg.product.title}</Text>
          <Text>{pkg.product.priceString}/month</Text>
        </TouchableOpacity>
      ))}

      <Button title="Restore Purchases" variant="ghost" onPress={restorePurchases} />
    </ScreenLayout>
  );
}

Restaurer les achats

Requis par Apple — les utilisateurs doivent pouvoir restaurer leurs achats sur de nouveaux appareils :

async function restorePurchases() {
  try {
    const customerInfo = await Purchases.restorePurchases();
    const isPro = customerInfo.entitlements.active["pro"] !== undefined;
    Alert.alert(isPro ? "Restored!" : "No active subscription found");
  } catch (error) {
    Alert.alert("Error", "Could not restore purchases");
  }
}

On this page