eduardweb.
Expo & EASAvansat#react-native#expo#revenuecat#in-app-purchase

RevenueCat în Expo: Cum am salvat 3 zile de muncă și nervi la integrarea IAP

De Florin Manea, 25 apr. 2026 · 2 vizualizări · 3 like-uri

Postat acum 2 zile
typescript
import Purchases, { PurchasesOffering } from 'react-native-purchases';

// Setup-ul inițial într-un useEffect în App.ts sau un Provider
const setupPurchases = async () => {
  if (Platform.OS === 'ios') {
    await Purchases.configure({ apiKey: 'apple_api_key' });
  } else {
    await Purchases.configure({ apiKey: 'google_api_key' });
  }
};

// Exemplu de checkout simplificat
const handleBuy = async (packageToBuy: PurchasesPackage) => {
  try {
    const { customerInfo } = await Purchases.purchasePackage(packageToBuy);
    if (customerInfo.entitlements.active['premium_access']) {
      // Update UI sau navigare
      console.log('User is now premium');
    }
  } catch (e: any) {
    if (!e.userCancelled) {
      console.error('Eroare la plată:', e.message);
    }
  }
};

Am integrat in-app purchases (IAP) de vreo cinci ori până acum în diverse stack-uri și pot să spun cu mâna pe inimă că procesul e printre cele mai frustrante chestii din viața unui dev. Mai ales pe Android, unde documentația Google pare scrisă de cineva care te urăște personal. De când am trecut pe Expo cu RevenueCat, lucrurile s-au simplificat, dar tot ai de tras cu setup-ul de permisiuni și certificate.

La ultimul proiect, un SaaS de fitness cu vreo 8.000 de useri activi, am decis să nu ne mai batem capul cu server-side validation scris de noi. Am ales RevenueCat. De ce? Pentru că am economisit cam 30% din timpul de dezvoltare pe partea de billing și am scăpat de mentenanța webhook-urilor care crăpau la fiecare update de API de la Apple. În plus, ai un dashboard centralizat unde vezi exact cine a dat refund și cine are subscriptia activă, fără să sapi în log-uri de baze de date.

Setup-ul care te scoate din minți

Înainte să te apuci de cod, trebuie să înțelegi că în Expo Go nu merge nimic pe partea de plăți. Punct. Ai nevoie de un Development Build folosind expo-dev-client. Am văzut destui juniori care încercau să testeze purchases-expo în clientul standard și se mirau că primesc erori criptice sau crash-uri.

Pe partea de Apple, e relativ liniște: faci un App Specific Shared Secret și gata. Dar pe Google Play Console... e distracție mare. Trebuie să creezi un Service Account în Google Cloud, să-i dai drepturi de „Financial Data”, să legi proiectele între ele și să aștepți uneori și 24 de ore să se propage permisiunile. Dacă nu vezi produsele în aplicație după ce ai făcut totul „ca la carte”, probabil e de la permisiunile din Google Cloud sau n-ai publicat un build în Closed Testing track. Am pățit să stau 4 ore să caut un typo într-un JSON de key file, doar ca să realizez că Google încă nu procesase schimbarea de permisiuni.

Entitlements și Offering-uri

Aici e magia RevenueCat. În loc să verifici în cod dacă userul are „pro_monthly_v1” sau „pro_yearly_v2”, verifici un „Entitlement”. E un layer de abstractizare care te salvează când vrei să schimbi prețurile sau ID-urile produselor fără să faci update la aplicație în store. Pur și simplu mapezi noul produs la vechiul entitlement în dashboard-ul lor și codul tău rămâne intact.

Trade-off-ul e evident: ești vendor locked-in. Dacă RevenueCat decide să schimbe prețurile drastic sau serviciul lor pică (rareori, dar s-a întâmplat), ai o problemă majoră. Totuși, la 1% comision după ce treci de pragul de 10k$ revenue lunar, eu zic că merită. Scapi de grija ratelor de schimb valutar și a taxelor locale pe care Apple și Google le gestionează oricum haotic în rapoartele lor native.

Testing-ul și Sandbox-ul

Nu testa niciodată cu contul tău principal de Apple ID. Fă-ți conturi de sandbox dedicate. Pe Android e ceva mai simplu, adaugi mail-ul la „License Testing” în Play Console, dar pe iOS trebuie să te deloghezi din App Store în setările telefonului (nu din iCloud!) și să folosești userul de test acolo.

Un mic pont: pe iOS, erorile de tip „Product not found” sunt de cele mai multe ori din cauză că n-ai semnat „Paid Applications Agreement” în App Store Connect. Pare stupid, dar e cea mai comună cauză de blocaj pentru care pierzi ore întregi. Pe un proiect recent, am stat o dimineață întreagă până m-am prins că clientul nu dăduse „Accept” la noile termene legale apărute peste noapte.

Când vine vorba de cod, ține logica simplă. Nu inițializa SDK-ul peste tot în aplicație. Fă un provider în root-ul proiectului și folosește un hook custom pentru a accesa starea abonamentului.

Voi cum gestionați refund-urile? Le lăsați pe seama store-urilor sau aveți logică custom în spate care verifică webhook-urile din RevenueCat ca să tăiați accesul instant?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.