@molecule/app-iap
Feature · iap · App (browser) · v1.0.2 · Apache-2.0
In-app purchase and subscription management
npm install @molecule/app-iapHow it works
@molecule/app-iap is a ready-made iap feature for the app (browser) side. It composes the core interfaces it needs, so it works with whichever providers your app has bonded.
import {
createNoopIAPProvider,
initialize,
order,
finish,
register,
refresh,
setProvider,
verify,
} from '@molecule/app-iap'
// Wire the provider at app startup (swap for an iOS/Android bond in production)
setProvider(createNoopIAPProvider())
await initialize()
register([{ id: 'com.example.pro_monthly', alias: 'pro_monthly', type: 'subscription' }])
await refresh()
const result = await order('pro_monthly')
if (result.success && result.product) {
await verify(result.product, '/api/iap/verify')
finish(result.product)
}Works with: @molecule/app-bond, @molecule/app-i18n
Reference
In-App Purchases interface for molecule.dev.
Provides a unified API for in-app purchases that works across different platforms (iOS App Store, Google Play, web Stripe).
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import {
createNoopIAPProvider,
initialize,
order,
finish,
register,
refresh,
setProvider,
verify,
} from '@molecule/app-iap'
// Wire the provider at app startup (swap for an iOS/Android bond in production)
setProvider(createNoopIAPProvider())
await initialize()
register([{ id: 'com.example.pro_monthly', alias: 'pro_monthly', type: 'subscription' }])
await refresh()
const result = await order('pro_monthly')
if (result.success && result.product) {
await verify(result.product, '/api/iap/verify')
finish(result.product)
}
Type
feature
Installation
npm install @molecule/app-iap @molecule/app-bond @molecule/app-i18n
API
Interfaces
ProductDefinition
Product definition for registration.
interface ProductDefinition {
/**
* Product ID (SKU) - platform-specific identifier.
*/
id: string
/**
* Product alias - cross-platform identifier.
*/
alias: string
/**
* Product type.
*/
type: ProductType
/**
* Product group (for subscription grouping).
*/
group?: string
}
Product
Full in-app product details (ID, type, state, pricing, ownership, transaction, subscription info).
interface Product {
/**
* Product ID (SKU).
*/
id: string
/**
* Product alias.
*/
alias: string
/**
* Product type.
*/
type: ProductType
/**
* Product state.
*/
state: ProductState
/**
* Product title.
*/
title: string
/**
* Product description.
*/
description: string
/**
* Formatted price string.
*/
price: string
/**
* Price in micros (cents * 10000).
*/
priceMicros: number
/**
* Currency code (ISO 4217).
*/
currency: string
/**
* Whether the product can be purchased.
*/
canPurchase: boolean
/**
* Whether the product is owned.
*/
owned: boolean
/**
* Transaction information (if applicable).
*/
transaction?: Transaction
/**
* Subscription period (for subscriptions).
*/
subscriptionPeriod?: SubscriptionPeriod
/**
* Introductory price (for subscriptions with trial).
*/
introPrice?: string
/**
* Trial period in days.
*/
trialPeriodDays?: number
/**
* Product group.
*/
group?: string
/**
* Raw platform-specific data.
*/
raw?: unknown
}
Transaction
Purchase transaction record (ID, receipt, purchase token, timestamps, validity).
interface Transaction {
/**
* Transaction ID.
*/
id: string
/**
* Platform-specific receipt.
*/
receipt?: string
/**
* App Store receipt (iOS).
*/
appStoreReceipt?: string
/**
* Purchase token (Android).
*/
purchaseToken?: string
/**
* Purchase time.
*/
purchaseTime?: Date
/**
* Expiration time (for subscriptions).
*/
expirationTime?: Date
/**
* Whether the purchase is valid.
*/
isValid?: boolean
/**
* Raw platform-specific data.
*/
raw?: unknown
}
IAPError
In-app purchase error with error code, product ID, and platform-specific details.
interface IAPError {
/**
* Error code.
*/
code: string | number
/**
* Error message.
*/
message: string
/**
* Product ID (if applicable).
*/
productId?: string
/**
* Raw error.
*/
raw?: unknown
}
PurchaseResult
Outcome of a purchase attempt (success flag, product, transaction, or error).
interface PurchaseResult {
/**
* Whether the purchase was successful.
*/
success: boolean
/**
* The purchased product.
*/
product?: Product
/**
* Transaction information.
*/
transaction?: Transaction
/**
* Error (if purchase failed).
*/
error?: IAPError
}
VerificationResult
Verification result from server.
interface VerificationResult {
/**
* Whether the receipt is valid.
*/
valid: boolean
/**
* Subscription expiration time.
*/
expirationTime?: Date
/**
* Whether the subscription is active.
*/
isActive?: boolean
/**
* Plan/tier information.
*/
plan?: string
/**
* Server response data.
*/
data?: unknown
}
IAPProvider
In-App Purchases provider interface.
interface IAPProvider {
/**
* Initializes the IAP system.
*/
initialize(): Promise<void>
/**
* Registers products for purchase.
*/
register(products: ProductDefinition[]): void
/**
* Refreshes product information from the store.
*/
refresh(): Promise<void>
/**
* Gets a product by ID or alias.
*/
get(idOrAlias: string): Product | undefined
/**
* Gets all registered products.
*/
getAll(): Product[]
/**
* Checks if a product can be purchased.
*/
canPurchase(idOrAlias: string): boolean
/**
* Initiates a purchase.
*/
order(idOrAlias: string): Promise<PurchaseResult>
/**
* Finishes a transaction (must be called after successful verification).
*/
finish(product: Product): void
/**
* Verifies a purchase with the server.
*/
verify(
product: Product,
verifyUrl: string,
additionalData?: Record<string, unknown>,
): Promise<VerificationResult>
/**
* Restores previous purchases.
*/
restore(): Promise<Product[]>
/**
* Opens the subscription management page.
*/
manageSubscriptions(): void
/**
* Subscribes to product events.
*/
when(idOrAlias: string): {
updated: (handler: ProductEventHandler) => void
approved: (handler: ProductEventHandler) => void
finished: (handler: ProductEventHandler) => void
cancelled: (handler: ProductEventHandler) => void
error: (handler: ErrorEventHandler) => void
}
/**
* Subscribes to global events.
*/
on(event: IAPEvent, handler: IAPEventHandler): () => void
/**
* Unsubscribes from events.
*/
off(handler: IAPEventHandler): void
/**
* Gets the platform name.
*/
getPlatform(): 'ios' | 'android' | 'web' | 'unknown'
/**
* Checks if IAP is available.
*/
isAvailable(): boolean
/**
* Destroys the IAP system.
*/
destroy(): void
}
Types
ProductType
In-app purchase product categories: one-time consumable, permanent non-consumable, or recurring subscription.
type ProductType = 'consumable' | 'non-consumable' | 'subscription'
ProductState
Purchase lifecycle state of an in-app product (registered, valid, approved, owned, cancelled, etc.).
type ProductState =
| 'registered'
| 'valid'
| 'invalid'
| 'requested'
| 'initiated'
| 'approved'
| 'finished'
| 'owned'
| 'cancelled'
| 'downloading'
SubscriptionPeriod
Subscription billing interval: weekly, monthly, yearly, or lifetime.
type SubscriptionPeriod = 'weekly' | 'monthly' | 'yearly' | 'lifetime'
IAPEvent
IAP lifecycle events: ready, product-updated, approved, finished, cancelled, error, pending, expired, restored.
type IAPEvent =
| 'ready'
| 'product-updated'
| 'approved'
| 'finished'
| 'cancelled'
| 'error'
| 'pending'
| 'expired'
| 'restored'
IAPEventHandler
Generic event handler for IAP events.
type IAPEventHandler<T = unknown> = (data: T) => void
ProductEventHandler
Event handler called with a Product when a product-related event occurs.
type ProductEventHandler = (product: Product) => void
ErrorEventHandler
Event handler called with an IAPError when a purchase error occurs.
type ErrorEventHandler = (error: IAPError) => void
Functions
createNoopIAPProvider()
Creates a no-op IAP provider for web/testing.
function createNoopIAPProvider(): IAPProvider
Returns: A no-op IAP provider that stubs all purchase operations.
setProvider(provider)
Sets the IAP provider.
function setProvider(provider: IAPProvider): void
provider— The IAP provider implementation to bond.
getProvider()
Gets the current IAP provider. Falls back to a no-op provider if none has been
bonded — on web this is correct (no store exists), but on iOS/Android a missing
real provider means every order() reports unavailable. The fallback warns when
it engages so the omission is visible rather than a silent failure.
function getProvider(): IAPProvider
Returns: The active IAP provider instance.
hasProvider()
Checks if an IAP provider has been bonded.
function hasProvider(): boolean
Returns: Whether an IAP provider is currently registered.
initialize()
Initializes the IAP system via the active provider.
function initialize(): Promise<void>
Returns: A promise that resolves when initialization is complete.
register(products)
Registers product definitions with the IAP provider.
function register(products: ProductDefinition[]): void
products— The product definitions to register for purchase availability.
Returns: Nothing.
refresh()
Refreshes product information from the store.
function refresh(): Promise<void>
Returns: A promise that resolves when product data has been refreshed.
get(idOrAlias)
Gets a product by its store ID or registered alias.
function get(idOrAlias: string): Product | undefined
idOrAlias— The product store ID or alias to look up.
Returns: The matching product, or undefined if not found.
getAll()
Gets all registered products.
function getAll(): Product[]
Returns: An array of all available products.
order(idOrAlias)
Initiates a purchase order for a product.
function order(idOrAlias: string): Promise<PurchaseResult>
idOrAlias— The product store ID or alias to purchase.
Returns: A promise that resolves with the purchase result.
finish(product)
Finishes a pending transaction, acknowledging delivery to the store.
function finish(product: Product): void
product— The product whose transaction should be finalized.
Returns: Nothing.
verify(product, verifyUrl, additionalData)
Verifies a purchase receipt with a server endpoint.
function verify(
product: Product,
verifyUrl: string,
additionalData?: Record<string, unknown>,
): Promise<VerificationResult>
product— The product whose purchase receipt to verify.verifyUrl— The server URL to send the verification request to.additionalData— Extra data to include in the verification payload.
Returns: A promise that resolves with the server verification result.
restore()
Restores previously completed purchases from the store.
function restore(): Promise<Product[]>
Returns: A promise that resolves with an array of restored products.
manageSubscriptions()
Opens the platform's subscription management UI.
function manageSubscriptions(): void
Returns: Nothing.
isAvailable()
Checks if in-app purchases are available on the current platform.
function isAvailable(): boolean
Returns: Whether the IAP system is available and functional.
getErrorMessage(error, t)
Gets a user-friendly error message.
function getErrorMessage(
error: unknown,
t?: (
key: string,
values?: Record<string, unknown>,
options?: { defaultValue?: string },
) => string,
): string
error— The IAP error object or unknown thrown value to translate.t— Optional i18n translation function for localized messages.
Returns: A user-friendly error message string.
Constants
errorMessages
Error code mapping for user-friendly messages. Derived from defaultTranslations to avoid duplicating strings.
const errorMessages: Record<string, string>
Injection Notes
Requirements
Peer dependencies:
@molecule/app-bond^1.0.1@molecule/app-i18n^1.0.1
Runtime Dependencies
-
@molecule/app-bond -
@molecule/app-i18n -
NO store provider ships with the fleet yet: the only built-in implementation is
createNoopIAPProvider(), andgetProvider()silently self-bonds it when nothing is wired — so without a real providerorder()ALWAYS fails withE_NOT_AVAILABLE,verify()returns{ valid: false }, andisAvailable()isfalse. To sell on iOS / Android, implementIAPProvideryourself (e.g. wrapping cordova-plugin-purchase, StoreKit 2, or Play Billing) and wire it withsetProvider()at startup. -
verify()POSTs the purchase to YOUR server: implement the endpoint with@molecule/api-payments-apple/@molecule/api-payments-google(receipt validation) and callfinish()only after the server says the receipt is valid — finishing first loses the purchase if validation fails. -
Error messages route through
t('iap.error.*')with English fallbacks; the@molecule/app-locales-iapbond supplies 79 translations.
Translations
Translation strings are provided by @molecule/app-locales-iap.