React Native In-App-Käufe mit RevenueCat implementieren
AI generated
RN
native
React Native · Monetarisierung · Abos · Billing
React Native In-App-Käufe mit RevenueCat implementieren
Abos ohne eigene StoreKit- und Billing-Logik

Wer In-App-Käufe in einer React-Native-App direkt über StoreKit und Google Play Billing umsetzt, verdoppelt jede Änderung an Produkten, Preisen und Empfangsprüfung für beide Plattformen. RevenueCat bündelt beide Billing-Systeme hinter einer gemeinsamen API mit Offerings, Entitlements und serverseitiger Quittungsprüfung, sodass sich Paywall, Kaufabwicklung und Abo-Status in einer einzigen React-Native-Codebasis pflegen lassen.

18 Min. Lesezeit react-native-purchases · Offerings · Entitlements · Webhooks Expo · Bare React Native · iOS · Android

1. Warum eigene StoreKit- und Billing-Integration schmerzt

Wer In-App-Käufe in React Native ohne eine Abstraktionsschicht umsetzt, muss zwei komplett unterschiedliche Billing-Systeme parallel pflegen. StoreKit auf iOS und Google Play Billing auf Android haben unterschiedliche Produktmodelle, unterschiedliche Quittungsformate und unterschiedliche Fehlerzustände. Jede Änderung an einem Abo-Produkt, jede neue Preisstufe und jede Anpassung an der Empfangsprüfung muss auf beiden Plattformen separat implementiert und getestet werden. Für In-App-Käufe in einer React-Native-App bedeutet das doppelten Wartungsaufwand für dieselbe Geschäftslogik.

Noch kritischer ist die serverseitige Quittungsprüfung. Ein Kauf, der nur clientseitig verifiziert wird, lässt sich mit modifizierten Apps oder manipulierten Quittungen fälschen. Korrekte Sicherheit erfordert einen eigenen Server, der Kaufbelege gegen die App-Store- und Play-Store-APIs validiert, Abo-Status synchron hält und auf Widerrufe, Rückerstattungen und Zahlungsprobleme reagiert. Genau diese Serverinfrastruktur, Quittungsprüfung, Retry-Logik und Statussynchronisation übernimmt RevenueCat als Managed Service, sodass die React-Native-App nur noch gegen eine einzige, plattformunabhängige API programmiert.

Der dritte Schmerzpunkt ist das Sandbox-Testing. Apples Sandbox-Umgebung hat eigene Latenzen, beschleunigte Abo-Zyklen und gelegentliche Inkonsistenzen, während Googles Testspur ein eigenes Setup mit Lizenz-Testern verlangt. Ohne eine Abstraktionsschicht müssen Entwickler beide Testumgebungen einzeln beherrschen, bevor der erste Kauf überhaupt zuverlässig durchläuft. RevenueCat normalisiert auch diesen Teil, indem Sandbox-Käufe im Dashboard genauso sichtbar sind wie Produktivkäufe.

2. RevenueCat-Grundkonzepte: Offerings, Packages, Entitlements

RevenueCat führt drei zentrale Begriffe ein, die das Denken über In-App-Käufe von plattformspezifischen Produkt-IDs auf Geschäftslogik verschieben. Ein Product ist die rohe Store-Referenz, also die Produkt-ID aus App Store Connect oder der Play Console. Ein Package bündelt ein Product mit einem Identifier wie $rc_monthly oder $rc_annual und macht Laufzeit-Varianten plattformübergreifend adressierbar, ohne dass der Code jemals die rohe Produkt-ID kennen muss. Ein Offering wiederum ist eine Sammlung von Packages, die zusammen einer Paywall entsprechen, zum Beispiel „Standard-Paywall" oder eine A/B-Test-Variante „Rabatt-Paywall". Das vierte und wichtigste Konzept ist das Entitlement. Ein Entitlement wie premium oder pro_features repräsentiert eine Freischaltung im Produkt, unabhängig davon, über welches Package oder welche Plattform sie erworben wurde. Der React-Native-Code fragt nie „hat der Nutzer Produkt X gekauft", sondern „hat der Nutzer das Entitlement premium". Dieses Modell erlaubt es, Preisexperimente, Rabattaktionen und neue Laufzeiten im RevenueCat-Dashboard zu ändern, ohne den App-Code oder die Store-Konfiguration anzufassen.

