Basic Store Implementation
This example shows how to implement a basic in-app purchase store using expo-iap.
Key Features Demonstrated
1. Connection Management
- Automatic connection handling with
useIAP
- Loading states for connection and products
2. Product Loading
- Loading both products and subscriptions
- Error handling for failed product fetches
3. Purchase Flow
- Initiating purchases with
requestPurchase
- Handling purchase updates and errors
- Proper transaction finishing
4. Receipt Validation
- Server-side receipt validation with platform-specific handling
- Error handling for validation failures
5. User Experience
- Visual feedback for purchase states
- Appropriate error messages
- Loading indicators
Platform Differences
Purchase Request Parameters
Important: iOS and Android have completely different parameter structures for requestPurchase
:
Unified Structure (v2.7.0+):
await requestPurchase({
request: {
ios: {
sku: productId,
andDangerouslyFinishTransactionAutomatically: false,
},
android: {
skus: [productId],
},
},
});
Platform-specific Implementation (v2.7.0+):
// New API (v2.7.0+) - No Platform.OS checks needed!
await requestPurchase({
request: {
ios: {
sku: productId,
// Set to false for manual transaction finishing
andDangerouslyFinishTransactionAutomatically: false,
},
android: {
skus: [productId],
},
},
});
Key iOS Options
andDangerouslyFinishTransactionAutomatically: false
:- Recommended: Set to
false
to manually handle transaction finishing - This allows proper receipt validation before completing the transaction
- Prevents race conditions and ensures proper purchase flow
- Recommended: Set to
Purchase Object Properties
Purchase objects have different properties on iOS and Android. When accessing platform-specific properties, TypeScript type casting is required:
// ✅ New unified approach (recommended)
const purchaseToken = purchase.purchaseToken; // Works on both iOS and Android
// ❌ Old platform-specific approach (deprecated)
// const purchaseToken = (purchase as ProductPurchaseAndroid).purchaseTokenAndroid;
// const jwsToken = (purchase as ProductPurchaseIos).jwsRepresentationIos;
// Platform-specific fields that are still needed
const packageName = (purchase as ProductPurchaseAndroid).packageNameAndroid;
const transactionReceipt = purchase.transactionReceipt; // Available on both platforms
Receipt Validation
Receipt validation requires different approaches:
- iOS: Send
transactionReceipt
to Apple's validation servers - Android: Send
purchaseToken
(unified field) andpackageName
to Google Play validation
This is handled in the validatePurchase
function with platform-specific logic.
Usage
import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import Store from './Store';
export default function App() {
return (
<NavigationContainer>
<Store />
</NavigationContainer>
);
}
Customization
You can customize this example by:
- Styling: Modify the
styles
object to match your app's design - Product IDs: Update
PRODUCT_IDS
andSUBSCRIPTION_IDS
with your actual product IDs - Validation: Implement proper server-side receipt validation
- Error Handling: Add more specific error handling for your use case
- Features: Add features like purchase restoration, subscription management, etc.
Next Steps
- Implement proper receipt validation
- Add purchase restoration
- Handle subscription management
- Add comprehensive error handling