@omendilly/react-native-nitro-iap
v0.0.1
Published
apple StoreKit sdk for react native made with nitro modules
Maintainers
Readme
@omendilly/react-native-nitro-iap (StoreKit 2)
React Native in‑app purchases for iOS built with Nitro Modules and StoreKit 2.
- Native: Uses StoreKit 2 under the hood
- Typed: End‑to‑end TypeScript types generated by Nitro
- Simple: Minimal API surface for common flows (fetch, buy, restore)
Requirements
- iOS 15.0+ (StoreKit 2) [[enforced by the podspec]]
- Xcode 15+
- React Native with
react-native-nitro-modules
Installation
# npm
npm install @omendilly/react-native-nitro-iap react-native-nitro-modules
# or yarn
yarn add @omendilly/react-native-nitro-iap react-native-nitro-modules
# or pnpm
pnpm add @omendilly/react-native-nitro-iap react-native-nitro-modulesiOS CocoaPods install:
cd ios && pod install && cd -iOS Setup
- Enable the
In‑App Purchasecapability in your iOS target. - Create products in App Store Connect and use their product identifiers.
- Optional: Use StoreKit configuration files for local testing in Xcode.
API
Import the module and types:
import { StoreKitModule, type SKProduct, type PurchaseResult } from '@omendilly/react-native-nitro-iap'getProducts(ids)
Fetch product metadata. Note: getProducts expects an array of { value: string } due to a Nitro/Swift interop workaround.
const ids = ['coins_100', 'premium_yearly']
const products: SKProduct[] = await StoreKitModule.getProducts(ids.map((id) => ({ value: id })))Returns items of shape:
type SKProduct = {
id: string
type: 'consumable' | 'nonConsumable' | 'autoRenewable' | 'nonRenewing'
title: string
description: string
price: string // localized price string
currencyCode: string
}purchase(id)
Initiates a purchase flow for the given product identifier.
const result: PurchaseResult = await StoreKitModule.purchase('premium_yearly')
// result.state: 'purchased' | 'pending' | 'failed' | 'deferred' | 'cancelled'type PurchaseResult = {
id: string
productId: string
state: 'purchased' | 'pending' | 'failed' | 'deferred' | 'cancelled'
transactionDate: number // ms since epoch
transactionId?: string
errorCode?: string
errorMessage?: string
}Notes:
- On success, the transaction is automatically finished.
- If the user cancels,
stateiscancelled.
restore()
Returns the current entitlements (non‑consumable, subscriptions) for the signed‑in App Store user.
const purchases: PurchaseResult[] = await StoreKitModule.restore()observeTransactions()
Starts a background listener to automatically finish new verified transactions (StoreKit 2 Transaction.updates). Call this once on app launch.
useEffect(() => {
StoreKitModule.observeTransactions()
}, [])finishTransaction(id)
Manually finish an unfinished transaction by its transactionId (rarely needed if observeTransactions() is active).
await StoreKitModule.finishTransaction('1000001234567890')End‑to‑end example
import { useEffect, useState } from 'react'
import { StoreKitModule, type SKProduct, type PurchaseResult } from '@omendilly/react-native-nitro-iap'
export function useIAP() {
const [products, setProducts] = useState<SKProduct[]>([])
useEffect(() => {
StoreKitModule.observeTransactions()
;(async () => {
const ids = ['coins_100', 'premium_yearly']
const list = await StoreKitModule.getProducts(ids.map((id) => ({ value: id })))
setProducts(list)
})()
}, [])
const buy = async (id: string): Promise<PurchaseResult> => {
return await StoreKitModule.purchase(id)
}
const restore = async (): Promise<PurchaseResult[]> => {
return await StoreKitModule.restore()
}
return { products, buy, restore }
}Notes and best practices
- Validate receipts or transactions on your backend for subscriptions/entitlements.
- Keep product identifiers in a single source of truth.
- For UI determinism, returned products are stably sorted by title (and then id).
Development
This package is built with Nitro Modules. If you modify the Nitro specs, regenerate code:
npm:
npm run specsyarn:
yarn specsbun:
bunx specsLicense
MIT