Diese Trennung zwischen Produkt, Package, Offering und Entitlement ist der eigentliche Wert von RevenueCat gegenüber einer selbstgebauten Lösung. Änderungen an Preisen, neue Länder-Preisstufen oder ein zusätzliches Jahresabo lassen sich im Dashboard konfigurieren und sind sofort in der App verfügbar, ohne ein neues Deployment. Die App-Logik bleibt stabil, weil sie ausschließlich gegen Entitlements prüft, während sich die zugrunde liegenden Packages und Offerings beliebig weiterentwickeln.

3. Produkte in App Store Connect und Play Console anlegen

Bevor RevenueCat überhaupt etwas anzeigen kann, müssen die eigentlichen In-App-Produkte in App Store Connect und in der Google Play Console angelegt werden. In App Store Connect wird unter „Auto-erneuerbare Abos" eine Abo-Gruppe erstellt und darin die einzelnen Laufzeiten (monatlich, jährlich) mit eindeutigen Produkt-IDs definiert, üblicherweise nach dem Muster com.app.premium.monthly. In der Play Console entsteht analog ein Abo-Produkt mit Basisplänen für dieselben Laufzeiten. Beide Stores verlangen zusätzlich Metadaten wie Anzeigename, Beschreibung und lokale Preisstufen pro Land.

Sobald die Produkte in beiden Stores existieren, werden sie im RevenueCat-Dashboard unter „Products" importiert und dort einem Entitlement zugeordnet, zum Beispiel wird sowohl com.app.premium.monthly als auch das entsprechende Android-Produkt dem Entitlement premium zugewiesen. Anschließend entsteht ein Offering, das beide Laufzeiten als Packages enthält. Dieser Schritt findet ausschließlich im Dashboard statt und erfordert keine Codeänderung in der React-Native-App, was Preisexperimente und neue Laufzeiten deutlich beschleunigt.

4. SDK-Installation und Konfiguration

Die Integration in eine React-Native- oder Expo-App beginnt mit der Installation von react-native-purchases. In einem Expo-Projekt mit Development Build oder EAS Build funktioniert das Paket wie jedes andere native Modul, solange kein Expo Go verwendet wird, da native Module in Expo Go nicht verfügbar sind. Nach der Installation wird die API-Konfiguration einmalig beim App-Start ausgeführt, idealerweise in der obersten Komponente noch vor dem ersten Rendern der eigentlichen App-Navigation.

Wichtig ist, dass für iOS und Android unterschiedliche API-Keys aus dem RevenueCat-Dashboard verwendet werden, auch wenn beide Plattformen dasselbe Entitlement-Setup teilen. Zusätzlich sollte direkt bei der Konfiguration ein appUserID übergeben werden, sobald ein Nutzer eingeloggt ist, damit Käufe eindeutig einem Konto zugeordnet werden und nicht nur an eine anonyme, geräteinterne ID gebunden bleiben. Ohne diesen Schritt gehen Abo-Zuordnungen bei Geräteneuinstallationen oder Plattformwechseln verloren.


# Install the RevenueCat SDK for React Native
npm install react-native-purchases

# For bare React Native projects, install native pods
cd ios && pod install && cd ..

# Expo projects need a Development Build since this is a native module
npx expo install expo-dev-client
eas build --profile development --platform all

// App.tsx - configure RevenueCat once at app startup
import { useEffect } from 'react';
import { Platform } from 'react-native';
import Purchases, { LOG_LEVEL } from 'react-native-purchases';

const IOS_API_KEY = 'appl_XXXXXXXXXXXXXXXXXXXXXXXXXXX';
const ANDROID_API_KEY = 'goog_XXXXXXXXXXXXXXXXXXXXXXXXXXX';

export function configurePurchases(userId?: string) {
  Purchases.setLogLevel(LOG_LEVEL.WARN);

  const apiKey = Platform.OS === 'ios' ? IOS_API_KEY : ANDROID_API_KEY;

  Purchases.configure({
    apiKey,
    appUserID: userId, // pass the logged-in user id to link purchases to an account
  });
}

export default function App() {
  useEffect(() => {
    configurePurchases();
  }, []);

  return null; // rest of the app tree
}

5. Paywall-UI: Offerings abrufen und anzeigen

Sobald das SDK konfiguriert ist, lässt sich das aktuelle Offering über Purchases.getOfferings() abrufen. Das zurückgegebene Objekt enthält ein current-Offering mit allen darin enthaltenen Packages, jedes Package trägt bereits die formatierte Preisangabe in der lokalen Währung des Nutzers. Für die Paywall-UI bedeutet das, dass keine eigene Preisformatierung oder Währungsumrechnung implementiert werden muss, RevenueCat liefert bereits store-lokalisierte Preise mit.

