Paiements mobiles
Achats in-app avec RevenueCat pour les abonnements iOS et Android, et pourquoi Stripe direct ne fonctionne pas sur mobile.
Paiements mobiles
Les achats in-app sur iOS et Android doivent passer par les systèmes de paiement d'Apple et Google. Vous ne pouvez pas utiliser le checkout Stripe directement pour les biens numériques vendus dans une app mobile.
Pourquoi pas Stripe direct ?
Apple et Google exigent que les biens numériques et abonnements vendus dans les apps utilisent leurs systèmes d'achat in-app (IAP) :
| Plateforme | Exigence | Commission |
|---|---|---|
| iOS | Apple IAP requis pour les biens numériques | 15-30% |
| Android | Google Play Billing requis pour les biens numériques | 15-30% |
Stripe peut toujours être utilisé pour : les biens physiques, les services effectués hors de l'app, ou les abonnements web qui ne déverrouillent pas de contenu in-app.
RevenueCat
RevenueCat est la solution recommandée. Il encapsule les API IAP d'Apple et Google dans un SDK unique et simple :
npx expo install react-native-purchasesConfiguration
import Purchases from "react-native-purchases";
import { Platform } from "react-native";
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();
}, []);Afficher les produits
async function loadOfferings() {
const offerings = await Purchases.getOfferings();
const current = offerings.current;
if (current) {
const monthly = current.monthly; // Forfait mensuel
const annual = current.annual; // Forfait annuel
return { monthly, annual };
}
}Acheter un abonnement
async function purchaseSubscription(packageToPurchase: PurchasesPackage) {
try {
const { customerInfo } = await Purchases.purchasePackage(packageToPurchase);
const isPro = customerInfo.entitlements.active["pro"] !== undefined;
if (isPro) {
// Débloquer les fonctionnalités premium
router.push("/dashboard");
}
} catch (error: any) {
if (!error.userCancelled) {
Alert.alert("Purchase Failed", error.message);
}
}
}Vérifier le statut d'abonnement
Synchronisez le statut d'abonnement avec votre base Supabase via les webhooks RevenueCat :
// Vérifier localement d'abord
const customerInfo = await Purchases.getCustomerInfo();
const isPro = customerInfo.entitlements.active["pro"] !== undefined;
// Le webhook RevenueCat met à jour votre base Supabase
// Configurez dans : RevenueCat Dashboard > Integrations > Webhooks
// Endpoint : https://your-project.supabase.co/functions/v1/revenucat-webhookSynchronisez le statut d'abonnement avec Convex via les webhooks RevenueCat :
// Vérifier localement d'abord
const customerInfo = await Purchases.getCustomerInfo();
const isPro = customerInfo.entitlements.active["pro"] !== undefined;
// Le webhook RevenueCat appelle votre action HTTP Convex
// Configurez dans : RevenueCat Dashboard > Integrations > Webhooks
// Endpoint : https://your-project.convex.site/revenucat-webhookRestaurer 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");
}
}Écran Paywall
Construisez un écran paywall :
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>
);
}Configuration App Store
- Créez les abonnements dans App Store Connect (iOS) et Google Play Console (Android)
- Ajoutez les IDs de produit dans le dashboard RevenueCat
- Créez les Entitlements (ex. "pro") et liez-les aux produits
- Configurez les endpoints webhook pour la validation côté serveur