expo-iap 4.2.7 → 4.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { DeveloperProvidedBillingDetailsAndroid, MutationField, Product, ProductQueryType, Purchase, QueryField, UserChoiceBillingDetails } from './types';
1
+ import type { DeveloperProvidedBillingDetailsAndroid, MutationField, Product, ProductQueryType, Purchase, PurchaseUpdatedListenerOptions, QueryField, UserChoiceBillingDetails } from './types';
2
2
  import { type PurchaseError } from './utils/errorMapping';
3
3
  export * from './types';
4
4
  export * from './modules/android';
@@ -44,7 +44,7 @@ export declare const emitter: ExpoIapEmitter;
44
44
  * TODO(v3.1.0): Remove legacy 'inapp' alias once downstream apps migrate to 'in-app'.
45
45
  */
46
46
  export type ProductTypeInput = ProductQueryType | 'inapp';
47
- export declare const purchaseUpdatedListener: (listener: (event: Purchase) => void) => {
47
+ export declare const purchaseUpdatedListener: (listener: (event: Purchase) => void, options?: PurchaseUpdatedListenerOptions | null) => {
48
48
  remove: () => void;
49
49
  };
50
50
  export declare const purchaseErrorListener: (listener: (error: PurchaseError) => void) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/build/index.js CHANGED
@@ -37,12 +37,80 @@ export var OpenIapEvent;
37
37
  // Resolved lazily so importing this module doesn't throw on unsupported platforms.
38
38
  export const emitter = {
39
39
  addListener(eventName, listener) {
40
- return getNativeModule().addListener(eventName, listener);
40
+ const nativeModule = getNativeModule();
41
+ const nativeSubscription = nativeModule.addListener(eventName, listener);
42
+ let removed = false;
43
+ return {
44
+ remove: () => {
45
+ if (removed) {
46
+ return;
47
+ }
48
+ removed = true;
49
+ if (typeof nativeSubscription?.remove === 'function') {
50
+ nativeSubscription.remove();
51
+ return;
52
+ }
53
+ nativeModule.removeListener?.(eventName, listener);
54
+ },
55
+ };
41
56
  },
42
57
  removeListener(eventName, listener) {
43
- return getNativeModule().removeListener(eventName, listener);
58
+ return getNativeModule().removeListener?.(eventName, listener);
44
59
  },
45
60
  };
61
+ let nonDedupingPurchaseUpdatedListenerCountIOS = 0;
62
+ const purchaseUpdatedDedupeHistoryLimitIOS = 512;
63
+ const purchaseUpdatedDedupeHistoryIOS = {
64
+ ids: new Set(),
65
+ order: [],
66
+ start: 0,
67
+ };
68
+ let purchaseUpdatedDedupeGenerationIOS = 0;
69
+ const purchaseUpdatedTransactionIdIOS = (purchase) => {
70
+ if (typeof purchase.id === 'string' && purchase.id.length > 0) {
71
+ return purchase.id;
72
+ }
73
+ return null;
74
+ };
75
+ const rememberPurchaseUpdatedTransactionIOS = (transactionId, history) => {
76
+ if (history.ids.has(transactionId)) {
77
+ return;
78
+ }
79
+ history.ids.add(transactionId);
80
+ history.order.push(transactionId);
81
+ if (history.order.length - history.start >
82
+ purchaseUpdatedDedupeHistoryLimitIOS) {
83
+ const evicted = history.order[history.start];
84
+ history.start += 1;
85
+ if (evicted != null) {
86
+ history.ids.delete(evicted);
87
+ }
88
+ if (history.start > 128 && history.start * 2 > history.order.length) {
89
+ history.order = history.order.slice(history.start);
90
+ history.start = 0;
91
+ }
92
+ }
93
+ };
94
+ const clearPurchaseUpdatedDedupeHistoryIOS = (history) => {
95
+ history.ids.clear();
96
+ history.order.length = 0;
97
+ history.start = 0;
98
+ };
99
+ const resetPurchaseUpdatedDedupeHistoryIOS = () => {
100
+ clearPurchaseUpdatedDedupeHistoryIOS(purchaseUpdatedDedupeHistoryIOS);
101
+ purchaseUpdatedDedupeGenerationIOS += 1;
102
+ };
103
+ const configurePurchaseUpdatedListenerOptionsIOS = (dedupeTransactionIOS) => {
104
+ if (Platform.OS !== 'ios')
105
+ return;
106
+ const nativeModule = getNativeModule();
107
+ const promise = nativeModule.setPurchaseUpdatedListenerOptions?.({
108
+ dedupeTransactionIOS,
109
+ });
110
+ void promise?.catch((error) => {
111
+ ExpoIapConsole.warn('Failed to configure purchase updated listener options:', error);
112
+ });
113
+ };
46
114
  const normalizeProductType = (type) => {
47
115
  if (type === 'inapp') {
48
116
  ExpoIapConsole.warn("'inapp' product type is deprecated and will be removed in v3.1.0. Use 'in-app' instead.");
@@ -79,13 +147,55 @@ const normalizePurchasePlatform = (purchase) => {
79
147
  return { ...purchase, platform: lowered };
80
148
  };
81
149
  const normalizePurchaseArray = (purchases) => purchases.map((purchase) => normalizePurchasePlatform(purchase));
82
- export const purchaseUpdatedListener = (listener) => {
150
+ export const purchaseUpdatedListener = (listener, options) => {
151
+ const receiveDuplicateTransactionUpdatesIOS = Platform.OS === 'ios' && options?.dedupeTransactionIOS === false;
152
+ const listenerDedupeHistoryIOS = {
153
+ ids: new Set(purchaseUpdatedDedupeHistoryIOS.ids),
154
+ order: purchaseUpdatedDedupeHistoryIOS.order.slice(purchaseUpdatedDedupeHistoryIOS.start),
155
+ start: 0,
156
+ };
157
+ let listenerDedupeGenerationIOS = purchaseUpdatedDedupeGenerationIOS;
83
158
  const wrappedListener = (event) => {
84
159
  const normalized = normalizePurchasePlatform(event);
160
+ if (Platform.OS === 'ios') {
161
+ if (listenerDedupeGenerationIOS !== purchaseUpdatedDedupeGenerationIOS) {
162
+ clearPurchaseUpdatedDedupeHistoryIOS(listenerDedupeHistoryIOS);
163
+ listenerDedupeGenerationIOS = purchaseUpdatedDedupeGenerationIOS;
164
+ }
165
+ const transactionId = purchaseUpdatedTransactionIdIOS(normalized);
166
+ if (transactionId != null) {
167
+ const isDuplicateForListener = listenerDedupeHistoryIOS.ids.has(transactionId);
168
+ rememberPurchaseUpdatedTransactionIOS(transactionId, listenerDedupeHistoryIOS);
169
+ rememberPurchaseUpdatedTransactionIOS(transactionId, purchaseUpdatedDedupeHistoryIOS);
170
+ if (!receiveDuplicateTransactionUpdatesIOS && isDuplicateForListener) {
171
+ return;
172
+ }
173
+ }
174
+ }
85
175
  listener(normalized);
86
176
  };
87
177
  const emitterSubscription = emitter.addListener(OpenIapEvent.PurchaseUpdated, wrappedListener);
88
- return emitterSubscription;
178
+ if (!receiveDuplicateTransactionUpdatesIOS) {
179
+ return emitterSubscription;
180
+ }
181
+ nonDedupingPurchaseUpdatedListenerCountIOS += 1;
182
+ configurePurchaseUpdatedListenerOptionsIOS(false);
183
+ let removed = false;
184
+ return {
185
+ remove: () => {
186
+ if (removed) {
187
+ return;
188
+ }
189
+ removed = true;
190
+ try {
191
+ emitterSubscription?.remove?.();
192
+ }
193
+ finally {
194
+ nonDedupingPurchaseUpdatedListenerCountIOS = Math.max(0, nonDedupingPurchaseUpdatedListenerCountIOS - 1);
195
+ configurePurchaseUpdatedListenerOptionsIOS(nonDedupingPurchaseUpdatedListenerCountIOS === 0);
196
+ }
197
+ },
198
+ };
89
199
  };
90
200
  export const purchaseErrorListener = (listener) => {
91
201
  const wrappedListener = (error) => {
@@ -275,13 +385,27 @@ export const subscriptionBillingIssueListener = (listener) => {
275
385
  *
276
386
  * @see {@link https://www.openiap.dev/docs/apis/init-connection}
277
387
  */
278
- export const initConnection = async (config) => ExpoIapModule.initConnection(config ?? null);
388
+ export const initConnection = async (config) => {
389
+ const result = await ExpoIapModule.initConnection(config ?? null);
390
+ if (result === true &&
391
+ Platform.OS === 'ios' &&
392
+ nonDedupingPurchaseUpdatedListenerCountIOS > 0) {
393
+ configurePurchaseUpdatedListenerOptionsIOS(false);
394
+ }
395
+ return result;
396
+ };
279
397
  /**
280
398
  * Close the store connection and release resources.
281
399
  *
282
400
  * @see {@link https://www.openiap.dev/docs/apis/end-connection}
283
401
  */
284
- export const endConnection = async () => ExpoIapModule.endConnection();
402
+ export const endConnection = async () => {
403
+ const result = await ExpoIapModule.endConnection();
404
+ if (result === true && Platform.OS === 'ios') {
405
+ resetPurchaseUpdatedDedupeHistoryIOS();
406
+ }
407
+ return result;
408
+ };
285
409
  /**
286
410
  * Retrieve products or subscriptions from the store by SKU.
287
411
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// External dependencies\nimport {Platform} from 'react-native';\n\n// Internal modules\nimport ExpoIapModule, {getNativeModule} from './ExpoIapModule';\nimport {\n isProductIOS,\n validateReceiptIOS,\n deepLinkToSubscriptionsIOS,\n syncIOS,\n} from './modules/ios';\nimport {\n isProductAndroid,\n validateReceiptAndroid,\n deepLinkToSubscriptionsAndroid,\n} from './modules/android';\nimport {ExpoIapConsole} from './utils/debug';\n\n// Types\nimport type {\n ActiveSubscription,\n AndroidSubscriptionOfferInput,\n DeepLinkOptions,\n DeveloperProvidedBillingDetailsAndroid,\n MutationField,\n MutationRequestPurchaseArgs,\n MutationValidateReceiptArgs,\n Product,\n ProductQueryType,\n ProductSubscription,\n Purchase,\n PurchaseOptions,\n QueryField,\n RequestPurchasePropsByPlatforms,\n RequestPurchaseAndroidProps,\n RequestPurchaseIosProps,\n RequestSubscriptionPropsByPlatforms,\n RequestSubscriptionAndroidProps,\n RequestSubscriptionIosProps,\n UserChoiceBillingDetails,\n} from './types';\nimport {ErrorCode} from './types';\nimport {createPurchaseError, type PurchaseError} from './utils/errorMapping';\n\n// Export all types\nexport * from './types';\nexport * from './modules/android';\nexport * from './modules/ios';\nexport * from './onside';\n\n// Get the native constant value\nexport enum OpenIapEvent {\n PurchaseUpdated = 'purchase-updated',\n PurchaseError = 'purchase-error',\n PromotedProductIOS = 'promoted-product-ios',\n UserChoiceBillingAndroid = 'user-choice-billing-android',\n /**\n * Fired when user selects developer billing in External Payments flow (Android 8.3.0+)\n * Only available in Japan. Contains externalTransactionToken for reporting.\n */\n DeveloperProvidedBillingAndroid = 'developer-provided-billing-android',\n /**\n * Fired when an active subscription enters a billing-issue state (cross-platform).\n * Unifies StoreKit 2 `Message.Reason.billingIssue` (iOS 18+) and Play Billing 8.1+\n * `Purchase.isSuspended`. NOT fired on the Meta Horizon flavor.\n */\n SubscriptionBillingIssue = 'subscription-billing-issue',\n}\n\ntype ExpoIapEventPayloads = {\n [OpenIapEvent.PurchaseUpdated]: Purchase;\n [OpenIapEvent.PurchaseError]: PurchaseError;\n [OpenIapEvent.PromotedProductIOS]:\n | Product\n | string\n | {id?: string; productId?: string};\n [OpenIapEvent.UserChoiceBillingAndroid]: UserChoiceBillingDetails;\n [OpenIapEvent.DeveloperProvidedBillingAndroid]: DeveloperProvidedBillingDetailsAndroid;\n [OpenIapEvent.SubscriptionBillingIssue]: Purchase;\n};\n\ntype ExpoIapEventListener<E extends OpenIapEvent> = (\n payload: ExpoIapEventPayloads[E],\n) => void;\n\ntype ExpoIapEmitter = {\n addListener<E extends OpenIapEvent>(\n eventName: E,\n listener: ExpoIapEventListener<E>,\n ): {remove: () => void};\n removeListener<E extends OpenIapEvent>(\n eventName: E,\n listener: ExpoIapEventListener<E>,\n ): void;\n};\n\n// Use the raw native module for listener calls — JSI HostObjects require the\n// real native module as `this` when calling addListener. Using a Proxy as\n// `this` triggers \"native state unsupported on Proxy\" on New Architecture / Hermes.\n// Resolved lazily so importing this module doesn't throw on unsupported platforms.\nexport const emitter: ExpoIapEmitter = {\n addListener(eventName, listener) {\n return getNativeModule().addListener(eventName, listener);\n },\n removeListener(eventName, listener) {\n return getNativeModule().removeListener(eventName, listener);\n },\n};\n\n/**\n * TODO(v3.1.0): Remove legacy 'inapp' alias once downstream apps migrate to 'in-app'.\n */\nexport type ProductTypeInput = ProductQueryType | 'inapp';\n\nconst normalizeProductType = (type?: ProductTypeInput) => {\n if (type === 'inapp') {\n ExpoIapConsole.warn(\n \"'inapp' product type is deprecated and will be removed in v3.1.0. Use 'in-app' instead.\",\n );\n }\n\n if (!type || type === 'inapp' || type === 'in-app') {\n return {\n canonical: 'in-app' as ProductQueryType,\n native: 'in-app' as const,\n };\n }\n if (type === 'subs') {\n return {\n canonical: 'subs' as ProductQueryType,\n native: 'subs' as const,\n };\n }\n if (type === 'all') {\n return {\n canonical: 'all' as ProductQueryType,\n native: 'all' as const,\n };\n }\n throw new Error(`Unsupported product type: ${type}`);\n};\n\nconst normalizePurchasePlatform = (purchase: Purchase): Purchase => {\n const platform = purchase.platform;\n if (typeof platform !== 'string') {\n return purchase;\n }\n\n const lowered = platform.toLowerCase();\n if (lowered === platform || (lowered !== 'ios' && lowered !== 'android')) {\n return purchase;\n }\n\n return {...purchase, platform: lowered};\n};\n\nconst normalizePurchaseArray = (purchases: Purchase[]): Purchase[] =>\n purchases.map((purchase) => normalizePurchasePlatform(purchase));\n\nexport const purchaseUpdatedListener = (\n listener: (event: Purchase) => void,\n) => {\n const wrappedListener = (event: Purchase) => {\n const normalized = normalizePurchasePlatform(event);\n listener(normalized);\n };\n const emitterSubscription = emitter.addListener(\n OpenIapEvent.PurchaseUpdated,\n wrappedListener,\n );\n return emitterSubscription;\n};\n\nexport const purchaseErrorListener = (\n listener: (error: PurchaseError) => void,\n) => {\n const wrappedListener = (error: PurchaseError) => {\n listener(error);\n };\n const emitterSubscription = emitter.addListener(\n OpenIapEvent.PurchaseError,\n wrappedListener,\n );\n return emitterSubscription;\n};\n\n/**\n * iOS-only listener for App Store promoted product events.\n * This fires when a user taps on a promoted product in the App Store.\n *\n * @param listener - Callback function that receives the promoted product details\n * @returns EventSubscription that can be used to unsubscribe\n *\n * @example\n * ```typescript\n * const subscription = promotedProductListenerIOS((product) => {\n * console.log('Promoted product:', product);\n * // Handle the promoted product\n * });\n *\n * // Later, clean up\n * subscription.remove();\n * ```\n *\n * @platform iOS\n */\nexport const promotedProductListenerIOS = (\n listener: (product: Product) => void,\n) => {\n if (Platform.OS !== 'ios') {\n ExpoIapConsole.warn(\n 'promotedProductListenerIOS: This listener is only available on iOS',\n );\n return {remove: () => {}};\n }\n\n let deliveredProductId: string | undefined;\n const deliver = (product: Product) => {\n const productId =\n product.id ?? (product as Product & {productId?: string}).productId;\n if (productId && productId === deliveredProductId) {\n return;\n }\n deliveredProductId = productId;\n listener(product);\n };\n\n const replayPendingProduct = () => {\n let pendingProduct: Promise<Product | null> | undefined;\n try {\n pendingProduct = ExpoIapModule.getPromotedProductIOS() as\n | Promise<Product | null>\n | undefined;\n } catch {\n return Promise.resolve();\n }\n\n if (!pendingProduct || typeof pendingProduct.then !== 'function') {\n return Promise.resolve();\n }\n\n return pendingProduct\n .then((product: Product | null) => {\n if (product) {\n deliver(product);\n }\n })\n .catch(() => {});\n };\n\n const subscription = emitter.addListener(\n OpenIapEvent.PromotedProductIOS,\n (payload) => {\n if (typeof payload === 'string') {\n void replayPendingProduct();\n return;\n }\n\n deliver(payload as Product);\n },\n );\n\n void replayPendingProduct();\n\n return subscription;\n};\n\n/**\n * Android-only listener for User Choice Billing events.\n * This fires when a user selects alternative billing instead of Google Play billing\n * in the User Choice Billing dialog (only in 'user-choice' mode).\n *\n * @param listener - Callback function that receives the external transaction token and product IDs\n * @returns EventSubscription that can be used to unsubscribe\n *\n * @example\n * ```typescript\n * const subscription = userChoiceBillingListenerAndroid((details) => {\n * console.log('User selected alternative billing');\n * console.log('Token:', details.externalTransactionToken);\n * console.log('Products:', details.products);\n *\n * // Process payment in your system, then report token to Google\n * await processPaymentAndReportToken(details);\n * });\n *\n * // Later, clean up\n * subscription.remove();\n * ```\n *\n * @platform Android\n */\nexport const userChoiceBillingListenerAndroid = (\n listener: (details: UserChoiceBillingDetails) => void,\n) => {\n if (Platform.OS !== 'android') {\n ExpoIapConsole.warn(\n 'userChoiceBillingListenerAndroid: This listener is only available on Android',\n );\n return {remove: () => {}};\n }\n return emitter.addListener(OpenIapEvent.UserChoiceBillingAndroid, listener);\n};\n\n/**\n * Android-only listener for Developer Provided Billing events (External Payments).\n * This fires when a user selects the developer's payment option in the External Payments\n * side-by-side choice dialog during purchase flow.\n *\n * Requires Google Play Billing Library 8.3.0+ and is currently only available in Japan.\n *\n * @param listener - Callback function that receives the external transaction token\n * @returns EventSubscription that can be used to unsubscribe\n *\n * @example\n * ```typescript\n * const subscription = developerProvidedBillingListenerAndroid(async (details) => {\n * console.log('User selected developer billing');\n * console.log('Token:', details.externalTransactionToken);\n *\n * // Process payment with your payment gateway\n * await processPaymentWithYourGateway(details.externalTransactionToken);\n *\n * // IMPORTANT: Report the token to Google Play within 24 hours\n * await reportExternalTransactionToGoogle(details.externalTransactionToken);\n * });\n *\n * // Later, clean up\n * subscription.remove();\n * ```\n *\n * @platform Android (8.3.0+, Japan only)\n */\nexport const developerProvidedBillingListenerAndroid = (\n listener: (details: DeveloperProvidedBillingDetailsAndroid) => void,\n) => {\n if (Platform.OS !== 'android') {\n ExpoIapConsole.warn(\n 'developerProvidedBillingListenerAndroid: This listener is only available on Android',\n );\n return {remove: () => {}};\n }\n return emitter.addListener(\n OpenIapEvent.DeveloperProvidedBillingAndroid,\n listener,\n );\n};\n\n/**\n * Listen for subscription billing-issue events (cross-platform).\n *\n * Fires when a user's active subscription enters a state that needs attention\n * for a payment problem. Unifies:\n * - iOS 18+ / Mac Catalyst 18+: StoreKit 2 `Message.Reason.billingIssue`.\n * - Android (Play Billing 8.1+): when `Purchase.isSuspendedAndroid === true`.\n * - Meta Horizon / iOS 17 / older platforms: never fires.\n *\n * Recommended UX: call `deepLinkToSubscriptions()` when this fires so the user\n * can update their payment method in the platform subscription center.\n *\n * @example\n * ```typescript\n * const subscription = subscriptionBillingIssueListener((purchase) => {\n * console.warn('Needs attention:', purchase.productId);\n * deepLinkToSubscriptions({\n * skuAndroid: purchase.productId,\n * packageNameAndroid: 'com.example.app',\n * });\n * });\n * ```\n */\nexport const subscriptionBillingIssueListener = (\n listener: (purchase: Purchase) => void,\n) => {\n // Mirror purchaseUpdatedListener's platform normalization so consumers get\n // a consistent payload regardless of native casing.\n const wrappedListener = (event: Purchase) => {\n listener(normalizePurchasePlatform(event));\n };\n return emitter.addListener(\n OpenIapEvent.SubscriptionBillingIssue,\n wrappedListener,\n );\n};\n\n/**\n * Initialize the store connection. Must be called before any other IAP API.\n *\n * @param config Optional connection config. Use `enableBillingProgramAndroid` (Android,\n * Play Billing 8.2.0+) to opt into External Payments etc. iOS ignores Android-specific fields.\n * @returns Promise resolving to `true` when the platform billing client is connected.\n * @throws When the platform billing client fails to initialize.\n *\n * @example\n * ```ts\n * await initConnection();\n * await initConnection({ enableBillingProgramAndroid: 'external-offer' });\n * ```\n *\n * @remarks When using `useIAP()`, connection is auto-managed on mount/unmount —\n * pass options to the hook instead of calling this directly.\n *\n * @see {@link https://www.openiap.dev/docs/apis/init-connection}\n */\nexport const initConnection: MutationField<'initConnection'> = async (config) =>\n ExpoIapModule.initConnection(config ?? null);\n\n/**\n * Close the store connection and release resources.\n *\n * @see {@link https://www.openiap.dev/docs/apis/end-connection}\n */\nexport const endConnection: MutationField<'endConnection'> = async () =>\n ExpoIapModule.endConnection();\n\n/**\n * Retrieve products or subscriptions from the store by SKU.\n *\n * @param request `ProductRequest` — `skus` (string[]) and optional `type`\n * (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).\n * @returns Promise resolving to a `FetchProductsResult` union — `Product[]` for `'in-app'`,\n * `ProductSubscription[]` for `'subs'`, or a mixed array for `'all'`.\n * @throws When the store rejects the request (empty `skus`, not connected,\n * network/store error). Unknown SKUs are simply omitted from the result, not thrown.\n *\n * @example\n * ```ts\n * const products = await fetchProducts({\n * skus: ['com.app.coins_100', 'com.app.premium'],\n * type: 'in-app',\n * });\n * ```\n *\n * @remarks This is a regular promise-based call. Don't confuse with `request*` APIs\n * (`requestPurchase`), which are event-based.\n *\n * @see {@link https://www.openiap.dev/docs/apis/fetch-products}\n */\nexport const fetchProducts: QueryField<'fetchProducts'> = async (request) => {\n ExpoIapConsole.debug('fetchProducts called with:', request);\n const {skus, type} = request ?? {};\n\n if (!Array.isArray(skus) || skus.length === 0) {\n throw createPurchaseError({\n message: 'No SKUs provided',\n code: ErrorCode.EmptySkuList,\n });\n }\n\n const {canonical, native} = normalizeProductType(\n type as ProductTypeInput | undefined,\n );\n const skuSet = new Set(skus);\n\n const filterIosItems = (\n items: unknown[],\n ): (Product | ProductSubscription)[] =>\n items.filter((item): item is Product | ProductSubscription => {\n if (!isProductIOS(item)) {\n return false;\n }\n const candidate = item as Product | ProductSubscription;\n return typeof candidate.id === 'string' && skuSet.has(candidate.id);\n });\n\n const filterAndroidItems = (\n items: unknown[],\n ): (Product | ProductSubscription)[] =>\n items.filter((item): item is Product | ProductSubscription => {\n if (!isProductAndroid(item)) {\n return false;\n }\n const candidate = item as Product | ProductSubscription;\n return typeof candidate.id === 'string' && skuSet.has(candidate.id);\n });\n\n const castResult = (\n items: (Product | ProductSubscription)[],\n ):\n | (Product | ProductSubscription)[]\n | Product[]\n | ProductSubscription[]\n | null => {\n if (canonical === 'in-app') {\n return items as Product[];\n }\n if (canonical === 'subs') {\n return items as ProductSubscription[];\n }\n // For 'all' type, items contain both Product and ProductSubscription\n // Return as ProductOrSubscription[] to preserve discriminated union\n return items;\n };\n\n if (Platform.OS === 'ios') {\n const rawItems = await ExpoIapModule.fetchProducts({skus, type: native});\n return castResult(filterIosItems(rawItems));\n }\n\n if (Platform.OS === 'android') {\n const rawItems = await ExpoIapModule.fetchProducts(native, skus);\n return castResult(filterAndroidItems(rawItems));\n }\n\n throw new Error('Unsupported platform');\n};\n\n/**\n * List the user's unfinished purchases — non-consumables, active subscriptions, and any\n * pending transactions not yet finished.\n *\n * @param options Optional `PurchaseOptions`. iOS-only flags:\n * `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.\n * @returns Promise resolving to an array of `Purchase` currently held by the store.\n * @throws When the platform query fails.\n *\n * @example\n * ```ts\n * const purchases = await getAvailablePurchases();\n * for (const p of purchases) {\n * if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });\n * }\n * ```\n *\n * @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}\n */\nexport const getAvailablePurchases: QueryField<\n 'getAvailablePurchases'\n> = async (options) => {\n const normalizedOptions: PurchaseOptions = {\n alsoPublishToEventListenerIOS:\n options?.alsoPublishToEventListenerIOS ?? false,\n onlyIncludeActiveItemsIOS: options?.onlyIncludeActiveItemsIOS ?? true,\n includeSuspendedAndroid: options?.includeSuspendedAndroid ?? false,\n };\n\n const resolvePurchases: () => Promise<Purchase[]> =\n Platform.select({\n ios: () =>\n ExpoIapModule.getAvailableItems(\n normalizedOptions.alsoPublishToEventListenerIOS,\n normalizedOptions.onlyIncludeActiveItemsIOS,\n ) as Promise<Purchase[]>,\n android: () =>\n ExpoIapModule.getAvailableItems(normalizedOptions) as Promise<\n Purchase[]\n >,\n }) ?? (() => Promise.resolve([] as Purchase[]));\n\n const purchases = await resolvePurchases();\n return normalizePurchaseArray(purchases as Purchase[]);\n};\n\n/**\n * Get all active subscriptions with detailed information.\n * Uses native OpenIAP module for accurate subscription status and renewal info.\n *\n * On iOS: Returns subscriptions with renewalInfoIOS containing pendingUpgradeProductId,\n * willAutoRenew, autoRenewPreference, and other renewal details.\n *\n * On Android: Filters available purchases to find active subscriptions (fallback implementation).\n *\n * @param subscriptionIds - Optional array of subscription product IDs to filter. If not provided, returns all active subscriptions.\n * @returns Promise resolving to array of active subscriptions with details\n *\n * @example\n * ```typescript\n * // Get all active subscriptions\n * const subs = await getActiveSubscriptions();\n *\n * // Get specific subscriptions\n * const premiumSubs = await getActiveSubscriptions(['premium', 'premium_year']);\n *\n * // Check for pending upgrades (iOS)\n * subs.forEach(sub => {\n * if (sub.renewalInfoIOS?.pendingUpgradeProductId) {\n * console.log(`Upgrade pending to: ${sub.renewalInfoIOS.pendingUpgradeProductId}`);\n * }\n * });\n * ```\n *\n * @see {@link https://www.openiap.dev/docs/apis/get-active-subscriptions}\n */\nexport const getActiveSubscriptions: QueryField<\n 'getActiveSubscriptions'\n> = async (subscriptionIds) => {\n const result = await ExpoIapModule.getActiveSubscriptions(\n subscriptionIds ?? null,\n );\n return (result ?? []) as ActiveSubscription[];\n};\n\n/**\n * Check if user has any active subscriptions.\n *\n * @param subscriptionIds - Optional array of subscription product IDs to check. If not provided, checks all subscriptions.\n * @returns Promise resolving to true if user has at least one active subscription\n *\n * @example\n * ```typescript\n * // Check any active subscription\n * const hasAny = await hasActiveSubscriptions();\n *\n * // Check specific subscriptions\n * const hasPremium = await hasActiveSubscriptions(['premium', 'premium_year']);\n * ```\n *\n * @see {@link https://www.openiap.dev/docs/apis/has-active-subscriptions}\n */\nexport const hasActiveSubscriptions: QueryField<\n 'hasActiveSubscriptions'\n> = async (subscriptionIds) => {\n return !!(await ExpoIapModule.hasActiveSubscriptions(\n subscriptionIds ?? null,\n ));\n};\n\n/**\n * Return the user's storefront country code.\n *\n * @see {@link https://www.openiap.dev/docs/apis/get-storefront}\n */\nexport const getStorefront: QueryField<'getStorefront'> = async () => {\n if (Platform.OS !== 'ios' && Platform.OS !== 'android') {\n return '';\n }\n return ExpoIapModule.getStorefront();\n};\n\n/**\n * Helper to normalize request props to platform-specific format\n */\nfunction normalizeRequestProps(\n request: RequestPurchasePropsByPlatforms,\n platform: 'ios',\n): RequestPurchaseIosProps | null | undefined;\nfunction normalizeRequestProps(\n request: RequestPurchasePropsByPlatforms,\n platform: 'android',\n): RequestPurchaseAndroidProps | null | undefined;\nfunction normalizeRequestProps(\n request: RequestSubscriptionPropsByPlatforms,\n platform: 'ios',\n): RequestSubscriptionIosProps | null | undefined;\nfunction normalizeRequestProps(\n request: RequestSubscriptionPropsByPlatforms,\n platform: 'android',\n): RequestSubscriptionAndroidProps | null | undefined;\nfunction normalizeRequestProps(\n request:\n | RequestPurchasePropsByPlatforms\n | RequestSubscriptionPropsByPlatforms,\n platform: 'ios' | 'android',\n) {\n // Support both new (apple/google) and legacy (ios/android) field names\n // New fields take precedence over deprecated ones\n if (platform === 'ios') {\n return request.apple ?? request.ios;\n }\n return request.google ?? request.android;\n}\n\n/**\n * Initiate a purchase or subscription flow. The result is delivered through\n * `purchaseUpdatedListener` — NOT the return value.\n *\n * @param args `RequestPurchaseProps`, discriminated by `type`:\n * - `type: 'in-app'` — pass `request.apple.sku` (iOS) and/or `request.google.skus` (Android).\n * - `type: 'subs'` — same shape, plus `request.google.subscriptionOffers: [{ sku, offerToken }]`.\n * @returns The dispatched purchase payload. **Do not rely on it** for the actual outcome.\n * @throws Synchronous rejection from the store (e.g. `E_NOT_PREPARED`, validation failure).\n *\n * @example\n * ```ts\n * await requestPurchase({\n * request: {\n * apple: { sku: 'com.app.premium' },\n * google: { skus: ['com.app.premium'] },\n * },\n * type: 'in-app',\n * });\n * ```\n *\n * @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /\n * {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.\n *\n * @see {@link https://www.openiap.dev/docs/apis/request-purchase}\n */\nexport const requestPurchase: MutationField<'requestPurchase'> = async (\n args,\n) => {\n const {request, type} = args;\n const {canonical, native} = normalizeProductType(type as ProductTypeInput);\n const isInAppPurchase = canonical === 'in-app';\n\n if (Platform.OS === 'ios') {\n const normalizedRequest = normalizeRequestProps(request, 'ios');\n\n if (!normalizedRequest?.sku) {\n throw new Error(\n 'Invalid request for Apple. The `sku` property is required and must be a string.\\n\\n' +\n 'Expected format:\\n' +\n ' requestPurchase({\\n' +\n ' request: {\\n' +\n ' apple: { sku: \"product_id\" },\\n' +\n ' google: { skus: [\"product_id\"] }\\n' +\n ' },\\n' +\n ' type: \"in-app\"\\n' +\n ' })\\n\\n' +\n 'See: https://hyochan.github.io/expo-iap/docs/api/methods/core-methods#requestpurchase',\n );\n }\n\n if (canonical !== 'in-app' && canonical !== 'subs') {\n throw new Error(`Unsupported product type: ${canonical}`);\n }\n\n const payload: MutationRequestPurchaseArgs = {\n type: canonical === 'in-app' ? 'in-app' : 'subs',\n request: {ios: normalizedRequest},\n useAlternativeBilling: args.useAlternativeBilling,\n };\n\n const purchase = (await ExpoIapModule.requestPurchase(payload)) as\n | Purchase\n | Purchase[]\n | null;\n\n if (Array.isArray(purchase)) {\n return normalizePurchaseArray(purchase);\n }\n\n if (purchase) {\n return normalizePurchasePlatform(purchase);\n }\n\n return canonical === 'subs' ? [] : null;\n }\n\n if (Platform.OS === 'android') {\n if (isInAppPurchase) {\n const normalizedRequest = normalizeRequestProps(\n request as RequestPurchasePropsByPlatforms,\n 'android',\n ) as RequestPurchaseAndroidProps | null | undefined;\n\n if (!normalizedRequest?.skus?.length) {\n throw new Error(\n 'Invalid request for Google. The `skus` property is required and must be a non-empty array.\\n\\n' +\n 'Expected format:\\n' +\n ' requestPurchase({\\n' +\n ' request: {\\n' +\n ' apple: { sku: \"product_id\" },\\n' +\n ' google: { skus: [\"product_id\"] }\\n' +\n ' },\\n' +\n ' type: \"in-app\"\\n' +\n ' })\\n\\n' +\n 'See: https://hyochan.github.io/expo-iap/docs/api/methods/core-methods#requestpurchase',\n );\n }\n\n const {\n skus,\n obfuscatedAccountId,\n obfuscatedProfileId,\n isOfferPersonalized,\n offerToken,\n } = normalizedRequest;\n\n const result = (await ExpoIapModule.requestPurchase({\n type: native,\n skuArr: skus,\n purchaseToken: undefined,\n replacementMode: -1,\n obfuscatedAccountId: obfuscatedAccountId,\n obfuscatedProfileId: obfuscatedProfileId,\n offerToken: offerToken,\n offerTokenArr: [],\n isOfferPersonalized: isOfferPersonalized ?? false,\n })) as Purchase[];\n\n return normalizePurchaseArray(result);\n }\n\n if (canonical === 'subs') {\n const normalizedRequest = normalizeRequestProps(\n request as RequestSubscriptionPropsByPlatforms,\n 'android',\n ) as RequestSubscriptionAndroidProps | null | undefined;\n\n if (!normalizedRequest?.skus?.length) {\n throw new Error(\n 'Invalid request for Google. The `skus` property is required and must be a non-empty array.\\n\\n' +\n 'Expected format:\\n' +\n ' requestPurchase({\\n' +\n ' request: {\\n' +\n ' apple: { sku: \"subscription_id\" },\\n' +\n ' google: { skus: [\"subscription_id\"] }\\n' +\n ' },\\n' +\n ' type: \"subs\"\\n' +\n ' })\\n\\n' +\n 'See: https://hyochan.github.io/expo-iap/docs/api/methods/core-methods#requestpurchase',\n );\n }\n\n const {\n skus,\n obfuscatedAccountId,\n obfuscatedProfileId,\n isOfferPersonalized,\n subscriptionOffers,\n replacementMode: replacementModeInput,\n purchaseToken: purchaseTokenInput,\n subscriptionProductReplacementParams,\n } = normalizedRequest;\n\n const normalizedOffers = subscriptionOffers ?? [];\n const replacementMode = replacementModeInput ?? -1;\n const purchaseToken = purchaseTokenInput ?? undefined;\n\n const result = (await ExpoIapModule.requestPurchase({\n type: native,\n skuArr: skus,\n purchaseToken,\n replacementMode,\n obfuscatedAccountId: obfuscatedAccountId,\n obfuscatedProfileId: obfuscatedProfileId,\n offerTokenArr: normalizedOffers.map(\n (offer: AndroidSubscriptionOfferInput) => offer.offerToken,\n ),\n subscriptionOffers: normalizedOffers,\n isOfferPersonalized: isOfferPersonalized ?? false,\n subscriptionProductReplacementParams:\n subscriptionProductReplacementParams ?? undefined,\n })) as Purchase[];\n\n return normalizePurchaseArray(result);\n }\n\n throw new Error(\n \"Invalid request for Android: Expected a valid request object with 'skus' array.\",\n );\n }\n\n throw new Error('Platform not supported');\n};\n\n/**\n * Complete a purchase transaction. Call after server-side verification to remove it\n * from the queue.\n *\n * @param args.purchase The `Purchase` to finalize.\n * @param args.isConsumable `true` for consumables (consumes the token so the SKU can be\n * re-bought, e.g. coins); `false` (default) for non-consumables and subscriptions.\n * @returns Promise that resolves once the platform finalizes the transaction.\n * @throws When the platform finalize call fails.\n *\n * @example\n * ```ts\n * // Inside purchaseUpdatedListener:\n * if (await verifyOnServer(purchase)) {\n * await finishTransaction({ purchase, isConsumable: false });\n * }\n * ```\n *\n * @remarks **Critical:** Android purchases must be finalized within 3 days or Google\n * auto-refunds. iOS unfinished transactions replay on every app launch.\n *\n * @see {@link https://www.openiap.dev/docs/apis/finish-transaction}\n */\nexport const finishTransaction: MutationField<'finishTransaction'> = async ({\n purchase,\n isConsumable = false,\n}) => {\n if (Platform.OS === 'ios') {\n await ExpoIapModule.finishTransaction(purchase, isConsumable);\n return;\n }\n\n if (Platform.OS === 'android') {\n const token = purchase.purchaseToken ?? undefined;\n\n if (!token) {\n throw createPurchaseError({\n message: 'Purchase token is required to finish transaction',\n code: ErrorCode.DeveloperError,\n productId: purchase.productId,\n platform: 'android',\n });\n }\n\n if (isConsumable) {\n await ExpoIapModule.consumePurchaseAndroid(token);\n return;\n }\n\n await ExpoIapModule.acknowledgePurchaseAndroid(token);\n return;\n }\n\n throw new Error('Unsupported Platform');\n};\n\n/**\n * Restore completed transactions (cross-platform behavior)\n *\n * - iOS: perform a lightweight sync to refresh transactions and ignore sync errors,\n * then fetch available purchases to surface restored items to the app.\n * - Android: simply fetch available purchases (restoration happens via query).\n *\n * This helper triggers the refresh flows but does not return the purchases; consumers should\n * call `getAvailablePurchases` or rely on hook state to inspect the latest items.\n *\n * @see {@link https://www.openiap.dev/docs/apis/restore-purchases}\n */\nexport const restorePurchases: MutationField<'restorePurchases'> = async () => {\n if (Platform.OS === 'ios') {\n await syncIOS().catch(() => undefined);\n }\n\n await getAvailablePurchases({\n alsoPublishToEventListenerIOS: false,\n onlyIncludeActiveItemsIOS: true,\n });\n};\n\n/**\n * Deeplinks to native interface that allows users to manage their subscriptions\n * @param options.skuAndroid - Required for Android to locate specific subscription (ignored on iOS)\n * @param options.packageNameAndroid - Required for Android to identify your app (ignored on iOS)\n *\n * @returns Promise that resolves when the deep link is successfully opened\n *\n * @throws {Error} When called on unsupported platform or when required Android parameters are missing\n *\n * @example\n * import { deepLinkToSubscriptions } from 'expo-iap';\n *\n * // Works on both iOS and Android\n * await deepLinkToSubscriptions({\n * skuAndroid: 'your_subscription_sku',\n * packageNameAndroid: 'com.example.app'\n * });\n *\n * @see {@link https://www.openiap.dev/docs/apis/deep-link-to-subscriptions}\n */\nexport const deepLinkToSubscriptions: MutationField<\n 'deepLinkToSubscriptions'\n> = async (options) => {\n if (Platform.OS === 'ios') {\n await deepLinkToSubscriptionsIOS();\n return;\n }\n\n if (Platform.OS === 'android') {\n await deepLinkToSubscriptionsAndroid((options as DeepLinkOptions) ?? null);\n return;\n }\n\n throw new Error(`Unsupported platform: ${Platform.OS}`);\n};\n\n/**\n * Internal receipt validation function (NOT RECOMMENDED for production use)\n *\n * WARNING: This function performs client-side validation which is NOT secure.\n * For production apps, always validate receipts on your secure server:\n * - iOS: Send receipt data to Apple's verification endpoint from your server\n * - Android: Use Google Play Developer API with service account credentials\n *\n * @deprecated Use verifyPurchase instead\n *\n * @see {@link https://www.openiap.dev/docs/apis/validate-receipt}\n */\nexport const validateReceipt: MutationField<'validateReceipt'> = async (\n options,\n) => {\n const {apple, google} = options as MutationValidateReceiptArgs;\n\n if (Platform.OS === 'ios') {\n if (!apple?.sku) {\n throw new Error('iOS validation requires apple.sku');\n }\n return validateReceiptIOS({apple: {sku: apple.sku}});\n }\n\n if (Platform.OS === 'android') {\n if (\n !google ||\n !google.sku ||\n !google.packageName ||\n !google.purchaseToken ||\n !google.accessToken\n ) {\n throw new Error(\n 'Android validation requires google.sku, google.packageName, google.purchaseToken, and google.accessToken',\n );\n }\n return validateReceiptAndroid({\n packageName: google.packageName,\n productId: google.sku,\n productToken: google.purchaseToken,\n accessToken: google.accessToken,\n isSub: google.isSub ?? undefined,\n });\n }\n\n throw new Error('Platform not supported');\n};\n\n/**\n * Verify purchase with the configured providers\n *\n * This function uses the native OpenIAP verifyPurchase implementation\n * which validates purchases using platform-specific methods.\n *\n * @param options - Receipt validation options containing the SKU\n * @returns Promise resolving to receipt validation result\n *\n * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase}\n */\nexport const verifyPurchase: MutationField<'verifyPurchase'> = async (\n options,\n) => {\n if (Platform.OS === 'ios' || Platform.OS === 'android') {\n return ExpoIapModule.verifyPurchase(options);\n }\n\n throw new Error(`Unsupported platform: ${Platform.OS}`);\n};\n\n/**\n * Verify purchase with a specific provider (e.g., IAPKit)\n *\n * This function allows you to verify purchases using external verification\n * services like IAPKit, which provide additional validation and security.\n *\n * @param options - Verification options including provider and credentials\n * @returns Promise resolving to provider-specific verification result\n *\n * @example\n * ```typescript\n * const result = await verifyPurchaseWithProvider({\n * provider: 'iapkit',\n * iapkit: {\n * apiKey: 'your-api-key',\n * apple: {\n * jws: purchase.purchaseToken // JWS from purchase\n * },\n * google: {\n * purchaseToken: purchase.purchaseToken\n * }\n * }\n * });\n * ```\n *\n * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}\n */\nexport const verifyPurchaseWithProvider: MutationField<\n 'verifyPurchaseWithProvider'\n> = async (options) => {\n if (Platform.OS === 'ios' || Platform.OS === 'android') {\n // Auto-fill apiKey from config if not provided and provider is iapkit\n if (\n options.provider === 'iapkit' &&\n options.iapkit &&\n !options.iapkit.apiKey\n ) {\n try {\n // Dynamically import expo-constants to avoid hard dependency\n const {default: Constants} = await import('expo-constants');\n const configApiKey = Constants.expoConfig?.extra?.iapkitApiKey;\n if (configApiKey) {\n options = {\n ...options,\n iapkit: {\n ...options.iapkit,\n apiKey: configApiKey,\n },\n };\n }\n } catch {\n throw new Error(\n 'expo-constants is required for auto-filling iapkitApiKey from config. ' +\n 'Please install it: npx expo install expo-constants\\n' +\n 'Or provide apiKey directly in verifyPurchaseWithProvider options.',\n );\n }\n }\n return ExpoIapModule.verifyPurchaseWithProvider(options);\n }\n\n throw new Error(`Unsupported platform: ${Platform.OS}`);\n};\n\nexport * from './useIAP';\nexport {useWebhookEvents} from './useWebhookEvents';\nexport type {\n UseWebhookEventsOptions,\n UseWebhookEventsResult,\n} from './useWebhookEvents';\nexport {connectWebhookStream, parseWebhookEventData} from './webhook-client';\nexport type {\n WebhookEventPayload,\n WebhookEventStream,\n WebhookEventType as WebhookEventTypeName,\n WebhookListener,\n WebhookListenerError,\n WebhookListenerOptions,\n} from './webhook-client';\nexport {kitApi, KitApiError} from './kit-api';\nexport type {\n KitApiOptions,\n KitSubscription,\n EntitlementsResponse,\n StatusResponse,\n} from './kit-api';\nexport {\n ErrorCodeUtils,\n ErrorCodeMapping,\n createPurchaseError,\n createPurchaseErrorFromPlatform,\n} from './utils/errorMapping';\nexport type {\n PurchaseError as ExpoPurchaseError,\n PurchaseErrorProps,\n} from './utils/errorMapping';\nexport {ExpoIapConsole} from './utils/debug';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["// External dependencies\nimport {Platform} from 'react-native';\n\n// Internal modules\nimport ExpoIapModule, {getNativeModule} from './ExpoIapModule';\nimport {\n isProductIOS,\n validateReceiptIOS,\n deepLinkToSubscriptionsIOS,\n syncIOS,\n} from './modules/ios';\nimport {\n isProductAndroid,\n validateReceiptAndroid,\n deepLinkToSubscriptionsAndroid,\n} from './modules/android';\nimport {ExpoIapConsole} from './utils/debug';\n\n// Types\nimport type {\n ActiveSubscription,\n AndroidSubscriptionOfferInput,\n DeepLinkOptions,\n DeveloperProvidedBillingDetailsAndroid,\n MutationField,\n MutationRequestPurchaseArgs,\n MutationValidateReceiptArgs,\n Product,\n ProductQueryType,\n ProductSubscription,\n Purchase,\n PurchaseOptions,\n PurchaseUpdatedListenerOptions,\n QueryField,\n RequestPurchasePropsByPlatforms,\n RequestPurchaseAndroidProps,\n RequestPurchaseIosProps,\n RequestSubscriptionPropsByPlatforms,\n RequestSubscriptionAndroidProps,\n RequestSubscriptionIosProps,\n UserChoiceBillingDetails,\n} from './types';\nimport {ErrorCode} from './types';\nimport {createPurchaseError, type PurchaseError} from './utils/errorMapping';\n\n// Export all types\nexport * from './types';\nexport * from './modules/android';\nexport * from './modules/ios';\nexport * from './onside';\n\n// Get the native constant value\nexport enum OpenIapEvent {\n PurchaseUpdated = 'purchase-updated',\n PurchaseError = 'purchase-error',\n PromotedProductIOS = 'promoted-product-ios',\n UserChoiceBillingAndroid = 'user-choice-billing-android',\n /**\n * Fired when user selects developer billing in External Payments flow (Android 8.3.0+)\n * Only available in Japan. Contains externalTransactionToken for reporting.\n */\n DeveloperProvidedBillingAndroid = 'developer-provided-billing-android',\n /**\n * Fired when an active subscription enters a billing-issue state (cross-platform).\n * Unifies StoreKit 2 `Message.Reason.billingIssue` (iOS 18+) and Play Billing 8.1+\n * `Purchase.isSuspended`. NOT fired on the Meta Horizon flavor.\n */\n SubscriptionBillingIssue = 'subscription-billing-issue',\n}\n\ntype ExpoIapEventPayloads = {\n [OpenIapEvent.PurchaseUpdated]: Purchase;\n [OpenIapEvent.PurchaseError]: PurchaseError;\n [OpenIapEvent.PromotedProductIOS]:\n | Product\n | string\n | {id?: string; productId?: string};\n [OpenIapEvent.UserChoiceBillingAndroid]: UserChoiceBillingDetails;\n [OpenIapEvent.DeveloperProvidedBillingAndroid]: DeveloperProvidedBillingDetailsAndroid;\n [OpenIapEvent.SubscriptionBillingIssue]: Purchase;\n};\n\ntype ExpoIapEventListener<E extends OpenIapEvent> = (\n payload: ExpoIapEventPayloads[E],\n) => void;\n\ntype ExpoIapEmitter = {\n addListener<E extends OpenIapEvent>(\n eventName: E,\n listener: ExpoIapEventListener<E>,\n ): {remove: () => void};\n removeListener<E extends OpenIapEvent>(\n eventName: E,\n listener: ExpoIapEventListener<E>,\n ): void;\n};\n\ntype NativePurchaseUpdatedOptionsModule = {\n setPurchaseUpdatedListenerOptions?: (\n options?: PurchaseUpdatedListenerOptions | null,\n ) => Promise<void>;\n};\n\n// Use the raw native module for listener calls — JSI HostObjects require the\n// real native module as `this` when calling addListener. Using a Proxy as\n// `this` triggers \"native state unsupported on Proxy\" on New Architecture / Hermes.\n// Resolved lazily so importing this module doesn't throw on unsupported platforms.\nexport const emitter: ExpoIapEmitter = {\n addListener(eventName, listener) {\n const nativeModule = getNativeModule();\n const nativeSubscription = nativeModule.addListener(eventName, listener);\n let removed = false;\n\n return {\n remove: () => {\n if (removed) {\n return;\n }\n removed = true;\n\n if (typeof nativeSubscription?.remove === 'function') {\n nativeSubscription.remove();\n return;\n }\n\n nativeModule.removeListener?.(eventName, listener);\n },\n };\n },\n removeListener(eventName, listener) {\n return getNativeModule().removeListener?.(eventName, listener);\n },\n};\n\nlet nonDedupingPurchaseUpdatedListenerCountIOS = 0;\nconst purchaseUpdatedDedupeHistoryLimitIOS = 512;\nconst purchaseUpdatedDedupeHistoryIOS = {\n ids: new Set<string>(),\n order: [] as string[],\n start: 0,\n};\nlet purchaseUpdatedDedupeGenerationIOS = 0;\n\ntype PurchaseUpdatedDedupeHistoryIOS = {\n ids: Set<string>;\n order: string[];\n start: number;\n};\n\nconst purchaseUpdatedTransactionIdIOS = (purchase: Purchase) => {\n if (typeof purchase.id === 'string' && purchase.id.length > 0) {\n return purchase.id;\n }\n return null;\n};\n\nconst rememberPurchaseUpdatedTransactionIOS = (\n transactionId: string,\n history: PurchaseUpdatedDedupeHistoryIOS,\n) => {\n if (history.ids.has(transactionId)) {\n return;\n }\n\n history.ids.add(transactionId);\n history.order.push(transactionId);\n if (\n history.order.length - history.start >\n purchaseUpdatedDedupeHistoryLimitIOS\n ) {\n const evicted = history.order[history.start];\n history.start += 1;\n if (evicted != null) {\n history.ids.delete(evicted);\n }\n if (history.start > 128 && history.start * 2 > history.order.length) {\n history.order = history.order.slice(history.start);\n history.start = 0;\n }\n }\n};\n\nconst clearPurchaseUpdatedDedupeHistoryIOS = (\n history: PurchaseUpdatedDedupeHistoryIOS,\n) => {\n history.ids.clear();\n history.order.length = 0;\n history.start = 0;\n};\n\nconst resetPurchaseUpdatedDedupeHistoryIOS = () => {\n clearPurchaseUpdatedDedupeHistoryIOS(purchaseUpdatedDedupeHistoryIOS);\n purchaseUpdatedDedupeGenerationIOS += 1;\n};\n\nconst configurePurchaseUpdatedListenerOptionsIOS = (\n dedupeTransactionIOS: boolean,\n) => {\n if (Platform.OS !== 'ios') return;\n\n const nativeModule = getNativeModule() as NativePurchaseUpdatedOptionsModule;\n const promise = nativeModule.setPurchaseUpdatedListenerOptions?.({\n dedupeTransactionIOS,\n });\n void promise?.catch((error: unknown) => {\n ExpoIapConsole.warn(\n 'Failed to configure purchase updated listener options:',\n error,\n );\n });\n};\n\n/**\n * TODO(v3.1.0): Remove legacy 'inapp' alias once downstream apps migrate to 'in-app'.\n */\nexport type ProductTypeInput = ProductQueryType | 'inapp';\n\nconst normalizeProductType = (type?: ProductTypeInput) => {\n if (type === 'inapp') {\n ExpoIapConsole.warn(\n \"'inapp' product type is deprecated and will be removed in v3.1.0. Use 'in-app' instead.\",\n );\n }\n\n if (!type || type === 'inapp' || type === 'in-app') {\n return {\n canonical: 'in-app' as ProductQueryType,\n native: 'in-app' as const,\n };\n }\n if (type === 'subs') {\n return {\n canonical: 'subs' as ProductQueryType,\n native: 'subs' as const,\n };\n }\n if (type === 'all') {\n return {\n canonical: 'all' as ProductQueryType,\n native: 'all' as const,\n };\n }\n throw new Error(`Unsupported product type: ${type}`);\n};\n\nconst normalizePurchasePlatform = (purchase: Purchase): Purchase => {\n const platform = purchase.platform;\n if (typeof platform !== 'string') {\n return purchase;\n }\n\n const lowered = platform.toLowerCase();\n if (lowered === platform || (lowered !== 'ios' && lowered !== 'android')) {\n return purchase;\n }\n\n return {...purchase, platform: lowered};\n};\n\nconst normalizePurchaseArray = (purchases: Purchase[]): Purchase[] =>\n purchases.map((purchase) => normalizePurchasePlatform(purchase));\n\nexport const purchaseUpdatedListener = (\n listener: (event: Purchase) => void,\n options?: PurchaseUpdatedListenerOptions | null,\n) => {\n const receiveDuplicateTransactionUpdatesIOS =\n Platform.OS === 'ios' && options?.dedupeTransactionIOS === false;\n const listenerDedupeHistoryIOS: PurchaseUpdatedDedupeHistoryIOS = {\n ids: new Set(purchaseUpdatedDedupeHistoryIOS.ids),\n order: purchaseUpdatedDedupeHistoryIOS.order.slice(\n purchaseUpdatedDedupeHistoryIOS.start,\n ),\n start: 0,\n };\n let listenerDedupeGenerationIOS = purchaseUpdatedDedupeGenerationIOS;\n\n const wrappedListener = (event: Purchase) => {\n const normalized = normalizePurchasePlatform(event);\n if (Platform.OS === 'ios') {\n if (listenerDedupeGenerationIOS !== purchaseUpdatedDedupeGenerationIOS) {\n clearPurchaseUpdatedDedupeHistoryIOS(listenerDedupeHistoryIOS);\n listenerDedupeGenerationIOS = purchaseUpdatedDedupeGenerationIOS;\n }\n const transactionId = purchaseUpdatedTransactionIdIOS(normalized);\n if (transactionId != null) {\n const isDuplicateForListener =\n listenerDedupeHistoryIOS.ids.has(transactionId);\n rememberPurchaseUpdatedTransactionIOS(\n transactionId,\n listenerDedupeHistoryIOS,\n );\n rememberPurchaseUpdatedTransactionIOS(\n transactionId,\n purchaseUpdatedDedupeHistoryIOS,\n );\n if (!receiveDuplicateTransactionUpdatesIOS && isDuplicateForListener) {\n return;\n }\n }\n }\n listener(normalized);\n };\n const emitterSubscription = emitter.addListener(\n OpenIapEvent.PurchaseUpdated,\n wrappedListener,\n );\n\n if (!receiveDuplicateTransactionUpdatesIOS) {\n return emitterSubscription;\n }\n\n nonDedupingPurchaseUpdatedListenerCountIOS += 1;\n configurePurchaseUpdatedListenerOptionsIOS(false);\n let removed = false;\n\n return {\n remove: () => {\n if (removed) {\n return;\n }\n removed = true;\n try {\n emitterSubscription?.remove?.();\n } finally {\n nonDedupingPurchaseUpdatedListenerCountIOS = Math.max(\n 0,\n nonDedupingPurchaseUpdatedListenerCountIOS - 1,\n );\n configurePurchaseUpdatedListenerOptionsIOS(\n nonDedupingPurchaseUpdatedListenerCountIOS === 0,\n );\n }\n },\n };\n};\n\nexport const purchaseErrorListener = (\n listener: (error: PurchaseError) => void,\n) => {\n const wrappedListener = (error: PurchaseError) => {\n listener(error);\n };\n const emitterSubscription = emitter.addListener(\n OpenIapEvent.PurchaseError,\n wrappedListener,\n );\n return emitterSubscription;\n};\n\n/**\n * iOS-only listener for App Store promoted product events.\n * This fires when a user taps on a promoted product in the App Store.\n *\n * @param listener - Callback function that receives the promoted product details\n * @returns EventSubscription that can be used to unsubscribe\n *\n * @example\n * ```typescript\n * const subscription = promotedProductListenerIOS((product) => {\n * console.log('Promoted product:', product);\n * // Handle the promoted product\n * });\n *\n * // Later, clean up\n * subscription.remove();\n * ```\n *\n * @platform iOS\n */\nexport const promotedProductListenerIOS = (\n listener: (product: Product) => void,\n) => {\n if (Platform.OS !== 'ios') {\n ExpoIapConsole.warn(\n 'promotedProductListenerIOS: This listener is only available on iOS',\n );\n return {remove: () => {}};\n }\n\n let deliveredProductId: string | undefined;\n const deliver = (product: Product) => {\n const productId =\n product.id ?? (product as Product & {productId?: string}).productId;\n if (productId && productId === deliveredProductId) {\n return;\n }\n deliveredProductId = productId;\n listener(product);\n };\n\n const replayPendingProduct = () => {\n let pendingProduct: Promise<Product | null> | undefined;\n try {\n pendingProduct = ExpoIapModule.getPromotedProductIOS() as\n | Promise<Product | null>\n | undefined;\n } catch {\n return Promise.resolve();\n }\n\n if (!pendingProduct || typeof pendingProduct.then !== 'function') {\n return Promise.resolve();\n }\n\n return pendingProduct\n .then((product: Product | null) => {\n if (product) {\n deliver(product);\n }\n })\n .catch(() => {});\n };\n\n const subscription = emitter.addListener(\n OpenIapEvent.PromotedProductIOS,\n (payload) => {\n if (typeof payload === 'string') {\n void replayPendingProduct();\n return;\n }\n\n deliver(payload as Product);\n },\n );\n\n void replayPendingProduct();\n\n return subscription;\n};\n\n/**\n * Android-only listener for User Choice Billing events.\n * This fires when a user selects alternative billing instead of Google Play billing\n * in the User Choice Billing dialog (only in 'user-choice' mode).\n *\n * @param listener - Callback function that receives the external transaction token and product IDs\n * @returns EventSubscription that can be used to unsubscribe\n *\n * @example\n * ```typescript\n * const subscription = userChoiceBillingListenerAndroid((details) => {\n * console.log('User selected alternative billing');\n * console.log('Token:', details.externalTransactionToken);\n * console.log('Products:', details.products);\n *\n * // Process payment in your system, then report token to Google\n * await processPaymentAndReportToken(details);\n * });\n *\n * // Later, clean up\n * subscription.remove();\n * ```\n *\n * @platform Android\n */\nexport const userChoiceBillingListenerAndroid = (\n listener: (details: UserChoiceBillingDetails) => void,\n) => {\n if (Platform.OS !== 'android') {\n ExpoIapConsole.warn(\n 'userChoiceBillingListenerAndroid: This listener is only available on Android',\n );\n return {remove: () => {}};\n }\n return emitter.addListener(OpenIapEvent.UserChoiceBillingAndroid, listener);\n};\n\n/**\n * Android-only listener for Developer Provided Billing events (External Payments).\n * This fires when a user selects the developer's payment option in the External Payments\n * side-by-side choice dialog during purchase flow.\n *\n * Requires Google Play Billing Library 8.3.0+ and is currently only available in Japan.\n *\n * @param listener - Callback function that receives the external transaction token\n * @returns EventSubscription that can be used to unsubscribe\n *\n * @example\n * ```typescript\n * const subscription = developerProvidedBillingListenerAndroid(async (details) => {\n * console.log('User selected developer billing');\n * console.log('Token:', details.externalTransactionToken);\n *\n * // Process payment with your payment gateway\n * await processPaymentWithYourGateway(details.externalTransactionToken);\n *\n * // IMPORTANT: Report the token to Google Play within 24 hours\n * await reportExternalTransactionToGoogle(details.externalTransactionToken);\n * });\n *\n * // Later, clean up\n * subscription.remove();\n * ```\n *\n * @platform Android (8.3.0+, Japan only)\n */\nexport const developerProvidedBillingListenerAndroid = (\n listener: (details: DeveloperProvidedBillingDetailsAndroid) => void,\n) => {\n if (Platform.OS !== 'android') {\n ExpoIapConsole.warn(\n 'developerProvidedBillingListenerAndroid: This listener is only available on Android',\n );\n return {remove: () => {}};\n }\n return emitter.addListener(\n OpenIapEvent.DeveloperProvidedBillingAndroid,\n listener,\n );\n};\n\n/**\n * Listen for subscription billing-issue events (cross-platform).\n *\n * Fires when a user's active subscription enters a state that needs attention\n * for a payment problem. Unifies:\n * - iOS 18+ / Mac Catalyst 18+: StoreKit 2 `Message.Reason.billingIssue`.\n * - Android (Play Billing 8.1+): when `Purchase.isSuspendedAndroid === true`.\n * - Meta Horizon / iOS 17 / older platforms: never fires.\n *\n * Recommended UX: call `deepLinkToSubscriptions()` when this fires so the user\n * can update their payment method in the platform subscription center.\n *\n * @example\n * ```typescript\n * const subscription = subscriptionBillingIssueListener((purchase) => {\n * console.warn('Needs attention:', purchase.productId);\n * deepLinkToSubscriptions({\n * skuAndroid: purchase.productId,\n * packageNameAndroid: 'com.example.app',\n * });\n * });\n * ```\n */\nexport const subscriptionBillingIssueListener = (\n listener: (purchase: Purchase) => void,\n) => {\n // Mirror purchaseUpdatedListener's platform normalization so consumers get\n // a consistent payload regardless of native casing.\n const wrappedListener = (event: Purchase) => {\n listener(normalizePurchasePlatform(event));\n };\n return emitter.addListener(\n OpenIapEvent.SubscriptionBillingIssue,\n wrappedListener,\n );\n};\n\n/**\n * Initialize the store connection. Must be called before any other IAP API.\n *\n * @param config Optional connection config. Use `enableBillingProgramAndroid` (Android,\n * Play Billing 8.2.0+) to opt into External Payments etc. iOS ignores Android-specific fields.\n * @returns Promise resolving to `true` when the platform billing client is connected.\n * @throws When the platform billing client fails to initialize.\n *\n * @example\n * ```ts\n * await initConnection();\n * await initConnection({ enableBillingProgramAndroid: 'external-offer' });\n * ```\n *\n * @remarks When using `useIAP()`, connection is auto-managed on mount/unmount —\n * pass options to the hook instead of calling this directly.\n *\n * @see {@link https://www.openiap.dev/docs/apis/init-connection}\n */\nexport const initConnection: MutationField<'initConnection'> = async (\n config,\n) => {\n const result = await ExpoIapModule.initConnection(config ?? null);\n if (\n result === true &&\n Platform.OS === 'ios' &&\n nonDedupingPurchaseUpdatedListenerCountIOS > 0\n ) {\n configurePurchaseUpdatedListenerOptionsIOS(false);\n }\n return result;\n};\n\n/**\n * Close the store connection and release resources.\n *\n * @see {@link https://www.openiap.dev/docs/apis/end-connection}\n */\nexport const endConnection: MutationField<'endConnection'> = async () => {\n const result = await ExpoIapModule.endConnection();\n if (result === true && Platform.OS === 'ios') {\n resetPurchaseUpdatedDedupeHistoryIOS();\n }\n return result;\n};\n\n/**\n * Retrieve products or subscriptions from the store by SKU.\n *\n * @param request `ProductRequest` — `skus` (string[]) and optional `type`\n * (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).\n * @returns Promise resolving to a `FetchProductsResult` union — `Product[]` for `'in-app'`,\n * `ProductSubscription[]` for `'subs'`, or a mixed array for `'all'`.\n * @throws When the store rejects the request (empty `skus`, not connected,\n * network/store error). Unknown SKUs are simply omitted from the result, not thrown.\n *\n * @example\n * ```ts\n * const products = await fetchProducts({\n * skus: ['com.app.coins_100', 'com.app.premium'],\n * type: 'in-app',\n * });\n * ```\n *\n * @remarks This is a regular promise-based call. Don't confuse with `request*` APIs\n * (`requestPurchase`), which are event-based.\n *\n * @see {@link https://www.openiap.dev/docs/apis/fetch-products}\n */\nexport const fetchProducts: QueryField<'fetchProducts'> = async (request) => {\n ExpoIapConsole.debug('fetchProducts called with:', request);\n const {skus, type} = request ?? {};\n\n if (!Array.isArray(skus) || skus.length === 0) {\n throw createPurchaseError({\n message: 'No SKUs provided',\n code: ErrorCode.EmptySkuList,\n });\n }\n\n const {canonical, native} = normalizeProductType(\n type as ProductTypeInput | undefined,\n );\n const skuSet = new Set(skus);\n\n const filterIosItems = (\n items: unknown[],\n ): (Product | ProductSubscription)[] =>\n items.filter((item): item is Product | ProductSubscription => {\n if (!isProductIOS(item)) {\n return false;\n }\n const candidate = item as Product | ProductSubscription;\n return typeof candidate.id === 'string' && skuSet.has(candidate.id);\n });\n\n const filterAndroidItems = (\n items: unknown[],\n ): (Product | ProductSubscription)[] =>\n items.filter((item): item is Product | ProductSubscription => {\n if (!isProductAndroid(item)) {\n return false;\n }\n const candidate = item as Product | ProductSubscription;\n return typeof candidate.id === 'string' && skuSet.has(candidate.id);\n });\n\n const castResult = (\n items: (Product | ProductSubscription)[],\n ):\n | (Product | ProductSubscription)[]\n | Product[]\n | ProductSubscription[]\n | null => {\n if (canonical === 'in-app') {\n return items as Product[];\n }\n if (canonical === 'subs') {\n return items as ProductSubscription[];\n }\n // For 'all' type, items contain both Product and ProductSubscription\n // Return as ProductOrSubscription[] to preserve discriminated union\n return items;\n };\n\n if (Platform.OS === 'ios') {\n const rawItems = await ExpoIapModule.fetchProducts({skus, type: native});\n return castResult(filterIosItems(rawItems));\n }\n\n if (Platform.OS === 'android') {\n const rawItems = await ExpoIapModule.fetchProducts(native, skus);\n return castResult(filterAndroidItems(rawItems));\n }\n\n throw new Error('Unsupported platform');\n};\n\n/**\n * List the user's unfinished purchases — non-consumables, active subscriptions, and any\n * pending transactions not yet finished.\n *\n * @param options Optional `PurchaseOptions`. iOS-only flags:\n * `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.\n * @returns Promise resolving to an array of `Purchase` currently held by the store.\n * @throws When the platform query fails.\n *\n * @example\n * ```ts\n * const purchases = await getAvailablePurchases();\n * for (const p of purchases) {\n * if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });\n * }\n * ```\n *\n * @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}\n */\nexport const getAvailablePurchases: QueryField<\n 'getAvailablePurchases'\n> = async (options) => {\n const normalizedOptions: PurchaseOptions = {\n alsoPublishToEventListenerIOS:\n options?.alsoPublishToEventListenerIOS ?? false,\n onlyIncludeActiveItemsIOS: options?.onlyIncludeActiveItemsIOS ?? true,\n includeSuspendedAndroid: options?.includeSuspendedAndroid ?? false,\n };\n\n const resolvePurchases: () => Promise<Purchase[]> =\n Platform.select({\n ios: () =>\n ExpoIapModule.getAvailableItems(\n normalizedOptions.alsoPublishToEventListenerIOS,\n normalizedOptions.onlyIncludeActiveItemsIOS,\n ) as Promise<Purchase[]>,\n android: () =>\n ExpoIapModule.getAvailableItems(normalizedOptions) as Promise<\n Purchase[]\n >,\n }) ?? (() => Promise.resolve([] as Purchase[]));\n\n const purchases = await resolvePurchases();\n return normalizePurchaseArray(purchases as Purchase[]);\n};\n\n/**\n * Get all active subscriptions with detailed information.\n * Uses native OpenIAP module for accurate subscription status and renewal info.\n *\n * On iOS: Returns subscriptions with renewalInfoIOS containing pendingUpgradeProductId,\n * willAutoRenew, autoRenewPreference, and other renewal details.\n *\n * On Android: Filters available purchases to find active subscriptions (fallback implementation).\n *\n * @param subscriptionIds - Optional array of subscription product IDs to filter. If not provided, returns all active subscriptions.\n * @returns Promise resolving to array of active subscriptions with details\n *\n * @example\n * ```typescript\n * // Get all active subscriptions\n * const subs = await getActiveSubscriptions();\n *\n * // Get specific subscriptions\n * const premiumSubs = await getActiveSubscriptions(['premium', 'premium_year']);\n *\n * // Check for pending upgrades (iOS)\n * subs.forEach(sub => {\n * if (sub.renewalInfoIOS?.pendingUpgradeProductId) {\n * console.log(`Upgrade pending to: ${sub.renewalInfoIOS.pendingUpgradeProductId}`);\n * }\n * });\n * ```\n *\n * @see {@link https://www.openiap.dev/docs/apis/get-active-subscriptions}\n */\nexport const getActiveSubscriptions: QueryField<\n 'getActiveSubscriptions'\n> = async (subscriptionIds) => {\n const result = await ExpoIapModule.getActiveSubscriptions(\n subscriptionIds ?? null,\n );\n return (result ?? []) as ActiveSubscription[];\n};\n\n/**\n * Check if user has any active subscriptions.\n *\n * @param subscriptionIds - Optional array of subscription product IDs to check. If not provided, checks all subscriptions.\n * @returns Promise resolving to true if user has at least one active subscription\n *\n * @example\n * ```typescript\n * // Check any active subscription\n * const hasAny = await hasActiveSubscriptions();\n *\n * // Check specific subscriptions\n * const hasPremium = await hasActiveSubscriptions(['premium', 'premium_year']);\n * ```\n *\n * @see {@link https://www.openiap.dev/docs/apis/has-active-subscriptions}\n */\nexport const hasActiveSubscriptions: QueryField<\n 'hasActiveSubscriptions'\n> = async (subscriptionIds) => {\n return !!(await ExpoIapModule.hasActiveSubscriptions(\n subscriptionIds ?? null,\n ));\n};\n\n/**\n * Return the user's storefront country code.\n *\n * @see {@link https://www.openiap.dev/docs/apis/get-storefront}\n */\nexport const getStorefront: QueryField<'getStorefront'> = async () => {\n if (Platform.OS !== 'ios' && Platform.OS !== 'android') {\n return '';\n }\n return ExpoIapModule.getStorefront();\n};\n\n/**\n * Helper to normalize request props to platform-specific format\n */\nfunction normalizeRequestProps(\n request: RequestPurchasePropsByPlatforms,\n platform: 'ios',\n): RequestPurchaseIosProps | null | undefined;\nfunction normalizeRequestProps(\n request: RequestPurchasePropsByPlatforms,\n platform: 'android',\n): RequestPurchaseAndroidProps | null | undefined;\nfunction normalizeRequestProps(\n request: RequestSubscriptionPropsByPlatforms,\n platform: 'ios',\n): RequestSubscriptionIosProps | null | undefined;\nfunction normalizeRequestProps(\n request: RequestSubscriptionPropsByPlatforms,\n platform: 'android',\n): RequestSubscriptionAndroidProps | null | undefined;\nfunction normalizeRequestProps(\n request:\n | RequestPurchasePropsByPlatforms\n | RequestSubscriptionPropsByPlatforms,\n platform: 'ios' | 'android',\n) {\n // Support both new (apple/google) and legacy (ios/android) field names\n // New fields take precedence over deprecated ones\n if (platform === 'ios') {\n return request.apple ?? request.ios;\n }\n return request.google ?? request.android;\n}\n\n/**\n * Initiate a purchase or subscription flow. The result is delivered through\n * `purchaseUpdatedListener` — NOT the return value.\n *\n * @param args `RequestPurchaseProps`, discriminated by `type`:\n * - `type: 'in-app'` — pass `request.apple.sku` (iOS) and/or `request.google.skus` (Android).\n * - `type: 'subs'` — same shape, plus `request.google.subscriptionOffers: [{ sku, offerToken }]`.\n * @returns The dispatched purchase payload. **Do not rely on it** for the actual outcome.\n * @throws Synchronous rejection from the store (e.g. `E_NOT_PREPARED`, validation failure).\n *\n * @example\n * ```ts\n * await requestPurchase({\n * request: {\n * apple: { sku: 'com.app.premium' },\n * google: { skus: ['com.app.premium'] },\n * },\n * type: 'in-app',\n * });\n * ```\n *\n * @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /\n * {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.\n *\n * @see {@link https://www.openiap.dev/docs/apis/request-purchase}\n */\nexport const requestPurchase: MutationField<'requestPurchase'> = async (\n args,\n) => {\n const {request, type} = args;\n const {canonical, native} = normalizeProductType(type as ProductTypeInput);\n const isInAppPurchase = canonical === 'in-app';\n\n if (Platform.OS === 'ios') {\n const normalizedRequest = normalizeRequestProps(request, 'ios');\n\n if (!normalizedRequest?.sku) {\n throw new Error(\n 'Invalid request for Apple. The `sku` property is required and must be a string.\\n\\n' +\n 'Expected format:\\n' +\n ' requestPurchase({\\n' +\n ' request: {\\n' +\n ' apple: { sku: \"product_id\" },\\n' +\n ' google: { skus: [\"product_id\"] }\\n' +\n ' },\\n' +\n ' type: \"in-app\"\\n' +\n ' })\\n\\n' +\n 'See: https://hyochan.github.io/expo-iap/docs/api/methods/core-methods#requestpurchase',\n );\n }\n\n if (canonical !== 'in-app' && canonical !== 'subs') {\n throw new Error(`Unsupported product type: ${canonical}`);\n }\n\n const payload: MutationRequestPurchaseArgs = {\n type: canonical === 'in-app' ? 'in-app' : 'subs',\n request: {ios: normalizedRequest},\n useAlternativeBilling: args.useAlternativeBilling,\n };\n\n const purchase = (await ExpoIapModule.requestPurchase(payload)) as\n | Purchase\n | Purchase[]\n | null;\n\n if (Array.isArray(purchase)) {\n return normalizePurchaseArray(purchase);\n }\n\n if (purchase) {\n return normalizePurchasePlatform(purchase);\n }\n\n return canonical === 'subs' ? [] : null;\n }\n\n if (Platform.OS === 'android') {\n if (isInAppPurchase) {\n const normalizedRequest = normalizeRequestProps(\n request as RequestPurchasePropsByPlatforms,\n 'android',\n ) as RequestPurchaseAndroidProps | null | undefined;\n\n if (!normalizedRequest?.skus?.length) {\n throw new Error(\n 'Invalid request for Google. The `skus` property is required and must be a non-empty array.\\n\\n' +\n 'Expected format:\\n' +\n ' requestPurchase({\\n' +\n ' request: {\\n' +\n ' apple: { sku: \"product_id\" },\\n' +\n ' google: { skus: [\"product_id\"] }\\n' +\n ' },\\n' +\n ' type: \"in-app\"\\n' +\n ' })\\n\\n' +\n 'See: https://hyochan.github.io/expo-iap/docs/api/methods/core-methods#requestpurchase',\n );\n }\n\n const {\n skus,\n obfuscatedAccountId,\n obfuscatedProfileId,\n isOfferPersonalized,\n offerToken,\n } = normalizedRequest;\n\n const result = (await ExpoIapModule.requestPurchase({\n type: native,\n skuArr: skus,\n purchaseToken: undefined,\n replacementMode: -1,\n obfuscatedAccountId: obfuscatedAccountId,\n obfuscatedProfileId: obfuscatedProfileId,\n offerToken: offerToken,\n offerTokenArr: [],\n isOfferPersonalized: isOfferPersonalized ?? false,\n })) as Purchase[];\n\n return normalizePurchaseArray(result);\n }\n\n if (canonical === 'subs') {\n const normalizedRequest = normalizeRequestProps(\n request as RequestSubscriptionPropsByPlatforms,\n 'android',\n ) as RequestSubscriptionAndroidProps | null | undefined;\n\n if (!normalizedRequest?.skus?.length) {\n throw new Error(\n 'Invalid request for Google. The `skus` property is required and must be a non-empty array.\\n\\n' +\n 'Expected format:\\n' +\n ' requestPurchase({\\n' +\n ' request: {\\n' +\n ' apple: { sku: \"subscription_id\" },\\n' +\n ' google: { skus: [\"subscription_id\"] }\\n' +\n ' },\\n' +\n ' type: \"subs\"\\n' +\n ' })\\n\\n' +\n 'See: https://hyochan.github.io/expo-iap/docs/api/methods/core-methods#requestpurchase',\n );\n }\n\n const {\n skus,\n obfuscatedAccountId,\n obfuscatedProfileId,\n isOfferPersonalized,\n subscriptionOffers,\n replacementMode: replacementModeInput,\n purchaseToken: purchaseTokenInput,\n subscriptionProductReplacementParams,\n } = normalizedRequest;\n\n const normalizedOffers = subscriptionOffers ?? [];\n const replacementMode = replacementModeInput ?? -1;\n const purchaseToken = purchaseTokenInput ?? undefined;\n\n const result = (await ExpoIapModule.requestPurchase({\n type: native,\n skuArr: skus,\n purchaseToken,\n replacementMode,\n obfuscatedAccountId: obfuscatedAccountId,\n obfuscatedProfileId: obfuscatedProfileId,\n offerTokenArr: normalizedOffers.map(\n (offer: AndroidSubscriptionOfferInput) => offer.offerToken,\n ),\n subscriptionOffers: normalizedOffers,\n isOfferPersonalized: isOfferPersonalized ?? false,\n subscriptionProductReplacementParams:\n subscriptionProductReplacementParams ?? undefined,\n })) as Purchase[];\n\n return normalizePurchaseArray(result);\n }\n\n throw new Error(\n \"Invalid request for Android: Expected a valid request object with 'skus' array.\",\n );\n }\n\n throw new Error('Platform not supported');\n};\n\n/**\n * Complete a purchase transaction. Call after server-side verification to remove it\n * from the queue.\n *\n * @param args.purchase The `Purchase` to finalize.\n * @param args.isConsumable `true` for consumables (consumes the token so the SKU can be\n * re-bought, e.g. coins); `false` (default) for non-consumables and subscriptions.\n * @returns Promise that resolves once the platform finalizes the transaction.\n * @throws When the platform finalize call fails.\n *\n * @example\n * ```ts\n * // Inside purchaseUpdatedListener:\n * if (await verifyOnServer(purchase)) {\n * await finishTransaction({ purchase, isConsumable: false });\n * }\n * ```\n *\n * @remarks **Critical:** Android purchases must be finalized within 3 days or Google\n * auto-refunds. iOS unfinished transactions replay on every app launch.\n *\n * @see {@link https://www.openiap.dev/docs/apis/finish-transaction}\n */\nexport const finishTransaction: MutationField<'finishTransaction'> = async ({\n purchase,\n isConsumable = false,\n}) => {\n if (Platform.OS === 'ios') {\n await ExpoIapModule.finishTransaction(purchase, isConsumable);\n return;\n }\n\n if (Platform.OS === 'android') {\n const token = purchase.purchaseToken ?? undefined;\n\n if (!token) {\n throw createPurchaseError({\n message: 'Purchase token is required to finish transaction',\n code: ErrorCode.DeveloperError,\n productId: purchase.productId,\n platform: 'android',\n });\n }\n\n if (isConsumable) {\n await ExpoIapModule.consumePurchaseAndroid(token);\n return;\n }\n\n await ExpoIapModule.acknowledgePurchaseAndroid(token);\n return;\n }\n\n throw new Error('Unsupported Platform');\n};\n\n/**\n * Restore completed transactions (cross-platform behavior)\n *\n * - iOS: perform a lightweight sync to refresh transactions and ignore sync errors,\n * then fetch available purchases to surface restored items to the app.\n * - Android: simply fetch available purchases (restoration happens via query).\n *\n * This helper triggers the refresh flows but does not return the purchases; consumers should\n * call `getAvailablePurchases` or rely on hook state to inspect the latest items.\n *\n * @see {@link https://www.openiap.dev/docs/apis/restore-purchases}\n */\nexport const restorePurchases: MutationField<'restorePurchases'> = async () => {\n if (Platform.OS === 'ios') {\n await syncIOS().catch(() => undefined);\n }\n\n await getAvailablePurchases({\n alsoPublishToEventListenerIOS: false,\n onlyIncludeActiveItemsIOS: true,\n });\n};\n\n/**\n * Deeplinks to native interface that allows users to manage their subscriptions\n * @param options.skuAndroid - Required for Android to locate specific subscription (ignored on iOS)\n * @param options.packageNameAndroid - Required for Android to identify your app (ignored on iOS)\n *\n * @returns Promise that resolves when the deep link is successfully opened\n *\n * @throws {Error} When called on unsupported platform or when required Android parameters are missing\n *\n * @example\n * import { deepLinkToSubscriptions } from 'expo-iap';\n *\n * // Works on both iOS and Android\n * await deepLinkToSubscriptions({\n * skuAndroid: 'your_subscription_sku',\n * packageNameAndroid: 'com.example.app'\n * });\n *\n * @see {@link https://www.openiap.dev/docs/apis/deep-link-to-subscriptions}\n */\nexport const deepLinkToSubscriptions: MutationField<\n 'deepLinkToSubscriptions'\n> = async (options) => {\n if (Platform.OS === 'ios') {\n await deepLinkToSubscriptionsIOS();\n return;\n }\n\n if (Platform.OS === 'android') {\n await deepLinkToSubscriptionsAndroid((options as DeepLinkOptions) ?? null);\n return;\n }\n\n throw new Error(`Unsupported platform: ${Platform.OS}`);\n};\n\n/**\n * Internal receipt validation function (NOT RECOMMENDED for production use)\n *\n * WARNING: This function performs client-side validation which is NOT secure.\n * For production apps, always validate receipts on your secure server:\n * - iOS: Send receipt data to Apple's verification endpoint from your server\n * - Android: Use Google Play Developer API with service account credentials\n *\n * @deprecated Use verifyPurchase instead\n *\n * @see {@link https://www.openiap.dev/docs/apis/validate-receipt}\n */\nexport const validateReceipt: MutationField<'validateReceipt'> = async (\n options,\n) => {\n const {apple, google} = options as MutationValidateReceiptArgs;\n\n if (Platform.OS === 'ios') {\n if (!apple?.sku) {\n throw new Error('iOS validation requires apple.sku');\n }\n return validateReceiptIOS({apple: {sku: apple.sku}});\n }\n\n if (Platform.OS === 'android') {\n if (\n !google ||\n !google.sku ||\n !google.packageName ||\n !google.purchaseToken ||\n !google.accessToken\n ) {\n throw new Error(\n 'Android validation requires google.sku, google.packageName, google.purchaseToken, and google.accessToken',\n );\n }\n return validateReceiptAndroid({\n packageName: google.packageName,\n productId: google.sku,\n productToken: google.purchaseToken,\n accessToken: google.accessToken,\n isSub: google.isSub ?? undefined,\n });\n }\n\n throw new Error('Platform not supported');\n};\n\n/**\n * Verify purchase with the configured providers\n *\n * This function uses the native OpenIAP verifyPurchase implementation\n * which validates purchases using platform-specific methods.\n *\n * @param options - Receipt validation options containing the SKU\n * @returns Promise resolving to receipt validation result\n *\n * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase}\n */\nexport const verifyPurchase: MutationField<'verifyPurchase'> = async (\n options,\n) => {\n if (Platform.OS === 'ios' || Platform.OS === 'android') {\n return ExpoIapModule.verifyPurchase(options);\n }\n\n throw new Error(`Unsupported platform: ${Platform.OS}`);\n};\n\n/**\n * Verify purchase with a specific provider (e.g., IAPKit)\n *\n * This function allows you to verify purchases using external verification\n * services like IAPKit, which provide additional validation and security.\n *\n * @param options - Verification options including provider and credentials\n * @returns Promise resolving to provider-specific verification result\n *\n * @example\n * ```typescript\n * const result = await verifyPurchaseWithProvider({\n * provider: 'iapkit',\n * iapkit: {\n * apiKey: 'your-api-key',\n * apple: {\n * jws: purchase.purchaseToken // JWS from purchase\n * },\n * google: {\n * purchaseToken: purchase.purchaseToken\n * }\n * }\n * });\n * ```\n *\n * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}\n */\nexport const verifyPurchaseWithProvider: MutationField<\n 'verifyPurchaseWithProvider'\n> = async (options) => {\n if (Platform.OS === 'ios' || Platform.OS === 'android') {\n // Auto-fill apiKey from config if not provided and provider is iapkit\n if (\n options.provider === 'iapkit' &&\n options.iapkit &&\n !options.iapkit.apiKey\n ) {\n try {\n // Dynamically import expo-constants to avoid hard dependency\n const {default: Constants} = await import('expo-constants');\n const configApiKey = Constants.expoConfig?.extra?.iapkitApiKey;\n if (configApiKey) {\n options = {\n ...options,\n iapkit: {\n ...options.iapkit,\n apiKey: configApiKey,\n },\n };\n }\n } catch {\n throw new Error(\n 'expo-constants is required for auto-filling iapkitApiKey from config. ' +\n 'Please install it: npx expo install expo-constants\\n' +\n 'Or provide apiKey directly in verifyPurchaseWithProvider options.',\n );\n }\n }\n return ExpoIapModule.verifyPurchaseWithProvider(options);\n }\n\n throw new Error(`Unsupported platform: ${Platform.OS}`);\n};\n\nexport * from './useIAP';\nexport {useWebhookEvents} from './useWebhookEvents';\nexport type {\n UseWebhookEventsOptions,\n UseWebhookEventsResult,\n} from './useWebhookEvents';\nexport {connectWebhookStream, parseWebhookEventData} from './webhook-client';\nexport type {\n WebhookEventPayload,\n WebhookEventStream,\n WebhookEventType as WebhookEventTypeName,\n WebhookListener,\n WebhookListenerError,\n WebhookListenerOptions,\n} from './webhook-client';\nexport {kitApi, KitApiError} from './kit-api';\nexport type {\n KitApiOptions,\n KitSubscription,\n EntitlementsResponse,\n StatusResponse,\n} from './kit-api';\nexport {\n ErrorCodeUtils,\n ErrorCodeMapping,\n createPurchaseError,\n createPurchaseErrorFromPlatform,\n} from './utils/errorMapping';\nexport type {\n PurchaseError as ExpoPurchaseError,\n PurchaseErrorProps,\n} from './utils/errorMapping';\nexport {ExpoIapConsole} from './utils/debug';\n"]}
package/build/types.d.ts CHANGED
@@ -1189,6 +1189,14 @@ export interface PurchaseOptions {
1189
1189
  onlyIncludeActiveItemsIOS?: (boolean | null);
1190
1190
  }
1191
1191
  export type PurchaseState = 'pending' | 'purchased' | 'unknown';
1192
+ export interface PurchaseUpdatedListenerOptions {
1193
+ /**
1194
+ * iOS only. Defaults to true. When false, listener callbacks also receive
1195
+ * StoreKit replay events for a transaction ID that was already emitted during
1196
+ * the current connection session. Android ignores this option.
1197
+ */
1198
+ dedupeTransactionIOS?: (boolean | null);
1199
+ }
1192
1200
  export type PurchaseVerificationProvider = 'iapkit';
1193
1201
  export interface Query {
1194
1202
  /**
@@ -1597,7 +1605,12 @@ export interface Subscription {
1597
1605
  promotedProductIOS: string;
1598
1606
  /** Fires when a purchase fails or is cancelled */
1599
1607
  purchaseError: PurchaseError;
1600
- /** Fires when a purchase completes successfully or a pending purchase resolves */
1608
+ /**
1609
+ * Fires when a purchase completes successfully or a pending purchase resolves
1610
+ * Options can opt iOS listeners into duplicate StoreKit transaction replays
1611
+ * for diagnostics; default listeners receive one event per transaction ID
1612
+ * during a single connection session.
1613
+ */
1601
1614
  purchaseUpdated: Purchase;
1602
1615
  /**
1603
1616
  * Fires when an active subscription enters a billing-issue state that needs user action
@@ -1619,6 +1632,7 @@ export interface Subscription {
1619
1632
  */
1620
1633
  userChoiceBillingAndroid: UserChoiceBillingDetails;
1621
1634
  }
1635
+ export type SubscriptionPurchaseUpdatedArgs = (PurchaseUpdatedListenerOptions | null) | undefined;
1622
1636
  export interface SubscriptionInfoIOS {
1623
1637
  introductoryOffer?: (SubscriptionOfferIOS | null);
1624
1638
  promotionalOffers?: (SubscriptionOfferIOS[] | null);
@@ -2027,7 +2041,7 @@ export type SubscriptionArgsMap = {
2027
2041
  developerProvidedBillingAndroid: never;
2028
2042
  promotedProductIOS: never;
2029
2043
  purchaseError: never;
2030
- purchaseUpdated: never;
2044
+ purchaseUpdated: SubscriptionPurchaseUpdatedArgs;
2031
2045
  subscriptionBillingIssue: never;
2032
2046
  userChoiceBillingAndroid: never;
2033
2047
  };