Eine robuste Paywall-Komponente sollte während des Ladens der Offerings einen Ladezustand anzeigen, da der Netzwerkaufruf je nach Verbindung spürbar Zeit braucht, und einen Fallback für den Fall bereitstellen, dass kein Offering konfiguriert oder verfügbar ist, etwa weil die Store-Produkte noch nicht freigegeben wurden. Häufig wird zusätzlich ein A/B-Test über mehrere Offerings gefahren, RevenueCat weist Nutzern dabei automatisch eine Variante zu und meldet diese an Analytics-Tools weiter, sodass Conversion-Unterschiede zwischen Paywall-Varianten direkt messbar werden.


// PaywallScreen.tsx - fetch offerings and render purchase options
import { useEffect, useState } from 'react';
import { View, Text, TouchableOpacity, ActivityIndicator } from 'react-native';
import Purchases, { PurchasesOffering } from 'react-native-purchases';

export function PaywallScreen() {
  const [offering, setOffering] = useState<PurchasesOffering | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function loadOfferings() {
      try {
        const offerings = await Purchases.getOfferings();
        setOffering(offerings.current);
      } catch (error) {
        console.error('Failed to load offerings', error);
      } finally {
        setLoading(false);
      }
    }
    loadOfferings();
  }, []);

  if (loading) return <ActivityIndicator />;
  if (!offering) return <Text>No offering available right now.</Text>;

  return (
    <View>
      {offering.availablePackages.map((pkg) => (
        <TouchableOpacity key={pkg.identifier} onPress={() => handlePurchase(pkg)}>
          <Text>{pkg.product.title} - {pkg.product.priceString}</Text>
        </TouchableOpacity>
      ))}
    </View>
  );
}

6. Kaufabwicklung: purchasePackage und Restore

Der eigentliche Kauf wird über Purchases.purchasePackage(package) ausgelöst, was intern die native Store-UI öffnet, den Zahlungsvorgang abwickelt und nach Abschluss ein CustomerInfo-Objekt mit dem aktuellen Entitlement-Status zurückgibt. Fehlerbehandlung ist hier zentral: Nutzer brechen den Kaufdialog ab, Zahlungsmethoden schlagen fehl, oder das Netzwerk bricht während der Quittungsprüfung ab. RevenueCat unterscheidet zwischen einem vom Nutzer abgebrochenen Kauf und einem tatsächlichen Fehler, sodass die App bei einem Abbruch keine Fehlermeldung anzeigen muss.

Ebenso unverzichtbar ist die Restore-Funktion über Purchases.restorePurchases(). Nutzer wechseln Geräte, installieren die App neu oder nutzen ein zweites Gerät mit demselben Store-Konto, und in all diesen Fällen erwarten sie, dass bereits erworbene Abos automatisch wieder erkannt werden. Ein Restore-Button in den Einstellungen ist bei iOS-Apps sogar eine Voraussetzung für die App-Store-Freigabe, da Apple das explizit als Review-Kriterium prüft. RevenueCat gleicht bei einem Restore die Store-Kontoinformationen mit dem eigenen Server ab und aktualisiert Entitlements entsprechend.


// Purchase flow with proper cancel vs. error handling
import Purchases, { PurchasesPackage, PurchasesError } from 'react-native-purchases';

async function handlePurchase(pkg: PurchasesPackage) {
  try {
    const { customerInfo } = await Purchases.purchasePackage(pkg);
    const isPremium = customerInfo.entitlements.active['premium'] !== undefined;
    if (isPremium) {
      // Unlock premium content in the UI
    }
  } catch (error) {
    const purchaseError = error as PurchasesError;
    if (purchaseError.userCancelled) {
      return; // user closed the native purchase sheet, no error UI needed
    }
    console.error('Purchase failed', purchaseError.message);
  }
}

async function handleRestore() {
  try {
    const customerInfo = await Purchases.restorePurchases();
    const isPremium = customerInfo.entitlements.active['premium'] !== undefined;
    return isPremium;
  } catch (error) {
    console.error('Restore failed', error);
    return false;
  }
}

7. Entitlement-Status reaktiv prüfen

Statt bei jedem App-Start manuell den Entitlement-Status abzufragen, bietet RevenueCat einen Listener über Purchases.addCustomerInfoUpdateListener, der bei jeder Änderung am Abo-Status automatisch feuert. Das ist wichtig, weil sich Entitlements auch außerhalb der App ändern können, etwa wenn ein Abo im App-Store-Kontoeinstellungen-Bildschirm gekündigt wird oder eine Zahlung fehlschlägt und der Store das Abo automatisch pausiert.

