expo-iap 3.0.7 → 3.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -17,25 +17,32 @@ import {
17
17
  } from './modules/android';
18
18
 
19
19
  // Types
20
- import {
20
+ import type {
21
+ AndroidSubscriptionOfferInput,
22
+ DeepLinkOptions,
23
+ FetchProductsResult,
24
+ MutationField,
25
+ MutationValidateReceiptArgs,
21
26
  Product,
27
+ ProductAndroid,
28
+ ProductIOS,
29
+ ProductQueryType,
30
+ ProductSubscription,
22
31
  Purchase,
23
- ErrorCode,
24
- RequestPurchaseProps,
32
+ PurchaseInput,
33
+ PurchaseOptions,
34
+ QueryField,
25
35
  RequestPurchasePropsByPlatforms,
26
36
  RequestPurchaseAndroidProps,
27
37
  RequestPurchaseIosProps,
28
38
  RequestSubscriptionPropsByPlatforms,
29
39
  RequestSubscriptionAndroidProps,
30
40
  RequestSubscriptionIosProps,
31
- ProductSubscription,
32
- PurchaseAndroid,
33
41
  DiscountOfferInputIOS,
34
- VoidResult,
35
- ReceiptValidationResult,
36
- AndroidSubscriptionOfferInput,
37
42
  } from './types';
43
+ import {ErrorCode} from './types';
38
44
  import {PurchaseError} from './purchase-error';
45
+ import {normalizePurchaseId, normalizePurchaseList} from './utils/purchase';
39
46
 
40
47
  // Export all types
41
48
  export * from './types';
@@ -90,32 +97,7 @@ export const emitter = (ExpoIapModule ||
90
97
  /**
91
98
  * TODO(v3.1.0): Remove legacy 'inapp' alias once downstream apps migrate to 'in-app'.
92
99
  */
93
- export type ProductTypeInput = 'inapp' | 'in-app' | 'subs';
94
- export type InAppTypeInput = Exclude<ProductTypeInput, 'subs'>;
95
-
96
- type PurchaseRequestInApp = {
97
- request: RequestPurchasePropsByPlatforms;
98
- type?: InAppTypeInput;
99
- };
100
-
101
- type PurchaseRequestSubscription = {
102
- request: RequestSubscriptionPropsByPlatforms;
103
- type: 'subs';
104
- };
105
-
106
- export type PurchaseRequestInput =
107
- | PurchaseRequestInApp
108
- | PurchaseRequestSubscription;
109
-
110
- export type PurchaseRequest =
111
- | {
112
- request: RequestPurchaseProps;
113
- type?: InAppTypeInput;
114
- }
115
- | {
116
- request: RequestSubscriptionPropsByPlatforms;
117
- type: 'subs';
118
- };
100
+ export type ProductTypeInput = ProductQueryType | 'inapp';
119
101
 
120
102
  const normalizeProductType = (type?: ProductTypeInput) => {
121
103
  if (type === 'inapp') {
@@ -126,16 +108,22 @@ const normalizeProductType = (type?: ProductTypeInput) => {
126
108
 
127
109
  if (!type || type === 'inapp' || type === 'in-app') {
128
110
  return {
129
- canonical: 'in-app' as const,
111
+ canonical: 'in-app' as ProductQueryType,
130
112
  native: 'inapp' as const,
131
113
  };
132
114
  }
133
115
  if (type === 'subs') {
134
116
  return {
135
- canonical: 'subs' as const,
117
+ canonical: 'subs' as ProductQueryType,
136
118
  native: 'subs' as const,
137
119
  };
138
120
  }
121
+ if (type === 'all') {
122
+ return {
123
+ canonical: 'all' as ProductQueryType,
124
+ native: 'all' as const,
125
+ };
126
+ }
139
127
  throw new Error(`Unsupported product type: ${type}`);
140
128
  };
141
129
 
@@ -144,8 +132,9 @@ export const purchaseUpdatedListener = (
144
132
  ) => {
145
133
  console.log('[JS] Registering purchaseUpdatedListener');
146
134
  const wrappedListener = (event: Purchase) => {
147
- console.log('[JS] purchaseUpdatedListener fired:', event);
148
- listener(event);
135
+ const normalized = normalizePurchaseId(event);
136
+ console.log('[JS] purchaseUpdatedListener fired:', normalized);
137
+ listener(normalized);
149
138
  };
150
139
  const emitterSubscription = emitter.addListener(
151
140
  OpenIapEvent.PurchaseUpdated,
@@ -203,112 +192,103 @@ export const promotedProductListenerIOS = (
203
192
  return emitter.addListener(OpenIapEvent.PromotedProductIOS, listener);
204
193
  };
205
194
 
206
- export function initConnection(): Promise<boolean> {
207
- const result = ExpoIapModule.initConnection();
208
- return Promise.resolve(result);
209
- }
195
+ export const initConnection: MutationField<'initConnection'> = async () =>
196
+ ExpoIapModule.initConnection();
210
197
 
211
- export async function endConnection(): Promise<boolean> {
212
- return ExpoIapModule.endConnection();
213
- }
198
+ export const endConnection: MutationField<'endConnection'> = async () =>
199
+ ExpoIapModule.endConnection();
214
200
 
215
201
  /**
216
202
  * Fetch products with unified API (v2.7.0+)
217
203
  *
218
- * @param params - Product fetch configuration
219
- * @param params.skus - Array of product SKUs to fetch
220
- * @param params.type - Type of products: 'in-app' for regular products (default) or 'subs' for subscriptions
221
- *
222
- * @example
223
- * ```typescript
224
- * // Regular products
225
- * const products = await fetchProducts({
226
- * skus: ['product1', 'product2'],
227
- * type: 'in-app'
228
- * });
229
- *
230
- * // Subscriptions
231
- * const subscriptions = await fetchProducts({
232
- * skus: ['sub1', 'sub2'],
233
- * type: 'subs'
234
- * });
235
- * ```
204
+ * @param request - Product fetch configuration
205
+ * @param request.skus - Array of product SKUs to fetch
206
+ * @param request.type - Product query type: 'in-app', 'subs', or 'all'
236
207
  */
237
- export const fetchProducts = async ({
238
- skus,
239
- type,
240
- }: {
241
- skus: string[];
242
- type?: ProductTypeInput;
243
- }): Promise<Product[] | ProductSubscription[]> => {
244
- if (!skus?.length) {
208
+ export const fetchProducts: QueryField<'fetchProducts'> = async (request) => {
209
+ const {skus, type} = request ?? {};
210
+
211
+ if (!Array.isArray(skus) || skus.length === 0) {
245
212
  throw new PurchaseError({
246
213
  message: 'No SKUs provided',
247
214
  code: ErrorCode.EmptySkuList,
248
215
  });
249
216
  }
250
217
 
251
- const {canonical, native} = normalizeProductType(type);
252
-
253
- if (Platform.OS === 'ios') {
254
- const rawItems = await ExpoIapModule.fetchProducts({skus, type: native});
218
+ const {canonical, native} = normalizeProductType(
219
+ type as ProductTypeInput | undefined,
220
+ );
221
+ const skuSet = new Set(skus);
255
222
 
256
- const filteredItems = rawItems.filter((item: unknown) => {
223
+ const filterIosItems = (
224
+ items: unknown[],
225
+ ): Product[] | ProductSubscription[] =>
226
+ items.filter((item): item is ProductIOS | ProductSubscription => {
257
227
  if (!isProductIOS(item)) {
258
228
  return false;
259
229
  }
260
- const isValid =
261
- typeof item === 'object' &&
262
- item !== null &&
263
- 'id' in item &&
264
- typeof item.id === 'string' &&
265
- skus.includes(item.id);
266
- return isValid;
230
+ const candidate = item as ProductIOS | ProductSubscription;
231
+ return typeof candidate.id === 'string' && skuSet.has(candidate.id);
267
232
  });
268
233
 
269
- return canonical === 'in-app'
270
- ? (filteredItems as Product[])
271
- : (filteredItems as ProductSubscription[]);
234
+ const filterAndroidItems = (
235
+ items: unknown[],
236
+ ): Product[] | ProductSubscription[] =>
237
+ items.filter((item): item is ProductAndroid | ProductSubscription => {
238
+ if (!isProductAndroid(item)) {
239
+ return false;
240
+ }
241
+ const candidate = item as ProductAndroid | ProductSubscription;
242
+ return typeof candidate.id === 'string' && skuSet.has(candidate.id);
243
+ });
244
+
245
+ const castResult = (
246
+ items: Product[] | ProductSubscription[],
247
+ ): FetchProductsResult => {
248
+ if (canonical === 'in-app') {
249
+ return items as Product[];
250
+ }
251
+ if (canonical === 'subs') {
252
+ return items as ProductSubscription[];
253
+ }
254
+ return items;
255
+ };
256
+
257
+ if (Platform.OS === 'ios') {
258
+ const rawItems = await ExpoIapModule.fetchProducts({skus, type: native});
259
+ return castResult(filterIosItems(rawItems));
272
260
  }
273
261
 
274
262
  if (Platform.OS === 'android') {
275
- const items = await ExpoIapModule.fetchProducts(native, skus);
276
- const filteredItems = items.filter((item: unknown) => {
277
- if (!isProductAndroid(item)) return false;
278
- return (
279
- typeof item === 'object' &&
280
- item !== null &&
281
- 'id' in item &&
282
- typeof item.id === 'string' &&
283
- skus.includes(item.id)
284
- );
285
- });
286
-
287
- return canonical === 'in-app'
288
- ? (filteredItems as Product[])
289
- : (filteredItems as ProductSubscription[]);
263
+ const rawItems = await ExpoIapModule.fetchProducts(native, skus);
264
+ return castResult(filterAndroidItems(rawItems));
290
265
  }
291
266
 
292
267
  throw new Error('Unsupported platform');
293
268
  };
294
269
 
295
- export const getAvailablePurchases = ({
296
- alsoPublishToEventListenerIOS = false,
297
- onlyIncludeActiveItemsIOS = true,
298
- }: {
299
- alsoPublishToEventListenerIOS?: boolean;
300
- onlyIncludeActiveItemsIOS?: boolean;
301
- } = {}): Promise<Purchase[]> =>
302
- (
270
+ export const getAvailablePurchases: QueryField<
271
+ 'getAvailablePurchases'
272
+ > = async (options) => {
273
+ const normalizedOptions: PurchaseOptions = {
274
+ alsoPublishToEventListenerIOS:
275
+ options?.alsoPublishToEventListenerIOS ?? false,
276
+ onlyIncludeActiveItemsIOS: options?.onlyIncludeActiveItemsIOS ?? true,
277
+ };
278
+
279
+ const resolvePurchases: () => Promise<Purchase[]> =
303
280
  Platform.select({
304
281
  ios: () =>
305
282
  ExpoIapModule.getAvailableItems(
306
- alsoPublishToEventListenerIOS,
307
- onlyIncludeActiveItemsIOS,
308
- ),
309
- android: () => ExpoIapModule.getAvailableItems(),
310
- }) || (() => Promise.resolve([]))
311
- )();
283
+ normalizedOptions.alsoPublishToEventListenerIOS,
284
+ normalizedOptions.onlyIncludeActiveItemsIOS,
285
+ ) as Promise<Purchase[]>,
286
+ android: () => ExpoIapModule.getAvailableItems() as Promise<Purchase[]>,
287
+ }) ?? (() => Promise.resolve([] as Purchase[]));
288
+
289
+ const purchases = await resolvePurchases();
290
+ return normalizePurchaseList(purchases);
291
+ };
312
292
 
313
293
  /**
314
294
  * Restore completed transactions (cross-platform behavior)
@@ -323,25 +303,15 @@ export const getAvailablePurchases = ({
323
303
  * @param options.onlyIncludeActiveItemsIOS - iOS only: whether to only include active items
324
304
  * @returns Promise resolving to the list of available/restored purchases
325
305
  */
326
- export const restorePurchases = async (
327
- options: {
328
- alsoPublishToEventListenerIOS?: boolean;
329
- onlyIncludeActiveItemsIOS?: boolean;
330
- } = {},
331
- ): Promise<Purchase[]> => {
306
+ export const restorePurchases: MutationField<'restorePurchases'> = async () => {
332
307
  if (Platform.OS === 'ios') {
333
- // Perform best-effort sync on iOS and ignore sync errors to avoid blocking restore flow
334
308
  await syncIOS().catch(() => undefined);
335
309
  }
336
310
 
337
- // Then, fetch available purchases for both platforms
338
- const purchases = await getAvailablePurchases({
339
- alsoPublishToEventListenerIOS:
340
- options.alsoPublishToEventListenerIOS ?? false,
341
- onlyIncludeActiveItemsIOS: options.onlyIncludeActiveItemsIOS ?? true,
311
+ await getAvailablePurchases({
312
+ alsoPublishToEventListenerIOS: false,
313
+ onlyIncludeActiveItemsIOS: true,
342
314
  });
343
-
344
- return purchases;
345
315
  };
346
316
 
347
317
  const offerToRecordIOS = (
@@ -417,11 +387,11 @@ function normalizeRequestProps(
417
387
  * });
418
388
  * ```
419
389
  */
420
- export const requestPurchase = (
421
- requestObj: PurchaseRequestInput,
422
- ): Promise<Purchase | Purchase[] | void> => {
423
- const {request, type} = requestObj;
424
- const {canonical, native} = normalizeProductType(type);
390
+ export const requestPurchase: MutationField<'requestPurchase'> = async (
391
+ args,
392
+ ) => {
393
+ const {request, type} = args;
394
+ const {canonical, native} = normalizeProductType(type as ProductTypeInput);
425
395
  const isInAppPurchase = canonical === 'in-app';
426
396
 
427
397
  if (Platform.OS === 'ios') {
@@ -441,27 +411,24 @@ export const requestPurchase = (
441
411
  withOffer,
442
412
  } = normalizedRequest;
443
413
 
444
- return (async () => {
445
- const offer = offerToRecordIOS(withOffer ?? undefined);
446
- const purchase = await ExpoIapModule.requestPurchase({
447
- sku,
448
- andDangerouslyFinishTransactionAutomatically,
449
- appAccountToken,
450
- quantity,
451
- withOffer: offer,
452
- });
414
+ const offer = offerToRecordIOS(withOffer ?? undefined);
415
+ const purchase = await ExpoIapModule.requestPurchase({
416
+ sku,
417
+ andDangerouslyFinishTransactionAutomatically,
418
+ appAccountToken,
419
+ quantity,
420
+ withOffer: offer,
421
+ });
453
422
 
454
- return purchase as Purchase;
455
- })();
423
+ return normalizePurchaseId(purchase as Purchase);
456
424
  }
457
425
 
458
426
  if (Platform.OS === 'android') {
459
427
  if (isInAppPurchase) {
460
- const normalizedRequest: RequestPurchaseAndroidProps | null | undefined =
461
- normalizeRequestProps(
462
- request as RequestPurchasePropsByPlatforms,
463
- 'android',
464
- );
428
+ const normalizedRequest = normalizeRequestProps(
429
+ request as RequestPurchasePropsByPlatforms,
430
+ 'android',
431
+ ) as RequestPurchaseAndroidProps | null | undefined;
465
432
 
466
433
  if (!normalizedRequest?.skus?.length) {
467
434
  throw new Error(
@@ -476,28 +443,25 @@ export const requestPurchase = (
476
443
  isOfferPersonalized,
477
444
  } = normalizedRequest;
478
445
 
479
- return (async () => {
480
- return ExpoIapModule.requestPurchase({
481
- type: native,
482
- skuArr: skus,
483
- purchaseToken: undefined,
484
- replacementMode: -1,
485
- obfuscatedAccountId: obfuscatedAccountIdAndroid,
486
- obfuscatedProfileId: obfuscatedProfileIdAndroid,
487
- offerTokenArr: [],
488
- isOfferPersonalized: isOfferPersonalized ?? false,
489
- }) as Promise<Purchase[]>;
490
- })();
446
+ const result = (await ExpoIapModule.requestPurchase({
447
+ type: native,
448
+ skuArr: skus,
449
+ purchaseToken: undefined,
450
+ replacementMode: -1,
451
+ obfuscatedAccountId: obfuscatedAccountIdAndroid,
452
+ obfuscatedProfileId: obfuscatedProfileIdAndroid,
453
+ offerTokenArr: [],
454
+ isOfferPersonalized: isOfferPersonalized ?? false,
455
+ })) as Purchase[];
456
+
457
+ return normalizePurchaseList(result);
491
458
  }
492
459
 
493
460
  if (canonical === 'subs') {
494
- const normalizedRequest:
495
- | RequestSubscriptionAndroidProps
496
- | null
497
- | undefined = normalizeRequestProps(
461
+ const normalizedRequest = normalizeRequestProps(
498
462
  request as RequestSubscriptionPropsByPlatforms,
499
463
  'android',
500
- );
464
+ ) as RequestSubscriptionAndroidProps | null | undefined;
501
465
 
502
466
  if (!normalizedRequest?.skus?.length) {
503
467
  throw new Error(
@@ -519,21 +483,21 @@ export const requestPurchase = (
519
483
  const replacementMode = replacementModeAndroid ?? -1;
520
484
  const purchaseToken = purchaseTokenAndroid ?? undefined;
521
485
 
522
- return (async () => {
523
- return ExpoIapModule.requestPurchase({
524
- type: native,
525
- skuArr: skus,
526
- purchaseToken,
527
- replacementMode,
528
- obfuscatedAccountId: obfuscatedAccountIdAndroid,
529
- obfuscatedProfileId: obfuscatedProfileIdAndroid,
530
- offerTokenArr: normalizedOffers.map(
531
- (so: AndroidSubscriptionOfferInput) => so.offerToken,
532
- ),
533
- subscriptionOffers: normalizedOffers,
534
- isOfferPersonalized: isOfferPersonalized ?? false,
535
- }) as Promise<Purchase[]>;
536
- })();
486
+ const result = (await ExpoIapModule.requestPurchase({
487
+ type: native,
488
+ skuArr: skus,
489
+ purchaseToken,
490
+ replacementMode,
491
+ obfuscatedAccountId: obfuscatedAccountIdAndroid,
492
+ obfuscatedProfileId: obfuscatedProfileIdAndroid,
493
+ offerTokenArr: normalizedOffers.map(
494
+ (offer: AndroidSubscriptionOfferInput) => offer.offerToken,
495
+ ),
496
+ subscriptionOffers: normalizedOffers,
497
+ isOfferPersonalized: isOfferPersonalized ?? false,
498
+ })) as Purchase[];
499
+
500
+ return normalizePurchaseList(result);
537
501
  }
538
502
 
539
503
  throw new Error(
@@ -541,53 +505,60 @@ export const requestPurchase = (
541
505
  );
542
506
  }
543
507
 
544
- return Promise.resolve(); // Fallback for unsupported platforms
508
+ throw new Error('Platform not supported');
545
509
  };
546
510
 
547
- export const finishTransaction = ({
511
+ const toPurchaseInput = (
512
+ purchase: Purchase | PurchaseInput,
513
+ ): PurchaseInput => ({
514
+ id: purchase.id,
515
+ ids: purchase.ids ?? undefined,
516
+ isAutoRenewing: purchase.isAutoRenewing,
517
+ platform: purchase.platform,
518
+ productId: purchase.productId,
519
+ purchaseState: purchase.purchaseState,
520
+ purchaseToken: purchase.purchaseToken ?? null,
521
+ quantity: purchase.quantity,
522
+ transactionDate: purchase.transactionDate,
523
+ });
524
+
525
+ export const finishTransaction: MutationField<'finishTransaction'> = async ({
548
526
  purchase,
549
527
  isConsumable = false,
550
- }: {
551
- purchase: Purchase;
552
- isConsumable?: boolean;
553
- }): Promise<VoidResult | boolean> => {
554
- return (
555
- Platform.select({
556
- ios: async () => {
557
- const transactionId = purchase.id;
558
- if (!transactionId) {
559
- return Promise.reject(
560
- new Error('purchase.id required to finish iOS transaction'),
561
- );
562
- }
563
- await ExpoIapModule.finishTransaction(transactionId);
564
- return Promise.resolve(true);
565
- },
566
- android: async () => {
567
- const androidPurchase = purchase as PurchaseAndroid;
568
-
569
- // Use purchaseToken if available, fallback to purchaseTokenAndroid for backward compatibility
570
- const token = androidPurchase.purchaseToken;
571
-
572
- if (!token) {
573
- return Promise.reject(
574
- new PurchaseError({
575
- message: 'Purchase token is required to finish transaction',
576
- code: ErrorCode.DeveloperError,
577
- productId: androidPurchase.productId,
578
- platform: 'android',
579
- }),
580
- );
581
- }
582
-
583
- if (isConsumable) {
584
- return ExpoIapModule.consumePurchaseAndroid(token);
585
- }
586
-
587
- return ExpoIapModule.acknowledgePurchaseAndroid(token);
588
- },
589
- }) || (() => Promise.reject(new Error('Unsupported Platform')))
590
- )();
528
+ }) => {
529
+ const normalizedPurchase = toPurchaseInput(purchase);
530
+
531
+ if (Platform.OS === 'ios') {
532
+ const transactionId = normalizedPurchase.id;
533
+ if (!transactionId) {
534
+ throw new Error('purchase.id required to finish iOS transaction');
535
+ }
536
+ await ExpoIapModule.finishTransaction(transactionId);
537
+ return;
538
+ }
539
+
540
+ if (Platform.OS === 'android') {
541
+ const token = normalizedPurchase.purchaseToken ?? undefined;
542
+
543
+ if (!token) {
544
+ throw new PurchaseError({
545
+ message: 'Purchase token is required to finish transaction',
546
+ code: ErrorCode.DeveloperError,
547
+ productId: normalizedPurchase.productId,
548
+ platform: 'android',
549
+ });
550
+ }
551
+
552
+ if (isConsumable) {
553
+ await ExpoIapModule.consumePurchaseAndroid(token);
554
+ return;
555
+ }
556
+
557
+ await ExpoIapModule.acknowledgePurchaseAndroid(token);
558
+ return;
559
+ }
560
+
561
+ throw new Error('Unsupported Platform');
591
562
  };
592
563
 
593
564
  /**
@@ -638,18 +609,16 @@ export const getStorefront = (): Promise<string> => {
638
609
  * - iOS: Send receipt data to Apple's verification endpoint from your server
639
610
  * - Android: Use Google Play Developer API with service account credentials
640
611
  */
641
- export const validateReceipt = async (
642
- sku: string,
643
- androidOptions?: {
644
- packageName: string;
645
- productToken: string;
646
- accessToken: string;
647
- isSub?: boolean;
648
- },
649
- ): Promise<ReceiptValidationResult> => {
612
+ export const validateReceipt: MutationField<'validateReceipt'> = async (
613
+ options,
614
+ ) => {
615
+ const {sku, androidOptions} = options as MutationValidateReceiptArgs;
616
+
650
617
  if (Platform.OS === 'ios') {
651
- return await validateReceiptIOS(sku);
652
- } else if (Platform.OS === 'android') {
618
+ return validateReceiptIOS({sku});
619
+ }
620
+
621
+ if (Platform.OS === 'android') {
653
622
  if (
654
623
  !androidOptions ||
655
624
  !androidOptions.packageName ||
@@ -660,16 +629,16 @@ export const validateReceipt = async (
660
629
  'Android validation requires packageName, productToken, and accessToken',
661
630
  );
662
631
  }
663
- return await validateReceiptAndroid({
632
+ return validateReceiptAndroid({
664
633
  packageName: androidOptions.packageName,
665
634
  productId: sku,
666
635
  productToken: androidOptions.productToken,
667
636
  accessToken: androidOptions.accessToken,
668
- isSub: androidOptions.isSub,
637
+ isSub: androidOptions.isSub ?? undefined,
669
638
  });
670
- } else {
671
- throw new Error('Platform not supported');
672
639
  }
640
+
641
+ throw new Error('Platform not supported');
673
642
  };
674
643
 
675
644
  /**
@@ -690,22 +659,20 @@ export const validateReceipt = async (
690
659
  * packageNameAndroid: 'com.example.app'
691
660
  * });
692
661
  */
693
- export const deepLinkToSubscriptions = (options: {
694
- skuAndroid?: string;
695
- packageNameAndroid?: string;
696
- }): Promise<void> => {
662
+ export const deepLinkToSubscriptions: MutationField<
663
+ 'deepLinkToSubscriptions'
664
+ > = async (options) => {
697
665
  if (Platform.OS === 'ios') {
698
- return deepLinkToSubscriptionsIOS();
666
+ await deepLinkToSubscriptionsIOS();
667
+ return;
699
668
  }
700
669
 
701
670
  if (Platform.OS === 'android') {
702
- return deepLinkToSubscriptionsAndroid({
703
- sku: options?.skuAndroid,
704
- packageName: options?.packageNameAndroid,
705
- });
671
+ await deepLinkToSubscriptionsAndroid((options as DeepLinkOptions) ?? null);
672
+ return;
706
673
  }
707
674
 
708
- return Promise.reject(new Error(`Unsupported platform: ${Platform.OS}`));
675
+ throw new Error(`Unsupported platform: ${Platform.OS}`);
709
676
  };
710
677
 
711
678
  export * from './useIAP';