openiap

Unified in-app purchase SDK for Expo and React Native apps, conforming to the OpenIAP spec across iOS and Android.

SDK
npm
v5.5.1
132stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
83/100Excellent
Development Activity100
Maintenance100
Community56
Maturity36
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
79/100Good
Architecture82
Code Quality85
Innovation78
Learning Curve70

expo-iap is an Expo Module that gives React Native and Expo apps a single, type-safe API for in-app purchases and subscriptions across iOS and Android. Instead of hand-rolling separate StoreKit and Play Billing integrations, developers call one set of functions — fetchProducts, requestPurchase, finishTransaction, getActiveSubscriptions — and the library routes each call to native StoreKit 2 (iOS) or Play Billing 9.1 (Android) code underneath.

The package conforms to the OpenIAP specification, a vendor-neutral protocol shared with react-native-iap, flutter_inapp_purchase, kmp-iap, and godot-iap. Types, error codes, and purchase flows are generated from a single GraphQL schema, so switching between these sibling libraries — or debugging a purchase error — follows the same mental model regardless of platform. A useIAP() React hook wraps connection lifecycle and event listeners for common cases, while the lower-level functions remain available for custom flows.

What You Get

  • A unified fetchProducts/requestPurchase/finishTransaction API that abstracts over StoreKit 2 and Play Billing 9.1
  • A useIAP() React hook managing connection lifecycle, purchase listeners, and subscription state
  • OpenIAP-generated TypeScript types and error codes shared with react-native-iap, flutter_inapp_purchase, kmp-iap, and godot-iap
  • Structured PurchaseError objects with platform-aware error codes instead of raw native exceptions
  • An Expo config plugin (app.plugin.js) for automatic native project configuration
  • Support for Amazon Appstore purchases via the Onside/Kepler integration alongside Apple and Google

Common Use Cases

  • Mobile app monetization — Expo/React Native teams selling consumables, non-consumables, or subscriptions add one dependency instead of separate iOS/Android purchase code
  • Cross-platform receipt verification — apps call verifyPurchase/verifyPurchaseWithProvider to validate purchases server-side using OpenIAP-standardized payloads
  • Migrating from react-native-iap — Expo-first projects moving off the older bridge-based library adopt expo-iap for tighter Expo Modules integration while keeping the same OpenIAP types
  • Restoring purchases across devices — restorePurchases and getAvailablePurchases let apps recover a user’s entitlements after reinstall or a device change

Under The Hood

Architecture index.ts exposes the OpenIAP-conformant query/mutation surface (fetchProducts, requestPurchase, finishTransaction, initConnection, getActiveSubscriptions, verifyPurchase) as thin typed wrappers around ExpoIapModule, the generated Expo native-module binding (ExpoIapModule.ts / getNativeModule), which in turn delegates to platform-specific native code — Swift/StoreKit 2 under ios/ and Kotlin/Play Billing under android/src/main/java. An emitter-based event system (OpenIapEvent, purchaseUpdatedListener, purchaseErrorListener, userChoiceBillingListenerAndroid) sits on top of the native bridge, and useIAP.ts composes those primitives into a single React hook that manages connection lifecycle, listener subscription/cleanup via refs and effects, and derived subscription state — so consumers can choose the low-level functional API or the hook without the two diverging.

Tech Stack The package is TypeScript-first, built on Expo Modules Core (expo-module-scripts, expo-modules-core) with peer dependencies on expo, react, and react-native, plus a dedicated Amazon Appstore integration (@amazon-devices/keplerscript-appstore-iap-lib). Native code is Swift on iOS (ExpoIapModule.swift, StoreKit 2) and Kotlin on Android, generated/maintained in lockstep with sibling libraries from a shared OpenIAP GraphQL schema. Bun drives builds and scripts (bun.lock, expo-module build/clean), TypeScript compiles the plugin separately (tsc —build plugin), and a dedicated GitHub Actions workflow (ci-expo-iap.yml) runs CI scoped to this package within the openiap monorepo.

Code Quality The src/tests directory holds a comprehensive suite (17 test files) covering the public hook (useIAP.test.tsx), error mapping, OpenIAP conformance, native module lifecycle, and edge cases like discriminated-union product responses — run via ts-jest with coverage collection configured in jest.config.js. Errors are handled explicitly through createPurchaseError/createPurchaseErrorFromNativeException, which normalize native StoreKit/Play Billing failures into a typed PurchaseError with a stable ErrorCode enum, rather than letting raw native exceptions leak through. The lint pipeline (lint:ci) chains TypeScript’s noEmit type-check, ESLint, Prettier, and ktlint for the Kotlin side, all enforced in CI.

What Makes It Unique Rather than shipping an isolated IAP wrapper, expo-iap is one of several sibling libraries (react-native-iap, flutter_inapp_purchase, kmp-iap, godot-iap) that all implement the same OpenIAP specification — a vendor-neutral protocol with types, error codes, and purchase-flow semantics generated from a single GraphQL schema and versioned centrally (openiap-versions.json). That shared-spec approach, backed by Meta and Amazon as sponsors, is aimed squarely at reducing the fragmentation that otherwise exists between per-platform, per-framework in-app-purchase implementations, and at making purchase-handling code easier for both humans and AI coding assistants to generate consistently.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search