Ein sauberes Muster ist, den Entitlement-Status in einem globalen Context oder Store wie Zustand zu halten und diesen Context durch den CustomerInfo-Listener aktuell zu halten. Jede Komponente, die prüfen muss, ob ein Nutzer Zugriff auf Premium-Inhalte hat, liest dann ausschließlich aus diesem zentralen Zustand, statt eigene RevenueCat-Aufrufe zu duplizieren. Das vermeidet Race Conditions zwischen mehreren gleichzeitigen Statusabfragen und hält die UI konsistent, sobald sich der Abo-Status ändert.

8. Server-seitige Validierung und Webhooks

Auch mit RevenueCat bleibt eine serverseitige Komponente sinnvoll, sobald Premium-Inhalte oder Funktionen über einen eigenen Backend-Dienst ausgeliefert werden, nicht nur clientseitig in React Native. RevenueCat sendet bei jedem relevanten Ereignis, etwa einer Verlängerung, einer Kündigung, einem Zahlungsproblem oder einem Rückerstattung, einen Webhook an eine vom Entwickler konfigurierte Server-URL. Der eigene Server aktualisiert daraufhin seine eigene Datenbank und kann unabhängig vom Client-Zustand entscheiden, ob ein Nutzer Zugriff auf serverseitige Premium-Ressourcen erhält.

Dieses Muster ist besonders wichtig für Abo-Verlängerungen im Hintergrund, die passieren, während die App gar nicht geöffnet ist. Ohne Webhook würde der Server erst beim nächsten App-Start über den aktuellen Status erfahren, mit Webhook ist die Serverdatenbank nahezu in Echtzeit synchron. Für zusätzliche Sicherheit signiert RevenueCat jeden Webhook-Aufruf mit einem Autorisierungsheader, den der eigene Endpunkt vor der Verarbeitung prüfen sollte, um gefälschte Aufrufe abzulehnen.


{
  "api_version": "1.0",
  "event": {
    "type": "RENEWAL",
    "id": "evt_1234567890",
    "app_user_id": "user_98765",
    "product_id": "com.app.premium.monthly",
    "entitlement_ids": ["premium"],
    "period_type": "NORMAL",
    "purchased_at_ms": 1769270400000,
    "expiration_at_ms": 1771948800000,
    "environment": "PRODUCTION",
    "store": "APP_STORE",
    "currency": "EUR",
    "price": 4.99
  }
}

9. Testing und Vergleich zu Alternativen

Für iOS-Tests bietet Xcode das StoreKit Testing Framework, mit dem sich Käufe, Abo-Verlängerungen und sogar Kündigungen vollständig lokal simulieren lassen, ohne echte Sandbox-Accounts oder Netzwerkverbindungen zur Apple-Infrastruktur. Für Produktionstests vor dem Launch sind zusätzlich echte Sandbox-Tester-Accounts in App Store Connect notwendig, da nur diese das reale Timing von Abo-Verlängerungen abbilden, wenn auch stark beschleunigt gegenüber der Produktivumgebung. Auf Android-Seite übernehmen Lizenz-Tester in der Play Console eine ähnliche Rolle.

RevenueCat ist nicht die einzige Lösung für diese Problemklasse, Adapty und Qonversion verfolgen einen ähnlichen Ansatz mit eigenen Stärken bei Paywall-A/B-Testing beziehungsweise Attribution. Die Wahl hängt stark davon ab, wie tief die Integration mit bestehenden Analytics- und Attributionstools sein muss und wie ausgereift die serverseitige Webhook-Infrastruktur des Anbieters bereits ist.

Kriterium RevenueCat Raw StoreKit / Play Billing Adapty / Qonversion
Setup-Aufwand Gering, SDK + Dashboard Hoch, zwei getrennte Implementierungen Gering bis mittel
Cross-Platform-API Ja, eine gemeinsame API Nein, plattformspezifisch Ja
Server-Quittungsprüfung Managed, inklusive Webhooks Muss selbst gebaut werden Managed
Analytics/Attribution Gut, viele Integrationen Keine eingebaut Teils Fokus-Feature
Preismodell Kostenlos bis Umsatzschwelle, dann % Keine Zusatzkosten Ähnlich RevenueCat

