GitHunt
FR

fr3em1nd/react-native-in-app-micro-purchases

A unified, high-level in-app purchase system for React Native that simplifies monetization across iOS, Android, and Web platforms while handling receipts, analytics, and fallbacks.

react-native-in-app-micro-purchases

A unified, high-level in-app purchase system for React Native that simplifies monetization across iOS, Android, and Web platforms while handling receipts, analytics, and fallbacks.

npm version
license

Created by Solomon Monotilla

Features

  • Unified API - One interface for iOS (StoreKit 2), Android (Google Play Billing), and Web (Stripe/PayPal)
  • Offline Receipt Validation - Caches receipts securely and auto-syncs when online
  • Web Fallback Support - Handle purchases in web apps via Stripe or PayPal
  • Built-in Analytics Hooks - Track purchase events with any analytics provider
  • Secure Storage - Platform-native encryption (iOS Keychain, Android Keystore)
  • React Hooks - Modern React integration with hooks API
  • TypeScript First - Full type definitions included
  • Test Mode Support - Easy sandbox/test environment configuration

Installation

npm install react-native-in-app-micro-purchases
# or
yarn add react-native-in-app-micro-purchases

iOS Setup

cd ios && pod install

Ensure your app has the In-App Purchase capability enabled in Xcode.

Android Setup

Add billing permission (automatically included via library manifest):

<uses-permission android:name="com.android.vending.BILLING" />

Web Setup (Optional)

For web fallback support, install Stripe:

npm install @stripe/stripe-js @stripe/react-stripe-js

Quick Start

Basic Usage

import { IAP } from 'react-native-in-app-micro-purchases';

// Initialize
await IAP.init({
  environment: __DEV__ ? 'sandbox' : 'production',
});

// Load products
const products = await IAP.getProducts(['premium_monthly', 'premium_yearly']);

// Make a purchase
try {
  const result = await IAP.purchase('premium_monthly');
  console.log('Purchased!', result);
} catch (error) {
  if (error.code === 'E_PURCHASE_CANCELLED') {
    console.log('User cancelled');
  } else {
    console.error('Purchase failed', error);
  }
}

// Restore purchases
const restored = await IAP.restorePurchases();

// Check subscription status
const status = await IAP.getSubscriptionStatus();

React Hooks

import { useInAppPurchase } from 'react-native-in-app-micro-purchases';

function Store() {
  const {
    isReady,
    isLoading,
    products,
    purchase,
    error,
  } = useInAppPurchase({
    productIds: ['premium_monthly', 'premium_yearly'],
  });

  if (!isReady) return <Loading />;

  return (
    <View>
      {products.map((product) => (
        <TouchableOpacity
          key={product.productId}
          onPress={() => purchase(product.productId)}
          disabled={isLoading}
        >
          <Text>{product.title}</Text>
          <Text>{product.price}</Text>
        </TouchableOpacity>
      ))}
      {error && <Text style={{ color: 'red' }}>{error.message}</Text>}
    </View>
  );
}

Subscription Hook

import { useSubscription } from 'react-native-in-app-micro-purchases';

