### Install Expo Dev Client and Run Source: https://hyochan.github.io/expo-iap/docs/2.7/guides/getting-started Installs the expo-dev-client for development builds and then runs the application on iOS or Android. This is necessary because Expo Go does not support native modules required for in-app purchases. ```bash npx expo install expo-dev-client npx expo run:ios # or npx expo run:android ``` -------------------------------- ### Install Expo IAP using npm Source: https://hyochan.github.io/expo-iap/docs/2.7/guides/getting-started Installs the expo-iap package using npm. This is the initial step for integrating in-app purchase functionality. ```bash npm install expo-iap ``` -------------------------------- ### Install Expo Modules Core for CLI Projects Source: https://hyochan.github.io/expo-iap/docs/2.7/guides/getting-started Installs the latest version of expo-modules-core, which is a prerequisite for React Native CLI projects before installing other Expo modules. ```bash npx install-expo-modules@latest ``` -------------------------------- ### Setup Documentation Development Environment Source: https://hyochan.github.io/expo-iap/docs/2.9/guides/support Instructions to set up the local environment for developing and previewing the project's documentation. This involves navigating to the docs directory, installing dependencies, and starting the development server. ```bash cd docs npm install npm start ``` -------------------------------- ### Run Example Project Source: https://hyochan.github.io/expo-iap/docs/guides/support Instructions to navigate to the example project directory, install its dependencies, and run the project on iOS or Android using Expo. ```bash cd example npm install npx expo run:ios # or run:android ``` -------------------------------- ### Install expo-iap Source: https://hyochan.github.io/expo-iap/docs/2.6/guides/faq Installs the expo-iap library using the Expo CLI. This is the primary command to get started with the library in your Expo project. ```bash npx expo install expo-iap ``` -------------------------------- ### Running the Expo IAP Example Project Source: https://hyochan.github.io/expo-iap/docs/2.7/guides/support Commands to install dependencies and run the example project for Expo IAP on iOS or Android. ```bash cd example npm install npx expo run:ios # or run:android ``` -------------------------------- ### Documentation Development Server Setup Source: https://hyochan.github.io/expo-iap/docs/guides/support Steps to set up and start the documentation development server locally. ```bash cd docs npm install npm start ``` -------------------------------- ### Run Expo Example Project Source: https://hyochan.github.io/expo-iap/docs/2.6/guides/support Installs dependencies and runs the example project for Expo IAP on iOS or Android using npx. ```bash cd example npm install npx expo run:ios # or run:android ``` -------------------------------- ### Setting up Documentation Development Environment Source: https://hyochan.github.io/expo-iap/docs/2.7/guides/support Steps to set up the documentation development environment for Expo IAP, including installing dependencies and starting the server. ```bash cd docs npm install npm start ``` -------------------------------- ### Install Pods for iOS (Bare Workflow) Source: https://hyochan.github.io/expo-iap/docs/2.7/installation Installs native dependencies for iOS projects using the bare workflow by running 'pod install' in the 'ios' directory. ```bash cd ios && pod install ``` -------------------------------- ### Install Expo CLI Source: https://hyochan.github.io/expo-iap/docs/2.7/installation Installs the Expo CLI globally, which is a prerequisite for creating development builds in the Expo managed workflow. ```bash npm install -g @expo/cli ``` -------------------------------- ### Run Expo IAP Example Project Source: https://hyochan.github.io/expo-iap/docs/2.9/guides/support Steps to run the example project for Expo IAP, including installing dependencies and running the project on iOS or Android using Expo CLI. ```bash cd example npm install npx expo run:ios # or run:android ``` -------------------------------- ### Install Expo IAP Package Source: https://hyochan.github.io/expo-iap/docs/2.7/installation Installs the Expo IAP package using npm. This is the initial step for integrating in-app purchase functionality into your project. ```bash npm install expo-iap ``` -------------------------------- ### Install Expo IAP Package Source: https://hyochan.github.io/expo-iap/docs/2.6/installation Installs the Expo IAP package using npm. This is the initial step for integrating in-app purchase functionality into your project. ```bash npm install expo-iap ``` -------------------------------- ### Install iOS Pods Source: https://hyochan.github.io/expo-iap/docs/2.6/installation Installs native dependencies for iOS by navigating to the 'ios' directory and running 'pod install'. This is required for the Expo Bare Workflow. ```bash cd ios && pod install ``` -------------------------------- ### Basic In-App Purchase Setup with Expo Source: https://hyochan.github.io/expo-iap/docs/getting-started/setup-ios Demonstrates the fundamental setup for in-app purchases using `expo-iap`. It includes initializing the IAP module, requesting products, handling purchase success and errors, and validating receipts. This example uses React hooks for managing the IAP state. ```javascript import {useIAP, ErrorCode} from 'expo-iap'; const productIds = [ 'com.yourapp.premium', 'com.yourapp.coins_100', 'com.yourapp.subscription_monthly', ]; function App() { const { connected, products, requestProducts, requestPurchase, validateReceipt, } = useIAP({ onPurchaseSuccess: (purchase) => { console.log('Purchase successful:', purchase); // Handle successful purchase validatePurchase(purchase); }, onPurchaseError: (error) => { console.error('Purchase failed:', error); // Handle purchase error }, }); React.useEffect(() => { if (connected) { requestProducts({skus: productIds, type: 'inapp'}); } }, [connected]); const validatePurchase = async (purchase) => { try { const result = await validateReceipt(purchase.transactionId); if (result.isValid) { // Grant user the purchased content console.log('Receipt is valid'); } } catch (error) { console.error('Validation failed:', error); } }; return ( {products.map((product) => ( requestPurchase({request: {sku: product.id}}) > {product.title} - {product.displayPrice} ))} ); } ``` -------------------------------- ### Prebuild Expo Project Source: https://hyochan.github.io/expo-iap/docs/2.7/installation Troubleshooting command for Expo projects to clean and rebuild native configurations, which can resolve issues with native modules. ```bash npx expo prebuild --clean ``` -------------------------------- ### Fetch Available Products with Expo IAP Source: https://hyochan.github.io/expo-iap/docs/2.7/guides/getting-started Fetches available products for purchase using the getProducts function from expo-iap. It requires a list of product IDs (SKUs) and should be called when the connection is established. ```javascript const productIds = [ 'com.example.product1', 'com.example.product2', 'com.example.subscription1', ]; useEffect(() => { if (connected) { getProducts({skus: productIds}); } }, [connected, getProducts]); ``` -------------------------------- ### Install Expo IAP using npm Source: https://hyochan.github.io/expo-iap/docs/2.9/installation Installs the expo-iap package using npm, a common package manager for Node.js projects. This is the first step in integrating in-app purchase functionality. ```bash npm install expo-iap ``` -------------------------------- ### Expo Prebuild for Clean Build Source: https://hyochan.github.io/expo-iap/docs/installation For Expo projects, this command uses the Expo CLI to prebuild the application with a clean slate. This is recommended for ensuring native configurations are up-to-date and free from previous build artifacts. ```bash npx expo prebuild --clean ``` -------------------------------- ### Prebuild Expo Project Source: https://hyochan.github.io/expo-iap/docs/installation Runs the `expo prebuild --clean` command to generate native directories and configurations for your Expo project. This is a necessary step after modifying `app.json` for native module support. ```bash npx expo prebuild --clean ``` -------------------------------- ### Initialize Expo IAP Connection Source: https://hyochan.github.io/expo-iap/docs/2.7/guides/getting-started Initializes the connection to the In-App Purchase API using the useIAP hook from expo-iap. It provides the connection status and other IAP-related functions. ```javascript import {useIAP} from 'expo-iap'; import { View, Text } from 'react-native'; import React, { useEffect } from 'react'; 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 ( Connection Status: {connected ? 'Connected' : 'Disconnected'} {/* Your app content */} ); } ``` -------------------------------- ### Expo Prebuild for Clean Build Source: https://hyochan.github.io/expo-iap/docs/2.9/installation For Expo projects, this command uses the Expo CLI to prebuild the application with a clean slate. This is recommended for ensuring native configurations are up-to-date and free from previous build artifacts. ```bash npx expo prebuild --clean ``` -------------------------------- ### Expo IAP Basic Usage Example Source: https://hyochan.github.io/expo-iap/docs/2.9/examples/complete-impl A foundational example demonstrating the basic usage patterns for Expo's In-App Purchase (IAP) module. This snippet is suitable for developers starting with Expo IAP and aims to illustrate core functionalities. ```javascript import * as IAP from 'expo-in-app-purchases'; async function exampleUsage() { await IAP.connectAsync(); const products = await IAP.getProductsAsync(['product_id_1', 'product_id_2']); console.log(products); // Further actions like purchasing, consuming, etc. await IAP.disconnectAsync(); } ``` -------------------------------- ### Prebuild Expo Project Source: https://hyochan.github.io/expo-iap/docs/2.6/installation Troubleshooting command for Expo projects that cleans and rebuilds the native project files. This is useful for resolving issues related to native module linking. ```bash npx expo prebuild --clean ``` -------------------------------- ### Add Billing Permission in Android build.gradle Source: https://hyochan.github.io/expo-iap/docs/2.7/guides/getting-started Adds the necessary implementation dependency for Google Play Billing client version 5.0.0 within the android/app/build.gradle file. This enables in-app purchase functionality on Android. ```java android { defaultConfig { // ... other configurations } } dependencies { // ... other dependencies implementation 'com.android.billingclient:billing:5.0.0' } ``` -------------------------------- ### Clean and Rebuild Pods for iOS Source: https://hyochan.github.io/expo-iap/docs/2.7/installation Troubleshooting step for iOS projects in the bare workflow to resolve issues by cleaning the 'Pods' directory and 'Podfile.lock', then reinstalling pods. ```bash cd ios rm -rf Pods Podfile.lock pod install ``` -------------------------------- ### Install iOS Pods Source: https://hyochan.github.io/expo-iap/docs/installation Navigates to the `ios` directory and installs the necessary CocoaPods dependencies for your React Native project. ```bash cd ios && pod install ``` -------------------------------- ### Start Documentation Server Source: https://hyochan.github.io/expo-iap/docs/2.6/guides/support Starts the documentation development server locally, allowing for previewing and testing documentation changes. ```bash cd docs npm install npm start ``` -------------------------------- ### Expo IAP Basic Setup and Purchase Flow Source: https://hyochan.github.io/expo-iap/docs/2.6/getting-started/setup-ios Demonstrates the basic setup for Expo IAP, including connecting to the service, fetching product details, requesting purchases, and validating receipts. It uses the `useIAP` hook and handles purchase success and error callbacks. ```javascript import {useIAP, ErrorCode} from 'expo-iap'; const productIds = [ 'com.yourapp.premium', 'com.yourapp.coins_100', 'com.yourapp.subscription_monthly', ]; function App() { const {connected, products, getProducts, requestPurchase, validateReceipt} = useIAP({ onPurchaseSuccess: (purchase) => { console.log('Purchase successful:', purchase); // Handle successful purchase validatePurchase(purchase); }, onPurchaseError: (error) => { console.error('Purchase failed:', error); // Handle purchase error }, }); React.useEffect(() => { if (connected) { getProducts(productIds); } }, [connected]); const validatePurchase = async (purchase) => { try { const result = await validateReceipt(purchase.transactionId); if (result.isValid) { // Grant user the purchased content console.log('Receipt is valid'); } } catch (error) { console.error('Validation failed:', error); } }; return ( {products.map((product) => ( requestPurchase({request: {sku: product.id}}) > {product.title} - {product.displayPrice} ))} ); } ``` -------------------------------- ### Install Expo IAP using npm Source: https://hyochan.github.io/expo-iap/docs/installation Installs the expo-iap package using npm. This is the first step for integrating in-app purchases into your Expo or React Native project. ```bash npm install expo-iap ``` -------------------------------- ### Basic Expo IAP Setup and Purchase Flow Source: https://hyochan.github.io/expo-iap/docs/2.7/getting-started/setup-ios Demonstrates the basic setup for Expo IAP, including connecting to the service, fetching product details, requesting purchases, and validating receipts. It uses the `useIAP` hook and handles purchase success and error callbacks. ```javascript import {useIAP, ErrorCode} from 'expo-iap'; const productIds = [ 'com.yourapp.premium', 'com.yourapp.coins_100', 'com.yourapp.subscription_monthly', ]; function App() { const {connected, products, getProducts, requestPurchase, validateReceipt} = useIAP({ onPurchaseSuccess: (purchase) => { console.log('Purchase successful:', purchase); // Handle successful purchase validatePurchase(purchase); }, onPurchaseError: (error) => { console.error('Purchase failed:', error); // Handle purchase error }, }); React.useEffect(() => { if (connected) { getProducts(productIds); } }, [connected]); const validatePurchase = async (purchase) => { try { const result = await validateReceipt(purchase.transactionId); if (result.isValid) { // Grant user the purchased content console.log('Receipt is valid'); } } catch (error) { console.error('Validation failed:', error); } }; return ( {products.map((product) => ( requestPurchase({request: {sku: product.id}}) } > {product.title} - {product.displayPrice} ))} ); } ``` -------------------------------- ### Install EAS CLI Source: https://hyochan.github.io/expo-iap/docs/installation Installs the EAS CLI globally, which is required for creating development builds and managing your Expo project's build process, especially for Expo Managed Workflow. ```bash npm install -g eas-cli ``` -------------------------------- ### Basic Expo IAP Setup Source: https://hyochan.github.io/expo-iap/docs/2.9/getting-started/setup-ios Demonstrates the basic setup for Expo IAP, including requesting products, handling purchases, and validating receipts. It uses the `useIAP` hook and requires product IDs for in-app purchases. ```javascript import {useIAP, ErrorCode} from 'expo-iap'; const productIds = [ 'com.yourapp.premium', 'com.yourapp.coins_100', 'com.yourapp.subscription_monthly', ]; function App() { const { connected, products, requestProducts, requestPurchase, validateReceipt, } = useIAP({ onPurchaseSuccess: (purchase) => { console.log('Purchase successful:', purchase); // Handle successful purchase validatePurchase(purchase); }, onPurchaseError: (error) => { console.error('Purchase failed:', error); // Handle purchase error }, }); React.useEffect(() => { if (connected) { requestProducts({skus: productIds, type: 'inapp'}); } }, [connected]); const validatePurchase = async (purchase) => { try { const result = await validateReceipt(purchase.productId); if (result.isValid) { // Grant user the purchased content console.log('Receipt is valid'); } } catch (error) { console.error('Validation failed:', error); } }; return ( {products.map((product) => ( requestPurchase({request: {sku: product.id}}) > {product.title} - {product.displayPrice} ))} ); } ``` -------------------------------- ### Install Expo Modules for React Native CLI Source: https://hyochan.github.io/expo-iap/docs/installation Installs the latest version of `expo-modules-core` for React Native CLI projects. This is a prerequisite for using Expo modules in a bare React Native project. ```bash npx install-expo-modules@latest ``` -------------------------------- ### Request Purchase with Expo IAP (iOS vs Android) Source: https://hyochan.github.io/expo-iap/docs/2.7/guides/getting-started Handles the purchase request for a given product ID, differentiating between iOS and Android platform requirements. iOS requires a single SKU, while Android accepts an array of SKUs. ```javascript import {Platform} from 'react-native'; const handlePurchase = async (productId: string) => { try { if (Platform.OS === 'ios') { // iOS: single product purchase await requestPurchase({ request: {sku: productId}, }); } else if (Platform.OS === 'android') { // Android: array of products (even for single purchase) await requestPurchase({ request: {skus: [productId]}, }); } } catch (error) { console.error('Purchase failed:', error); } }; ``` -------------------------------- ### Install Pods for iOS Source: https://hyochan.github.io/expo-iap/docs/2.9/installation Installs native dependencies for iOS projects using CocoaPods. This command is run after navigating to the 'ios' directory and is essential for linking native libraries required by Expo IAP. ```bash cd ios && pod install ``` -------------------------------- ### Install Expo CLI Source: https://hyochan.github.io/expo-iap/docs/2.6/installation Installs the Expo CLI globally, which is required for creating custom development clients in the Expo Managed Workflow. This is necessary for using native modules like Expo IAP. ```bash npm install -g @expo/cli ``` -------------------------------- ### Initialize and Manage Expo IAP Store Source: https://hyochan.github.io/expo-iap/docs/2.9/examples/complete-impl This snippet shows the complete setup for an Expo In-App Purchase store. It includes initializing the store connection, loading products and subscriptions, handling purchase updates, and managing errors. It utilizes `useState` and `useEffect` hooks for state management and side effects. ```javascript import React, {useEffect, useState} from 'react'; import { View, Text, FlatList, TouchableOpacity, Alert, StyleSheet, ActivityIndicator, Platform, } from 'react-native'; import {useIAP, ProductPurchaseAndroid} from 'expo-iap'; // Define your product IDs const PRODUCT_IDS = [ 'com.yourapp.premium', 'com.yourapp.remove_ads', 'com.yourapp.extra_features', ]; const SUBSCRIPTION_IDS = [ 'com.yourapp.premium_monthly', 'com.yourapp.premium_yearly', ]; export default function Store() { const { connected, products, subscriptions, currentPurchase, currentPurchaseError, requestProducts, requestPurchase, finishTransaction, } = useIAP(); const [loading, setLoading] = useState(false); const [purchasedItems, setPurchasedItems] = useState(new Set()); // Initialize store useEffect(() => { if (connected) { loadProducts(); } }, [connected]); // Handle purchase updates useEffect(() => { if (currentPurchase) { handlePurchaseUpdate(currentPurchase); } }, [currentPurchase]); // Handle purchase errors useEffect(() => { if (currentPurchaseError) { handlePurchaseError(currentPurchaseError); } }, [currentPurchaseError]); const loadProducts = async () => { try { setLoading(true); // Load both products and subscriptions await Promise.all([ fetchProducts({skus: PRODUCT_IDS, type: 'inapp'}), fetchProducts({skus: SUBSCRIPTION_IDS, type: 'subs'}), ]); console.log('Products loaded successfully'); } catch (error) { console.error('Failed to load products:', error); Alert.alert('Error', 'Failed to load store products'); } finally { setLoading(false); } }; const handlePurchaseUpdate = async (purchase) => { try { console.log('Processing purchase:', purchase.productId); // Here you would typically validate the receipt on your server const isValid = await validatePurchase(purchase); if (isValid) { // Grant the purchase to the user await grantPurchase(purchase); // Update local state setPurchasedItems((prev) => new Set([...prev, purchase.productId])); // Finish the transaction await finishTransaction({purchase}); Alert.alert( 'Purchase Successful', `Thank you for purchasing ${purchase.productId}!`); } else { Alert.alert('Error', 'Purchase validation failed'); } } catch (error) { console.error('Error processing purchase:', error); Alert.alert('Error', 'Failed to process purchase'); } }; const handlePurchaseError = (error) => { console.error('Purchase error:', error); switch (error.code) { case 'E_USER_CANCELLED': // User cancelled - no need to show error break; case 'E_NETWORK_ERROR': Alert.alert( 'Network Error', 'Please check your internet connection and try again.'); break; case 'E_ITEM_UNAVAILABLE': Alert.alert( 'Product Unavailable', 'This product is currently unavailable.'); break; default: Alert.alert( 'Purchase Failed', error.message || 'Unknown error occurred'); break; } }; const buyProduct = async (productId) => { if (!connected) { Alert.alert('Error', 'Store is not connected'); return; } try { console.log('Requesting purchase for:', productId); // Platform-specific purchase requests (v2.7.0+) await requestPurchase({ request: { ios: { sku: productId, // Important: Set to false to manually handle transaction finishing // This allows proper receipt validation before finishing the transaction andDangerouslyFinishTransactionAutomatically: false, }, android: { skus: [productId], }, }, }); } catch (error) { console.error('Purchase request failed:', error); Alert.alert('Error', 'Failed to initiate purchase'); } }; const validatePurchase = async (purchase) => { // IMPORTANT: Platform-specific validation requirements: // - iOS: Only needs receiptData and productId // - Android: Requires packageName, purchaseToken, and optionally accessToken // Always check required parameters BEFORE attempting validation! try { // Handle both iOS and Android validation ``` -------------------------------- ### Install/Uninstall Packages (npm) Source: https://hyochan.github.io/expo-iap/docs/2.9/guides/migration Demonstrates the npm commands to uninstall react-native-iap and install expo-iap, including the necessary pod install for iOS. ```bash npm install react-native-iap ``` ```bash npm install expo-iap ``` ```bash npm uninstall react-native-iap npm install expo-iap # For iOS cd ios && pod install && cd .. ``` -------------------------------- ### Install EAS CLI Source: https://hyochan.github.io/expo-iap/docs/2.9/installation Installs the EAS CLI globally, which is required for creating development builds in the Expo managed workflow. EAS CLI is essential for managing builds and deploying applications built with Expo. ```bash npm install -g eas-cli ``` -------------------------------- ### Install Expo Dev Client Source: https://hyochan.github.io/expo-iap/docs/2.9/guides/getting-started Installs the expo-dev-client package, which is required for development builds when using native modules like expo-iap. It also shows commands to run the development build on iOS or Android. ```bash npx expo install expo-dev-client ``` ```bash npx expo run:ios # or npx expo run:android ``` -------------------------------- ### Basic Expo IAP Setup for Android Source: https://hyochan.github.io/expo-iap/docs/getting-started/setup-android Demonstrates the basic setup for Expo In-App Purchases (IAP) on Android. It initializes the IAP context, defines product IDs, fetches products and subscriptions, and renders them. Includes error handling for purchase events. ```javascript import {useIAP, ErrorCode} from 'expo-iap'; const androidProductIds = [ 'premium_upgrade', 'coins_100', 'monthly_subscription', ]; function App() { const {connected, products, subscriptions, requestProducts, requestPurchase} = useIAP({ onPurchaseSuccess: (purchase) => { console.log('Purchase successful:', purchase); handleSuccessfulPurchase(purchase); }, onPurchaseError: (error) => { console.error('Purchase failed:', error); handlePurchaseError(error); }, }); React.useEffect(() => { if (connected) { // Fetch products and subscriptions fetchProducts({ skus: androidProductIds.filter((id) => !id.includes('subscription')), type: 'inapp', }); fetchProducts({ skus: androidProductIds.filter((id) => id.includes('subscription')), type: 'subs', }); } }, [connected]); return ( {/* Render products */} {products.map((product) => ( ))} {/* Render subscriptions */} {subscriptions.map((subscription) => ( ))} ); } ``` -------------------------------- ### Clear Node Modules and Reinstall Source: https://hyochan.github.io/expo-iap/docs/2.7/installation Troubleshooting step to resolve installation issues by removing the 'node_modules' directory and reinstalling project dependencies. ```bash rm -rf node_modules npm install ``` -------------------------------- ### Install Expo Modules for React Native CLI Source: https://hyochan.github.io/expo-iap/docs/2.9/installation Installs the latest version of expo-modules for React Native CLI projects. This command ensures that the necessary core Expo modules are available for integrating Expo libraries into existing React Native applications. ```bash npx install-expo-modules@latest ``` -------------------------------- ### Basic Expo IAP Integration for Android Source: https://hyochan.github.io/expo-iap/docs/2.6/getting-started/setup-android This JavaScript code demonstrates the basic setup for Expo IAP, including connecting to the service, fetching products and subscriptions, and handling purchase success or error callbacks. It uses the `useIAP` hook and defines product IDs for Android. ```javascript import {useIAP, ErrorCode} from 'expo-iap'; const androidProductIds = [ 'premium_upgrade', 'coins_100', 'monthly_subscription', ]; function App() { const { connected, products, subscriptions, getProducts, getSubscriptions, requestPurchase, } = useIAP({ onPurchaseSuccess: (purchase) => { console.log('Purchase successful:', purchase); handleSuccessfulPurchase(purchase); }, onPurchaseError: (error) => { console.error('Purchase failed:', error); handlePurchaseError(error); }, }); React.useEffect(() => { if (connected) { // Fetch products and subscriptions getProducts( androidProductIds.filter((id) => !id.includes('subscription')), ); getSubscriptions( androidProductIds.filter((id) => id.includes('subscription')), ); } }, [connected]); return ( {/* Render products */} {products.map((product) => ( ))} {/* Render subscriptions */} {subscriptions.map((subscription) => ( ))} ); } ``` -------------------------------- ### Verify Expo IAP Connection Source: https://hyochan.github.io/expo-iap/docs/2.6/installation A React Native component that uses the `useIAP` hook from `expo-iap` to check and log the connection status to the In-App Purchase service. This helps verify the installation. ```javascript import {useIAP} from 'expo-iap'; function TestComponent() { const {connected} = useIAP(); console.log('IAP Connection status:', connected); return null; } ``` -------------------------------- ### Basic Expo IAP Setup for Android Source: https://hyochan.github.io/expo-iap/docs/2.9/getting-started/setup-android Demonstrates the basic setup for Expo IAP on Android, including connecting to the service, fetching products and subscriptions, and handling purchase success or errors. It utilizes the `useIAP` hook and `requestProducts` for fetching items. ```javascript import {useIAP, ErrorCode} from 'expo-iap'; const androidProductIds = [ 'premium_upgrade', 'coins_100', 'monthly_subscription', ]; function App() { const {connected, products, subscriptions, requestProducts, requestPurchase} = useIAP({ onPurchaseSuccess: (purchase) => { console.log('Purchase successful:', purchase); handleSuccessfulPurchase(purchase); }, onPurchaseError: (error) => { console.error('Purchase failed:', error); handlePurchaseError(error); }, }); React.useEffect(() => { if (connected) { // Fetch products and subscriptions requestProducts({ skus: androidProductIds.filter((id) => !id.includes('subscription')), type: 'inapp', }); requestProducts({ skus: androidProductIds.filter((id) => id.includes('subscription')), type: 'subs', }); } }, [connected]); return ( {/* Render products */} {products.map((product) => ( ))} {/* Render subscriptions */} {subscriptions.map((subscription) => ( ))} ); } ``` -------------------------------- ### Verify Expo IAP Connection Source: https://hyochan.github.io/expo-iap/docs/2.9/installation A React Native component that uses the useIAP hook from expo-iap to check the connection status to the in-app purchase service. The connection status is logged to the console, helping to verify the installation and configuration. ```javascript import {useIAP} from 'expo-iap'; function TestComponent() { const {connected} = useIAP(); console.log('IAP Connection status:', connected); return null; } ``` -------------------------------- ### Clone Repository and Install Dependencies Source: https://hyochan.github.io/expo-iap/docs/guides/support Steps to fork the expo-iap repository, clone it locally, and install project dependencies using npm, yarn, or bun. ```bash git clone https://github.com/your-username/expo-iap.git cd expo-iap ``` ```bash npm install ``` ```bash yarn install ``` ```bash bun install ``` -------------------------------- ### Complete Offer Code Redemption Example (iOS & Android) Source: https://hyochan.github.io/expo-iap/docs/2.9/guides/offer-code-redemption This comprehensive example demonstrates how to handle offer code redemption across both iOS and Android platforms using `expo-iap` and React Native's `Platform` module. It includes setting up a `purchaseUpdatedListener` to handle post-redemption purchase updates. ```javascript import {Platform} from 'react-native'; import { presentCodeRedemptionSheet, openRedeemOfferCodeAndroid, purchaseUpdatedListener, } from 'expo-iap'; import { useEffect } from 'react'; const handleRedeemCode = async () => { try { if (Platform.OS === 'ios') { // Present native iOS redemption sheet const result = await presentCodeRedemptionSheet(); if (result) { console.log('Redemption sheet presented'); } } else if (Platform.OS === 'android') { // Open Play Store for Android await openRedeemOfferCodeAndroid(); } } catch (error) { console.error('Error redeeming code:', error); } }; // Set up listener for purchase updates after redemption useEffect(() => { const subscription = purchaseUpdatedListener((purchase) => { console.log('Purchase updated after redemption:', purchase); // Handle the new purchase/subscription }); return () => { subscription.remove(); }; }, []); ``` -------------------------------- ### Fetch Products and Subscriptions on Connection Source: https://hyochan.github.io/expo-iap/docs/2.7/examples/complete-impl Fetches available products and subscriptions from the store once the Expo IAP connection is established. This useEffect hook ensures that product and subscription data are loaded into the application state when the `connected` status is true. It includes error handling for the fetching process. ```javascript useEffect(() => { if (!connected) return; const initializeStore = async () => { try { await getProducts(productSkus); await getSubscriptions(subscriptionSkus); } catch (error) { console.error('Failed to initialize store:', error); } }; initializeStore(); }, [connected]); ``` -------------------------------- ### Initialize and Manage In-App Purchases with Expo Source: https://hyochan.github.io/expo-iap/docs/2.7/examples/complete-impl This snippet initializes the Expo In-App Purchase module, loads products and subscriptions, and handles the purchase lifecycle including updates and errors. It uses `useEffect` hooks to manage connection status and purchase events. ```javascript import React, {useEffect, useState} from 'react'; import { View, Text, FlatList, TouchableOpacity, Alert, StyleSheet, ActivityIndicator, Platform, } from 'react-native'; import {useIAP, ProductPurchaseAndroid} from 'expo-iap'; // Define your product IDs const PRODUCT_IDS = [ 'com.yourapp.premium', 'com.yourapp.remove_ads', 'com.yourapp.extra_features', ]; const SUBSCRIPTION_IDS = [ 'com.yourapp.premium_monthly', 'com.yourapp.premium_yearly', ]; export default function Store() { const { connected, products, subscriptions, currentPurchase, currentPurchaseError, getProducts, getSubscriptions, requestPurchase, finishTransaction, } = useIAP(); const [loading, setLoading] = useState(false); const [purchasedItems, setPurchasedItems] = useState(new Set()); // Initialize store useEffect(() => { if (connected) { loadProducts(); } }, [connected]); // Handle purchase updates useEffect(() => { if (currentPurchase) { handlePurchaseUpdate(currentPurchase); } }, [currentPurchase]); // Handle purchase errors useEffect(() => { if (currentPurchaseError) { handlePurchaseError(currentPurchaseError); } }, [currentPurchaseError]); const loadProducts = async () => { try { setLoading(true); // Load both products and subscriptions await Promise.all([ getProducts({skus: PRODUCT_IDS}), getSubscriptions({skus: SUBSCRIPTION_IDS}), ]); console.log('Products loaded successfully'); } catch (error) { console.error('Failed to load products:', error); Alert.alert('Error', 'Failed to load store products'); } finally { setLoading(false); } }; const handlePurchaseUpdate = async (purchase) => { try { console.log('Processing purchase:', purchase.productId); // Here you would typically validate the receipt on your server const isValid = await validatePurchase(purchase); if (isValid) { // Grant the purchase to the user await grantPurchase(purchase); // Update local state setPurchasedItems((prev) => new Set([...prev, purchase.productId])); // Finish the transaction await finishTransaction({purchase}); Alert.alert( 'Purchase Successful', `Thank you for purchasing ${purchase.productId}!`); } else { Alert.alert('Error', 'Purchase validation failed'); } } catch (error) { console.error('Error processing purchase:', error); Alert.alert('Error', 'Failed to process purchase'); } }; const handlePurchaseError = (error) => { console.error('Purchase error:', error); switch (error.code) { case 'E_USER_CANCELLED': // User cancelled - no need to show error break; case 'E_NETWORK_ERROR': Alert.alert( 'Network Error', 'Please check your internet connection and try again.'); break; case 'E_ITEM_UNAVAILABLE': Alert.alert( 'Product Unavailable', 'This product is currently unavailable.'); break; default: Alert.alert( 'Purchase Failed', error.message || 'Unknown error occurred'); break; } }; const buyProduct = async (productId) => { if (!connected) { Alert.alert('Error', 'Store is not connected'); return; } try { console.log('Requesting purchase for:', productId); // Platform-specific purchase requests // iOS and Android have different parameter requirements if (Platform.OS === 'ios') { await requestPurchase({ request: { sku: productId, // Important: Set to false to manually handle transaction finishing // This allows proper receipt validation before finishing the transaction andDangerouslyFinishTransactionAutomatically: false, }, }); } /* Platform.OS === "android" */ else { await requestPurchase({ request: {skus: [productId]}, }); } } catch (error) { console.error('Purchase request failed:', error); Alert.alert('Error', 'Failed to initiate purchase'); } }; const validatePurchase = async (purchase) => { // IMPORTANT: Platform-specific validation requirements: // - iOS: Only needs receiptData and productId // - Android: Requires packageName, purchaseToken, and optionally accessToken ``` -------------------------------- ### Reset Metro Cache Source: https://hyochan.github.io/expo-iap/docs/2.7/installation Troubleshooting command for React Native projects to reset the Metro bundler cache, which can help resolve build and bundling issues. ```bash npx react-native start --reset-cache ``` -------------------------------- ### Verify Expo IAP Connection Source: https://hyochan.github.io/expo-iap/docs/2.7/installation A React component that uses the useIAP hook from expo-iap to check and log the connection status to the In-App Purchase service. ```javascript import {useIAP} from 'expo-iap'; function TestComponent() { const {connected} = useIAP(); console.log('IAP Connection status:', connected); return null; } ``` -------------------------------- ### Run Expo Prebuild Source: https://hyochan.github.io/expo-iap/docs/2.9/installation Executes the 'expo prebuild --clean' command to generate native iOS and Android directories with necessary configurations. This command is crucial after modifying app.json for native module integration, ensuring the project's native build files are up-to-date. ```bash npx expo prebuild --clean ``` -------------------------------- ### Handle Purchase Updates and Validation (React) Source: https://hyochan.github.io/expo-iap/docs/2.7/guides/getting-started This snippet shows how to use useEffect to automatically handle purchase updates when a new purchase is detected. It includes platform-specific logic for validating receipts on iOS and Android before finishing the transaction. ```javascript useEffect(() => { if (currentPurchase) { // Platform-specific validation const validateAndFinish = async () => { try { if (Platform.OS === 'ios') { // iOS: Simple validation await validateReceiptOnServer({ receiptData: currentPurchase.transactionReceipt, productId: currentPurchase.productId, }); } else if (Platform.OS === 'android') { // Android: Check required parameters first const purchaseToken = currentPurchase.purchaseTokenAndroid; const packageName = currentPurchase.packageNameAndroid; if (!purchaseToken || !packageName) { throw new Error( 'Android validation requires packageName and purchaseToken', ); } await validateReceiptOnServer({ packageName, purchaseToken, productId: currentPurchase.productId, }); } // If validation successful, finish the transaction await finishTransaction({purchase: currentPurchase}); } catch (error) { console.error('Receipt validation failed:', error); } }; validateAndFinish(); } }, [currentPurchase, finishTransaction]); ``` -------------------------------- ### Clear Node Modules and Reinstall Source: https://hyochan.github.io/expo-iap/docs/2.6/installation Troubleshooting step to remove the 'node_modules' directory and reinstall dependencies. This can resolve issues caused by corrupted or outdated packages. ```bash rm -rf node_modules npm install ``` -------------------------------- ### Enable Verbose Logging in Expo IAP Source: https://hyochan.github.io/expo-iap/docs/2.6/guides/troubleshooting Enables debug mode for the expo-iap library during development. This helps in getting more detailed logs for debugging purchase flows. ```javascript import {setDebugMode} from 'expo-iap'; // Enable debug mode in development if (__DEV__) { setDebugMode(true); } ``` -------------------------------- ### Installing Dependencies with npm, yarn, or bun Source: https://hyochan.github.io/expo-iap/docs/2.7/guides/support Instructions for installing project dependencies using different package managers: npm, yarn, or bun. ```bash npm install # or yarn install # or bun install ``` -------------------------------- ### Verify Expo IAP Connection Source: https://hyochan.github.io/expo-iap/docs/installation A simple React Native component using the `useIAP` hook from `expo-iap` to check and log the connection status to the In-App Purchase service. ```javascript import {useIAP} from 'expo-iap'; function TestComponent() { const {connected} = useIAP(); console.log('IAP Connection status:', connected); return null; } ``` -------------------------------- ### Basic App Navigation Setup Source: https://hyochan.github.io/expo-iap/docs/2.6/examples/basic-store Demonstrates the basic setup for a React Native application using Expo, including navigation setup with `@react-navigation/native` and rendering a `Store` component. ```javascript import React from 'react'; import {NavigationContainer} from '@react-navigation/native'; import Store from './Store'; export default function App() { return ( ); } ```