expo-iap 2.9.0 → 2.9.1

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/CONTRIBUTING.md +2 -2
  3. package/README.md +3 -3
  4. package/build/ExpoIap.types.d.ts +33 -15
  5. package/build/ExpoIap.types.d.ts.map +1 -1
  6. package/build/ExpoIap.types.js +64 -17
  7. package/build/ExpoIap.types.js.map +1 -1
  8. package/build/index.d.ts +0 -13
  9. package/build/index.d.ts.map +1 -1
  10. package/build/index.js +22 -22
  11. package/build/index.js.map +1 -1
  12. package/build/modules/ios.d.ts +3 -7
  13. package/build/modules/ios.d.ts.map +1 -1
  14. package/build/modules/ios.js +1 -6
  15. package/build/modules/ios.js.map +1 -1
  16. package/build/types/ExpoIapAndroid.types.d.ts +0 -32
  17. package/build/types/ExpoIapAndroid.types.d.ts.map +1 -1
  18. package/build/types/ExpoIapAndroid.types.js +1 -5
  19. package/build/types/ExpoIapAndroid.types.js.map +1 -1
  20. package/build/types/ExpoIapIOS.types.d.ts +3 -27
  21. package/build/types/ExpoIapIOS.types.d.ts.map +1 -1
  22. package/build/types/ExpoIapIOS.types.js.map +1 -1
  23. package/build/useIAP.d.ts +1 -5
  24. package/build/useIAP.d.ts.map +1 -1
  25. package/build/useIAP.js +35 -26
  26. package/build/useIAP.js.map +1 -1
  27. package/build/utils/errorMapping.d.ts.map +1 -1
  28. package/build/utils/errorMapping.js +24 -0
  29. package/build/utils/errorMapping.js.map +1 -1
  30. package/ios/ExpoIap.podspec +1 -1
  31. package/ios/ExpoIapModule.swift +43 -30
  32. package/package.json +1 -1
  33. package/src/ExpoIap.types.ts +84 -37
  34. package/src/index.ts +25 -49
  35. package/src/modules/ios.ts +4 -9
  36. package/src/types/ExpoIapAndroid.types.ts +2 -36
  37. package/src/types/ExpoIapIOS.types.ts +3 -27
  38. package/src/useIAP.ts +41 -34
  39. package/src/utils/errorMapping.ts +24 -0
package/build/useIAP.d.ts CHANGED
@@ -6,7 +6,6 @@ type UseIap = {
6
6
  promotedProductsIOS: Purchase[];
7
7
  promotedProductIdIOS?: string;
8
8
  subscriptions: SubscriptionProduct[];
9
- purchaseHistories: Purchase[];
10
9
  availablePurchases: Purchase[];
11
10
  currentPurchase?: Purchase;
12
11
  currentPurchaseError?: PurchaseError;
@@ -19,7 +18,6 @@ type UseIap = {
19
18
  isConsumable?: boolean;
20
19
  }) => Promise<PurchaseResult | boolean>;
21
20
  getAvailablePurchases: (skus: string[]) => Promise<void>;
