fr3em1nd/react-native-in-app-micro-purchases
A unified, high-level in-app purchase system for React Native that simplifies monetization across iOS, Android, and Web platforms while handling receipts, analytics, and fallbacks.
react-native-in-app-micro-purchases
A unified, high-level in-app purchase system for React Native that simplifies monetization across iOS, Android, and Web platforms while handling receipts, analytics, and fallbacks.
Created by Solomon Monotilla
Features
- Unified API - One interface for iOS (StoreKit 2), Android (Google Play Billing), and Web (Stripe/PayPal)
- Offline Receipt Validation - Caches receipts securely and auto-syncs when online
- Web Fallback Support - Handle purchases in web apps via Stripe or PayPal
- Built-in Analytics Hooks - Track purchase events with any analytics provider
- Secure Storage - Platform-native encryption (iOS Keychain, Android Keystore)
- React Hooks - Modern React integration with hooks API
- TypeScript First - Full type definitions included
- Test Mode Support - Easy sandbox/test environment configuration
Installation
npm install react-native-in-app-micro-purchases
# or
yarn add react-native-in-app-micro-purchasesiOS Setup
cd ios && pod installEnsure your app has the In-App Purchase capability enabled in Xcode.
Android Setup
Add billing permission (automatically included via library manifest):
<uses-permission android:name="com.android.vending.BILLING" />Web Setup (Optional)
For web fallback support, install Stripe:
npm install @stripe/stripe-js @stripe/react-stripe-jsQuick Start
Basic Usage
import { IAP } from 'react-native-in-app-micro-purchases';
// Initialize
await IAP.init({
environment: __DEV__ ? 'sandbox' : 'production',
});
// Load products
const products = await IAP.getProducts(['premium_monthly', 'premium_yearly']);
// Make a purchase
try {
const result = await IAP.purchase('premium_monthly');
console.log('Purchased!', result);
} catch (error) {
if (error.code === 'E_PURCHASE_CANCELLED') {
console.log('User cancelled');
} else {
console.error('Purchase failed', error);
}
}
// Restore purchases
const restored = await IAP.restorePurchases();
// Check subscription status
const status = await IAP.getSubscriptionStatus();React Hooks
import { useInAppPurchase } from 'react-native-in-app-micro-purchases';
function Store() {
const {
isReady,
isLoading,
products,
purchase,
error,
} = useInAppPurchase({
productIds: ['premium_monthly', 'premium_yearly'],
});
if (!isReady) return <Loading />;
return (
<View>
{products.map((product) => (
<TouchableOpacity
key={product.productId}
onPress={() => purchase(product.productId)}
disabled={isLoading}
>
<Text>{product.title}</Text>
<Text>{product.price}</Text>
</TouchableOpacity>
))}
{error && <Text style={{ color: 'red' }}>{error.message}</Text>}
</View>
);
}Subscription Hook
import { useSubscription } from 'react-native-in-app-micro-purchases';
function PremiumContent() {
const { isSubscribed, isInTrial, subscription } = useSubscription({
productId: 'premium_monthly',
});
if (!isSubscribed) {
return <SubscribePrompt />;
}
return (
<View>
{isInTrial && <Text>You're in a free trial!</Text>}
<PremiumFeatures />
</View>
);
}API Reference
IAP.init(config)
Initialize the IAP system.
interface IAPConfig {
apiKey?: string; // API key for server validation
environment?: 'production' | 'sandbox';
platform?: 'ios' | 'android' | 'web';
stripePublishableKey?: string; // For web
paypalClientId?: string; // For web
receiptValidationEndpoint?: string;
autoFinishTransactions?: boolean; // Default: true
debug?: boolean;
}
await IAP.init(config);IAP.getProducts(productIds)
Fetch products from the store.
const products = await IAP.getProducts(['sku1', 'sku2']);
// Returns: Product[]IAP.purchase(productId, options?)
Purchase a product.
const purchase = await IAP.purchase('sku1', {
quantity: 1,
applicationUsername: 'user_123', // For server tracking
});
// Returns: PurchaseIAP.restorePurchases()
Restore previous purchases.
const purchases = await IAP.restorePurchases();
// Returns: Purchase[]IAP.getSubscriptionStatus(productId?)
Get current subscription status.
const status = await IAP.getSubscriptionStatus('premium_monthly');
// Returns: SubscriptionInfo | nullIAP.validateReceipt(receiptData)
Validate a receipt (requires server endpoint configured).
const validation = await IAP.validateReceipt(purchase.receipt);
// Returns: ReceiptValidationResponseIAP.syncReceipts()
Sync any queued receipts (for offline validation).
const { synced, failed } = await IAP.syncReceipts();IAP.setTestMode(enabled)
Enable/disable test mode.
IAP.setTestMode(true);IAP.setAnalyticsProvider(provider)
Set up analytics tracking.
IAP.setAnalyticsProvider({
trackEvent: (name, properties) => {
// Send to Amplitude, Firebase, Segment, etc.
analytics.track(name, properties);
},
});Analytics Events
The following events are automatically tracked:
| Event | Description |
|---|---|
purchase_started |
User initiated purchase |
purchase_completed |
Successful purchase |
purchase_failed |
Failed purchase |
purchase_cancelled |
User cancelled purchase |
subscription_renewed |
Subscription renewal |
subscription_expired |
Subscription expiry |
products_loaded |
Products fetched |
restore_completed |
Purchases restored |
Error Handling
import { IAPError, IAPErrorCode, isUserCancellation } from 'react-native-in-app-micro-purchases';
try {
await IAP.purchase('product_id');
} catch (error) {
if (isUserCancellation(error)) {
// User cancelled - no action needed
return;
}
if (error instanceof IAPError) {
switch (error.code) {
case IAPErrorCode.PRODUCT_NOT_FOUND:
console.log('Product not found');
break;
case IAPErrorCode.NETWORK_ERROR:
console.log('Network error - try again');
break;
case IAPErrorCode.PURCHASE_ALREADY_OWNED:
console.log('Already purchased');
break;
default:
console.log('Purchase failed:', error.message);
}
}
}Web Fallback
For web apps, configure Stripe or PayPal:
await IAP.init({
platform: 'web',
stripePublishableKey: 'pk_live_xxx',
});
// Purchase works the same way
await IAP.purchase('price_123'); // Stripe price IDServer-Side Receipt Validation
Configure an endpoint for receipt validation:
await IAP.init({
receiptValidationEndpoint: 'https://your-api.com/validate-receipt',
apiKey: 'your-api-key',
});Your endpoint will receive:
{
"receipt": "base64_receipt_data",
"productId": "premium_monthly",
"transactionId": "txn_123",
"platform": "ios",
"isSandbox": false
}TypeScript
Full TypeScript support is included:
import type {
Product,
Purchase,
SubscriptionInfo,
IAPConfig,
IAPError,
} from 'react-native-in-app-micro-purchases';Testing
Enable sandbox mode for testing:
await IAP.init({
environment: 'sandbox',
});
// Or toggle at runtime
IAP.setTestMode(true);iOS Testing
- Use sandbox Apple ID accounts
- Test in TestFlight or Xcode
Android Testing
- Add test accounts in Google Play Console
- Use license testing
Contributing
Contributions are welcome! Please read the contributing guidelines first.
Support the Project
If you find this library helpful and want to support its development, consider buying me a coffee!
PayPal: paypal.me/jobmyt86
Your support helps me maintain this library, add new features, and keep it up to date with the latest platform changes. Thank you!
Author
Solomon Monotilla
- PayPal: paypal.me/jobmyt86
- GitHub: @fr3em1nd
License
MIT