expo-iap 3.4.11 → 3.4.13

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/useIAP.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { requestPurchase as requestPurchaseInternal, type ActiveSubscription, type ProductTypeInput } from './index';
2
- import type { Product, ProductSubscription, Purchase, MutationRequestPurchaseArgs, VerifyPurchaseProps, VerifyPurchaseResult, VerifyPurchaseWithProviderProps, VerifyPurchaseWithProviderResult } from './types';
2
+ import type { Product, ProductSubscription, Purchase, MutationRequestPurchaseArgs, VerifyPurchaseProps, VerifyPurchaseResult, VerifyPurchaseWithProviderProps, VerifyPurchaseWithProviderResult, PurchaseOptions } from './types';
3
3
  import type { PurchaseError } from './utils/errorMapping';
4
4
  type UseIap = {
5
5
  connected: boolean;
@@ -12,7 +12,7 @@ type UseIap = {
12
12
  purchase: Purchase;
13
13
  isConsumable?: boolean;
14
14
  }) => Promise<void>;
15
- getAvailablePurchases: () => Promise<void>;
15
+ getAvailablePurchases: (options?: PurchaseOptions) => Promise<void>;
16
16
  fetchProducts: (params: {
17
17
  skus: string[];
18
18
  type?: ProductTypeInput;
@@ -22,7 +22,7 @@ type UseIap = {
22
22
  validateReceipt: (props: VerifyPurchaseProps) => Promise<VerifyPurchaseResult>;
23
23
  verifyPurchase: (props: VerifyPurchaseProps) => Promise<VerifyPurchaseResult>;
24
24
  verifyPurchaseWithProvider: (props: VerifyPurchaseWithProviderProps) => Promise<VerifyPurchaseWithProviderResult>;
25
- restorePurchases: () => Promise<void>;
25
+ restorePurchases: (options?: PurchaseOptions) => Promise<void>;
26
26
  getPromotedProductIOS: () => Promise<Product | null>;
27
27
  /**
28
28
  * @deprecated Use promotedProductListenerIOS to receive the productId,
@@ -31,6 +31,12 @@ type UseIap = {
31
31
  requestPurchaseOnPromotedProductIOS: () => Promise<boolean>;
32
32
  getActiveSubscriptions: (subscriptionIds?: string[]) => Promise<void>;
33
33
  hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise<boolean>;
34
+ /**
35
+ * Manually retry the store connection.
36
+ * Useful when the initial auto-connect fails (e.g., Play Store not ready at mount time).
37
+ * Updates the `connected` state on success.
38
+ */
39
+ reconnect: () => Promise<boolean>;
34
40
  checkAlternativeBillingAvailabilityAndroid: () => Promise<boolean>;
35
41
  showAlternativeBillingDialogAndroid: () => Promise<boolean>;
36
42
  createAlternativeBillingTokenAndroid: (sku?: string) => Promise<string | null>;
@@ -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
@@ -130,11 +130,12 @@ export function useIAP(options) {
130
130
  mergeWithDuplicateCheck,
131
131
  normalizeProductQueryType,
132
132
  ]);
133
- const getAvailablePurchasesInternal = useCallback(async () => {
133
+ const getAvailablePurchasesInternal = useCallback(async (options) => {
134
134
  try {
135
135
  const result = await getAvailablePurchases({
136
- alsoPublishToEventListenerIOS: false,
137
- onlyIncludeActiveItemsIOS: true,
136
+ alsoPublishToEventListenerIOS: options?.alsoPublishToEventListenerIOS ?? false,
137
+ onlyIncludeActiveItemsIOS: options?.onlyIncludeActiveItemsIOS ?? true,
138
+ includeSuspendedAndroid: options?.includeSuspendedAndroid ?? false,
138
139
  });
139
140
  setAvailablePurchases(result);
140
141
  }
@@ -178,24 +179,30 @@ export function useIAP(options) {
178
179
  if (subscriptionsRefState.current.some((sub) => sub.id === productId)) {
179
180
  await fetchProductsInternal({ skus: [productId], type: 'subs' });
180
181
  await getAvailablePurchasesInternal();
182
+ await getActiveSubscriptionsInternal();
181
183
  }
182
184
  }
183
185
  catch (error) {
184
186
  ExpoIapConsole.warn('Failed to refresh subscription status:', error);
185
187
  }
186
- }, [fetchProductsInternal, getAvailablePurchasesInternal]);
188
+ }, [
189
+ fetchProductsInternal,
190
+ getAvailablePurchasesInternal,
191
+ getActiveSubscriptionsInternal,
192
+ ]);
187
193
  // Restore completed transactions with cross-platform behavior.
188
194
  // iOS: best-effort sync (ignore sync errors) then fetch available purchases.
189
195
  // Android: fetch available purchases directly.
190
- const restorePurchasesInternal = useCallback(async () => {
196
+ const restorePurchasesInternal = useCallback(async (options) => {
191
197
  try {
192
198
  // iOS: Try to sync first, but don't fail if sync errors occur
193
199
  if (Platform.OS === 'ios') {
194
200
  await syncIOS().catch(() => undefined); // syncIOS returns Promise<boolean>, we don't need the result
195
201
  }
196
202
  const purchases = await getAvailablePurchases({
197
- alsoPublishToEventListenerIOS: false,
198
- onlyIncludeActiveItemsIOS: true,
203
+ alsoPublishToEventListenerIOS: options?.alsoPublishToEventListenerIOS ?? false,
204
+ onlyIncludeActiveItemsIOS: options?.onlyIncludeActiveItemsIOS ?? true,
205
+ includeSuspendedAndroid: options?.includeSuspendedAndroid ?? false,
199
206
  });
200
207
  setAvailablePurchases(purchases);
201
208
  }
@@ -214,14 +221,25 @@ export function useIAP(options) {
214
221
  const verifyPurchaseWithProvider = useCallback(async (props) => {
215
222
  return verifyPurchaseWithProviderInternal(props);
216
223
  }, []);
224
+ // Build config from options (prefer new enableBillingProgramAndroid over deprecated alternativeBillingModeAndroid)
225
+ const buildConnectionConfig = useCallback(() => {
226
+ return optionsRef.current?.enableBillingProgramAndroid ||
227
+ optionsRef.current?.alternativeBillingModeAndroid
228
+ ? {
229
+ enableBillingProgramAndroid: optionsRef.current.enableBillingProgramAndroid,
230
+ alternativeBillingModeAndroid: optionsRef.current.alternativeBillingModeAndroid,
231
+ }
232
+ : undefined;
233
+ }, []);
217
234
  const initIapWithSubscriptions = useCallback(async () => {
218
235
  // CRITICAL: Register listeners BEFORE initConnection to avoid race condition
219
236
  // Events might fire immediately after initConnection, so listeners must be ready
220
237
  // Register purchase update listener BEFORE initConnection to avoid race conditions.
221
238
  subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(async (purchase) => {
222
- if ('expirationDateIOS' in purchase) {
223
- await refreshSubscriptionStatus(purchase.id);
224
- }
239
+ // Refresh subscription status for both iOS and Android subscription purchases.
240
+ // refreshSubscriptionStatus internally checks whether the product is a known
241
+ // subscription, so it is safe to call unconditionally for any purchase event.
242
+ await refreshSubscriptionStatus(purchase.productId);
225
243
  if (optionsRef.current?.onPurchaseSuccess) {
226
244
  optionsRef.current.onPurchaseSuccess(purchase);
227
245
  }
@@ -249,14 +267,7 @@ export function useIAP(options) {
249
267
  });
250
268
  }
251
269
  // NOW call initConnection after listeners are ready
252
- // Build config from options (prefer new enableBillingProgramAndroid over deprecated alternativeBillingModeAndroid)
253
- const config = optionsRef.current?.enableBillingProgramAndroid ||
254
- optionsRef.current?.alternativeBillingModeAndroid
255
- ? {
256
- enableBillingProgramAndroid: optionsRef.current.enableBillingProgramAndroid,
257
- alternativeBillingModeAndroid: optionsRef.current.alternativeBillingModeAndroid,
258
- }
259
- : undefined;
270
+ const config = buildConnectionConfig();
260
271
  try {
261
272
  const result = await initConnection(config);
262
273
  setConnected(result);
@@ -279,7 +290,44 @@ export function useIAP(options) {
279
290
  subscriptionsRef.current.purchaseUpdate = undefined;
280
291
  subscriptionsRef.current.promotedProductIOS = undefined;
281
292
  }
282
- }, [refreshSubscriptionStatus, invokeOnError]);
293
+ }, [buildConnectionConfig, refreshSubscriptionStatus, invokeOnError]);
294
+ // Manual reconnect method for when the initial auto-connect fails.
295
+ // Re-runs initConnection and updates the connected state.
296
+ // Re-registers event listeners if they were cleaned up during a previous failure.
297
+ const reconnect = useCallback(async () => {
298
+ const config = buildConnectionConfig();
299
+ try {
300
+ const result = await initConnection(config);
301
+ setConnected(result);
302
+ if (result) {
303
+ // Re-register listeners if they were cleaned up during a previous failure
304
+ if (!subscriptionsRef.current.purchaseUpdate) {
305
+ subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(async (purchase) => {
306
+ await refreshSubscriptionStatus(purchase.productId);
307
+ if (optionsRef.current?.onPurchaseSuccess) {
308
+ optionsRef.current.onPurchaseSuccess(purchase);
309
+ }
310
+ });
311
+ }
312
+ if (Platform.OS === 'ios' &&
313
+ !subscriptionsRef.current.promotedProductIOS) {
314
+ subscriptionsRef.current.promotedProductIOS =
315
+ promotedProductListenerIOS((product) => {
316
+ setPromotedProductIOS(product);
317
+ if (optionsRef.current?.onPromotedProductIOS) {
318
+ optionsRef.current.onPromotedProductIOS(product);
319
+ }
320
+ });
321
+ }
322
+ }
323
+ return result;
324
+ }
325
+ catch (error) {
326
+ ExpoIapConsole.error('[useIAP] reconnect failed:', error);
327
+ invokeOnError(error);
328
+ return false;
329
+ }
330
+ }, [buildConnectionConfig, refreshSubscriptionStatus, invokeOnError]);
283
331
  useEffect(() => {
284
332
  initIapWithSubscriptions();
285
333
  const currentSubscriptions = subscriptionsRef.current;
@@ -311,6 +359,8 @@ export function useIAP(options) {
311
359
  requestPurchaseOnPromotedProductIOS,
312
360
  getActiveSubscriptions: getActiveSubscriptionsInternal,
313
361
  hasActiveSubscriptions: hasActiveSubscriptionsInternal,
362
+ // Reconnect method for manual retry
363
+ reconnect,
314
364
  // Alternative billing methods (Android only)
315
365
  checkAlternativeBillingAvailabilityAndroid,
316
366
  showAlternativeBillingDialogAndroid,
@@ -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 finishTransaction as finishTransactionInternal,\n requestPurchase as requestPurchaseInternal,\n fetchProducts,\n validateReceipt as validateReceiptInternal,\n verifyPurchase as verifyPurchaseInternal,\n verifyPurchaseWithProvider as verifyPurchaseWithProviderInternal,\n getActiveSubscriptions,\n hasActiveSubscriptions,\n type ActiveSubscription,\n type ProductTypeInput,\n} from './index';\nimport {ExpoIapConsole} from './utils/debug';\nimport {\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n syncIOS,\n} from './modules/ios';\nimport {\n checkAlternativeBillingAvailabilityAndroid,\n showAlternativeBillingDialogAndroid,\n createAlternativeBillingTokenAndroid,\n} from './modules/android';\n\n// Types\nimport type {\n Product,\n ProductSubscription,\n ProductQueryType,\n ProductRequest,\n Purchase,\n MutationRequestPurchaseArgs,\n PurchaseInput,\n VerifyPurchaseProps,\n VerifyPurchaseResult,\n VerifyPurchaseWithProviderProps,\n VerifyPurchaseWithProviderResult,\n ProductAndroid,\n ProductSubscriptionIOS,\n} from './types';\nimport {ErrorCode} from './types';\nimport type {PurchaseError} from './utils/errorMapping';\nimport {\n getUserFriendlyErrorMessage,\n isUserCancelledError,\n isRecoverableError,\n} from './utils/errorMapping';\n\ntype UseIap = {\n connected: boolean;\n products: Product[];\n subscriptions: ProductSubscription[];\n availablePurchases: Purchase[];\n promotedProductIOS?: Product;\n activeSubscriptions: ActiveSubscription[];\n finishTransaction: ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }) => Promise<void>;\n getAvailablePurchases: () => Promise<void>;\n fetchProducts: (params: {\n skus: string[];\n type?: ProductTypeInput;\n }) => Promise<void>;\n\n requestPurchase: (\n params: MutationRequestPurchaseArgs,\n ) => ReturnType<typeof requestPurchaseInternal>;\n /** @deprecated Use verifyPurchase instead */\n validateReceipt: (\n props: VerifyPurchaseProps,\n ) => Promise<VerifyPurchaseResult>;\n verifyPurchase: (props: VerifyPurchaseProps) => Promise<VerifyPurchaseResult>;\n verifyPurchaseWithProvider: (\n props: VerifyPurchaseWithProviderProps,\n ) => Promise<VerifyPurchaseWithProviderResult>;\n restorePurchases: () => Promise<void>;\n getPromotedProductIOS: () => Promise<Product | null>;\n /**\n * @deprecated Use promotedProductListenerIOS to receive the productId,\n * then call requestPurchase with that SKU instead.\n */\n requestPurchaseOnPromotedProductIOS: () => Promise<boolean>;\n getActiveSubscriptions: (subscriptionIds?: string[]) => Promise<void>;\n hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise<boolean>;\n checkAlternativeBillingAvailabilityAndroid: () => Promise<boolean>;\n showAlternativeBillingDialogAndroid: () => Promise<boolean>;\n createAlternativeBillingTokenAndroid: (\n sku?: string,\n ) => Promise<string | null>;\n};\n\nexport interface UseIAPOptions {\n onPurchaseSuccess?: (purchase: Purchase) => void;\n onPurchaseError?: (error: PurchaseError) => void;\n /**\n * Callback for general errors from hook methods like fetchProducts,\n * getAvailablePurchases, getActiveSubscriptions, restorePurchases, etc.\n * These are Promise-based operations that can fail due to network issues\n * or store unavailability.\n */\n onError?: (error: Error) => void;\n onPromotedProductIOS?: (product: Product) => void;\n /**\n * Alternative billing mode for Android\n * If not specified, defaults to NONE (standard Google Play billing)\n * @deprecated Use enableBillingProgramAndroid instead.\n * - 'user-choice' → 'user-choice-billing'\n * - 'alternative-only' → 'external-offer'\n */\n alternativeBillingModeAndroid?: 'none' | 'user-choice' | 'alternative-only';\n /**\n * Enable a specific billing program for Android (8.2.0+)\n * When set, enables the specified billing program for external transactions.\n * Use 'external-payments' for Developer Provided Billing (Japan only, 8.3.0+).\n * Use 'user-choice-billing' for User Choice Billing (7.0+).\n */\n enableBillingProgramAndroid?:\n | 'unspecified'\n | 'external-content-link'\n | 'external-offer'\n | 'external-payments'\n | 'user-choice-billing';\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 [subscriptions, setSubscriptions] = useState<ProductSubscription[]>([]);\n\n const [availablePurchases, setAvailablePurchases] = useState<Purchase[]>([]);\n const [promotedProductIOS, setPromotedProductIOS] = useState<Product>();\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 promotedProductIOS?: EventSubscription;\n }>({});\n\n const subscriptionsRefState = useRef<ProductSubscription[]>([]);\n\n useEffect(() => {\n subscriptionsRefState.current = subscriptions;\n }, [subscriptions]);\n\n const normalizeProductQueryType = useCallback(\n (type?: ProductTypeInput): ProductQueryType => {\n if (!type || type === 'inapp' || type === 'in-app') {\n return 'in-app';\n }\n return type;\n },\n [],\n );\n\n const canonicalProductType = useCallback(\n (value?: string): ProductQueryType => {\n if (!value) {\n return 'in-app';\n }\n\n const normalized = value.trim().toLowerCase().replace(/[_-]/g, '');\n return normalized === 'subs' ? 'subs' : 'in-app';\n },\n [],\n );\n\n const toPurchaseInput = useCallback(\n (purchase: Purchase): PurchaseInput => ({\n id: purchase.id,\n ids: purchase.ids ?? undefined,\n isAutoRenewing: purchase.isAutoRenewing,\n platform: purchase.platform,\n productId: purchase.productId,\n purchaseState: purchase.purchaseState,\n purchaseToken: purchase.purchaseToken ?? null,\n quantity: purchase.quantity,\n store: purchase.store,\n transactionDate: purchase.transactionDate,\n transactionId: purchase.transactionId,\n }),\n [],\n );\n\n // Helper function to invoke onError callback\n const invokeOnError = useCallback((error: unknown) => {\n if (optionsRef.current?.onError) {\n optionsRef.current.onError(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }, []);\n\n const fetchProductsInternal = useCallback(\n async (params: {\n skus: string[];\n type?: ProductTypeInput;\n }): Promise<void> => {\n try {\n const queryType = normalizeProductQueryType(params.type);\n const request: ProductRequest = {skus: params.skus, type: queryType};\n const result = await fetchProducts(request);\n const items = (result ?? []) as (Product | ProductSubscription)[];\n\n ExpoIapConsole.debug('Fetched products:', items);\n\n if (queryType === 'subs') {\n const subscriptionsResult = items as ProductSubscription[];\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n subscriptionsResult,\n (subscription) => subscription.id,\n ),\n );\n } else if (queryType === 'in-app') {\n const productsResult = items as Product[];\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n productsResult,\n (product) => product.id,\n ),\n );\n } else {\n // For 'all' type, need to properly distinguish between products and subscriptions\n // On Android, check subscriptionOfferDetailsAndroid to determine if it's a real subscription\n const productItems = items.filter((item) => {\n // iOS: check type\n if (Platform.OS === 'ios') {\n return canonicalProductType(item.type as string) === 'in-app';\n }\n // Android: check if it has actual subscription details\n const androidItem = item as ProductAndroid;\n return (\n !androidItem.subscriptionOfferDetailsAndroid ||\n (Array.isArray(androidItem.subscriptionOfferDetailsAndroid) &&\n androidItem.subscriptionOfferDetailsAndroid.length === 0)\n );\n }) as Product[];\n\n const subscriptionItems = items.filter((item) => {\n // iOS: check type\n if (Platform.OS === 'ios') {\n return (\n canonicalProductType(\n item.type as ProductSubscriptionIOS['type'],\n ) === 'subs'\n );\n }\n // Android: check if it has actual subscription details\n const androidItem = item as ProductAndroid;\n\n return (\n androidItem.subscriptionOfferDetailsAndroid &&\n Array.isArray(androidItem.subscriptionOfferDetailsAndroid) &&\n androidItem.subscriptionOfferDetailsAndroid.length > 0\n );\n }) as ProductSubscription[];\n\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n productItems,\n (product) => product.id,\n ),\n );\n\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n subscriptionItems,\n (subscription) => subscription.id,\n ),\n );\n }\n } catch (error) {\n ExpoIapConsole.error('Error fetching products:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [\n canonicalProductType,\n invokeOnError,\n mergeWithDuplicateCheck,\n normalizeProductQueryType,\n ],\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 ExpoIapConsole.error('Error fetching available purchases:', error);\n invokeOnError(error);\n throw error;\n }\n }, [invokeOnError]);\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 ExpoIapConsole.error('Error getting active subscriptions:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [invokeOnError],\n );\n\n const hasActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<boolean> => {\n try {\n return await hasActiveSubscriptions(subscriptionIds);\n } catch (error) {\n ExpoIapConsole.error('Error checking active subscriptions:', error);\n return false;\n }\n },\n [],\n );\n\n const finishTransaction = useCallback(\n async ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }): Promise<void> => {\n await finishTransactionInternal({\n purchase: toPurchaseInput(purchase),\n isConsumable,\n });\n },\n [toPurchaseInput],\n );\n\n const requestPurchaseWithReset = useCallback(\n (requestObj: MutationRequestPurchaseArgs) => {\n return requestPurchaseInternal(requestObj);\n },\n [],\n );\n\n const refreshSubscriptionStatus = useCallback(\n async (productId: string) => {\n try {\n if (subscriptionsRefState.current.some((sub) => sub.id === productId)) {\n await fetchProductsInternal({skus: [productId], type: 'subs'});\n await getAvailablePurchasesInternal();\n }\n } catch (error) {\n ExpoIapConsole.warn('Failed to refresh subscription status:', error);\n }\n },\n [fetchProductsInternal, getAvailablePurchasesInternal],\n );\n\n // Restore completed transactions with cross-platform behavior.\n // iOS: best-effort sync (ignore sync errors) then fetch available purchases.\n // Android: fetch available purchases directly.\n const restorePurchasesInternal = useCallback(async (): Promise<void> => {\n try {\n // iOS: Try to sync first, but don't fail if sync errors occur\n if (Platform.OS === 'ios') {\n await syncIOS().catch(() => undefined); // syncIOS returns Promise<boolean>, we don't need the result\n }\n\n const purchases = await getAvailablePurchases({\n alsoPublishToEventListenerIOS: false,\n onlyIncludeActiveItemsIOS: true,\n });\n setAvailablePurchases(purchases);\n } catch (error) {\n ExpoIapConsole.warn('Failed to restore purchases:', error);\n invokeOnError(error);\n throw error;\n }\n }, [invokeOnError]);\n\n const validateReceipt = useCallback(async (props: VerifyPurchaseProps) => {\n return validateReceiptInternal(props);\n }, []);\n\n const verifyPurchase = useCallback(async (props: VerifyPurchaseProps) => {\n return verifyPurchaseInternal(props);\n }, []);\n\n const verifyPurchaseWithProvider = useCallback(\n async (props: VerifyPurchaseWithProviderProps) => {\n return verifyPurchaseWithProviderInternal(props);\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 // Register purchase update listener BEFORE initConnection to avoid race conditions.\n subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(\n async (purchase: Purchase) => {\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 (!connectedRef.current && error.code === ErrorCode.InitConnection) {\n return; // Ignore initialization error before connected\n }\n const friendly = getUserFriendlyErrorMessage(error);\n if (!isUserCancelledError(error) && !isRecoverableError(error)) {\n ExpoIapConsole.warn('[useIAP] Purchase error:', friendly);\n }\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.promotedProductIOS = promotedProductListenerIOS(\n (product: Product) => {\n setPromotedProductIOS(product);\n\n if (optionsRef.current?.onPromotedProductIOS) {\n optionsRef.current.onPromotedProductIOS(product);\n }\n },\n );\n }\n\n // NOW call initConnection after listeners are ready\n // Build config from options (prefer new enableBillingProgramAndroid over deprecated alternativeBillingModeAndroid)\n const config =\n optionsRef.current?.enableBillingProgramAndroid ||\n optionsRef.current?.alternativeBillingModeAndroid\n ? {\n enableBillingProgramAndroid:\n optionsRef.current.enableBillingProgramAndroid,\n alternativeBillingModeAndroid:\n optionsRef.current.alternativeBillingModeAndroid,\n }\n : undefined;\n\n try {\n const result = await initConnection(config);\n setConnected(result);\n if (!result) {\n // If connection failed, clean up listeners\n ExpoIapConsole.warn(\n '[useIAP] Connection failed, cleaning up listeners...',\n );\n subscriptionsRef.current.purchaseUpdate?.remove();\n subscriptionsRef.current.promotedProductIOS?.remove();\n subscriptionsRef.current.purchaseUpdate = undefined;\n subscriptionsRef.current.promotedProductIOS = undefined;\n // Keep purchaseError listener registered to capture subsequent retries\n }\n } catch (error) {\n ExpoIapConsole.error('initConnection failed:', error);\n invokeOnError(error);\n // Clean up listeners on error\n subscriptionsRef.current.purchaseUpdate?.remove();\n subscriptionsRef.current.promotedProductIOS?.remove();\n subscriptionsRef.current.purchaseUpdate = undefined;\n subscriptionsRef.current.promotedProductIOS = undefined;\n }\n }, [refreshSubscriptionStatus, invokeOnError]);\n\n useEffect(() => {\n initIapWithSubscriptions();\n const currentSubscriptions = subscriptionsRef.current;\n\n return () => {\n currentSubscriptions.purchaseUpdate?.remove();\n currentSubscriptions.purchaseError?.remove();\n currentSubscriptions.promotedProductIOS?.remove();\n endConnection();\n setConnected(false);\n };\n }, [initIapWithSubscriptions]);\n\n return {\n connected,\n products,\n subscriptions,\n finishTransaction,\n availablePurchases,\n promotedProductIOS,\n activeSubscriptions,\n getAvailablePurchases: getAvailablePurchasesInternal,\n fetchProducts: fetchProductsInternal,\n requestPurchase: requestPurchaseWithReset,\n validateReceipt,\n verifyPurchase,\n verifyPurchaseWithProvider,\n restorePurchases: restorePurchasesInternal,\n // internal getters kept for hook state management\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n getActiveSubscriptions: getActiveSubscriptionsInternal,\n hasActiveSubscriptions: hasActiveSubscriptionsInternal,\n // Alternative billing methods (Android only)\n checkAlternativeBillingAvailabilityAndroid,\n showAlternativeBillingDialogAndroid,\n createAlternativeBillingTokenAndroid,\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 verifyPurchase as verifyPurchaseInternal,\n verifyPurchaseWithProvider as verifyPurchaseWithProviderInternal,\n getActiveSubscriptions,\n hasActiveSubscriptions,\n type ActiveSubscription,\n type ProductTypeInput,\n} from './index';\nimport {ExpoIapConsole} from './utils/debug';\nimport {\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n syncIOS,\n} from './modules/ios';\nimport {\n checkAlternativeBillingAvailabilityAndroid,\n showAlternativeBillingDialogAndroid,\n createAlternativeBillingTokenAndroid,\n} from './modules/android';\n\n// Types\nimport type {\n Product,\n ProductSubscription,\n ProductQueryType,\n ProductRequest,\n Purchase,\n MutationRequestPurchaseArgs,\n PurchaseInput,\n VerifyPurchaseProps,\n VerifyPurchaseResult,\n VerifyPurchaseWithProviderProps,\n VerifyPurchaseWithProviderResult,\n ProductAndroid,\n ProductSubscriptionIOS,\n PurchaseOptions,\n} from './types';\nimport {ErrorCode} from './types';\nimport type {PurchaseError} from './utils/errorMapping';\nimport {\n getUserFriendlyErrorMessage,\n isUserCancelledError,\n isRecoverableError,\n} from './utils/errorMapping';\n\ntype UseIap = {\n connected: boolean;\n products: Product[];\n subscriptions: ProductSubscription[];\n availablePurchases: Purchase[];\n promotedProductIOS?: Product;\n activeSubscriptions: ActiveSubscription[];\n finishTransaction: ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }) => Promise<void>;\n getAvailablePurchases: (options?: PurchaseOptions) => Promise<void>;\n fetchProducts: (params: {\n skus: string[];\n type?: ProductTypeInput;\n }) => Promise<void>;\n\n requestPurchase: (\n params: MutationRequestPurchaseArgs,\n ) => ReturnType<typeof requestPurchaseInternal>;\n /** @deprecated Use verifyPurchase instead */\n validateReceipt: (\n props: VerifyPurchaseProps,\n ) => Promise<VerifyPurchaseResult>;\n verifyPurchase: (props: VerifyPurchaseProps) => Promise<VerifyPurchaseResult>;\n verifyPurchaseWithProvider: (\n props: VerifyPurchaseWithProviderProps,\n ) => Promise<VerifyPurchaseWithProviderResult>;\n restorePurchases: (options?: PurchaseOptions) => Promise<void>;\n getPromotedProductIOS: () => Promise<Product | null>;\n /**\n * @deprecated Use promotedProductListenerIOS to receive the productId,\n * then call requestPurchase with that SKU instead.\n */\n requestPurchaseOnPromotedProductIOS: () => Promise<boolean>;\n getActiveSubscriptions: (subscriptionIds?: string[]) => Promise<void>;\n hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise<boolean>;\n /**\n * Manually retry the store connection.\n * Useful when the initial auto-connect fails (e.g., Play Store not ready at mount time).\n * Updates the `connected` state on success.\n */\n reconnect: () => Promise<boolean>;\n checkAlternativeBillingAvailabilityAndroid: () => Promise<boolean>;\n showAlternativeBillingDialogAndroid: () => Promise<boolean>;\n createAlternativeBillingTokenAndroid: (\n sku?: string,\n ) => Promise<string | null>;\n};\n\nexport interface UseIAPOptions {\n onPurchaseSuccess?: (purchase: Purchase) => void;\n onPurchaseError?: (error: PurchaseError) => void;\n /**\n * Callback for general errors from hook methods like fetchProducts,\n * getAvailablePurchases, getActiveSubscriptions, restorePurchases, etc.\n * These are Promise-based operations that can fail due to network issues\n * or store unavailability.\n */\n onError?: (error: Error) => void;\n onPromotedProductIOS?: (product: Product) => void;\n /**\n * Alternative billing mode for Android\n * If not specified, defaults to NONE (standard Google Play billing)\n * @deprecated Use enableBillingProgramAndroid instead.\n * - 'user-choice' → 'user-choice-billing'\n * - 'alternative-only' → 'external-offer'\n */\n alternativeBillingModeAndroid?: 'none' | 'user-choice' | 'alternative-only';\n /**\n * Enable a specific billing program for Android (8.2.0+)\n * When set, enables the specified billing program for external transactions.\n * Use 'external-payments' for Developer Provided Billing (Japan only, 8.3.0+).\n * Use 'user-choice-billing' for User Choice Billing (7.0+).\n */\n enableBillingProgramAndroid?:\n | 'unspecified'\n | 'external-content-link'\n | 'external-offer'\n | 'external-payments'\n | 'user-choice-billing';\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 [subscriptions, setSubscriptions] = useState<ProductSubscription[]>([]);\n\n const [availablePurchases, setAvailablePurchases] = useState<Purchase[]>([]);\n const [promotedProductIOS, setPromotedProductIOS] = useState<Product>();\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 promotedProductIOS?: EventSubscription;\n }>({});\n\n const subscriptionsRefState = useRef<ProductSubscription[]>([]);\n\n useEffect(() => {\n subscriptionsRefState.current = subscriptions;\n }, [subscriptions]);\n\n const normalizeProductQueryType = useCallback(\n (type?: ProductTypeInput): ProductQueryType => {\n if (!type || type === 'inapp' || type === 'in-app') {\n return 'in-app';\n }\n return type;\n },\n [],\n );\n\n const canonicalProductType = useCallback(\n (value?: string): ProductQueryType => {\n if (!value) {\n return 'in-app';\n }\n\n const normalized = value.trim().toLowerCase().replace(/[_-]/g, '');\n return normalized === 'subs' ? 'subs' : 'in-app';\n },\n [],\n );\n\n const toPurchaseInput = useCallback(\n (purchase: Purchase): PurchaseInput => ({\n id: purchase.id,\n ids: purchase.ids ?? undefined,\n isAutoRenewing: purchase.isAutoRenewing,\n platform: purchase.platform,\n productId: purchase.productId,\n purchaseState: purchase.purchaseState,\n purchaseToken: purchase.purchaseToken ?? null,\n quantity: purchase.quantity,\n store: purchase.store,\n transactionDate: purchase.transactionDate,\n transactionId: purchase.transactionId,\n }),\n [],\n );\n\n // Helper function to invoke onError callback\n const invokeOnError = useCallback((error: unknown) => {\n if (optionsRef.current?.onError) {\n optionsRef.current.onError(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }, []);\n\n const fetchProductsInternal = useCallback(\n async (params: {\n skus: string[];\n type?: ProductTypeInput;\n }): Promise<void> => {\n try {\n const queryType = normalizeProductQueryType(params.type);\n const request: ProductRequest = {skus: params.skus, type: queryType};\n const result = await fetchProducts(request);\n const items = (result ?? []) as (Product | ProductSubscription)[];\n\n ExpoIapConsole.debug('Fetched products:', items);\n\n if (queryType === 'subs') {\n const subscriptionsResult = items as ProductSubscription[];\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n subscriptionsResult,\n (subscription) => subscription.id,\n ),\n );\n } else if (queryType === 'in-app') {\n const productsResult = items as Product[];\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n productsResult,\n (product) => product.id,\n ),\n );\n } else {\n // For 'all' type, need to properly distinguish between products and subscriptions\n // On Android, check subscriptionOfferDetailsAndroid to determine if it's a real subscription\n const productItems = items.filter((item) => {\n // iOS: check type\n if (Platform.OS === 'ios') {\n return canonicalProductType(item.type as string) === 'in-app';\n }\n // Android: check if it has actual subscription details\n const androidItem = item as ProductAndroid;\n return (\n !androidItem.subscriptionOfferDetailsAndroid ||\n (Array.isArray(androidItem.subscriptionOfferDetailsAndroid) &&\n androidItem.subscriptionOfferDetailsAndroid.length === 0)\n );\n }) as Product[];\n\n const subscriptionItems = items.filter((item) => {\n // iOS: check type\n if (Platform.OS === 'ios') {\n return (\n canonicalProductType(\n item.type as ProductSubscriptionIOS['type'],\n ) === 'subs'\n );\n }\n // Android: check if it has actual subscription details\n const androidItem = item as ProductAndroid;\n\n return (\n androidItem.subscriptionOfferDetailsAndroid &&\n Array.isArray(androidItem.subscriptionOfferDetailsAndroid) &&\n androidItem.subscriptionOfferDetailsAndroid.length > 0\n );\n }) as ProductSubscription[];\n\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n productItems,\n (product) => product.id,\n ),\n );\n\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n subscriptionItems,\n (subscription) => subscription.id,\n ),\n );\n }\n } catch (error) {\n ExpoIapConsole.error('Error fetching products:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [\n canonicalProductType,\n invokeOnError,\n mergeWithDuplicateCheck,\n normalizeProductQueryType,\n ],\n );\n\n const getAvailablePurchasesInternal = useCallback(\n async (options?: PurchaseOptions): Promise<void> => {\n try {\n const result = await getAvailablePurchases({\n alsoPublishToEventListenerIOS:\n options?.alsoPublishToEventListenerIOS ?? false,\n onlyIncludeActiveItemsIOS: options?.onlyIncludeActiveItemsIOS ?? true,\n includeSuspendedAndroid: options?.includeSuspendedAndroid ?? false,\n });\n setAvailablePurchases(result);\n } catch (error) {\n ExpoIapConsole.error('Error fetching available purchases:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [invokeOnError],\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 ExpoIapConsole.error('Error getting active subscriptions:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [invokeOnError],\n );\n\n const hasActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<boolean> => {\n try {\n return await hasActiveSubscriptions(subscriptionIds);\n } catch (error) {\n ExpoIapConsole.error('Error checking active subscriptions:', error);\n return false;\n }\n },\n [],\n );\n\n const finishTransaction = useCallback(\n async ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }): Promise<void> => {\n await finishTransactionInternal({\n purchase: toPurchaseInput(purchase),\n isConsumable,\n });\n },\n [toPurchaseInput],\n );\n\n const requestPurchaseWithReset = useCallback(\n (requestObj: MutationRequestPurchaseArgs) => {\n return requestPurchaseInternal(requestObj);\n },\n [],\n );\n\n const refreshSubscriptionStatus = useCallback(\n async (productId: string) => {\n try {\n if (subscriptionsRefState.current.some((sub) => sub.id === productId)) {\n await fetchProductsInternal({skus: [productId], type: 'subs'});\n await getAvailablePurchasesInternal();\n await getActiveSubscriptionsInternal();\n }\n } catch (error) {\n ExpoIapConsole.warn('Failed to refresh subscription status:', error);\n }\n },\n [\n fetchProductsInternal,\n getAvailablePurchasesInternal,\n getActiveSubscriptionsInternal,\n ],\n );\n\n // Restore completed transactions with cross-platform behavior.\n // iOS: best-effort sync (ignore sync errors) then fetch available purchases.\n // Android: fetch available purchases directly.\n const restorePurchasesInternal = useCallback(\n async (options?: PurchaseOptions): Promise<void> => {\n try {\n // iOS: Try to sync first, but don't fail if sync errors occur\n if (Platform.OS === 'ios') {\n await syncIOS().catch(() => undefined); // syncIOS returns Promise<boolean>, we don't need the result\n }\n\n const purchases = await getAvailablePurchases({\n alsoPublishToEventListenerIOS:\n options?.alsoPublishToEventListenerIOS ?? false,\n onlyIncludeActiveItemsIOS: options?.onlyIncludeActiveItemsIOS ?? true,\n includeSuspendedAndroid: options?.includeSuspendedAndroid ?? false,\n });\n setAvailablePurchases(purchases);\n } catch (error) {\n ExpoIapConsole.warn('Failed to restore purchases:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [invokeOnError],\n );\n\n const validateReceipt = useCallback(async (props: VerifyPurchaseProps) => {\n return validateReceiptInternal(props);\n }, []);\n\n const verifyPurchase = useCallback(async (props: VerifyPurchaseProps) => {\n return verifyPurchaseInternal(props);\n }, []);\n\n const verifyPurchaseWithProvider = useCallback(\n async (props: VerifyPurchaseWithProviderProps) => {\n return verifyPurchaseWithProviderInternal(props);\n },\n [],\n );\n\n // Build config from options (prefer new enableBillingProgramAndroid over deprecated alternativeBillingModeAndroid)\n const buildConnectionConfig = useCallback(() => {\n return optionsRef.current?.enableBillingProgramAndroid ||\n optionsRef.current?.alternativeBillingModeAndroid\n ? {\n enableBillingProgramAndroid:\n optionsRef.current.enableBillingProgramAndroid,\n alternativeBillingModeAndroid:\n optionsRef.current.alternativeBillingModeAndroid,\n }\n : undefined;\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 // Register purchase update listener BEFORE initConnection to avoid race conditions.\n subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(\n async (purchase: Purchase) => {\n // Refresh subscription status for both iOS and Android subscription purchases.\n // refreshSubscriptionStatus internally checks whether the product is a known\n // subscription, so it is safe to call unconditionally for any purchase event.\n await refreshSubscriptionStatus(purchase.productId);\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 (!connectedRef.current && error.code === ErrorCode.InitConnection) {\n return; // Ignore initialization error before connected\n }\n const friendly = getUserFriendlyErrorMessage(error);\n if (!isUserCancelledError(error) && !isRecoverableError(error)) {\n ExpoIapConsole.warn('[useIAP] Purchase error:', friendly);\n }\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.promotedProductIOS = promotedProductListenerIOS(\n (product: Product) => {\n setPromotedProductIOS(product);\n\n if (optionsRef.current?.onPromotedProductIOS) {\n optionsRef.current.onPromotedProductIOS(product);\n }\n },\n );\n }\n\n // NOW call initConnection after listeners are ready\n const config = buildConnectionConfig();\n\n try {\n const result = await initConnection(config);\n setConnected(result);\n if (!result) {\n // If connection failed, clean up listeners\n ExpoIapConsole.warn(\n '[useIAP] Connection failed, cleaning up listeners...',\n );\n subscriptionsRef.current.purchaseUpdate?.remove();\n subscriptionsRef.current.promotedProductIOS?.remove();\n subscriptionsRef.current.purchaseUpdate = undefined;\n subscriptionsRef.current.promotedProductIOS = undefined;\n // Keep purchaseError listener registered to capture subsequent retries\n }\n } catch (error) {\n ExpoIapConsole.error('initConnection failed:', error);\n invokeOnError(error);\n // Clean up listeners on error\n subscriptionsRef.current.purchaseUpdate?.remove();\n subscriptionsRef.current.promotedProductIOS?.remove();\n subscriptionsRef.current.purchaseUpdate = undefined;\n subscriptionsRef.current.promotedProductIOS = undefined;\n }\n }, [buildConnectionConfig, refreshSubscriptionStatus, invokeOnError]);\n\n // Manual reconnect method for when the initial auto-connect fails.\n // Re-runs initConnection and updates the connected state.\n // Re-registers event listeners if they were cleaned up during a previous failure.\n const reconnect = useCallback(async (): Promise<boolean> => {\n const config = buildConnectionConfig();\n\n try {\n const result = await initConnection(config);\n setConnected(result);\n\n if (result) {\n // Re-register listeners if they were cleaned up during a previous failure\n if (!subscriptionsRef.current.purchaseUpdate) {\n subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(\n async (purchase: Purchase) => {\n await refreshSubscriptionStatus(purchase.productId);\n\n if (optionsRef.current?.onPurchaseSuccess) {\n optionsRef.current.onPurchaseSuccess(purchase);\n }\n },\n );\n }\n\n if (\n Platform.OS === 'ios' &&\n !subscriptionsRef.current.promotedProductIOS\n ) {\n subscriptionsRef.current.promotedProductIOS =\n promotedProductListenerIOS((product: Product) => {\n setPromotedProductIOS(product);\n\n if (optionsRef.current?.onPromotedProductIOS) {\n optionsRef.current.onPromotedProductIOS(product);\n }\n });\n }\n }\n\n return result;\n } catch (error) {\n ExpoIapConsole.error('[useIAP] reconnect failed:', error);\n invokeOnError(error);\n return false;\n }\n }, [buildConnectionConfig, refreshSubscriptionStatus, invokeOnError]);\n\n useEffect(() => {\n initIapWithSubscriptions();\n const currentSubscriptions = subscriptionsRef.current;\n\n return () => {\n currentSubscriptions.purchaseUpdate?.remove();\n currentSubscriptions.purchaseError?.remove();\n currentSubscriptions.promotedProductIOS?.remove();\n endConnection();\n setConnected(false);\n };\n }, [initIapWithSubscriptions]);\n\n return {\n connected,\n products,\n subscriptions,\n finishTransaction,\n availablePurchases,\n promotedProductIOS,\n activeSubscriptions,\n getAvailablePurchases: getAvailablePurchasesInternal,\n fetchProducts: fetchProductsInternal,\n requestPurchase: requestPurchaseWithReset,\n validateReceipt,\n verifyPurchase,\n verifyPurchaseWithProvider,\n restorePurchases: restorePurchasesInternal,\n // internal getters kept for hook state management\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n getActiveSubscriptions: getActiveSubscriptionsInternal,\n hasActiveSubscriptions: hasActiveSubscriptionsInternal,\n // Reconnect method for manual retry\n reconnect,\n // Alternative billing methods (Android only)\n checkAlternativeBillingAvailabilityAndroid,\n showAlternativeBillingDialogAndroid,\n createAlternativeBillingTokenAndroid,\n };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
- <coverage generated="1774373402019" clover="3.2.0">
3
- <project timestamp="1774373402019" name="All files">
2
+ <coverage generated="1774548212878" clover="3.2.0">
3
+ <project timestamp="1774548212878" name="All files">
4
4
  <metrics statements="528" coveredstatements="493" conditionals="274" coveredconditionals="241" methods="116" coveredmethods="92" elements="918" coveredelements="826" complexity="0" loc="528" ncloc="528" packages="4" files="7" classes="7"/>
5
5
  <package name="src">
6
6
  <metrics statements="224" coveredstatements="216" conditionals="118" coveredconditionals="109" methods="48" coveredmethods="37"/>