expo-iap 2.8.6 → 2.9.0-rc.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 (44) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/CLAUDE.md +7 -0
  3. package/CONTRIBUTING.md +3 -4
  4. package/android/src/main/java/expo/modules/iap/ExpoIapModule.kt +120 -7
  5. package/android/src/main/java/expo/modules/iap/Types.kt +1 -1
  6. package/build/helpers/subscription.d.ts.map +1 -1
  7. package/build/helpers/subscription.js +3 -6
  8. package/build/helpers/subscription.js.map +1 -1
  9. package/build/index.d.ts +31 -5
  10. package/build/index.d.ts.map +1 -1
  11. package/build/index.js +53 -25
  12. package/build/index.js.map +1 -1
  13. package/build/modules/android.d.ts.map +1 -1
  14. package/build/modules/android.js.map +1 -1
  15. package/build/modules/ios.d.ts.map +1 -1
  16. package/build/modules/ios.js.map +1 -1
  17. package/build/types/ExpoIapAndroid.types.d.ts +2 -2
  18. package/build/types/ExpoIapAndroid.types.d.ts.map +1 -1
  19. package/build/types/ExpoIapAndroid.types.js.map +1 -1
  20. package/build/types/ExpoIapIOS.types.d.ts +3 -3
  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 +12 -4
  24. package/build/useIAP.d.ts.map +1 -1
  25. package/build/useIAP.js +10 -5
  26. package/build/useIAP.js.map +1 -1
  27. package/ios/ExpoIap.podspec +1 -0
  28. package/ios/ExpoIapModule.swift +354 -1159
  29. package/jest.config.js +14 -17
  30. package/package.json +5 -3
  31. package/plugin/build/withIAP.d.ts +7 -1
  32. package/plugin/build/withIAP.js +16 -2
  33. package/plugin/build/withLocalOpenIAP.d.ts +9 -0
  34. package/plugin/build/withLocalOpenIAP.js +85 -0
  35. package/plugin/src/withIAP.ts +21 -2
  36. package/plugin/src/withLocalOpenIAP.ts +66 -0
  37. package/plugin/tsconfig.tsbuildinfo +1 -1
  38. package/src/helpers/subscription.ts +21 -28
  39. package/src/index.ts +70 -33
  40. package/src/modules/android.ts +7 -7
  41. package/src/modules/ios.ts +11 -5
  42. package/src/types/ExpoIapAndroid.types.ts +3 -4
  43. package/src/types/ExpoIapIOS.types.ts +4 -3
  44. package/src/useIAP.ts +40 -12
