Getting Started
expo-iap
is a powerful in-app purchase solution specifically designed for Expo and React Native applications. It provides a unified API for handling in-app purchases across iOS and Android platforms with comprehensive error handling and modern TypeScript support.
Requirements
- React Native 0.64 or later, or Expo SDK 45 or later
- Node.js 16 or later
- iOS 12+ for iOS apps
- Android API level 21+ for Android apps
Installation
Install the package using your favorite package manager:
npm install expo-iap
Expo Managed Workflow
Since in-app purchases require native modules that aren't available in Expo Go, you'll need to use expo-dev-client
for development builds.
npx expo install expo-dev-client
npx expo run:ios # or npx expo run:android
Learn more about converting from Expo Go to development builds.
React Native CLI Projects
For React Native CLI projects, install expo-modules-core
first:
npx install-expo-modules@latest
Learn more about installing Expo modules in existing React Native projects.
iOS Configuration
For iOS projects, you need to configure StoreKit capabilities:
- Open your iOS project in Xcode
- Select your target in the project navigator
- Go to "Signing & Capabilities" tab
- Click "+" and add "In-App Purchase" capability
Android Configuration
For Android, ensure your app is configured for Google Play Billing:
- Open
android/app/build.gradle
- Add the billing permission:
android {
defaultConfig {
// ... other configurations
}
}
dependencies {
// ... other dependencies
implementation 'com.android.billingclient:billing:5.0.0'
}
Quick Start
1. Initialize the connection
import {useIAP} from 'expo-iap';
export default function App() {
const {
connected,
products,
purchaseHistory,
getProducts,
requestPurchase,
finishTransaction,
} = useIAP();
// Initialize connection when component mounts
useEffect(() => {
// Connection is automatically handled by useIAP
}, []);
return (
<View>
<Text>Connection Status: {connected ? 'Connected' : 'Disconnected'}</Text>
{/* Your app content */}
</View>
);
}
2. Fetch available products
const productIds = [
'com.example.product1',
'com.example.product2',
'com.example.subscription1',
];
useEffect(() => {
if (connected) {
getProducts({skus: productIds});
}
}, [connected, getProducts]);
3. Request a purchase
const handlePurchase = async (productId: string) => {
try {
await requestPurchase({sku: productId});
} catch (error) {
console.error('Purchase failed:', error);
}
};
4. Handle purchase updates
The useIAP
hook automatically handles purchase updates. When a purchase is successful, you should validate the receipt on your server and then finish the transaction:
useEffect(() => {
if (currentPurchase) {
// Validate receipt on your server
validateReceiptOnServer(currentPurchase)
.then(() => {
// If validation successful, finish the transaction
finishTransaction({purchase: currentPurchase});
})
.catch((error) => {
console.error('Receipt validation failed:', error);
});
}
}, [currentPurchase, finishTransaction]);
Best Practices
-
Handle connection lifecycle: The
useIAP
hook automatically manages the connection lifecycle, but be aware of when your app is connected before making purchase requests. -
Test thoroughly: Test with sandbox accounts and real devices. In-app purchases don't work in simulators/emulators. Use Apple's Sandbox environment and Google Play Console's testing features.
-
Implement comprehensive error handling: Handle various purchase scenarios including user cancellation, network errors, and invalid products. See our error handling guide for common issues and solutions.
-
Restore purchases properly: Implement purchase restoration for non-consumable products and subscriptions. This is required by app store guidelines and essential for users who reinstall your app.
-
Server-side receipt validation is recommended: For production apps, it's highly recommended to validate receipts on your secure server before granting access to content or features. See Apple's receipt validation guide and Google Play's verification guide.
-
Finish transactions after validation: Always call
finishTransaction
after successfully validating a purchase on your server. Failing to do so will cause the purchase to remain in a pending state and may trigger repeated purchase prompts. -
Check server-side validation libraries: Consider using open-source libraries like node-app-store-receipt-verify for iOS or google-play-billing-validator for Android to simplify server-side validation.
Next Steps
- Review our Complete Store Implementation for a full, production-ready example
- Learn about the purchase lifecycle and proper state management
- Check out common troubleshooting tips and solutions
- Explore the API reference for detailed method documentation