function PremiumContent() {
  const { isSubscribed, isInTrial, subscription } = useSubscription({
    productId: 'premium_monthly',
  });

  if (!isSubscribed) {
    return <SubscribePrompt />;
  }

  return (
    <View>
      {isInTrial && <Text>You're in a free trial!</Text>}
      <PremiumFeatures />
    </View>
  );
}

API Reference

IAP.init(config)

Initialize the IAP system.

interface IAPConfig {
  apiKey?: string;                    // API key for server validation
  environment?: 'production' | 'sandbox';
  platform?: 'ios' | 'android' | 'web';
  stripePublishableKey?: string;      // For web
  paypalClientId?: string;            // For web
  receiptValidationEndpoint?: string;
  autoFinishTransactions?: boolean;   // Default: true
  debug?: boolean;
}

await IAP.init(config);

IAP.getProducts(productIds)

Fetch products from the store.

const products = await IAP.getProducts(['sku1', 'sku2']);
// Returns: Product[]

IAP.purchase(productId, options?)

Purchase a product.

const purchase = await IAP.purchase('sku1', {
  quantity: 1,
  applicationUsername: 'user_123', // For server tracking
});
// Returns: Purchase

IAP.restorePurchases()

Restore previous purchases.

const purchases = await IAP.restorePurchases();
// Returns: Purchase[]

IAP.getSubscriptionStatus(productId?)

Get current subscription status.

const status = await IAP.getSubscriptionStatus('premium_monthly');
// Returns: SubscriptionInfo | null

IAP.validateReceipt(receiptData)

Validate a receipt (requires server endpoint configured).

const validation = await IAP.validateReceipt(purchase.receipt);
// Returns: ReceiptValidationResponse

IAP.syncReceipts()

Sync any queued receipts (for offline validation).

const { synced, failed } = await IAP.syncReceipts();

IAP.setTestMode(enabled)

Enable/disable test mode.

IAP.setTestMode(true);

IAP.setAnalyticsProvider(provider)

Set up analytics tracking.

IAP.setAnalyticsProvider({
  trackEvent: (name, properties) => {
    // Send to Amplitude, Firebase, Segment, etc.
    analytics.track(name, properties);
  },
});

Analytics Events

The following events are automatically tracked:

Event Description
purchase_started User initiated purchase
purchase_completed Successful purchase
purchase_failed Failed purchase
purchase_cancelled User cancelled purchase
subscription_renewed Subscription renewal
subscription_expired Subscription expiry
products_loaded Products fetched
restore_completed Purchases restored

Error Handling

import { IAPError, IAPErrorCode, isUserCancellation } from 'react-native-in-app-micro-purchases';

try {
  await IAP.purchase('product_id');
} catch (error) {
  if (isUserCancellation(error)) {
    // User cancelled - no action needed
    return;
  }

  if (error instanceof IAPError) {
    switch (error.code) {
      case IAPErrorCode.PRODUCT_NOT_FOUND:
        console.log('Product not found');
        break;
      case IAPErrorCode.NETWORK_ERROR:
        console.log('Network error - try again');
        break;
      case IAPErrorCode.PURCHASE_ALREADY_OWNED:
        console.log('Already purchased');
        break;
      default:
        console.log('Purchase failed:', error.message);
    }
  }
}

Web Fallback

For web apps, configure Stripe or PayPal:

await IAP.init({
  platform: 'web',
  stripePublishableKey: 'pk_live_xxx',
});

// Purchase works the same way
await IAP.purchase('price_123'); // Stripe price ID

Server-Side Receipt Validation

Configure an endpoint for receipt validation:

await IAP.init({
  receiptValidationEndpoint: 'https://your-api.com/validate-receipt',
  apiKey: 'your-api-key',
});

Your endpoint will receive:

{
  "receipt": "base64_receipt_data",
  "productId": "premium_monthly",
  "transactionId": "txn_123",
  "platform": "ios",
  "isSandbox": false
}

TypeScript

Full TypeScript support is included:

import type {
  Product,
  Purchase,
  SubscriptionInfo,
  IAPConfig,
  IAPError,
} from 'react-native-in-app-micro-purchases';

Testing

Enable sandbox mode for testing:

await IAP.init({
  environment: 'sandbox',
});

// Or toggle at runtime
IAP.setTestMode(true);

iOS Testing

  • Use sandbox Apple ID accounts
  • Test in TestFlight or Xcode

Android Testing

  • Add test accounts in Google Play Console
  • Use license testing

Contributing

Contributions are welcome! Please read the contributing guidelines first.

Support the Project

If you find this library helpful and want to support its development, consider buying me a coffee!

PayPal

PayPal: paypal.me/jobmyt86

Your support helps me maintain this library, add new features, and keep it up to date with the latest platform changes. Thank you!

Author

Solomon Monotilla

License

MIT

Support