package/src/index.ts CHANGED
@@ -45,7 +45,7 @@ export {
45
45
  // Get the native constant value
46
46
  export const PI = ExpoIapModule.PI;
47
47
 
48
- export enum IapEvent {
48
+ export enum OpenIapEvent {
49
49
  PurchaseUpdated = 'purchase-updated',
50
50
  PurchaseError = 'purchase-error',
51
51
  /** @deprecated Use PurchaseUpdated instead. This will be removed in a future version. */
@@ -73,7 +73,7 @@ export const purchaseUpdatedListener = (
73
73
  listener: (event: Purchase) => void,
74
74
  ) => {
75
75
  const emitterSubscription = emitter.addListener(
76
- IapEvent.PurchaseUpdated,
76
+ OpenIapEvent.PurchaseUpdated,
77
77
  listener,
78
78
  );
79
79
  return emitterSubscription;
@@ -82,7 +82,7 @@ export const purchaseUpdatedListener = (
82
82
  export const purchaseErrorListener = (
83
83
  listener: (error: PurchaseError) => void,
84
84
  ) => {
85
- return emitter.addListener(IapEvent.PurchaseError, listener);
85
+ return emitter.addListener(OpenIapEvent.PurchaseError, listener);
86
86
  };
87
87
 
88
88
  /**
@@ -114,7 +114,7 @@ export const promotedProductListenerIOS = (
114
114
  );
115
115
  return {remove: () => {}};
116
116
  }
117
- return emitter.addListener(IapEvent.PromotedProductIOS, listener);
117
+ return emitter.addListener(OpenIapEvent.PromotedProductIOS, listener);
118
118
  };
119
119
 
120
120
  export function initConnection(): Promise<boolean> {
@@ -124,7 +124,7 @@ export function initConnection(): Promise<boolean> {
124
124
 
125
125
  export const getProducts = async (skus: string[]): Promise<Product[]> => {
126
126
  console.warn(
127
- "`getProducts` is deprecated. Use `requestProducts({ skus, type: 'inapp' })` instead. This function will be removed in version 3.0.0.",
127
+ "`getProducts` is deprecated. Use `fetchProducts({ skus, type: 'inapp' })` instead. This function will be removed in version 3.0.0.",
128
128
  );
129
129
  if (!skus?.length) {
130
130
  return Promise.reject(new Error('"skus" is required'));
@@ -132,7 +132,7 @@ export const getProducts = async (skus: string[]): Promise<Product[]> => {
132
132
 
133
133
  return Platform.select({
134
134
  ios: async () => {
135
- const rawItems = await ExpoIapModule.requestProducts(skus);
135
+ const rawItems = await ExpoIapModule.fetchProducts(skus);
136
136
  return rawItems.filter((item: unknown) => {
137
137
  if (!isProductIOS(item)) return false;
138
138
  return (
@@ -145,7 +145,7 @@ export const getProducts = async (skus: string[]): Promise<Product[]> => {
145
145
  }) as Product[];
146
146
  },
147
147
  android: async () => {
148
- const products = await ExpoIapModule.requestProducts('inapp', skus);
148
+ const products = await ExpoIapModule.fetchProducts('inapp', skus);
149
149
  return products.filter((product: unknown) =>
150
150
  isProductAndroid<Product>(product),
151
151
  );
@@ -158,7 +158,7 @@ export const getSubscriptions = async (
158
158
  skus: string[],
159
159
  ): Promise<SubscriptionProduct[]> => {
160
160
  console.warn(
161
- "`getSubscriptions` is deprecated. Use `requestProducts({ skus, type: 'subs' })` instead. This function will be removed in version 3.0.0.",
161
+ "`getSubscriptions` is deprecated. Use `fetchProducts({ skus, type: 'subs' })` instead. This function will be removed in version 3.0.0.",
162
162
  );
163
163
  if (!skus?.length) {
164
164
  return Promise.reject(new Error('"skus" is required'));
@@ -166,7 +166,7 @@ export const getSubscriptions = async (
166
166
 
167
167
  return Platform.select({
168
168
  ios: async () => {
169
- const rawItems = await ExpoIapModule.requestProducts(skus);
169
+ const rawItems = await ExpoIapModule.fetchProducts(skus);
170
170
  return rawItems.filter((item: unknown) => {
171
171
  if (!isProductIOS(item)) return false;
172
172
  return (
@@ -179,7 +179,7 @@ export const getSubscriptions = async (
179
179
  }) as SubscriptionProduct[];
180
180
  },
181
181
  android: async () => {
182
- const rawItems = await ExpoIapModule.requestProducts('subs', skus);
182
+ const rawItems = await ExpoIapModule.fetchProducts('subs', skus);
183
183
  return rawItems.filter((item: unknown) => {
184
184
  if (!isProductAndroid(item)) return false;
185
185
  return (
@@ -200,28 +200,28 @@ export async function endConnection(): Promise<boolean> {
200
200
  }
201
201
 
202
202
  /**
203
- * Request products with unified API (v2.7.0+)
203
+ * Fetch products with unified API (v2.7.0+)
204
204
  *
205
- * @param params - Product request configuration
205
+ * @param params - Product fetch configuration
206
206
  * @param params.skus - Array of product SKUs to fetch
207
207
  * @param params.type - Type of products: 'inapp' for regular products (default) or 'subs' for subscriptions
208
208
  *
209
209
  * @example
210
210
  * ```typescript
211
211
  * // Regular products
212
- * const products = await requestProducts({
212
+ * const products = await fetchProducts({
213
213
  * skus: ['product1', 'product2'],
214
214
  * type: 'inapp'
215
215
  * });
216
216
  *
217
217
  * // Subscriptions
218
- * const subscriptions = await requestProducts({
218
+ * const subscriptions = await fetchProducts({
219
219
  * skus: ['sub1', 'sub2'],
220
220
  * type: 'subs'
221
221
  * });
222
222
  * ```
223
223
  */
224
- export const requestProducts = async ({
224
+ export const fetchProducts = async ({
225
225
  skus,
226
226
  type = 'inapp',
227
227
  }: {
@@ -233,7 +233,7 @@ export const requestProducts = async ({
233
233
  }
234
234
 
235
235
  if (Platform.OS === 'ios') {
236
- const rawItems = await ExpoIapModule.requestProducts(skus);
236
+ const rawItems = await ExpoIapModule.fetchProducts(skus);
237
237
  const filteredItems = rawItems.filter((item: unknown) => {
238
238
  if (!isProductIOS(item)) return false;
239
239
  return (
@@ -251,7 +251,7 @@ export const requestProducts = async ({
251
251
  }
252
252
 
253
253
  if (Platform.OS === 'android') {
254
- const items = await ExpoIapModule.requestProducts(type, skus);
254
+ const items = await ExpoIapModule.fetchProducts(type, skus);
255
255
  const filteredItems = items.filter((item: unknown) => {
256
256
  if (!isProductAndroid(item)) return false;
257
257
  return (
@@ -271,6 +271,41 @@ export const requestProducts = async ({
271
271
  throw new Error('Unsupported platform');
272
272
  };
273
273
 
274
+ /**
275
+ * @deprecated Use `fetchProducts` instead. This method will be removed in version 3.0.0.
276
+ *
277
+ * The 'request' prefix should only be used for event-based operations that trigger
278
+ * purchase flows. Since this function simply fetches product information, it has been
279
+ * renamed to `fetchProducts` to follow OpenIAP terminology guidelines.
280
+ *
281
+ * @example
282
+ * ```typescript
283
+ * // Old way (deprecated)
284
+ * const products = await requestProducts({
285
+ * skus: ['com.example.product1'],
286
+ * type: 'inapp'
287
+ * });
288
+ *
289
+ * // New way (recommended)
290
+ * const products = await fetchProducts({
291
+ * skus: ['com.example.product1'],
292
+ * type: 'inapp'
293
+ * });
294
+ * ```
295
+ */
296
+ export const requestProducts = async ({
297
+ skus,
298
+ type = 'inapp',
299
+ }: {
300
+ skus: string[];
301
+ type?: 'inapp' | 'subs';
302
+ }): Promise<Product[] | SubscriptionProduct[]> => {
303
+ console.warn(
304
+ "`requestProducts` is deprecated. Use `fetchProducts` instead. The 'request' prefix should only be used for event-based operations. This method will be removed in version 3.0.0."
305
+ );
306
+ return fetchProducts({ skus, type });
307
+ };
308
+
274
309
  /**
275
310
  * @deprecated Use `getPurchaseHistories` instead. This function will be removed in version 3.0.0.
276
311
  */
@@ -291,10 +326,8 @@ export const getPurchaseHistory = ({
291
326
  '`getPurchaseHistory` is deprecated. Use `getPurchaseHistories` instead. This function will be removed in version 3.0.0.',
292
327
  );
293
328
  return getPurchaseHistories({
294
- alsoPublishToEventListenerIOS:
295
- alsoPublishToEventListenerIOS ?? alsoPublishToEventListener,
296
- onlyIncludeActiveItemsIOS:
297
- onlyIncludeActiveItemsIOS ?? onlyIncludeActiveItems,
329
+ alsoPublishToEventListenerIOS: alsoPublishToEventListenerIOS ?? alsoPublishToEventListener,
330
+ onlyIncludeActiveItemsIOS: onlyIncludeActiveItemsIOS ?? onlyIncludeActiveItems,
298
331
  });
299
332
  };
300
333
 
@@ -357,9 +390,8 @@ export const getAvailablePurchases = ({
357
390
  ),
358
391
  android: async () => {
359
392
  const products = await ExpoIapModule.getAvailableItemsByType('inapp');
360
- const subscriptions = await ExpoIapModule.getAvailableItemsByType(
361
- 'subs',
362
- );
393
+ const subscriptions =
394
+ await ExpoIapModule.getAvailableItemsByType('subs');
363
395
  return products.concat(subscriptions);
364
396
  },
365
397
  }) || (() => Promise.resolve([]))
@@ -433,7 +465,11 @@ const normalizeRequestProps = (
433
465
  */
434
466
  export const requestPurchase = (
435
467
  requestObj: PurchaseRequest,
436
- ): Promise<Purchase | Purchase[] | void> => {
468
+ ): Promise<
469
+ | Purchase
470
+ | Purchase[]
471
+ | void
472
+ > => {
437
473
  const {request, type = 'inapp'} = requestObj;
438
474
 
439
475
  if (Platform.OS === 'ios') {
@@ -463,7 +499,9 @@ export const requestPurchase = (
463
499
  offer,
464
500
  );
465
501
 
466
- return type === 'inapp' ? (purchase as Purchase) : (purchase as Purchase);
502
+ return type === 'inapp'
503
+ ? (purchase as Purchase)
504
+ : (purchase as Purchase);
467
505
  })();
468
506
  }
469
507
 
@@ -591,11 +629,10 @@ export const finishTransaction = ({
591
629
  },
592
630
  android: async () => {
593
631
  const androidPurchase = purchase as PurchaseAndroid;
594
-
632
+
595
633
  // Use purchaseToken if available, fallback to purchaseTokenAndroid for backward compatibility
596
- const token =
597
- androidPurchase.purchaseToken || androidPurchase.purchaseTokenAndroid;
598
-
634
+ const token = androidPurchase.purchaseToken || androidPurchase.purchaseTokenAndroid;
635
+
599
636
  if (!token) {
600
637
  return Promise.reject(
601
638
  new PurchaseError(
@@ -605,8 +642,8 @@ export const finishTransaction = ({
605
642
  undefined,
606
643
  'E_DEVELOPER_ERROR' as ErrorCode,
607
644
  androidPurchase.productId,
608
- 'android',
609
- ),
645
+ 'android'
646
+ )
610
647
  );
611
648
  }
612
649
 
@@ -639,7 +676,7 @@ export const getStorefrontIOS = (): Promise<string> => {
639
676
  console.warn('getStorefrontIOS: This method is only available on iOS');
640
677
  return Promise.resolve('');
641
678
  }
642
- return ExpoIapModule.getStorefront();
679
+ return ExpoIapModule.getStorefrontIOS();
643
680
  };
644
681
 
645
682
  /**
@@ -26,7 +26,7 @@ export function isProductAndroid<T extends {platform?: string}>(
26
26
  * @param {string} params.sku - The product's SKU (on Android)
27
27
  * @param {string} params.packageName - The package name of your Android app (e.g., 'com.example.app')
28
28
  * @returns {Promise<void>}
29
- *
29
+ *
30
30
  * @example
31
31
  * ```typescript
32
32
  * await deepLinkToSubscriptionsAndroid({
@@ -43,11 +43,9 @@ export const deepLinkToSubscriptionsAndroid = async ({
43
43
  packageName: string;
44
44
  }): Promise<void> => {
45
45
  if (!packageName) {
46
- throw new Error(
47
- 'packageName is required for deepLinkToSubscriptionsAndroid',
48
- );
46
+ throw new Error('packageName is required for deepLinkToSubscriptionsAndroid');
49
47
  }
50
-
48
+
51
49
  return Linking.openURL(
52
50
  `https://play.google.com/store/account/subscriptions?package=${packageName}&sku=${sku}`,
53
51
  );
@@ -120,9 +118,11 @@ export const acknowledgePurchaseAndroid = ({
120
118
  * Open the Google Play Store to redeem offer codes (Android only).
121
119
  * Note: Google Play does not provide a direct API to redeem codes within the app.
122
120
  * This function opens the Play Store where users can manually enter their codes.
123
- *
121
+ *
124
122
  * @returns {Promise<void>}
125
123
  */
126
124
  export const openRedeemOfferCodeAndroid = async (): Promise<void> => {
127
- return Linking.openURL(`https://play.google.com/redeem?code=`);
125
+ return Linking.openURL(
126
+ `https://play.google.com/redeem?code=`
127
+ );
128
128
  };
@@ -5,7 +5,11 @@ import {purchaseUpdatedListener} from '..';
5
5
  import ExpoIapModule from '../ExpoIapModule';
6
6
 
7
7
  // Types
8
- import {Product, Purchase, PurchaseError} from '../ExpoIap.types';
8
+ import {
9
+ Product,
10
+ Purchase,
11
+ PurchaseError,
12
+ } from '../ExpoIap.types';
9
13
  import type {
10
14
  ProductStatusIOS,
11
15
  AppTransactionIOS,
@@ -133,7 +137,9 @@ export const subscriptionStatusIOS = (
133
137
  *
134
138
  * @platform iOS
135
139
  */
136
- export const currentEntitlementIOS = (sku: string): Promise<Purchase> => {
140
+ export const currentEntitlementIOS = (
141
+ sku: string,
142
+ ): Promise<Purchase> => {
137
143
  return ExpoIapModule.currentEntitlementIOS(sku);
138
144
  };
139
145
 
@@ -318,7 +324,7 @@ export const buyPromotedProductIOS = (): Promise<void> => {
318
324
 
319
325
  /**
320
326
  * Get pending transactions that haven't been finished yet (iOS only).
321
- *
327
+ *
322
328
  * @returns Promise resolving to array of pending transactions
323
329
  * @platform iOS
324
330
  */
@@ -328,9 +334,9 @@ export const getPendingTransactionsIOS = (): Promise<any[]> => {
328
334
 
329
335
  /**
330
336
  * Clear a specific transaction (iOS only).
331
- *
337
+ *
332
338
  * @returns Promise resolving when transaction is cleared
333
- * @platform iOS
339
+ * @platform iOS
334
340
  */
335
341
  export const clearTransactionIOS = (): Promise<void> => {
336
342
  return ExpoIapModule.clearTransactionIOS();
@@ -31,7 +31,7 @@ type ProductSubscriptionAndroidOfferDetail = {
31
31
  export type ProductAndroid = ProductCommon & {
32
32
  nameAndroid: string;
33
33
  oneTimePurchaseOfferDetailsAndroid?: ProductAndroidOneTimePurchaseOfferDetail;
34
- platform: 'android';
34
+ platform: "android";
35
35
  subscriptionOfferDetailsAndroid?: ProductSubscriptionAndroidOfferDetail[];
36
36
  /**
37
37
  * @deprecated Use `nameAndroid` instead. This field will be removed in v2.9.0.
@@ -144,7 +144,7 @@ export const PurchaseStateAndroid = PurchaseAndroidState;
144
144
 
145
145
  // Legacy naming for backward compatibility
146
146
  export type ProductPurchaseAndroid = PurchaseCommon & {
147
- platform: 'android';
147
+ platform: "android";
148
148
  /**
149
149
  * @deprecated Use `purchaseToken` instead. This field will be removed in a future version.
150
150
  */
@@ -167,8 +167,7 @@ export type PurchaseAndroid = ProductPurchaseAndroid;
167
167
  /**
168
168
  * @deprecated Use `ProductAndroidOneTimePurchaseOfferDetail` instead. This type will be removed in v2.9.0.
169
169
  */
170
- export type OneTimePurchaseOfferDetails =
171
- ProductAndroidOneTimePurchaseOfferDetail;
170
+ export type OneTimePurchaseOfferDetails = ProductAndroidOneTimePurchaseOfferDetail;
172
171
 
173
172
  /**
174
173
  * @deprecated Use `ProductSubscriptionAndroidOfferDetail` instead. This type will be removed in v2.9.0.
@@ -30,7 +30,7 @@ export type ProductIOS = ProductCommon & {
30
30
  displayNameIOS: string;
31
31
  isFamilyShareableIOS: boolean;
32
32
  jsonRepresentationIOS: string;
33
- platform: 'ios';
33
+ platform: "ios";
34
34
  subscriptionInfoIOS?: SubscriptionInfo;
35
35
  /**
36
36
  * @deprecated Use `displayNameIOS` instead. This field will be removed in v2.9.0.
@@ -69,7 +69,7 @@ export type ProductSubscriptionIOS = ProductIOS & {
69
69
  introductoryPricePaymentModeIOS?: PaymentMode;
70
70
  introductoryPriceNumberOfPeriodsIOS?: string;
71
71
  introductoryPriceSubscriptionPeriodIOS?: SubscriptionIosPeriod;
72
- platform: 'ios';
72
+ platform: "ios";
73
73
  subscriptionPeriodNumberIOS?: string;
74
74
  subscriptionPeriodUnitIOS?: SubscriptionIosPeriod;
75
75
  /**
@@ -140,7 +140,7 @@ export type ProductStatusIOS = {
140
140
  // Legacy naming for backward compatibility
141
141
  export type ProductPurchaseIOS = PurchaseCommon & {
142
142
  // iOS basic fields
143
- platform: 'ios';
143
+ platform: "ios";
144
144
  quantityIOS?: number;
145
145
  originalTransactionDateIOS?: number;
146
146
  originalTransactionIdentifierIOS?: string;
@@ -179,6 +179,7 @@ export type ProductPurchaseIOS = PurchaseCommon & {
179
179
  // Preferred naming
180
180
  export type PurchaseIOS = ProductPurchaseIOS;
181
181
 
182
+
182
183
  export type AppTransactionIOS = {
183
184
  appTransactionId?: string; // Only available in iOS 18.4+
184
185
  originalPlatform?: string; // Only available in iOS 18.4+
package/src/useIAP.ts CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  getPurchaseHistories,
15
15
  finishTransaction as finishTransactionInternal,
16
16
  requestPurchase as requestPurchaseInternal,
17
- requestProducts,
17
+ fetchProducts,
18
18
  validateReceipt as validateReceiptInternal,
19
19
  getActiveSubscriptions,
20
20
  hasActiveSubscriptions,
@@ -60,18 +60,26 @@ type UseIap = {
60
60
  }) => Promise<PurchaseResult | boolean>;
61
61
  getAvailablePurchases: (skus: string[]) => Promise<void>;
62
62
  getPurchaseHistories: (skus: string[]) => Promise<void>;
63
+ fetchProducts: (params: {
64
+ skus: string[];
65
+ type?: 'inapp' | 'subs';
66
+ }) => Promise<void>;
67
+ /**
68
+ * @deprecated Use fetchProducts({ skus, type: 'inapp' | 'subs' }) instead. This method will be removed in version 3.0.0.
69
+ * The 'request' prefix should only be used for event-based operations.
70
+ */
63
71
  requestProducts: (params: {
64
72
  skus: string[];
65
73
  type?: 'inapp' | 'subs';
66
74
  }) => Promise<void>;
67
75
  /**
68
- * @deprecated Use requestProducts({ skus, type: 'inapp' }) instead. This method will be removed in version 3.0.0.
69
- * Note: This method internally uses requestProducts, so no deprecation warning is shown.
76
+ * @deprecated Use fetchProducts({ skus, type: 'inapp' }) instead. This method will be removed in version 3.0.0.
77
+ * Note: This method internally uses fetchProducts, so no deprecation warning is shown.
70
78
  */
71
79
  getProducts: (skus: string[]) => Promise<void>;
72
80
  /**
73
- * @deprecated Use requestProducts({ skus, type: 'subs' }) instead. This method will be removed in version 3.0.0.
74
- * Note: This method internally uses requestProducts, so no deprecation warning is shown.
81
+ * @deprecated Use fetchProducts({ skus, type: 'subs' }) instead. This method will be removed in version 3.0.0.
82
+ * Note: This method internally uses fetchProducts, so no deprecation warning is shown.
75
83
  */
76
84
  getSubscriptions: (skus: string[]) => Promise<void>;
77
85
  requestPurchase: (params: {
@@ -99,7 +107,9 @@ type UseIap = {
99
107
  };
100
108
 
101
109
  export interface UseIAPOptions {
102
- onPurchaseSuccess?: (purchase: Purchase) => void;
110
+ onPurchaseSuccess?: (
111
+ purchase: Purchase,
112
+ ) => void;
103
113
  onPurchaseError?: (error: PurchaseError) => void;
104
114
  onSyncError?: (error: Error) => void;
105
115
  shouldAutoSyncPurchases?: boolean; // New option to control auto-syncing
@@ -115,8 +125,12 @@ export function useIAP(options?: UseIAPOptions): UseIap {
115
125
  const [products, setProducts] = useState<Product[]>([]);
116
126
  const [promotedProductsIOS] = useState<Purchase[]>([]);
117
127
  const [subscriptions, setSubscriptions] = useState<SubscriptionProduct[]>([]);
118
- const [purchaseHistories, setPurchaseHistories] = useState<Purchase[]>([]);
119
- const [availablePurchases, setAvailablePurchases] = useState<Purchase[]>([]);
128
+ const [purchaseHistories, setPurchaseHistories] = useState<Purchase[]>(
129
+ [],
130
+ );
131
+ const [availablePurchases, setAvailablePurchases] = useState<
132
+ Purchase[]
133
+ >([]);
120
134
  const [currentPurchase, setCurrentPurchase] = useState<Purchase>();
121
135
  const [promotedProductIOS, setPromotedProductIOS] = useState<Product>();
122
136
  const [currentPurchaseError, setCurrentPurchaseError] =
@@ -177,7 +191,7 @@ export function useIAP(options?: UseIAPOptions): UseIap {
177
191
  const getProductsInternal = useCallback(
178
192
  async (skus: string[]): Promise<void> => {
179
193
  try {
180
- const result = await requestProducts({skus, type: 'inapp'});
194
+ const result = await fetchProducts({skus, type: 'inapp'});
181
195
  setProducts((prevProducts) =>
182
196
  mergeWithDuplicateCheck(
183
197
  prevProducts,
@@ -195,7 +209,7 @@ export function useIAP(options?: UseIAPOptions): UseIap {
195
209
  const getSubscriptionsInternal = useCallback(
196
210
  async (skus: string[]): Promise<void> => {
197
211
  try {
198
- const result = await requestProducts({skus, type: 'subs'});
212
+ const result = await fetchProducts({skus, type: 'subs'});
199
213
  setSubscriptions((prevSubscriptions) =>
200
214
  mergeWithDuplicateCheck(
201
215
  prevSubscriptions,
@@ -210,13 +224,13 @@ export function useIAP(options?: UseIAPOptions): UseIap {
210
224
  [mergeWithDuplicateCheck],
211
225
  );
212
226
 
213
- const requestProductsInternal = useCallback(
227
+ const fetchProductsInternal = useCallback(
214
228
  async (params: {
215
229
  skus: string[];
216
230
  type?: 'inapp' | 'subs';
217
231
  }): Promise<void> => {
218
232
  try {
219
- const result = await requestProducts(params);
233
+ const result = await fetchProducts(params);
220
234
  if (params.type === 'subs') {
221
235
  setSubscriptions((prevSubscriptions) =>
222
236
  mergeWithDuplicateCheck(
@@ -241,6 +255,19 @@ export function useIAP(options?: UseIAPOptions): UseIap {
241
255
  [mergeWithDuplicateCheck],
242
256
  );
243
257
 
258
+ const requestProductsInternal = useCallback(
259
+ async (params: {
260
+ skus: string[];
261
+ type?: 'inapp' | 'subs';
262
+ }): Promise<void> => {
263
+ console.warn(
264
+ "`requestProducts` is deprecated in useIAP hook. Use the new `fetchProducts` method instead. The 'request' prefix should only be used for event-based operations."
265
+ );
266
+ return fetchProductsInternal(params);
267
+ },
268
+ [fetchProductsInternal],
269
+ );
270
+
244
271
  const getAvailablePurchasesInternal = useCallback(async (): Promise<void> => {
245
272
  try {
246
273
  const result = await getAvailablePurchases();
@@ -454,6 +481,7 @@ export function useIAP(options?: UseIAPOptions): UseIap {
454
481
  clearCurrentPurchaseError,
455
482
  getAvailablePurchases: getAvailablePurchasesInternal,
456
483
  getPurchaseHistories: getPurchaseHistoriesInternal,
484
+ fetchProducts: fetchProductsInternal,
457
485
  requestProducts: requestProductsInternal,
458
486
  requestPurchase: requestPurchaseWithReset,
459
487
  validateReceipt,