In der Praxis überwiegt der Zeitgewinn durch RevenueCat die moderaten Umsatzgebühren bei den meisten Teams deutlich, insbesondere weil die Alternative, eine eigene serverseitige Quittungsprüfung mit vollständiger Webhook-Infrastruktur, Wochen an Entwicklungszeit kostet, die sich bei einer wachsenden App immer wieder in Wartungsaufwand niederschlägt.

Mironsoft

React Native Entwicklung, App-Monetarisierung und Backend-Integration

In-App-Käufe zuverlässig in eurer React-Native-App verankern?

Wir implementieren RevenueCat-Paywalls, Entitlement-Logik und serverseitige Webhook-Anbindung, damit Abo-Umsätze zuverlässig ankommen und sich Preisexperimente ohne neues App-Release fahren lassen.

RevenueCat-Setup

Offerings, Entitlements und Produktkonfiguration in App Store Connect und Play Console

Paywall-Entwicklung

Konversionsstarke Paywall-UI mit A/B-Test-Anbindung und Restore-Flow

Backend-Integration

Webhook-Verarbeitung und Entitlement-Synchronisation mit eigenem Server

10. Zusammenfassung

React Native In-App-Käufe mit RevenueCat lösen das Kernproblem der doppelten Billing-Implementierung, indem StoreKit und Google Play Billing hinter einer gemeinsamen API aus Offerings, Packages und Entitlements verschwinden. Statt Produkt-IDs direkt im App-Code abzufragen, prüft die Anwendung nur noch gegen Entitlements wie premium, während Preisänderungen und neue Laufzeiten im Dashboard konfiguriert werden, ohne ein neues App-Release zu erfordern.

Server-seitige Webhooks halten die eigene Backend-Datenbank synchron mit Verlängerungen, Kündigungen und Zahlungsproblemen, auch wenn die App gerade nicht geöffnet ist. In Kombination mit StoreKit Testing und Sandbox-Accounts lässt sich der komplette Kauf- und Abo-Lebenszyklus vor dem Launch zuverlässig validieren. Gegenüber einer selbstgebauten Lösung überwiegt der eingesparte Entwicklungs- und Wartungsaufwand die moderaten RevenueCat-Gebühren in den allermeisten Projekten deutlich.

React Native In-App-Käufe mit RevenueCat — Das Wichtigste auf einen Blick

Konzepte

Offerings bündeln Packages, Packages referenzieren Store-Produkte, Entitlements entkoppeln Geschäftslogik von Store-Details.

Integration

react-native-purchases konfigurieren, Offerings abrufen, mit purchasePackage kaufen, mit restorePurchases wiederherstellen.

Server-Synchronisation

Webhooks für Verlängerungen, Kündigungen und Zahlungsprobleme halten das eigene Backend in Echtzeit aktuell.

Testing

StoreKit Testing in Xcode für lokale Simulation, Sandbox-Accounts und Play-Console-Lizenztester vor dem Launch.

11. FAQ: React Native In-App-Käufe mit RevenueCat

1Was ist RevenueCat?
Ein Managed Service, der StoreKit und Play Billing hinter einer gemeinsamen API vereint, für Kaufabwicklung, Entitlement-Prüfung und Quittungsvalidierung.
2Package vs. Offering vs. Entitlement?
Package = Store-Produkt mit Laufzeit. Offering = Bündel von Packages für eine Paywall. Entitlement = die eigentliche Freischaltung, unabhängig vom Kaufweg.
3Funktioniert es in Expo Go?
Nein, natives Modul. Development Build oder Bare React Native mit Pods notwendig.
4Warum ist Restore Pflicht?
Apple prüft das im App-Review. Nutzer müssen Abos bei Geräteneuinstallation wiederherstellen können.
5Wie prüfe ich Premium-Zugriff?
customerInfo.entitlements.active['premium'] abfragen, nie direkt gegen Produkt-IDs prüfen.
6Wozu Webhooks?
Synchronisieren Verlängerungen und Kündigungen mit dem eigenen Backend, auch wenn die App geschlossen ist.
7Wie teste ich Käufe?
StoreKit Testing in Xcode lokal, ergänzend Sandbox-Accounts und Play-Console-Lizenztester.
8Was kostet RevenueCat?
Kostenlos bis zu einer Umsatzschwelle, danach prozentualer Anteil am Umsatz.
9Preisänderungen ohne Release?
Ja, solange die App gegen Entitlements statt Produkt-IDs prüft, wirken Dashboard-Änderungen sofort.
10RevenueCat vs. Adapty/Qonversion?
Ähnliche Grundabstraktion, RevenueCat ist Marktführer mit breitester Analytics-Integration.