Expo IAP
Expo IAP is a powerful in-app purchase solution for Expo and React Native applications. It provides a unified API for handling in-app purchases across iOS and Android platforms with comprehensive error h### 📚 Guides
- Getting Started: Complete guide to implementing in-app purchases
- Purchase Lifecycle: Understanding connection management and best practices
- Purchase Implementation: Detailed purchase flow and event handling
- Migration Guide: Migrating from react-native-iap to expo-iap
- FAQ: Frequently asked questions and solutions
- Support: Getting help and community resources
🛠️ Advanced Topicsnd modern TypeScript support.
✨ Features
- 🔄 Cross-platform Support: Works seamlessly on both iOS and Android
- 🎯 TypeScript First: Full TypeScript support with comprehensive type definitions
- 🛡️ Centralized Error Handling: Unified error management with platform-specific error code mapping
- 🎣 React Hooks: Modern React hooks API with
useIAP
- 📱 Expo Compatible: Built specifically for Expo with a seamless plugin experience
- 🔍 Receipt Validation: Built-in receipt validation for both platforms
- 💎 Products & Subscriptions: Support for both one-time purchases and subscriptions
- 🚀 Performance Optimized: Efficient caching and minimal re-renders
🚀 Quick Start
Installation
Install the package using your favorite package manager:
npm install expo-iap
1. Basic Setup
First, import and initialize the IAP hook:
import {useIAP} from 'expo-iap';
function MyStore() {
const {
connected,
products,
getProducts,
requestPurchase,
currentPurchase,
finishTransaction,
} = useIAP();
const productIds = ['your.product.id', 'your.premium.subscription'];
}
2. Fetch Products
Load your products when the store connects:
useEffect(() => {
if (connected) {
// Fetch your products
getProducts(productIds);
}
}, [connected]);
3. Display Products
Show available products to users:
return (
<View>
<Text>Store Status: {connected ? 'Connected' : 'Connecting...'}</Text>
{products.map((product) => (
<View key={product.id} style={styles.productItem}>
<Text style={styles.productTitle}>{product.title}</Text>
<Text style={styles.productPrice}>{product.displayPrice}</Text>
<Button title="Buy Now" onPress={() => handlePurchase(product.id)} />
</View>
))}
</View>
);
4. Handle Purchases
Process purchase requests:
const handlePurchase = async (productId: string) => {
try {
await requestPurchase({
request: {sku: productId},
});
} catch (error) {
console.error('Purchase failed:', error);
}
};
5. Complete Transactions
Finish purchases when they complete:
useEffect(() => {
if (currentPurchase) {
const completePurchase = async () => {
try {
// Grant the purchase to user here
console.log('Purchase completed:', currentPurchase.id);
// Finish the transaction
await finishTransaction({
purchase: currentPurchase,
isConsumable: true, // Set based on your product type
});
} catch (error) {
console.error('Failed to complete purchase:', error);
}
};
completePurchase();
}
}, [currentPurchase]);
Complete Basic Example
Here's a complete working example:
import React, {useEffect} from 'react';
import {View, Text, Button, StyleSheet} from 'react-native';
import {useIAP} from 'expo-iap';
export default function SimpleStore() {
const {
connected,
products,
getProducts,
requestPurchase,
currentPurchase,
finishTransaction,
} = useIAP();
const productIds = ['com.example.coins.pack1', 'com.example.premium'];
useEffect(() => {
if (connected) {
getProducts(productIds);
}
}, [connected]);
useEffect(() => {
if (currentPurchase) {
const completePurchase = async () => {
try {
console.log('Purchase completed:', currentPurchase.id);
await finishTransaction({
purchase: currentPurchase,
isConsumable: true,
});
} catch (error) {
console.error('Failed to complete purchase:', error);
}
};
completePurchase();
}
}, [currentPurchase]);
const handlePurchase = async (productId: string) => {
try {
await requestPurchase({
request: {sku: productId},
});
} catch (error) {
console.error('Purchase failed:', error);
}
};
return (
<View style={styles.container}>
<Text style={styles.status}>
Store: {connected ? 'Connected ✅' : 'Connecting...'}
</Text>
{products.map((product) => (
<View key={product.id} style={styles.product}>
<Text style={styles.title}>{product.title}</Text>
<Text style={styles.price}>{product.displayPrice}</Text>
<Button title="Buy Now" onPress={() => handlePurchase(product.id)} />
</View>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {padding: 20},
status: {fontSize: 16, marginBottom: 20},
product: {
padding: 15,
marginVertical: 5,
backgroundColor: '#f0f0f0',
borderRadius: 8,
},
title: {fontSize: 16, fontWeight: 'bold'},
price: {fontSize: 14, color: '#666', marginVertical: 5},
});
🏗️ Architecture
Expo IAP is built with a modern architecture that emphasizes:
- Type Safety: Comprehensive TypeScript definitions for all APIs
- Error Resilience: Centralized error handling with meaningful error codes
- Platform Abstraction: Unified API that handles platform differences internally
- Performance: Optimized for minimal bundle size and runtime performance
📱 Platform Support
Platform | Support | Notes |
---|---|---|
iOS | ✅ | StoreKit 1 & 2 |
Android | ✅ | Google Play Billing v5+ |
Expo Go | ⚠️ | Limited (requires custom development client) |
Expo Dev Client | ✅ | Full support |
Bare React Native | ✅ | Full support |
🎯 What's Next?
📦 Setup & Configuration
- Installation Guide: Install and configure Expo IAP
- iOS Setup: App Store Connect and Xcode configuration
- Android Setup: Google Play Console setup
🔧 Implementation
- API Reference: Complete useIAP hook documentation
- Basic Store Example: Simple product store implementation
- Complete Store Example: Production-ready store with validation
� Guides
- Getting Started: Complete guide to implementing in-app purchases
- Purchase Lifecycle: Understanding connection management and best practices
- Purchase Implementation: Detailed purchase flow and event handling
- Migration Guide: Migrating from react-native-iap to expo-iap
- FAQ: Frequently asked questions and solutions
- Support: Getting help and community resources
�🛠️ Advanced Topics
- Receipt Validation: Secure purchase validation
- Error Handling: Comprehensive error management
- Subscription Management: Handle recurring subscriptions
- Troubleshooting: Common issues and solutions
🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.