patterntypescriptreact-nativeMajor
In-App Purchases with expo-in-app-purchases or react-native-iap
Viewed 0 times
in-app purchasesIAPStoreKitGoogle Play Billingreceipt validationsubscriptionsreact-native-iap
Error Messages
Problem
In-app purchases require integration with Apple StoreKit (iOS) and Google Play Billing (Android), handling purchase flows, receipt validation, and subscription management correctly.
Solution
Use
react-native-iap (more features) or expo-in-app-purchases (simpler Expo-native API). Always validate receipts server-side — never trust client-side validation. Implement purchaseUpdatedListener and purchaseErrorListener. Handle pending purchases from previous sessions on app start.Why
Client-side receipt validation can be bypassed. Server-side validation against Apple/Google APIs is the only trustworthy method. Apple and Google both provide server-to-server validation endpoints and webhooks for subscription events.
Gotchas
- You must call
finishTransactionafter every purchase — unfinished transactions are re-delivered on every launch - Sandbox accounts on iOS require a real device in most cases; simulator IAP is unreliable
- Google Play requires a minimum of 20 internal testers to test billing before release
- App Store review requires the IAP flow to be demonstrable — have a 'restore purchases' button
Code Snippets
expo-in-app-purchases listener with server validation
import * as InAppPurchases from 'expo-in-app-purchases';
async function initPurchases() {
await InAppPurchases.connectAsync();
InAppPurchases.setPurchaseListener(({ responseCode, results }) => {
if (responseCode === InAppPurchases.IAPResponseCode.OK) {
results?.forEach(async (purchase) => {
if (!purchase.acknowledged) {
await validateReceiptOnServer(purchase.transactionReceipt);
await InAppPurchases.finishTransactionAsync(purchase, true);
}
});
}
});
}Revisions (0)
No revisions yet.