Purchase Flow
This guide demonstrates a clean purchase flow using react-native-iap with the useIAP hook and the new platform‑specific request shape.
Note that the example code was heavily vibe-coded with Claude and is quite verbose/messy for demonstration purposes - use it as a reference only. :::
Flow Overview
-
Initialize:
useIAPmanages the store connection lifecycle -
Load products:
fetchProducts({ skus, type: 'in-app' }) -
Start purchase:
requestPurchase({ request: { ios: { sku }, android: { skus: [sku] } }, type: 'in-app' }) -
Receive callbacks:
onPurchaseSuccess/onPurchaseError(fromuseIAP) -
Validate server‑side: send receipt/JWS or token to your backend
-
Finish transaction:
finishTransaction({ purchase, isConsumable })
Connect → Fetch Products → Request Purchase → Server Validate → Finish Transaction
Key Concepts
1. Connection Management
useIAPautomatically opens/closes the connection- Exposes
connected, convenient for showing loading states
2. Product Loading
- Load in‑app products or subscriptions (set
type) - Handle and log failed product fetches
3. Purchase Flow
- Start purchases via unified request shape (no
Platform.OSbranching) - Use
onPurchaseSuccess/onPurchaseErrorfromuseIAP - Always call
finishTransactionafter server validation
4. Receipt Validation
- Perform validation on your backend (never only on device)
- iOS: validate the receipt/JWS; Android: validate purchase token + package name
5. User Experience
- Provide clear states for loading, success, and error
- Show subscription management/deep‑links when appropriate
Platform Differences
Purchase Request Parameters
Use the modern, platform‑specific request container (v2.7.0+). This avoids manual Platform.OS checks:
await requestPurchase({
request: {
ios: {sku: productId, quantity: 1},
android: {skus: [productId]},
},
type: 'in-app',
});
Notes:
- Keep
andDangerouslyFinishTransactionAutomaticallyoff (default) to validate first.
Key iOS Options
appAccountToken: set per user to correlate receipts on your backendquantity: purchase quantity for iOS (consumables)
Purchase Object Properties
Purchase objects have different properties on iOS and Android. When accessing platform-specific properties, TypeScript type casting is required:
// Unified fields
const token = purchase.purchaseToken; // iOS JWS or Android token
// Android-only helpers
// const pkg = (purchase as PurchaseAndroid).packageNameAndroid;
Receipt Validation
Receipt validation requires different approaches:
- iOS: verify receipt/JWS on your server against Apple
- Android: verify token and package name against Google Play Developer API
Usage
import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import PurchaseFlow from './purchase-flow';
export default function App() {
return (
<NavigationContainer>
<PurchaseFlow />
</NavigationContainer>
);
}
Customization
You can customize this example by:
- Styling: Modify the
stylesobject to match your app's design - Product IDs: Update
PRODUCT_IDSwith 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