22
- getPurchaseHistories: (skus: string[]) => Promise<void>;
23
21
  fetchProducts: (params: {
24
22
  skus: string[];
25
23
  type?: 'inapp' | 'subs';
@@ -55,8 +53,6 @@ type UseIap = {
55
53
  restorePurchases: () => Promise<void>;
56
54
  getPromotedProductIOS: () => Promise<Product | null>;
57
55
  requestPurchaseOnPromotedProductIOS: () => Promise<void>;
58
- /** @deprecated Use requestPurchaseOnPromotedProductIOS instead */
59
- buyPromotedProductIOS: () => Promise<void>;
60
56
  getActiveSubscriptions: (subscriptionIds?: string[]) => Promise<void>;
61
57
  hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise<boolean>;
62
58
  };
@@ -69,7 +65,7 @@ export interface UseIAPOptions {
69
65
  }
70
66
  /**
71
67
  * React Hook for managing In-App Purchases.
72
- * See documentation at https://expo-iap.hyo.dev/docs/hooks/useIAP
68
+ * See documentation at https://hyochan.github.io/expo-iap/docs/hooks/useIAP
73
69
  */
74
70
  export declare function useIAP(options?: UseIAPOptions): UseIap;
75
71
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"useIAP.d.ts","sourceRoot":"","sources":["../src/useIAP.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useIAP.d.ts","sourceRoot":"","sources":["../src/useIAP.ts"],"names":[],"mappings":"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"}
package/build/useIAP.js CHANGED
@@ -2,18 +2,21 @@
2
2
  import { useCallback, useEffect, useState, useRef } from 'react';
3
3
  import { Platform } from 'react-native';
4
4
  // Internal modules
5
- import { endConnection, initConnection, purchaseErrorListener, purchaseUpdatedListener, promotedProductListenerIOS, getAvailablePurchases, getPurchaseHistories, finishTransaction as finishTransactionInternal, requestPurchase as requestPurchaseInternal, fetchProducts, validateReceipt as validateReceiptInternal, getActiveSubscriptions, hasActiveSubscriptions, } from '.';
5
+ import { endConnection, initConnection, purchaseErrorListener, purchaseUpdatedListener, promotedProductListenerIOS, getAvailablePurchases, finishTransaction as finishTransactionInternal, requestPurchase as requestPurchaseInternal, fetchProducts, validateReceipt as validateReceiptInternal, getActiveSubscriptions, hasActiveSubscriptions, } from '.';
6
6
  import { syncIOS, getPromotedProductIOS, requestPurchaseOnPromotedProductIOS, } from './modules/ios';
7
+ // Types
8
+ import { ErrorCode, } from './ExpoIap.types';
9
+ import { getUserFriendlyErrorMessage, isUserCancelledError, isRecoverableError, } from './utils/errorMapping';
7
10
  /**
8
11
  * React Hook for managing In-App Purchases.
9
- * See documentation at https://expo-iap.hyo.dev/docs/hooks/useIAP
12
+ * See documentation at https://hyochan.github.io/expo-iap/docs/hooks/useIAP
10
13
  */
11
14
  export function useIAP(options) {
12
15
  const [connected, setConnected] = useState(false);
13
16
  const [products, setProducts] = useState([]);
14
17
  const [promotedProductsIOS] = useState([]);
15
18
  const [subscriptions, setSubscriptions] = useState([]);
16
- const [purchaseHistories, setPurchaseHistories] = useState([]);
19
+ // Removed in v2.9.0: purchaseHistories state and related API
17
20
  const [availablePurchases, setAvailablePurchases] = useState([]);
18
21
  const [currentPurchase, setCurrentPurchase] = useState();
19
22
  const [promotedProductIOS, setPromotedProductIOS] = useState();
@@ -21,6 +24,7 @@ export function useIAP(options) {
21
24
  const [promotedProductIdIOS] = useState();
22
25
  const [activeSubscriptions, setActiveSubscriptions] = useState([]);
23
26
  const optionsRef = useRef(options);
27
+ const connectedRef = useRef(false);
24
28
  // Helper function to merge arrays with duplicate checking
25
29
  const mergeWithDuplicateCheck = useCallback((existingItems, newItems, getKey) => {
26
30
  const merged = [...existingItems];
@@ -35,6 +39,9 @@ export function useIAP(options) {
35
39
  useEffect(() => {
36
40
  optionsRef.current = options;
37
41
  }, [options]);
42
+ useEffect(() => {
43
+ connectedRef.current = connected;
44
+ }, [connected]);
38
45
  const subscriptionsRef = useRef({});
39
46
  const subscriptionsRefState = useRef([]);
40
47
  useEffect(() => {
@@ -113,13 +120,7 @@ export function useIAP(options) {
113
120
  return false;
114
121
  }
115
122
  }, []);
116
- /**
117
- * @deprecated Use getAvailablePurchases instead. This function is just calling getAvailablePurchases internally.
118
- * Will be removed in v2.9.0
119
- */
120
- const getPurchaseHistoriesInternal = useCallback(async () => {
121
- setPurchaseHistories(await getPurchaseHistories());
122
- }, []);
123
+ // NOTE: getPurchaseHistories removed in v2.9.0. Use getAvailablePurchases instead.
123
124
  const finishTransaction = useCallback(async ({ purchase, isConsumable, }) => {
124
125
  try {
125
126
  return await finishTransactionInternal({
@@ -202,9 +203,29 @@ export function useIAP(options) {
202
203
  optionsRef.current.onPurchaseSuccess(purchase);
203
204
  }
204
205
  });
205
- // IMPORTANT: Do NOT register the purchase error listener until after initConnection succeeds.
206
- // Some platforms may emit an initialization error event (E_INIT_CONNECTION) during startup.
207
- // Delaying registration prevents noisy, misleading errors before the connection is ready.
206
+ // Register purchase error listener EARLY. Ignore init-related errors until connected.
207
+ subscriptionsRef.current.purchaseError = purchaseErrorListener((error) => {
208
+ if (!connectedRef.current &&
209
+ error.code === ErrorCode.E_INIT_CONNECTION) {
210
+ return; // Ignore initialization error before connected
211
+ }
212
+ const friendly = getUserFriendlyErrorMessage(error);
213
+ console.log('[useIAP] Purchase error callback triggered:', error);
214
+ if (isUserCancelledError(error)) {
215
+ console.log('[useIAP] User cancelled purchase');
216
+ }
217
+ else if (isRecoverableError(error)) {
218
+ console.log('[useIAP] Recoverable purchase error:', friendly);
219
+ }
220
+ else {
221
+ console.warn('[useIAP] Purchase error:', friendly);
222
+ }
223
+ setCurrentPurchase(undefined);
224
+ setCurrentPurchaseError(error);
225
+ if (optionsRef.current?.onPurchaseError) {
226
+ optionsRef.current.onPurchaseError(error);
227
+ }
228
+ });
208
229
  if (Platform.OS === 'ios') {
209
230
  // iOS promoted products listener
210
231
  subscriptionsRef.current.promotedProductsIOS = promotedProductListenerIOS((product) => {
@@ -227,18 +248,9 @@ export function useIAP(options) {
227
248
  subscriptionsRef.current.promotedProductsIOS?.remove();
228
249
  subscriptionsRef.current.purchaseUpdate = undefined;
229
250
  subscriptionsRef.current.promotedProductsIOS = undefined;
230
- // Do not register error listener when connection fails
251
+ // Keep purchaseError listener registered to capture subsequent retries
231
252
  return;
232
253
  }
233
- // Now that the connection is established, register the purchase error listener.
234
- subscriptionsRef.current.purchaseError = purchaseErrorListener((error) => {
235
- console.log('[useIAP] Purchase error callback triggered:', error);
236
- setCurrentPurchase(undefined);
237
- setCurrentPurchaseError(error);
238
- if (optionsRef.current?.onPurchaseError) {
239
- optionsRef.current.onPurchaseError(error);
240
- }
241
- });
242
254
  }, [refreshSubscriptionStatus]);
243
255
  useEffect(() => {
244
256
  initIapWithSubscriptions();
@@ -258,7 +270,6 @@ export function useIAP(options) {
258
270
  promotedProductsIOS,
259
271
  promotedProductIdIOS,
260
272
  subscriptions,
261
- purchaseHistories,
262
273
  finishTransaction,
263
274
  availablePurchases,
264
275
  currentPurchase,
@@ -268,7 +279,6 @@ export function useIAP(options) {
268
279
  clearCurrentPurchase,
269
280
  clearCurrentPurchaseError,
270
281
  getAvailablePurchases: getAvailablePurchasesInternal,
271
- getPurchaseHistories: getPurchaseHistoriesInternal,
272
282
  fetchProducts: fetchProductsInternal,
273
283
  requestProducts: requestProductsInternal,
274
284
  requestPurchase: requestPurchaseWithReset,
@@ -278,7 +288,6 @@ export function useIAP(options) {
278
288
  getSubscriptions: getSubscriptionsInternal,
279
289
  getPromotedProductIOS,
280
290
  requestPurchaseOnPromotedProductIOS,
281
- buyPromotedProductIOS: requestPurchaseOnPromotedProductIOS, // deprecated alias
282
291
  getActiveSubscriptions: getActiveSubscriptionsInternal,
283
292
  hasActiveSubscriptions: hasActiveSubscriptionsInternal,
284
293
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useIAP.js","sourceRoot":"","sources":["../src/useIAP.ts"],"names":[],"mappings":"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","sourcesContent":["// External dependencies\nimport {useCallback, useEffect, useState, useRef} from 'react';\nimport {Platform} from 'react-native';\nimport {EventSubscription} from 'expo-modules-core';\n\n// Internal modules\nimport {\n endConnection,\n initConnection,\n purchaseErrorListener,\n purchaseUpdatedListener,\n promotedProductListenerIOS,\n getAvailablePurchases,\n getPurchaseHistories,\n finishTransaction as finishTransactionInternal,\n requestPurchase as requestPurchaseInternal,\n fetchProducts,\n validateReceipt as validateReceiptInternal,\n getActiveSubscriptions,\n hasActiveSubscriptions,\n type ActiveSubscription,\n} from '.';\nimport {\n syncIOS,\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n} from './modules/ios';\n\n// Types\nimport {\n Product,\n Purchase,\n PurchaseError,\n PurchaseResult,\n SubscriptionProduct,\n RequestPurchaseProps,\n RequestSubscriptionProps,\n} from './ExpoIap.types';\n\ntype UseIap = {\n connected: boolean;\n products: Product[];\n promotedProductsIOS: Purchase[];\n promotedProductIdIOS?: string;\n subscriptions: SubscriptionProduct[];\n purchaseHistories: Purchase[];\n availablePurchases: Purchase[];\n currentPurchase?: Purchase;\n currentPurchaseError?: PurchaseError;\n promotedProductIOS?: Product;\n activeSubscriptions: ActiveSubscription[];\n clearCurrentPurchase: () => void;\n clearCurrentPurchaseError: () => void;\n finishTransaction: ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }) => Promise<PurchaseResult | boolean>;\n getAvailablePurchases: (skus: string[]) => Promise<void>;\n getPurchaseHistories: (skus: string[]) => Promise<void>;\n fetchProducts: (params: {\n skus: string[];\n type?: 'inapp' | 'subs';\n }) => Promise<void>;\n /**\n * @deprecated Use fetchProducts({ skus, type: 'inapp' | 'subs' }) instead. This method will be removed in version 3.0.0.\n * The 'request' prefix should only be used for event-based operations.\n */\n requestProducts: (params: {\n skus: string[];\n type?: 'inapp' | 'subs';\n }) => Promise<void>;\n /**\n * @deprecated Use fetchProducts({ skus, type: 'inapp' }) instead. This method will be removed in version 3.0.0.\n * Note: This method internally uses fetchProducts, so no deprecation warning is shown.\n */\n getProducts: (skus: string[]) => Promise<void>;\n /**\n * @deprecated Use fetchProducts({ skus, type: 'subs' }) instead. This method will be removed in version 3.0.0.\n * Note: This method internally uses fetchProducts, so no deprecation warning is shown.\n */\n getSubscriptions: (skus: string[]) => Promise<void>;\n requestPurchase: (params: {\n request: RequestPurchaseProps | RequestSubscriptionProps;\n type?: 'inapp' | 'subs';\n }) => Promise<any>;\n validateReceipt: (\n sku: string,\n androidOptions?: {\n packageName: string;\n productToken: string;\n accessToken: string;\n isSub?: boolean;\n },\n ) => Promise<any>;\n restorePurchases: () => Promise<void>;\n getPromotedProductIOS: () => Promise<Product | null>;\n requestPurchaseOnPromotedProductIOS: () => Promise<void>;\n /** @deprecated Use requestPurchaseOnPromotedProductIOS instead */\n buyPromotedProductIOS: () => Promise<void>;\n getActiveSubscriptions: (subscriptionIds?: string[]) => Promise<void>;\n hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise<boolean>;\n};\n\nexport interface UseIAPOptions {\n onPurchaseSuccess?: (purchase: Purchase) => void;\n onPurchaseError?: (error: PurchaseError) => void;\n onSyncError?: (error: Error) => void;\n shouldAutoSyncPurchases?: boolean; // New option to control auto-syncing\n onPromotedProductIOS?: (product: Product) => void;\n}\n\n/**\n * React Hook for managing In-App Purchases.\n * See documentation at https://expo-iap.hyo.dev/docs/hooks/useIAP\n */\nexport function useIAP(options?: UseIAPOptions): UseIap {\n const [connected, setConnected] = useState<boolean>(false);\n const [products, setProducts] = useState<Product[]>([]);\n const [promotedProductsIOS] = useState<Purchase[]>([]);\n const [subscriptions, setSubscriptions] = useState<SubscriptionProduct[]>([]);\n const [purchaseHistories, setPurchaseHistories] = useState<Purchase[]>([]);\n const [availablePurchases, setAvailablePurchases] = useState<Purchase[]>([]);\n const [currentPurchase, setCurrentPurchase] = useState<Purchase>();\n const [promotedProductIOS, setPromotedProductIOS] = useState<Product>();\n const [currentPurchaseError, setCurrentPurchaseError] =\n useState<PurchaseError>();\n const [promotedProductIdIOS] = useState<string>();\n const [activeSubscriptions, setActiveSubscriptions] = useState<\n ActiveSubscription[]\n >([]);\n\n const optionsRef = useRef<UseIAPOptions | undefined>(options);\n\n // Helper function to merge arrays with duplicate checking\n const mergeWithDuplicateCheck = useCallback(\n <T>(\n existingItems: T[],\n newItems: T[],\n getKey: (item: T) => string,\n ): T[] => {\n const merged = [...existingItems];\n newItems.forEach((newItem) => {\n const isDuplicate = merged.some(\n (existingItem) => getKey(existingItem) === getKey(newItem),\n );\n if (!isDuplicate) {\n merged.push(newItem);\n }\n });\n return merged;\n },\n [],\n );\n\n useEffect(() => {\n optionsRef.current = options;\n }, [options]);\n\n const subscriptionsRef = useRef<{\n purchaseUpdate?: EventSubscription;\n purchaseError?: EventSubscription;\n promotedProductsIOS?: EventSubscription;\n promotedProductIOS?: EventSubscription;\n }>({});\n\n const subscriptionsRefState = useRef<SubscriptionProduct[]>([]);\n\n useEffect(() => {\n subscriptionsRefState.current = subscriptions;\n }, [subscriptions]);\n\n const clearCurrentPurchase = useCallback(() => {\n setCurrentPurchase(undefined);\n }, []);\n\n const clearCurrentPurchaseError = useCallback(() => {\n setCurrentPurchaseError(undefined);\n }, []);\n\n const getProductsInternal = useCallback(\n async (skus: string[]): Promise<void> => {\n try {\n const result = await fetchProducts({skus, type: 'inapp'});\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n result as Product[],\n (product) => product.id,\n ),\n );\n } catch (error) {\n console.error('Error fetching products:', error);\n }\n },\n [mergeWithDuplicateCheck],\n );\n\n const getSubscriptionsInternal = useCallback(\n async (skus: string[]): Promise<void> => {\n try {\n const result = await fetchProducts({skus, type: 'subs'});\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n result as SubscriptionProduct[],\n (subscription) => subscription.id,\n ),\n );\n } catch (error) {\n console.error('Error fetching subscriptions:', error);\n }\n },\n [mergeWithDuplicateCheck],\n );\n\n const fetchProductsInternal = useCallback(\n async (params: {\n skus: string[];\n type?: 'inapp' | 'subs';\n }): Promise<void> => {\n try {\n const result = await fetchProducts(params);\n\n if (params.type === 'subs') {\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n result as SubscriptionProduct[],\n (subscription) => subscription.id,\n ),\n );\n } else {\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n result as Product[],\n (product) => product.id,\n ),\n );\n }\n } catch (error) {\n console.error('Error fetching products:', error);\n }\n },\n [mergeWithDuplicateCheck],\n );\n\n const requestProductsInternal = useCallback(\n async (params: {\n skus: string[];\n type?: 'inapp' | 'subs';\n }): Promise<void> => {\n console.warn(\n \"`requestProducts` is deprecated in useIAP hook. Use the new `fetchProducts` method instead. The 'request' prefix should only be used for event-based operations.\",\n );\n return fetchProductsInternal(params);\n },\n [fetchProductsInternal],\n );\n\n const getAvailablePurchasesInternal = useCallback(async (): Promise<void> => {\n try {\n const result = await getAvailablePurchases({\n alsoPublishToEventListenerIOS: false,\n onlyIncludeActiveItemsIOS: true,\n });\n setAvailablePurchases(result);\n } catch (error) {\n console.error('Error fetching available purchases:', error);\n }\n }, []);\n\n const getActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<void> => {\n try {\n const result = await getActiveSubscriptions(subscriptionIds);\n setActiveSubscriptions(result);\n } catch (error) {\n console.error('Error getting active subscriptions:', error);\n // Preserve existing state on error\n }\n },\n [],\n );\n\n const hasActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<boolean> => {\n try {\n return await hasActiveSubscriptions(subscriptionIds);\n } catch (error) {\n console.error('Error checking active subscriptions:', error);\n return false;\n }\n },\n [],\n );\n\n /**\n * @deprecated Use getAvailablePurchases instead. This function is just calling getAvailablePurchases internally.\n * Will be removed in v2.9.0\n */\n const getPurchaseHistoriesInternal = useCallback(async (): Promise<void> => {\n setPurchaseHistories(await getPurchaseHistories());\n }, []);\n\n const finishTransaction = useCallback(\n async ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }): Promise<PurchaseResult | boolean> => {\n try {\n return await finishTransactionInternal({\n purchase,\n isConsumable,\n });\n } catch (err) {\n throw err;\n } finally {\n if (purchase.id === currentPurchase?.id) {\n clearCurrentPurchase();\n }\n if (purchase.id === currentPurchaseError?.productId) {\n clearCurrentPurchaseError();\n }\n }\n },\n [\n currentPurchase?.id,\n currentPurchaseError?.productId,\n clearCurrentPurchase,\n clearCurrentPurchaseError,\n ],\n );\n\n const requestPurchaseWithReset = useCallback(\n async (requestObj: {request: any; type?: 'inapp' | 'subs'}) => {\n clearCurrentPurchase();\n clearCurrentPurchaseError();\n\n try {\n return await requestPurchaseInternal(requestObj);\n } catch (error) {\n throw error;\n }\n },\n [clearCurrentPurchase, clearCurrentPurchaseError],\n );\n\n const refreshSubscriptionStatus = useCallback(\n async (productId: string) => {\n try {\n if (subscriptionsRefState.current.some((sub) => sub.id === productId)) {\n await getSubscriptionsInternal([productId]);\n await getAvailablePurchasesInternal();\n }\n } catch (error) {\n console.warn('Failed to refresh subscription status:', error);\n }\n },\n [getAvailablePurchasesInternal, getSubscriptionsInternal],\n );\n\n const restorePurchases = useCallback(async (): Promise<void> => {\n try {\n if (Platform.OS === 'ios') {\n await syncIOS().catch((error) => {\n if (optionsRef.current?.onSyncError) {\n optionsRef.current.onSyncError(error);\n } else {\n console.warn('Error restoring purchases:', error);\n }\n });\n }\n await getAvailablePurchasesInternal();\n } catch (error) {\n console.warn('Failed to restore purchases:', error);\n }\n }, [getAvailablePurchasesInternal]);\n\n const validateReceipt = useCallback(\n async (\n sku: string,\n androidOptions?: {\n packageName: string;\n productToken: string;\n accessToken: string;\n isSub?: boolean;\n },\n ) => {\n return validateReceiptInternal(sku, androidOptions);\n },\n [],\n );\n\n const initIapWithSubscriptions = useCallback(async (): Promise<void> => {\n // CRITICAL: Register listeners BEFORE initConnection to avoid race condition\n // Events might fire immediately after initConnection, so listeners must be ready\n console.log('[useIAP] Setting up event listeners BEFORE initConnection...');\n\n // Register purchase update listener BEFORE initConnection to avoid race conditions.\n subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(\n async (purchase: Purchase) => {\n console.log('[useIAP] Purchase success callback triggered:', purchase);\n setCurrentPurchaseError(undefined);\n setCurrentPurchase(purchase);\n\n if ('expirationDateIOS' in purchase) {\n await refreshSubscriptionStatus(purchase.id);\n }\n\n if (optionsRef.current?.onPurchaseSuccess) {\n optionsRef.current.onPurchaseSuccess(purchase);\n }\n },\n );\n\n // IMPORTANT: Do NOT register the purchase error listener until after initConnection succeeds.\n // Some platforms may emit an initialization error event (E_INIT_CONNECTION) during startup.\n // Delaying registration prevents noisy, misleading errors before the connection is ready.\n\n if (Platform.OS === 'ios') {\n // iOS promoted products listener\n subscriptionsRef.current.promotedProductsIOS = promotedProductListenerIOS(\n (product: Product) => {\n console.log('[useIAP] Promoted product callback triggered:', product);\n setPromotedProductIOS(product);\n\n if (optionsRef.current?.onPromotedProductIOS) {\n optionsRef.current.onPromotedProductIOS(product);\n }\n },\n );\n }\n\n console.log(\n '[useIAP] Event listeners registered, now calling initConnection...',\n );\n\n // NOW call initConnection after listeners are ready\n const result = await initConnection();\n setConnected(result);\n console.log('[useIAP] initConnection result:', result);\n if (!result) {\n // If connection failed, clean up listeners\n console.warn('[useIAP] Connection failed, cleaning up listeners...');\n subscriptionsRef.current.purchaseUpdate?.remove();\n subscriptionsRef.current.promotedProductsIOS?.remove();\n subscriptionsRef.current.purchaseUpdate = undefined;\n subscriptionsRef.current.promotedProductsIOS = undefined;\n // Do not register error listener when connection fails\n return;\n }\n\n // Now that the connection is established, register the purchase error listener.\n subscriptionsRef.current.purchaseError = purchaseErrorListener(\n (error: PurchaseError) => {\n console.log('[useIAP] Purchase error callback triggered:', error);\n setCurrentPurchase(undefined);\n setCurrentPurchaseError(error);\n\n if (optionsRef.current?.onPurchaseError) {\n optionsRef.current.onPurchaseError(error);\n }\n },\n );\n }, [refreshSubscriptionStatus]);\n\n useEffect(() => {\n initIapWithSubscriptions();\n const currentSubscriptions = subscriptionsRef.current;\n\n return () => {\n currentSubscriptions.purchaseUpdate?.remove();\n currentSubscriptions.purchaseError?.remove();\n currentSubscriptions.promotedProductsIOS?.remove();\n currentSubscriptions.promotedProductIOS?.remove();\n endConnection();\n setConnected(false);\n };\n }, [initIapWithSubscriptions]);\n\n return {\n connected,\n products,\n promotedProductsIOS,\n promotedProductIdIOS,\n subscriptions,\n purchaseHistories,\n finishTransaction,\n availablePurchases,\n currentPurchase,\n currentPurchaseError,\n promotedProductIOS,\n activeSubscriptions,\n clearCurrentPurchase,\n clearCurrentPurchaseError,\n getAvailablePurchases: getAvailablePurchasesInternal,\n getPurchaseHistories: getPurchaseHistoriesInternal,\n fetchProducts: fetchProductsInternal,\n requestProducts: requestProductsInternal,\n requestPurchase: requestPurchaseWithReset,\n validateReceipt,\n restorePurchases,\n getProducts: getProductsInternal,\n getSubscriptions: getSubscriptionsInternal,\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n buyPromotedProductIOS: requestPurchaseOnPromotedProductIOS, // deprecated alias\n getActiveSubscriptions: getActiveSubscriptionsInternal,\n hasActiveSubscriptions: hasActiveSubscriptionsInternal,\n };\n}\n"]}
1
+ {"version":3,"file":"useIAP.js","sourceRoot":"","sources":["../src/useIAP.ts"],"names":[],"mappings":"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","sourcesContent":["// External dependencies\nimport {useCallback, useEffect, useState, useRef} from 'react';\nimport {Platform} from 'react-native';\nimport {EventSubscription} from 'expo-modules-core';\n\n// Internal modules\nimport {\n endConnection,\n initConnection,\n purchaseErrorListener,\n purchaseUpdatedListener,\n promotedProductListenerIOS,\n getAvailablePurchases,\n finishTransaction as finishTransactionInternal,\n requestPurchase as requestPurchaseInternal,\n fetchProducts,\n validateReceipt as validateReceiptInternal,\n getActiveSubscriptions,\n hasActiveSubscriptions,\n type ActiveSubscription,\n} from '.';\nimport {\n syncIOS,\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n} from './modules/ios';\n\n// Types\nimport {\n Product,\n Purchase,\n PurchaseError,\n PurchaseResult,\n SubscriptionProduct,\n RequestPurchaseProps,\n RequestSubscriptionProps,\n ErrorCode,\n} from './ExpoIap.types';\nimport {\n getUserFriendlyErrorMessage,\n isUserCancelledError,\n isRecoverableError,\n} from './utils/errorMapping';\n\ntype UseIap = {\n connected: boolean;\n products: Product[];\n promotedProductsIOS: Purchase[];\n promotedProductIdIOS?: string;\n subscriptions: SubscriptionProduct[];\n availablePurchases: Purchase[];\n currentPurchase?: Purchase;\n currentPurchaseError?: PurchaseError;\n promotedProductIOS?: Product;\n activeSubscriptions: ActiveSubscription[];\n clearCurrentPurchase: () => void;\n clearCurrentPurchaseError: () => void;\n finishTransaction: ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }) => Promise<PurchaseResult | boolean>;\n getAvailablePurchases: (skus: string[]) => Promise<void>;\n fetchProducts: (params: {\n skus: string[];\n type?: 'inapp' | 'subs';\n }) => Promise<void>;\n /**\n * @deprecated Use fetchProducts({ skus, type: 'inapp' | 'subs' }) instead. This method will be removed in version 3.0.0.\n * The 'request' prefix should only be used for event-based operations.\n */\n requestProducts: (params: {\n skus: string[];\n type?: 'inapp' | 'subs';\n }) => Promise<void>;\n /**\n * @deprecated Use fetchProducts({ skus, type: 'inapp' }) instead. This method will be removed in version 3.0.0.\n * Note: This method internally uses fetchProducts, so no deprecation warning is shown.\n */\n getProducts: (skus: string[]) => Promise<void>;\n /**\n * @deprecated Use fetchProducts({ skus, type: 'subs' }) instead. This method will be removed in version 3.0.0.\n * Note: This method internally uses fetchProducts, so no deprecation warning is shown.\n */\n getSubscriptions: (skus: string[]) => Promise<void>;\n requestPurchase: (params: {\n request: RequestPurchaseProps | RequestSubscriptionProps;\n type?: 'inapp' | 'subs';\n }) => Promise<any>;\n validateReceipt: (\n sku: string,\n androidOptions?: {\n packageName: string;\n productToken: string;\n accessToken: string;\n isSub?: boolean;\n },\n ) => Promise<any>;\n restorePurchases: () => Promise<void>;\n getPromotedProductIOS: () => Promise<Product | null>;\n requestPurchaseOnPromotedProductIOS: () => Promise<void>;\n getActiveSubscriptions: (subscriptionIds?: string[]) => Promise<void>;\n hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise<boolean>;\n};\n\nexport interface UseIAPOptions {\n onPurchaseSuccess?: (purchase: Purchase) => void;\n onPurchaseError?: (error: PurchaseError) => void;\n onSyncError?: (error: Error) => void;\n shouldAutoSyncPurchases?: boolean; // New option to control auto-syncing\n onPromotedProductIOS?: (product: Product) => void;\n}\n\n/**\n * React Hook for managing In-App Purchases.\n * See documentation at https://hyochan.github.io/expo-iap/docs/hooks/useIAP\n */\nexport function useIAP(options?: UseIAPOptions): UseIap {\n const [connected, setConnected] = useState<boolean>(false);\n const [products, setProducts] = useState<Product[]>([]);\n const [promotedProductsIOS] = useState<Purchase[]>([]);\n const [subscriptions, setSubscriptions] = useState<SubscriptionProduct[]>([]);\n // Removed in v2.9.0: purchaseHistories state and related API\n const [availablePurchases, setAvailablePurchases] = useState<Purchase[]>([]);\n const [currentPurchase, setCurrentPurchase] = useState<Purchase>();\n const [promotedProductIOS, setPromotedProductIOS] = useState<Product>();\n const [currentPurchaseError, setCurrentPurchaseError] =\n useState<PurchaseError>();\n const [promotedProductIdIOS] = useState<string>();\n const [activeSubscriptions, setActiveSubscriptions] = useState<\n ActiveSubscription[]\n >([]);\n\n const optionsRef = useRef<UseIAPOptions | undefined>(options);\n const connectedRef = useRef<boolean>(false);\n\n // Helper function to merge arrays with duplicate checking\n const mergeWithDuplicateCheck = useCallback(\n <T>(\n existingItems: T[],\n newItems: T[],\n getKey: (item: T) => string,\n ): T[] => {\n const merged = [...existingItems];\n newItems.forEach((newItem) => {\n const isDuplicate = merged.some(\n (existingItem) => getKey(existingItem) === getKey(newItem),\n );\n if (!isDuplicate) {\n merged.push(newItem);\n }\n });\n return merged;\n },\n [],\n );\n\n useEffect(() => {\n optionsRef.current = options;\n }, [options]);\n\n useEffect(() => {\n connectedRef.current = connected;\n }, [connected]);\n\n const subscriptionsRef = useRef<{\n purchaseUpdate?: EventSubscription;\n purchaseError?: EventSubscription;\n promotedProductsIOS?: EventSubscription;\n promotedProductIOS?: EventSubscription;\n }>({});\n\n const subscriptionsRefState = useRef<SubscriptionProduct[]>([]);\n\n useEffect(() => {\n subscriptionsRefState.current = subscriptions;\n }, [subscriptions]);\n\n const clearCurrentPurchase = useCallback(() => {\n setCurrentPurchase(undefined);\n }, []);\n\n const clearCurrentPurchaseError = useCallback(() => {\n setCurrentPurchaseError(undefined);\n }, []);\n\n const getProductsInternal = useCallback(\n async (skus: string[]): Promise<void> => {\n try {\n const result = await fetchProducts({skus, type: 'inapp'});\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n result as Product[],\n (product) => product.id,\n ),\n );\n } catch (error) {\n console.error('Error fetching products:', error);\n }\n },\n [mergeWithDuplicateCheck],\n );\n\n const getSubscriptionsInternal = useCallback(\n async (skus: string[]): Promise<void> => {\n try {\n const result = await fetchProducts({skus, type: 'subs'});\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n result as SubscriptionProduct[],\n (subscription) => subscription.id,\n ),\n );\n } catch (error) {\n console.error('Error fetching subscriptions:', error);\n }\n },\n [mergeWithDuplicateCheck],\n );\n\n const fetchProductsInternal = useCallback(\n async (params: {\n skus: string[];\n type?: 'inapp' | 'subs';\n }): Promise<void> => {\n try {\n const result = await fetchProducts(params);\n\n if (params.type === 'subs') {\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n result as SubscriptionProduct[],\n (subscription) => subscription.id,\n ),\n );\n } else {\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n result as Product[],\n (product) => product.id,\n ),\n );\n }\n } catch (error) {\n console.error('Error fetching products:', error);\n }\n },\n [mergeWithDuplicateCheck],\n );\n\n const requestProductsInternal = useCallback(\n async (params: {\n skus: string[];\n type?: 'inapp' | 'subs';\n }): Promise<void> => {\n console.warn(\n \"`requestProducts` is deprecated in useIAP hook. Use the new `fetchProducts` method instead. The 'request' prefix should only be used for event-based operations.\",\n );\n return fetchProductsInternal(params);\n },\n [fetchProductsInternal],\n );\n\n const getAvailablePurchasesInternal = useCallback(async (): Promise<void> => {\n try {\n const result = await getAvailablePurchases({\n alsoPublishToEventListenerIOS: false,\n onlyIncludeActiveItemsIOS: true,\n });\n setAvailablePurchases(result);\n } catch (error) {\n console.error('Error fetching available purchases:', error);\n }\n }, []);\n\n const getActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<void> => {\n try {\n const result = await getActiveSubscriptions(subscriptionIds);\n setActiveSubscriptions(result);\n } catch (error) {\n console.error('Error getting active subscriptions:', error);\n // Preserve existing state on error\n }\n },\n [],\n );\n\n const hasActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<boolean> => {\n try {\n return await hasActiveSubscriptions(subscriptionIds);\n } catch (error) {\n console.error('Error checking active subscriptions:', error);\n return false;\n }\n },\n [],\n );\n\n // NOTE: getPurchaseHistories removed in v2.9.0. Use getAvailablePurchases instead.\n\n const finishTransaction = useCallback(\n async ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }): Promise<PurchaseResult | boolean> => {\n try {\n return await finishTransactionInternal({\n purchase,\n isConsumable,\n });\n } catch (err) {\n throw err;\n } finally {\n if (purchase.id === currentPurchase?.id) {\n clearCurrentPurchase();\n }\n if (purchase.id === currentPurchaseError?.productId) {\n clearCurrentPurchaseError();\n }\n }\n },\n [\n currentPurchase?.id,\n currentPurchaseError?.productId,\n clearCurrentPurchase,\n clearCurrentPurchaseError,\n ],\n );\n\n const requestPurchaseWithReset = useCallback(\n async (requestObj: {request: any; type?: 'inapp' | 'subs'}) => {\n clearCurrentPurchase();\n clearCurrentPurchaseError();\n\n try {\n return await requestPurchaseInternal(requestObj);\n } catch (error) {\n throw error;\n }\n },\n [clearCurrentPurchase, clearCurrentPurchaseError],\n );\n\n const refreshSubscriptionStatus = useCallback(\n async (productId: string) => {\n try {\n if (subscriptionsRefState.current.some((sub) => sub.id === productId)) {\n await getSubscriptionsInternal([productId]);\n await getAvailablePurchasesInternal();\n }\n } catch (error) {\n console.warn('Failed to refresh subscription status:', error);\n }\n },\n [getAvailablePurchasesInternal, getSubscriptionsInternal],\n );\n\n const restorePurchases = useCallback(async (): Promise<void> => {\n try {\n if (Platform.OS === 'ios') {\n await syncIOS().catch((error) => {\n if (optionsRef.current?.onSyncError) {\n optionsRef.current.onSyncError(error);\n } else {\n console.warn('Error restoring purchases:', error);\n }\n });\n }\n await getAvailablePurchasesInternal();\n } catch (error) {\n console.warn('Failed to restore purchases:', error);\n }\n }, [getAvailablePurchasesInternal]);\n\n const validateReceipt = useCallback(\n async (\n sku: string,\n androidOptions?: {\n packageName: string;\n productToken: string;\n accessToken: string;\n isSub?: boolean;\n },\n ) => {\n return validateReceiptInternal(sku, androidOptions);\n },\n [],\n );\n\n const initIapWithSubscriptions = useCallback(async (): Promise<void> => {\n // CRITICAL: Register listeners BEFORE initConnection to avoid race condition\n // Events might fire immediately after initConnection, so listeners must be ready\n console.log('[useIAP] Setting up event listeners BEFORE initConnection...');\n\n // Register purchase update listener BEFORE initConnection to avoid race conditions.\n subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(\n async (purchase: Purchase) => {\n console.log('[useIAP] Purchase success callback triggered:', purchase);\n setCurrentPurchaseError(undefined);\n setCurrentPurchase(purchase);\n\n if ('expirationDateIOS' in purchase) {\n await refreshSubscriptionStatus(purchase.id);\n }\n\n if (optionsRef.current?.onPurchaseSuccess) {\n optionsRef.current.onPurchaseSuccess(purchase);\n }\n },\n );\n\n // Register purchase error listener EARLY. Ignore init-related errors until connected.\n subscriptionsRef.current.purchaseError = purchaseErrorListener(\n (error: PurchaseError) => {\n if (\n !connectedRef.current &&\n error.code === ErrorCode.E_INIT_CONNECTION\n ) {\n return; // Ignore initialization error before connected\n }\n const friendly = getUserFriendlyErrorMessage(error);\n console.log('[useIAP] Purchase error callback triggered:', error);\n if (isUserCancelledError(error)) {\n console.log('[useIAP] User cancelled purchase');\n } else if (isRecoverableError(error)) {\n console.log('[useIAP] Recoverable purchase error:', friendly);\n } else {\n console.warn('[useIAP] Purchase error:', friendly);\n }\n setCurrentPurchase(undefined);\n setCurrentPurchaseError(error);\n\n if (optionsRef.current?.onPurchaseError) {\n optionsRef.current.onPurchaseError(error);\n }\n },\n );\n\n if (Platform.OS === 'ios') {\n // iOS promoted products listener\n subscriptionsRef.current.promotedProductsIOS = promotedProductListenerIOS(\n (product: Product) => {\n console.log('[useIAP] Promoted product callback triggered:', product);\n setPromotedProductIOS(product);\n\n if (optionsRef.current?.onPromotedProductIOS) {\n optionsRef.current.onPromotedProductIOS(product);\n }\n },\n );\n }\n\n console.log(\n '[useIAP] Event listeners registered, now calling initConnection...',\n );\n\n // NOW call initConnection after listeners are ready\n const result = await initConnection();\n setConnected(result);\n console.log('[useIAP] initConnection result:', result);\n if (!result) {\n // If connection failed, clean up listeners\n console.warn('[useIAP] Connection failed, cleaning up listeners...');\n subscriptionsRef.current.purchaseUpdate?.remove();\n subscriptionsRef.current.promotedProductsIOS?.remove();\n subscriptionsRef.current.purchaseUpdate = undefined;\n subscriptionsRef.current.promotedProductsIOS = undefined;\n // Keep purchaseError listener registered to capture subsequent retries\n return;\n }\n }, [refreshSubscriptionStatus]);\n\n useEffect(() => {\n initIapWithSubscriptions();\n const currentSubscriptions = subscriptionsRef.current;\n\n return () => {\n currentSubscriptions.purchaseUpdate?.remove();\n currentSubscriptions.purchaseError?.remove();\n currentSubscriptions.promotedProductsIOS?.remove();\n currentSubscriptions.promotedProductIOS?.remove();\n endConnection();\n setConnected(false);\n };\n }, [initIapWithSubscriptions]);\n\n return {\n connected,\n products,\n promotedProductsIOS,\n promotedProductIdIOS,\n subscriptions,\n finishTransaction,\n availablePurchases,\n currentPurchase,\n currentPurchaseError,\n promotedProductIOS,\n activeSubscriptions,\n clearCurrentPurchase,\n clearCurrentPurchaseError,\n getAvailablePurchases: getAvailablePurchasesInternal,\n fetchProducts: fetchProductsInternal,\n requestProducts: requestProductsInternal,\n requestPurchase: requestPurchaseWithReset,\n validateReceipt,\n restorePurchases,\n getProducts: getProductsInternal,\n getSubscriptions: getSubscriptionsInternal,\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n getActiveSubscriptions: getActiveSubscriptionsInternal,\n hasActiveSubscriptions: hasActiveSubscriptionsInternal,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"errorMapping.d.ts","sourceRoot":"","sources":["../../src/utils/errorMapping.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAUxD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CASlD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAUtD;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CAyB9D"}
1
+ {"version":3,"file":"errorMapping.d.ts","sourceRoot":"","sources":["../../src/utils/errorMapping.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAUxD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAWlD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CActD;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,CA2C9D"}
@@ -27,6 +27,8 @@ export function isNetworkError(error) {
27
27
  ErrorCode.E_NETWORK_ERROR,
28
28
  ErrorCode.E_REMOTE_ERROR,
29
29
  ErrorCode.E_SERVICE_ERROR,
30
+ ErrorCode.E_SERVICE_DISCONNECTED,
31
+ ErrorCode.E_BILLING_UNAVAILABLE,
30
32
  ];
31
33
  const errorCode = typeof error === 'string' ? error : error?.code;
32
34
  return networkErrors.includes(errorCode);
@@ -42,6 +44,10 @@ export function isRecoverableError(error) {
42
44
  ErrorCode.E_REMOTE_ERROR,
43
45
  ErrorCode.E_SERVICE_ERROR,
44
46
  ErrorCode.E_INTERRUPTED,
47
+ ErrorCode.E_SERVICE_DISCONNECTED,
48
+ ErrorCode.E_BILLING_UNAVAILABLE,
49
+ ErrorCode.E_QUERY_PRODUCT,
50
+ ErrorCode.E_INIT_CONNECTION,
45
51
  ];
46
52
  const errorCode = typeof error === 'string' ? error : error?.code;
47
53
  return recoverableErrors.includes(errorCode);
@@ -58,20 +64,38 @@ export function getUserFriendlyErrorMessage(error) {
58
64
  return 'Purchase was cancelled by user';
59
65
  case ErrorCode.E_NETWORK_ERROR:
60
66
  return 'Network connection error. Please check your internet connection and try again.';
67
+ case ErrorCode.E_SERVICE_DISCONNECTED:
68
+ return 'Billing service disconnected. Please try again.';
69
+ case ErrorCode.E_BILLING_UNAVAILABLE:
70
+ return 'Billing is unavailable on this device or account.';
61
71
  case ErrorCode.E_ITEM_UNAVAILABLE:
62
72
  return 'This item is not available for purchase';
73
+ case ErrorCode.E_ITEM_NOT_OWNED:
74
+ return "You don't own this item";
63
75
  case ErrorCode.E_ALREADY_OWNED:
64
76
  return 'You already own this item';
77
+ case ErrorCode.E_SKU_NOT_FOUND:
78
+ return 'Requested product could not be found';
79
+ case ErrorCode.E_SKU_OFFER_MISMATCH:
80
+ return 'Selected offer does not match the SKU';
65
81
  case ErrorCode.E_DEFERRED_PAYMENT:
66
82
  return 'Payment is pending approval';
67
83
  case ErrorCode.E_NOT_PREPARED:
68
84
  return 'In-app purchase is not ready. Please try again later.';
69
85
  case ErrorCode.E_SERVICE_ERROR:
70
86
  return 'Store service error. Please try again later.';
87
+ case ErrorCode.E_FEATURE_NOT_SUPPORTED:
88
+ return 'This feature is not supported on this device.';
71
89
  case ErrorCode.E_TRANSACTION_VALIDATION_FAILED:
72
90
  return 'Transaction could not be verified';
73
91
  case ErrorCode.E_RECEIPT_FAILED:
74
92
  return 'Receipt processing failed';
93
+ case ErrorCode.E_EMPTY_SKU_LIST:
94
+ return 'No product IDs provided';
95
+ case ErrorCode.E_INIT_CONNECTION:
96
+ return 'Failed to initialize billing connection';
97
+ case ErrorCode.E_QUERY_PRODUCT:
98
+ return 'Failed to query products. Please try again later.';
75
99
  default:
76
100
  return error?.message || 'An unexpected error occurred';
77
101
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errorMapping.js","sourceRoot":"","sources":["../../src/utils/errorMapping.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,SAAS,EAAC,MAAM,kBAAkB,CAAC;AAE3C;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAU;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,KAAK,SAAS,CAAC,gBAAgB,CAAC;IAC9C,CAAC;IAED,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,gBAAgB,CAAC;IACnD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAAU;IACvC,MAAM,aAAa,GAAG;QACpB,SAAS,CAAC,eAAe;QACzB,SAAS,CAAC,cAAc;QACxB,SAAS,CAAC,eAAe;KAC1B,CAAC;IAEF,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC;IAClE,OAAO,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAU;IAC3C,MAAM,iBAAiB,GAAG;QACxB,SAAS,CAAC,eAAe;QACzB,SAAS,CAAC,cAAc;QACxB,SAAS,CAAC,eAAe;QACzB,SAAS,CAAC,aAAa;KACxB,CAAC;IAEF,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC;IAClE,OAAO,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAAU;IACpD,MAAM,SAAS,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC;IAElE,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,SAAS,CAAC,gBAAgB;YAC7B,OAAO,gCAAgC,CAAC;QAC1C,KAAK,SAAS,CAAC,eAAe;YAC5B,OAAO,gFAAgF,CAAC;QAC1F,KAAK,SAAS,CAAC,kBAAkB;YAC/B,OAAO,yCAAyC,CAAC;QACnD,KAAK,SAAS,CAAC,eAAe;YAC5B,OAAO,2BAA2B,CAAC;QACrC,KAAK,SAAS,CAAC,kBAAkB;YAC/B,OAAO,6BAA6B,CAAC;QACvC,KAAK,SAAS,CAAC,cAAc;YAC3B,OAAO,uDAAuD,CAAC;QACjE,KAAK,SAAS,CAAC,eAAe;YAC5B,OAAO,8CAA8C,CAAC;QACxD,KAAK,SAAS,CAAC,+BAA+B;YAC5C,OAAO,mCAAmC,CAAC;QAC7C,KAAK,SAAS,CAAC,gBAAgB;YAC7B,OAAO,2BAA2B,CAAC;QACrC;YACE,OAAO,KAAK,EAAE,OAAO,IAAI,8BAA8B,CAAC;IAC5D,CAAC;AACH,CAAC","sourcesContent":["/**\n * Error mapping utilities for expo-iap\n * Provides helper functions for handling platform-specific errors\n */\n\nimport {ErrorCode} from '../ExpoIap.types';\n\n/**\n * Checks if an error is a user cancellation\n * @param error Error object or error code\n * @returns True if the error represents user cancellation\n */\nexport function isUserCancelledError(error: any): boolean {\n if (typeof error === 'string') {\n return error === ErrorCode.E_USER_CANCELLED;\n }\n\n if (error && error.code) {\n return error.code === ErrorCode.E_USER_CANCELLED;\n }\n\n return false;\n}\n\n/**\n * Checks if an error is related to network connectivity\n * @param error Error object or error code\n * @returns True if the error is network-related\n */\nexport function isNetworkError(error: any): boolean {\n const networkErrors = [\n ErrorCode.E_NETWORK_ERROR,\n ErrorCode.E_REMOTE_ERROR,\n ErrorCode.E_SERVICE_ERROR,\n ];\n\n const errorCode = typeof error === 'string' ? error : error?.code;\n return networkErrors.includes(errorCode);\n}\n\n/**\n * Checks if an error is recoverable (user can retry)\n * @param error Error object or error code\n * @returns True if the error is potentially recoverable\n */\nexport function isRecoverableError(error: any): boolean {\n const recoverableErrors = [\n ErrorCode.E_NETWORK_ERROR,\n ErrorCode.E_REMOTE_ERROR,\n ErrorCode.E_SERVICE_ERROR,\n ErrorCode.E_INTERRUPTED,\n ];\n\n const errorCode = typeof error === 'string' ? error : error?.code;\n return recoverableErrors.includes(errorCode);\n}\n\n/**\n * Gets a user-friendly error message for display\n * @param error Error object or error code\n * @returns User-friendly error message\n */\nexport function getUserFriendlyErrorMessage(error: any): string {\n const errorCode = typeof error === 'string' ? error : error?.code;\n\n switch (errorCode) {\n case ErrorCode.E_USER_CANCELLED:\n return 'Purchase was cancelled by user';\n case ErrorCode.E_NETWORK_ERROR:\n return 'Network connection error. Please check your internet connection and try again.';\n case ErrorCode.E_ITEM_UNAVAILABLE:\n return 'This item is not available for purchase';\n case ErrorCode.E_ALREADY_OWNED:\n return 'You already own this item';\n case ErrorCode.E_DEFERRED_PAYMENT:\n return 'Payment is pending approval';\n case ErrorCode.E_NOT_PREPARED:\n return 'In-app purchase is not ready. Please try again later.';\n case ErrorCode.E_SERVICE_ERROR:\n return 'Store service error. Please try again later.';\n case ErrorCode.E_TRANSACTION_VALIDATION_FAILED:\n return 'Transaction could not be verified';\n case ErrorCode.E_RECEIPT_FAILED:\n return 'Receipt processing failed';\n default:\n return error?.message || 'An unexpected error occurred';\n }\n}\n"]}
1
+ {"version":3,"file":"errorMapping.js","sourceRoot":"","sources":["../../src/utils/errorMapping.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Error mapping utilities for expo-iap\n * Provides helper functions for handling platform-specific errors\n */\n\nimport {ErrorCode} from '../ExpoIap.types';\n\n/**\n * Checks if an error is a user cancellation\n * @param error Error object or error code\n * @returns True if the error represents user cancellation\n */\nexport function isUserCancelledError(error: any): boolean {\n if (typeof error === 'string') {\n return error === ErrorCode.E_USER_CANCELLED;\n }\n\n if (error && error.code) {\n return error.code === ErrorCode.E_USER_CANCELLED;\n }\n\n return false;\n}\n\n/**\n * Checks if an error is related to network connectivity\n * @param error Error object or error code\n * @returns True if the error is network-related\n */\nexport function isNetworkError(error: any): boolean {\n const networkErrors = [\n ErrorCode.E_NETWORK_ERROR,\n ErrorCode.E_REMOTE_ERROR,\n ErrorCode.E_SERVICE_ERROR,\n ErrorCode.E_SERVICE_DISCONNECTED,\n ErrorCode.E_BILLING_UNAVAILABLE,\n ];\n\n const errorCode = typeof error === 'string' ? error : error?.code;\n return networkErrors.includes(errorCode);\n}\n\n/**\n * Checks if an error is recoverable (user can retry)\n * @param error Error object or error code\n * @returns True if the error is potentially recoverable\n */\nexport function isRecoverableError(error: any): boolean {\n const recoverableErrors = [\n ErrorCode.E_NETWORK_ERROR,\n ErrorCode.E_REMOTE_ERROR,\n ErrorCode.E_SERVICE_ERROR,\n ErrorCode.E_INTERRUPTED,\n ErrorCode.E_SERVICE_DISCONNECTED,\n ErrorCode.E_BILLING_UNAVAILABLE,\n ErrorCode.E_QUERY_PRODUCT,\n ErrorCode.E_INIT_CONNECTION,\n ];\n\n const errorCode = typeof error === 'string' ? error : error?.code;\n return recoverableErrors.includes(errorCode);\n}\n\n/**\n * Gets a user-friendly error message for display\n * @param error Error object or error code\n * @returns User-friendly error message\n */\nexport function getUserFriendlyErrorMessage(error: any): string {\n const errorCode = typeof error === 'string' ? error : error?.code;\n\n switch (errorCode) {\n case ErrorCode.E_USER_CANCELLED:\n return 'Purchase was cancelled by user';\n case ErrorCode.E_NETWORK_ERROR:\n return 'Network connection error. Please check your internet connection and try again.';\n case ErrorCode.E_SERVICE_DISCONNECTED:\n return 'Billing service disconnected. Please try again.';\n case ErrorCode.E_BILLING_UNAVAILABLE:\n return 'Billing is unavailable on this device or account.';\n case ErrorCode.E_ITEM_UNAVAILABLE:\n return 'This item is not available for purchase';\n case ErrorCode.E_ITEM_NOT_OWNED:\n return \"You don't own this item\";\n case ErrorCode.E_ALREADY_OWNED:\n return 'You already own this item';\n case ErrorCode.E_SKU_NOT_FOUND:\n return 'Requested product could not be found';\n case ErrorCode.E_SKU_OFFER_MISMATCH:\n return 'Selected offer does not match the SKU';\n case ErrorCode.E_DEFERRED_PAYMENT:\n return 'Payment is pending approval';\n case ErrorCode.E_NOT_PREPARED:\n return 'In-app purchase is not ready. Please try again later.';\n case ErrorCode.E_SERVICE_ERROR:\n return 'Store service error. Please try again later.';\n case ErrorCode.E_FEATURE_NOT_SUPPORTED:\n return 'This feature is not supported on this device.';\n case ErrorCode.E_TRANSACTION_VALIDATION_FAILED:\n return 'Transaction could not be verified';\n case ErrorCode.E_RECEIPT_FAILED:\n return 'Receipt processing failed';\n case ErrorCode.E_EMPTY_SKU_LIST:\n return 'No product IDs provided';\n case ErrorCode.E_INIT_CONNECTION:\n return 'Failed to initialize billing connection';\n case ErrorCode.E_QUERY_PRODUCT:\n return 'Failed to query products. Please try again later.';\n default:\n return error?.message || 'An unexpected error occurred';\n }\n}\n"]}
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
21
21
  s.static_framework = true
22
22
 
23
23
  s.dependency 'ExpoModulesCore'
24
- s.dependency 'openiap', '~> 1.1.6'
24
+ s.dependency 'openiap', '~> 1.1.7'
25
25
 
26
26
  # Swift/Objective-C compatibility
27
27
  s.pod_target_xcconfig = {
@@ -312,26 +312,15 @@ public class ExpoIapModule: Module {
312
312
  AsyncFunction("getPromotedProductIOS") { () async throws -> [String: Any?]? in
313
313
  logDebug("getPromotedProductIOS called")
314
314
 
315
- if let promotedProduct = try await OpenIapModule.shared.getPromotedProductIOS() {
316
- return [
317
- "productIdentifier": promotedProduct.productIdentifier,
318
- "localizedTitle": promotedProduct.localizedTitle,
319
- "localizedDescription": promotedProduct.localizedDescription,
320
- "price": promotedProduct.price,
321
- "priceLocale": [
322
- "currencyCode": promotedProduct.priceLocale.currencyCode,
323
- "currencySymbol": promotedProduct.priceLocale.currencySymbol
324
- ]
325
- ]
315
+ if let promoted = try await OpenIapModule.shared.getPromotedProductIOS() {
316
+ // Fetch full product info by SKU to conform to OpenIapProduct
317
+ let request = OpenIapProductRequest(skus: [promoted.productIdentifier], type: .all)
318
+ let products = try await OpenIapModule.shared.fetchProducts(request)
319
+ let serialized = OpenIapSerialization.products(products)
320
+ return serialized.first
326
321
  }
327
322
  return nil
328
323
  }
329
-
330
- AsyncFunction("buyPromotedProductIOS") { () async throws in
331
- logDebug("buyPromotedProductIOS called")
332
- try await OpenIapModule.shared.requestPurchaseOnPromotedProductIOS()
333
- }
334
-
335
324
  AsyncFunction("getStorefrontIOS") { () async throws -> String in
336
325
  logDebug("getStorefrontIOS called")
337
326
  return try await OpenIapModule.shared.getStorefrontIOS()
@@ -363,15 +352,41 @@ public class ExpoIapModule: Module {
363
352
  logDebug("subscriptionStatusIOS called for sku: \(sku)")
364
353
 
365
354
  if let statuses = try await OpenIapModule.shared.subscriptionStatusIOS(sku: sku) {
355
+ // Align output with SubscriptionStatusIOS in TS:
356
+ // { state: SubscriptionState; renewalInfo?: { jsonRepresentation?: string; willAutoRenew: boolean; autoRenewPreference?: string } }
366
357
  return statuses.map { status in
367
- return [
368
- "state": status.state,
369
- "autoRenewStatus": status.renewalInfo?.autoRenewStatus,
370
- "autoRenewPreference": status.renewalInfo?.autoRenewPreference,
371
- "expirationReason": status.renewalInfo?.expirationReason,
372
- "currentProductID": status.renewalInfo?.currentProductID,
373
- "gracePeriodExpirationDate": status.renewalInfo?.gracePeriodExpirationDate
358
+ var dict: [String: Any?] = [
359
+ "state": status.state
374
360
  ]
361
+
362
+ if let info = status.renewalInfo {
363
+ // Convert autoRenewStatus to a proper boolean for willAutoRenew
364
+ let willAutoRenew: Bool = {
365
+ // Try boolean first
366
+ if let b = info.autoRenewStatus as? Bool { return b }
367
+ // Fallback to string normalization
368
+ let normalized = String(describing: info.autoRenewStatus).lowercased()
369
+ let truthy = Set([
370
+ "willrenew",
371
+ "will_autorenew",
372
+ "will-auto-renew",
373
+ "auto_renew_on",
374
+ "true",
375
+ "1",
376
+ "on",
377
+ "yes",
378
+ ])
379
+ return truthy.contains(normalized)
380
+ }()
381
+
382
+ let renewalInfo: [String: Any?] = [
383
+ "willAutoRenew": willAutoRenew,
384
+ "autoRenewPreference": info.autoRenewPreference
385
+ ]
386
+ dict["renewalInfo"] = renewalInfo
387
+ }
388
+
389
+ return dict
375
390
  }
376
391
  }
377
392
  return nil
@@ -411,16 +426,14 @@ public class ExpoIapModule: Module {
411
426
  }
412
427
  }
413
428
 
414
- purchaseErrorSub = OpenIapModule.shared.purchaseErrorListener { [weak self] error in
429
+ purchaseErrorSub = OpenIapModule.shared.purchaseErrorListener { [weak self] (event: OpenIapErrorEvent) in
415
430
  Task { @MainActor in
416
431
  guard let self else { return }
417
432
  logDebug("❌ Purchase error callback - sending error event")
418
- // Use OpenIapPurchaseError alias for clarity/parity
419
- let err: OpenIapPurchaseError = error
420
433
  let errorData: [String: Any?] = [
421
- "code": err.code,
422
- "message": err.message,
423
- "productId": err.productId,
434
+ "code": event.code,
435
+ "message": event.message,
436
+ "productId": event.productId
424
437
  ]
425
438
  self.sendEvent(OpenIapEvent.PurchaseError, errorData)
426
439
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-iap",
3
- "version": "2.9.0",
3
+ "version": "2.9.1",
4
4
  "description": "In App Purchase module in Expo",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",