react-native-iap 15.1.0 → 15.2.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 (96) hide show
  1. package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +171 -114
  2. package/android/src/main/java/com/margelo/nitro/iap/ProductQueryHelpers.kt +42 -0
  3. package/android/src/test/java/com/margelo/nitro/iap/ProductQueryHelpersTest.kt +140 -0
  4. package/ios/HybridRnIap.swift +72 -1
  5. package/lib/module/hooks/useIAP.js +11 -1
  6. package/lib/module/hooks/useIAP.js.map +1 -1
  7. package/lib/module/hooks/useWebhookEvents.js +113 -0
  8. package/lib/module/hooks/useWebhookEvents.js.map +1 -0
  9. package/lib/module/index.js +405 -131
  10. package/lib/module/index.js.map +1 -1
  11. package/lib/module/kit-api.js +161 -0
  12. package/lib/module/kit-api.js.map +1 -0
  13. package/lib/module/types.js +16 -0
  14. package/lib/module/types.js.map +1 -1
  15. package/lib/module/utils/error.js.map +1 -1
  16. package/lib/module/utils/errorMapping.js +6 -0
  17. package/lib/module/utils/errorMapping.js.map +1 -1
  18. package/lib/module/webhook-client.js +164 -0
  19. package/lib/module/webhook-client.js.map +1 -0
  20. package/lib/typescript/plugin/src/withIAP.d.ts +1 -1
  21. package/lib/typescript/src/hooks/useIAP.d.ts +172 -2
  22. package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
  23. package/lib/typescript/src/hooks/useWebhookEvents.d.ts +55 -0
  24. package/lib/typescript/src/hooks/useWebhookEvents.d.ts.map +1 -0
  25. package/lib/typescript/src/index.d.ts +283 -129
  26. package/lib/typescript/src/index.d.ts.map +1 -1
  27. package/lib/typescript/src/kit-api.d.ts +54 -0
  28. package/lib/typescript/src/kit-api.d.ts.map +1 -0
  29. package/lib/typescript/src/specs/RnIap.nitro.d.ts +24 -0
  30. package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
  31. package/lib/typescript/src/types.d.ts +320 -75
  32. package/lib/typescript/src/types.d.ts.map +1 -1
  33. package/lib/typescript/src/utils/error.d.ts +3 -0
  34. package/lib/typescript/src/utils/error.d.ts.map +1 -1
  35. package/lib/typescript/src/utils/errorMapping.d.ts +6 -0
  36. package/lib/typescript/src/utils/errorMapping.d.ts.map +1 -1
  37. package/lib/typescript/src/webhook-client.d.ts +82 -0
  38. package/lib/typescript/src/webhook-client.d.ts.map +1 -0
  39. package/nitrogen/generated/android/NitroIap+autolinking.cmake +3 -0
  40. package/nitrogen/generated/android/c++/JAdvancedCommerceInfoIOS.hpp +118 -0
  41. package/nitrogen/generated/android/c++/JAdvancedCommerceItemDetailsIOS.hpp +62 -0
  42. package/nitrogen/generated/android/c++/JAdvancedCommerceItemIOS.hpp +78 -0
  43. package/nitrogen/generated/android/c++/JAdvancedCommerceRefundIOS.hpp +62 -0
  44. package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +52 -0
  45. package/nitrogen/generated/android/c++/JHybridRnIapSpec.hpp +3 -0
  46. package/nitrogen/generated/android/c++/JPurchase.hpp +11 -0
  47. package/nitrogen/generated/android/c++/JPurchaseIOS.hpp +16 -1
  48. package/nitrogen/generated/android/c++/JRequestPurchaseResult.hpp +11 -0
  49. package/nitrogen/generated/android/c++/JVariant_NullType_AdvancedCommerceInfoIOS.cpp +26 -0
  50. package/nitrogen/generated/android/c++/JVariant_NullType_AdvancedCommerceInfoIOS.hpp +84 -0
  51. package/nitrogen/generated/android/c++/JVariant_NullType_AdvancedCommerceItemDetailsIOS.cpp +26 -0
  52. package/nitrogen/generated/android/c++/JVariant_NullType_AdvancedCommerceItemDetailsIOS.hpp +74 -0
  53. package/nitrogen/generated/android/c++/JVariant_NullType_Array_AdvancedCommerceRefundIOS_.cpp +35 -0
  54. package/nitrogen/generated/android/c++/JVariant_NullType_Array_AdvancedCommerceRefundIOS_.hpp +84 -0
  55. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/AdvancedCommerceInfoIOS.kt +59 -0
  56. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/AdvancedCommerceItemDetailsIOS.kt +38 -0
  57. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/AdvancedCommerceItemIOS.kt +44 -0
  58. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/AdvancedCommerceRefundIOS.kt +38 -0
  59. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +22 -0
  60. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseIOS.kt +5 -2
  61. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_NullType_AdvancedCommerceInfoIOS.kt +53 -0
  62. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_NullType_AdvancedCommerceItemDetailsIOS.kt +53 -0
  63. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_NullType_Array_AdvancedCommerceRefundIOS_.kt +53 -0
  64. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.hpp +166 -0
  65. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Umbrella.hpp +12 -0
  66. package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +32 -0
  67. package/nitrogen/generated/ios/swift/AdvancedCommerceInfoIOS.swift +294 -0
  68. package/nitrogen/generated/ios/swift/AdvancedCommerceItemDetailsIOS.swift +61 -0
  69. package/nitrogen/generated/ios/swift/AdvancedCommerceItemIOS.swift +141 -0
  70. package/nitrogen/generated/ios/swift/AdvancedCommerceRefundIOS.swift +61 -0
  71. package/nitrogen/generated/ios/swift/HybridRnIapSpec.swift +3 -0
  72. package/nitrogen/generated/ios/swift/HybridRnIapSpec_cxx.swift +57 -0
  73. package/nitrogen/generated/ios/swift/PurchaseIOS.swift +39 -2
  74. package/nitrogen/generated/ios/swift/Variant_NullType_AdvancedCommerceInfoIOS.swift +18 -0
  75. package/nitrogen/generated/ios/swift/Variant_NullType_AdvancedCommerceItemDetailsIOS.swift +18 -0
  76. package/nitrogen/generated/ios/swift/Variant_NullType__AdvancedCommerceRefundIOS_.swift +18 -0
  77. package/nitrogen/generated/shared/c++/AdvancedCommerceInfoIOS.hpp +117 -0
  78. package/nitrogen/generated/shared/c++/AdvancedCommerceItemDetailsIOS.hpp +86 -0
  79. package/nitrogen/generated/shared/c++/AdvancedCommerceItemIOS.hpp +99 -0
  80. package/nitrogen/generated/shared/c++/AdvancedCommerceRefundIOS.hpp +86 -0
  81. package/nitrogen/generated/shared/c++/HybridRnIapSpec.cpp +3 -0
  82. package/nitrogen/generated/shared/c++/HybridRnIapSpec.hpp +3 -0
  83. package/nitrogen/generated/shared/c++/PurchaseIOS.hpp +9 -2
  84. package/openiap-versions.json +3 -3
  85. package/package.json +1 -1
  86. package/plugin/build/withIAP.d.ts +1 -1
  87. package/plugin/src/withIAP.ts +1 -1
  88. package/src/hooks/useIAP.ts +185 -2
  89. package/src/hooks/useWebhookEvents.ts +180 -0
  90. package/src/index.ts +440 -130
  91. package/src/kit-api.ts +225 -0
  92. package/src/specs/RnIap.nitro.ts +31 -0
  93. package/src/types.ts +330 -75
  94. package/src/utils/error.ts +3 -0
  95. package/src/utils/errorMapping.ts +12 -0
  96. package/src/webhook-client.ts +312 -0
@@ -39,7 +39,9 @@ const toErrorMessage = error => {
39
39
 
40
40
  // Export hooks
41
41
  export { useIAP } from "./hooks/useIAP.js";
42
-
42
+ export { useWebhookEvents } from "./hooks/useWebhookEvents.js";
43
+ export { connectWebhookStream, parseWebhookEventData } from "./webhook-client.js";
44
+ export { kitApi, KitApiError } from "./kit-api.js";
43
45
  // Restore completed transactions (cross-platform)
44
46
  // Development utilities removed - use type bridge functions directly if needed
45
47
 
@@ -170,12 +172,14 @@ export const resetListenerState = () => {
170
172
  promotedProductNativeAttached = false;
171
173
  userChoiceBillingNativeAttached = false;
172
174
  developerProvidedBillingNativeAttached = false;
175
+ subscriptionBillingIssueNativeAttached = false;
173
176
  // Clear all JS listeners since native side clears them in endConnection
174
177
  purchaseUpdateJsListeners.clear();
175
178
  purchaseErrorJsListeners.clear();
176
179
  promotedProductJsListeners.clear();
177
180
  userChoiceBillingJsListeners.clear();
178
181
  developerProvidedBillingJsListeners.clear();
182
+ subscriptionBillingIssueJsListeners.clear();
179
183
  };
180
184
  export const purchaseUpdatedListener = listener => {
181
185
  purchaseUpdateJsListeners.add(listener);
@@ -388,25 +392,105 @@ export const developerProvidedBillingListenerAndroid = listener => {
388
392
  };
389
393
  };
390
394
 
395
+ /**
396
+ * Listen for subscription billing-issue events (cross-platform).
397
+ *
398
+ * Fires when an active subscription enters a billing-issue state:
399
+ * - iOS 18+ / Mac Catalyst 18+: via StoreKit 2 `Message.Reason.billingIssue`.
400
+ * - Android (Play Billing 8.1+): when `isSuspendedAndroid === true` is observed.
401
+ * - Horizon / iOS 17 / older platforms: never fires.
402
+ *
403
+ * Recommended UX: on fire, call `deepLinkToSubscriptions()` so the user can
404
+ * update their payment method in the platform subscription center.
405
+ *
406
+ * @param listener - Function to call with the affected Purchase
407
+ * @returns EventSubscription with remove() method to unsubscribe
408
+ *
409
+ * @example
410
+ * ```typescript
411
+ * const subscription = subscriptionBillingIssueListener((purchase) => {
412
+ * console.warn('Subscription needs attention:', purchase.productId);
413
+ * deepLinkToSubscriptions({skuAndroid: purchase.productId, packageNameAndroid: 'com.example.app'});
414
+ * });
415
+ *
416
+ * subscription.remove();
417
+ * ```
418
+ */
419
+
420
+ const subscriptionBillingIssueJsListeners = new Set();
421
+ let subscriptionBillingIssueNativeAttached = false;
422
+ const subscriptionBillingIssueNativeHandler = nitroPurchase => {
423
+ if (!validateNitroPurchase(nitroPurchase)) {
424
+ RnIapConsole.warn('[subscriptionBillingIssueListener] dropped malformed native payload');
425
+ return;
426
+ }
427
+ const purchase = convertNitroPurchaseToPurchase(nitroPurchase);
428
+ for (const listener of subscriptionBillingIssueJsListeners) {
429
+ try {
430
+ listener(purchase);
431
+ } catch (e) {
432
+ RnIapConsole.error('[subscriptionBillingIssueListener] callback threw:', e);
433
+ }
434
+ }
435
+ };
436
+ function tryAttachSubscriptionBillingIssueNative() {
437
+ if (subscriptionBillingIssueNativeAttached) return;
438
+ try {
439
+ IAP.instance.addSubscriptionBillingIssueListener(subscriptionBillingIssueNativeHandler);
440
+ subscriptionBillingIssueNativeAttached = true;
441
+ } catch (e) {
442
+ const msg = toErrorMessage(e);
443
+ if (msg.includes('Nitro runtime not installed')) {
444
+ RnIapConsole.warn('[subscriptionBillingIssueListener] Nitro not ready yet; will retry on next registration after initConnection()');
445
+ } else {
446
+ throw e;
447
+ }
448
+ }
449
+ }
450
+ export const subscriptionBillingIssueListener = listener => {
451
+ subscriptionBillingIssueJsListeners.add(listener);
452
+ // Retry attachment every call so a listener registered before initConnection()
453
+ // doesn't stay permanently inert once Nitro is ready.
454
+ try {
455
+ tryAttachSubscriptionBillingIssueNative();
456
+ } catch (error) {
457
+ subscriptionBillingIssueJsListeners.delete(listener);
458
+ throw error;
459
+ }
460
+ return {
461
+ remove: () => {
462
+ subscriptionBillingIssueJsListeners.delete(listener);
463
+ }
464
+ };
465
+ };
466
+
391
467
  // ------------------------------
392
468
  // Query API
393
469
  // ------------------------------
394
470
 
395
471
  /**
396
- * Fetch products from the store
397
- * @param params - Product request configuration
398
- * @param params.skus - Array of product SKUs to fetch
399
- * @param params.type - Optional filter: 'in-app' (default) for products, 'subs' for subscriptions, or 'all' for both.
400
- * @returns Promise<Product[]> - Array of products from the store
472
+ * Retrieve products or subscriptions from the store by SKU.
401
473
  *
402
- * @example
403
- * ```typescript
404
- * // Regular products
405
- * const products = await fetchProducts({ skus: ['product1', 'product2'] });
474
+ * @param request `ProductRequest` — `skus` (string[]) and optional `type`
475
+ * (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
476
+ * @returns Promise resolving to a `FetchProductsResult` union — `Product[]` for `'in-app'`,
477
+ * `ProductSubscription[]` for `'subs'`, a mixed array for `'all'`, or `null`
478
+ * (the schema retains the nullable branch for backwards compatibility).
479
+ * @throws When the store rejects the request (empty `skus`, not connected,
480
+ * network/store error). Unknown SKUs are simply omitted from the result, not thrown.
406
481
  *
407
- * // Subscriptions
408
- * const subscriptions = await fetchProducts({ skus: ['sub1', 'sub2'], type: 'subs' });
482
+ * @example
483
+ * ```ts
484
+ * const products = await fetchProducts({
485
+ * skus: ['com.app.coins_100', 'com.app.premium'],
486
+ * type: 'in-app',
487
+ * });
409
488
  * ```
489
+ *
490
+ * @remarks This is a regular promise-based call. Don't confuse with `request*` APIs
491
+ * (`requestPurchase`), which are event-based.
492
+ *
493
+ * @see {@link https://www.openiap.dev/docs/apis/fetch-products}
410
494
  */
411
495
  export const fetchProducts = async request => {
412
496
  const {
@@ -480,22 +564,40 @@ export const fetchProducts = async request => {
480
564
  return convertedProducts;
481
565
  } catch (error) {
482
566
  RnIapConsole.error('[fetchProducts] Failed:', error);
483
- throw error;
567
+ const parsedError = parseErrorStringToJsonObj(error);
568
+ throw createPurchaseError({
569
+ code: parsedError.code,
570
+ message: parsedError.message,
571
+ responseCode: parsedError.responseCode,
572
+ debugMessage: parsedError.debugMessage,
573
+ productId: parsedError.productId,
574
+ productIds: parsedError.productIds,
575
+ productType: parsedError.productType,
576
+ isEmptyProductList: parsedError.isEmptyProductList,
577
+ platform: Platform.OS === 'ios' ? 'ios' : 'android'
578
+ });
484
579
  }
485
580
  };
486
581
 
487
582
  /**
488
- * Get available purchases (purchased items not yet consumed/finished)
489
- * @param params - Options for getting available purchases
490
- * @param params.alsoPublishToEventListener - Whether to also publish to event listener
491
- * @param params.onlyIncludeActiveItems - Whether to only include active items
583
+ * List the user's unfinished purchases non-consumables, active subscriptions, and any
584
+ * pending transactions not yet finished.
585
+ *
586
+ * @param options Optional `PurchaseOptions`.
587
+ * - iOS: `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.
588
+ * - Android: `includeSuspendedAndroid` (include subscriptions in a paused/grace state).
589
+ * @returns Promise resolving to an array of `Purchase` currently held by the store.
590
+ * @throws When the platform query fails.
492
591
  *
493
592
  * @example
494
- * ```typescript
495
- * const purchases = await getAvailablePurchases({
496
- * onlyIncludeActiveItemsIOS: true
497
- * });
593
+ * ```ts
594
+ * const purchases = await getAvailablePurchases();
595
+ * for (const p of purchases) {
596
+ * if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });
597
+ * }
498
598
  * ```
599
+ *
600
+ * @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}
499
601
  */
500
602
  export const getAvailablePurchases = async options => {
501
603
  const alsoPublishToEventListenerIOS = Boolean(options?.alsoPublishToEventListenerIOS ?? false);
@@ -552,6 +654,8 @@ export const getAvailablePurchases = async options => {
552
654
  * Request the promoted product from the App Store (iOS only)
553
655
  * @returns Promise<Product | null> - The promoted product or null if none available
554
656
  * @platform iOS
657
+ *
658
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios}
555
659
  */
556
660
  export const getPromotedProductIOS = async () => {
557
661
  if (Platform.OS !== 'ios') {
@@ -576,6 +680,20 @@ export const getPromotedProductIOS = async () => {
576
680
  }
577
681
  };
578
682
  export const requestPromotedProductIOS = getPromotedProductIOS;
683
+
684
+ /**
685
+ * Get the storefront identifier for the user's App Store account (iOS only)
686
+ * @returns Promise<string> - The storefront identifier (e.g., 'USA' for United States)
687
+ * @platform iOS
688
+ *
689
+ * @example
690
+ * ```typescript
691
+ * const storefront = await getStorefrontIOS();
692
+ * console.log('User storefront:', storefront); // e.g., 'USA', 'GBR', 'KOR'
693
+ * ```
694
+ *
695
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-storefront-ios}
696
+ */
579
697
  export const getStorefrontIOS = async () => {
580
698
  if (Platform.OS !== 'ios') {
581
699
  throw new Error('getStorefrontIOS is only available on iOS');
@@ -588,6 +706,12 @@ export const getStorefrontIOS = async () => {
588
706
  throw error;
589
707
  }
590
708
  };
709
+
710
+ /**
711
+ * Return the user's storefront country code.
712
+ *
713
+ * @see {@link https://www.openiap.dev/docs/apis/get-storefront}
714
+ */
591
715
  export const getStorefront = async () => {
592
716
  if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
593
717
  RnIapConsole.warn('[getStorefront] Storefront lookup is only supported on iOS and Android.');
@@ -609,6 +733,28 @@ export const getStorefront = async () => {
609
733
  throw error;
610
734
  }
611
735
  };
736
+
737
+ /**
738
+ * iOS only - Gets the original app transaction ID if the app was purchased from the App Store
739
+ * @platform iOS
740
+ * @description
741
+ * This function retrieves the original app transaction information if the app was purchased
742
+ * from the App Store. Returns null if the app was not purchased (e.g., free app or TestFlight).
743
+ *
744
+ * @returns {Promise<string | null>} The original app transaction ID or null
745
+ *
746
+ * @example
747
+ * ```typescript
748
+ * const appTransaction = await getAppTransactionIOS();
749
+ * if (appTransaction) {
750
+ * console.log('App was purchased, transaction ID:', appTransaction);
751
+ * } else {
752
+ * console.log('App was not purchased from App Store');
753
+ * }
754
+ * ```
755
+ *
756
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios}
757
+ */
612
758
  export const getAppTransactionIOS = async () => {
613
759
  if (Platform.OS !== 'ios') {
614
760
  throw new Error('getAppTransactionIOS is only available on iOS');
@@ -634,6 +780,16 @@ export const getAppTransactionIOS = async () => {
634
780
  throw error;
635
781
  }
636
782
  };
783
+
784
+ /**
785
+ * Get subscription status for a product (iOS only)
786
+ * @param sku - The product SKU
787
+ * @returns Promise<SubscriptionStatusIOS[]> - Array of subscription status objects
788
+ * @throws Error when called on non-iOS platforms or when IAP is not initialized
789
+ * @platform iOS
790
+ *
791
+ * @see {@link https://www.openiap.dev/docs/apis/ios/subscription-status-ios}
792
+ */
637
793
  export const subscriptionStatusIOS = async sku => {
638
794
  if (Platform.OS !== 'ios') {
639
795
  throw new Error('subscriptionStatusIOS is only available on iOS');
@@ -653,6 +809,15 @@ export const subscriptionStatusIOS = async sku => {
653
809
  });
654
810
  }
655
811
  };
812
+
813
+ /**
814
+ * Get current entitlement for a product (iOS only)
815
+ * @param sku - The product SKU
816
+ * @returns Promise<Purchase | null> - Current entitlement or null
817
+ * @platform iOS
818
+ *
819
+ * @see {@link https://www.openiap.dev/docs/apis/ios/current-entitlement-ios}
820
+ */
656
821
  export const currentEntitlementIOS = async sku => {
657
822
  if (Platform.OS !== 'ios') {
658
823
  return null;
@@ -675,6 +840,15 @@ export const currentEntitlementIOS = async sku => {
675
840
  });
676
841
  }
677
842
  };
843
+
844
+ /**
845
+ * Get latest transaction for a product (iOS only)
846
+ * @param sku - The product SKU
847
+ * @returns Promise<Purchase | null> - Latest transaction or null
848
+ * @platform iOS
849
+ *
850
+ * @see {@link https://www.openiap.dev/docs/apis/ios/latest-transaction-ios}
851
+ */
678
852
  export const latestTransactionIOS = async sku => {
679
853
  if (Platform.OS !== 'ios') {
680
854
  return null;
@@ -697,6 +871,14 @@ export const latestTransactionIOS = async sku => {
697
871
  });
698
872
  }
699
873
  };
874
+
875
+ /**
876
+ * Get pending transactions (iOS only)
877
+ * @returns Promise<Purchase[]> - Array of pending transactions
878
+ * @platform iOS
879
+ *
880
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios}
881
+ */
700
882
  export const getPendingTransactionsIOS = async () => {
701
883
  if (Platform.OS !== 'ios') {
702
884
  return [];
@@ -715,6 +897,38 @@ export const getPendingTransactionsIOS = async () => {
715
897
  });
716
898
  }
717
899
  };
900
+
901
+ /**
902
+ * List every StoreKit transaction (finished + unfinished) for the current user.
903
+ *
904
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios}
905
+ */
906
+ export const getAllTransactionsIOS = async () => {
907
+ if (Platform.OS !== 'ios') {
908
+ return [];
909
+ }
910
+ try {
911
+ const nitroPurchases = await IAP.instance.getAllTransactionsIOS();
912
+ return nitroPurchases.map(convertNitroPurchaseToPurchase).filter(purchase => purchase.platform === 'ios');
913
+ } catch (error) {
914
+ RnIapConsole.error('[getAllTransactionsIOS] Failed:', error);
915
+ const parsedError = parseErrorStringToJsonObj(error);
916
+ throw createPurchaseError({
917
+ code: parsedError.code,
918
+ message: parsedError.message,
919
+ responseCode: parsedError.responseCode,
920
+ debugMessage: parsedError.debugMessage
921
+ });
922
+ }
923
+ };
924
+
925
+ /**
926
+ * Show manage subscriptions screen (iOS only)
927
+ * @returns Promise<Purchase[]> - Subscriptions where auto-renewal status changed
928
+ * @platform iOS
929
+ *
930
+ * @see {@link https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios}
931
+ */
718
932
  export const showManageSubscriptionsIOS = async () => {
719
933
  if (Platform.OS !== 'ios') {
720
934
  return [];
@@ -733,6 +947,15 @@ export const showManageSubscriptionsIOS = async () => {
733
947
  });
734
948
  }
735
949
  };
950
+
951
+ /**
952
+ * Check if user is eligible for intro offer (iOS only)
953
+ * @param groupID - The subscription group ID
954
+ * @returns Promise<boolean> - Eligibility status
955
+ * @platform iOS
956
+ *
957
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios}
958
+ */
736
959
  export const isEligibleForIntroOfferIOS = async groupID => {
737
960
  if (Platform.OS !== 'ios') {
738
961
  return false;
@@ -750,6 +973,14 @@ export const isEligibleForIntroOfferIOS = async groupID => {
750
973
  });
751
974
  }
752
975
  };
976
+
977
+ /**
978
+ * Get receipt data (iOS only)
979
+ * @returns Promise<string> - Base64 encoded receipt data
980
+ * @platform iOS
981
+ *
982
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios}
983
+ */
753
984
  export const getReceiptDataIOS = async () => {
754
985
  if (Platform.OS !== 'ios') {
755
986
  throw new Error('getReceiptDataIOS is only available on iOS');
@@ -810,6 +1041,15 @@ export const requestReceiptRefreshIOS = async () => {
810
1041
  });
811
1042
  }
812
1043
  };
1044
+
1045
+ /**
1046
+ * Check if transaction is verified (iOS only)
1047
+ * @param sku - The product SKU
1048
+ * @returns Promise<boolean> - Verification status
1049
+ * @platform iOS
1050
+ *
1051
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios}
1052
+ */
813
1053
  export const isTransactionVerifiedIOS = async sku => {
814
1054
  if (Platform.OS !== 'ios') {
815
1055
  return false;
@@ -827,6 +1067,15 @@ export const isTransactionVerifiedIOS = async sku => {
827
1067
  });
828
1068
  }
829
1069
  };
1070
+
1071
+ /**
1072
+ * Get transaction JWS representation (iOS only)
1073
+ * @param sku - The product SKU
1074
+ * @returns Promise<string | null> - JWS representation or null
1075
+ * @platform iOS
1076
+ *
1077
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios}
1078
+ */
830
1079
  export const getTransactionJwsIOS = async sku => {
831
1080
  if (Platform.OS !== 'ios') {
832
1081
  return null;
@@ -850,25 +1099,23 @@ export const getTransactionJwsIOS = async sku => {
850
1099
  // ------------------------------
851
1100
 
852
1101
  /**
853
- * Initialize connection to the store
854
- * @param config - Optional configuration including alternative billing mode for Android
855
- * @param config.alternativeBillingModeAndroid - Alternative billing mode: 'none', 'user-choice', or 'alternative-only'
1102
+ * Initialize the store connection. Must be called before any other IAP API.
1103
+ *
1104
+ * @param config Optional connection config. Use `enableBillingProgramAndroid` (Android,
1105
+ * Play Billing 8.2.0+) to opt into External Payments etc. iOS ignores Android-specific fields.
1106
+ * @returns Promise resolving to `true` when the platform billing client is connected.
1107
+ * @throws When the platform billing client fails to initialize.
856
1108
  *
857
1109
  * @example
858
- * ```typescript
859
- * // Standard billing (default)
1110
+ * ```ts
860
1111
  * await initConnection();
1112
+ * await initConnection({ enableBillingProgramAndroid: 'external-offer' });
1113
+ * ```
861
1114
  *
862
- * // User choice billing (Android)
863
- * await initConnection({
864
- * alternativeBillingModeAndroid: 'user-choice'
865
- * });
1115
+ * @remarks When using `useIAP()`, connection is auto-managed on mount/unmount —
1116
+ * pass options to the hook instead of calling this directly.
866
1117
  *
867
- * // Alternative billing only (Android)
868
- * await initConnection({
869
- * alternativeBillingModeAndroid: 'alternative-only'
870
- * });
871
- * ```
1118
+ * @see {@link https://www.openiap.dev/docs/apis/init-connection}
872
1119
  */
873
1120
  export const initConnection = async config => {
874
1121
  try {
@@ -886,7 +1133,9 @@ export const initConnection = async config => {
886
1133
  };
887
1134
 
888
1135
  /**
889
- * End connection to the store
1136
+ * Close the store connection and release resources.
1137
+ *
1138
+ * @see {@link https://www.openiap.dev/docs/apis/end-connection}
890
1139
  */
891
1140
  export const endConnection = async () => {
892
1141
  try {
@@ -905,6 +1154,12 @@ export const endConnection = async () => {
905
1154
  });
906
1155
  }
907
1156
  };
1157
+
1158
+ /**
1159
+ * Restore non-consumable and active subscription purchases.
1160
+ *
1161
+ * @see {@link https://www.openiap.dev/docs/apis/restore-purchases}
1162
+ */
908
1163
  export const restorePurchases = async () => {
909
1164
  try {
910
1165
  if (Platform.OS === 'ios') {
@@ -927,9 +1182,30 @@ export const restorePurchases = async () => {
927
1182
  };
928
1183
 
929
1184
  /**
930
- * Request a purchase for products or subscriptions
931
- * ⚠️ Important: This is an event-based operation, not promise-based.
932
- * Listen for events through purchaseUpdatedListener or purchaseErrorListener.
1185
+ * Initiate a purchase or subscription flow. The result is delivered through
1186
+ * `purchaseUpdatedListener` NOT the return value.
1187
+ *
1188
+ * @param request `RequestPurchaseProps`, discriminated by `type`:
1189
+ * - `type: 'in-app'` — pass `request.apple.sku` (iOS) and/or `request.google.skus` (Android).
1190
+ * - `type: 'subs'` — same shape, plus `request.google.subscriptionOffers: [{ sku, offerToken }]`.
1191
+ * @returns The dispatched purchase payload. **Do not rely on it** for the actual outcome.
1192
+ * @throws Synchronous rejection from the store (e.g. `E_NOT_PREPARED`, validation failure).
1193
+ *
1194
+ * @example
1195
+ * ```ts
1196
+ * await requestPurchase({
1197
+ * request: {
1198
+ * apple: { sku: 'com.app.premium' },
1199
+ * google: { skus: ['com.app.premium'] },
1200
+ * },
1201
+ * type: 'in-app',
1202
+ * });
1203
+ * ```
1204
+ *
1205
+ * @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /
1206
+ * {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.
1207
+ *
1208
+ * @see {@link https://www.openiap.dev/docs/apis/request-purchase}
933
1209
  */
934
1210
  export const requestPurchase = async request => {
935
1211
  try {
@@ -1043,19 +1319,28 @@ export const requestPurchase = async request => {
1043
1319
  };
1044
1320
 
1045
1321
  /**
1046
- * Finish a transaction (consume or acknowledge)
1047
- * @param params - Transaction finish parameters
1048
- * @param params.purchase - The purchase to finish
1049
- * @param params.isConsumable - Whether this is a consumable product (Android only)
1050
- * @returns Promise<void> - Resolves when the transaction is successfully finished
1322
+ * Complete a purchase transaction. Call after server-side verification to remove it
1323
+ * from the queue.
1324
+ *
1325
+ * @param args.purchase The `Purchase` to finalize.
1326
+ * @param args.isConsumable `true` for consumables (consumes the token so the SKU can be
1327
+ * re-bought, e.g. coins); `false` (default) for non-consumables and subscriptions.
1328
+ * @returns Promise that resolves once the platform finalizes the transaction.
1329
+ * @throws When the platform finalize call fails.
1051
1330
  *
1052
1331
  * @example
1053
- * ```typescript
1054
- * await finishTransaction({
1055
- * purchase: myPurchase,
1056
- * isConsumable: true
1332
+ * ```ts
1333
+ * purchaseUpdatedListener(async (purchase) => {
1334
+ * if (await verifyOnServer(purchase)) {
1335
+ * await finishTransaction({ purchase, isConsumable: false });
1336
+ * }
1057
1337
  * });
1058
1338
  * ```
1339
+ *
1340
+ * @remarks **Critical:** Android purchases must be finalized within 3 days or Google
1341
+ * auto-refunds. iOS unfinished transactions replay on every app launch.
1342
+ *
1343
+ * @see {@link https://www.openiap.dev/docs/apis/finish-transaction}
1059
1344
  */
1060
1345
  export const finishTransaction = async args => {
1061
1346
  const {
@@ -1118,6 +1403,8 @@ export const finishTransaction = async args => {
1118
1403
  * ```typescript
1119
1404
  * await acknowledgePurchaseAndroid('purchase_token_here');
1120
1405
  * ```
1406
+ *
1407
+ * @see {@link https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android}
1121
1408
  */
1122
1409
  export const acknowledgePurchaseAndroid = async purchaseToken => {
1123
1410
  try {
@@ -1152,6 +1439,8 @@ export const acknowledgePurchaseAndroid = async purchaseToken => {
1152
1439
  * ```typescript
1153
1440
  * await consumePurchaseAndroid('purchase_token_here');
1154
1441
  * ```
1442
+ *
1443
+ * @see {@link https://www.openiap.dev/docs/apis/android/consume-purchase-android}
1155
1444
  */
1156
1445
  export const consumePurchaseAndroid = async purchaseToken => {
1157
1446
  try {
@@ -1204,6 +1493,8 @@ export const consumePurchaseAndroid = async purchaseToken => {
1204
1493
  * }
1205
1494
  * });
1206
1495
  * ```
1496
+ *
1497
+ * @see {@link https://www.openiap.dev/docs/apis/validate-receipt}
1207
1498
  */
1208
1499
  export const validateReceipt = async options => {
1209
1500
  const {
@@ -1311,9 +1602,28 @@ export const validateReceipt = async options => {
1311
1602
  *
1312
1603
  * @param options - Receipt validation options containing the SKU
1313
1604
  * @returns Promise resolving to receipt validation result
1605
+ *
1606
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase}
1314
1607
  */
1315
1608
  export const verifyPurchase = validateReceipt;
1316
1609
 
1610
+ /**
1611
+ * iOS-only receipt validation alias.
1612
+ *
1613
+ * @deprecated Use `verifyPurchase` (or `validateReceipt`) instead. Kept so
1614
+ * consumers who imported `validateReceiptIOS` — which is still declared on the
1615
+ * OpenIAP Query interface — keep working. Throws on non-iOS platforms.
1616
+ *
1617
+ * @see {@link https://www.openiap.dev/docs/apis/ios/validate-receipt-ios}
1618
+ */
1619
+ export const validateReceiptIOS = async options => {
1620
+ if (Platform.OS !== 'ios') {
1621
+ throw new Error('validateReceiptIOS is only available on iOS');
1622
+ }
1623
+ const result = await validateReceipt(options);
1624
+ return result;
1625
+ };
1626
+
1317
1627
  /**
1318
1628
  * Verify purchase with a specific provider (e.g., IAPKit)
1319
1629
  *
@@ -1334,6 +1644,8 @@ export const verifyPurchase = validateReceipt;
1334
1644
  * },
1335
1645
  * });
1336
1646
  * ```
1647
+ *
1648
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}
1337
1649
  */
1338
1650
  export const verifyPurchaseWithProvider = async options => {
1339
1651
  try {
@@ -1373,6 +1685,8 @@ export const verifyPurchaseWithProvider = async options => {
1373
1685
  * Sync iOS purchases with App Store (iOS only)
1374
1686
  * @returns Promise<boolean>
1375
1687
  * @platform iOS
1688
+ *
1689
+ * @see {@link https://www.openiap.dev/docs/apis/ios/sync-ios}
1376
1690
  */
1377
1691
  export const syncIOS = async () => {
1378
1692
  if (Platform.OS !== 'ios') {
@@ -1397,6 +1711,8 @@ export const syncIOS = async () => {
1397
1711
  * Present the code redemption sheet for offer codes (iOS only)
1398
1712
  * @returns Promise<boolean> - Indicates whether the redemption sheet was presented
1399
1713
  * @platform iOS
1714
+ *
1715
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios}
1400
1716
  */
1401
1717
  export const presentCodeRedemptionSheetIOS = async () => {
1402
1718
  if (Platform.OS !== 'ios') {
@@ -1436,6 +1752,8 @@ export const presentCodeRedemptionSheetIOS = async () => {
1436
1752
  *
1437
1753
  * @returns Promise<boolean> - true when the request triggers successfully
1438
1754
  * @platform iOS
1755
+ *
1756
+ * @see {@link https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios}
1439
1757
  */
1440
1758
  export const requestPurchaseOnPromotedProductIOS = async () => {
1441
1759
  if (Platform.OS !== 'ios') {
@@ -1469,6 +1787,8 @@ export const requestPurchaseOnPromotedProductIOS = async () => {
1469
1787
  * Clear unfinished transactions on iOS
1470
1788
  * @returns Promise<boolean>
1471
1789
  * @platform iOS
1790
+ *
1791
+ * @see {@link https://www.openiap.dev/docs/apis/ios/clear-transaction-ios}
1472
1792
  */
1473
1793
  export const clearTransactionIOS = async () => {
1474
1794
  if (Platform.OS !== 'ios') {
@@ -1494,6 +1814,8 @@ export const clearTransactionIOS = async () => {
1494
1814
  * @param sku - The product SKU to refund
1495
1815
  * @returns Promise<string | null> - The refund status or null if not available
1496
1816
  * @platform iOS
1817
+ *
1818
+ * @see {@link https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios}
1497
1819
  */
1498
1820
  export const beginRefundRequestIOS = async sku => {
1499
1821
  if (Platform.OS !== 'ios') {
@@ -1514,72 +1836,11 @@ export const beginRefundRequestIOS = async sku => {
1514
1836
  }
1515
1837
  };
1516
1838
 
1517
- /**
1518
- * Get subscription status for a product (iOS only)
1519
- * @param sku - The product SKU
1520
- * @returns Promise<SubscriptionStatusIOS[]> - Array of subscription status objects
1521
- * @throws Error when called on non-iOS platforms or when IAP is not initialized
1522
- * @platform iOS
1523
- */
1524
- /**
1525
- * Get current entitlement for a product (iOS only)
1526
- * @param sku - The product SKU
1527
- * @returns Promise<Purchase | null> - Current entitlement or null
1528
- * @platform iOS
1529
- */
1530
- /**
1531
- * Get latest transaction for a product (iOS only)
1532
- * @param sku - The product SKU
1533
- * @returns Promise<Purchase | null> - Latest transaction or null
1534
- * @platform iOS
1535
- */
1536
- /**
1537
- * Get pending transactions (iOS only)
1538
- * @returns Promise<Purchase[]> - Array of pending transactions
1539
- * @platform iOS
1540
- */
1541
- /**
1542
- * Show manage subscriptions screen (iOS only)
1543
- * @returns Promise<Purchase[]> - Subscriptions where auto-renewal status changed
1544
- * @platform iOS
1545
- */
1546
- /**
1547
- * Check if user is eligible for intro offer (iOS only)
1548
- * @param groupID - The subscription group ID
1549
- * @returns Promise<boolean> - Eligibility status
1550
- * @platform iOS
1551
- */
1552
- /**
1553
- * Get receipt data (iOS only)
1554
- * @returns Promise<string> - Base64 encoded receipt data
1555
- * @platform iOS
1556
- */
1557
- /**
1558
- * Check if transaction is verified (iOS only)
1559
- * @param sku - The product SKU
1560
- * @returns Promise<boolean> - Verification status
1561
- * @platform iOS
1562
- */
1563
- /**
1564
- * Get transaction JWS representation (iOS only)
1565
- * @param sku - The product SKU
1566
- * @returns Promise<string | null> - JWS representation or null
1567
- * @platform iOS
1568
- */
1569
- /**
1570
- * Get the storefront identifier for the user's App Store account (iOS only)
1571
- * @returns Promise<string> - The storefront identifier (e.g., 'USA' for United States)
1572
- * @platform iOS
1573
- *
1574
- * @example
1575
- * ```typescript
1576
- * const storefront = await getStorefrontIOS();
1577
- * console.log('User storefront:', storefront); // e.g., 'USA', 'GBR', 'KOR'
1578
- * ```
1579
- */
1580
1839
  /**
1581
1840
  * Deeplinks to native interface that allows users to manage their subscriptions
1582
1841
  * Cross-platform alias aligning with expo-iap
1842
+ *
1843
+ * @see {@link https://www.openiap.dev/docs/apis/deep-link-to-subscriptions}
1583
1844
  */
1584
1845
  export const deepLinkToSubscriptions = async options => {
1585
1846
  const resolvedOptions = options ?? undefined;
@@ -1624,25 +1885,6 @@ export const deepLinkToSubscriptionsIOS = async () => {
1624
1885
  }
1625
1886
  };
1626
1887
 
1627
- /**
1628
- * iOS only - Gets the original app transaction ID if the app was purchased from the App Store
1629
- * @platform iOS
1630
- * @description
1631
- * This function retrieves the original app transaction information if the app was purchased
1632
- * from the App Store. Returns null if the app was not purchased (e.g., free app or TestFlight).
1633
- *
1634
- * @returns {Promise<string | null>} The original app transaction ID or null
1635
- *
1636
- * @example
1637
- * ```typescript
1638
- * const appTransaction = await getAppTransactionIOS();
1639
- * if (appTransaction) {
1640
- * console.log('App was purchased, transaction ID:', appTransaction);
1641
- * } else {
1642
- * console.log('App was not purchased from App Store');
1643
- * }
1644
- * ```
1645
- */
1646
1888
  /**
1647
1889
  * Get all active subscriptions with detailed information (OpenIAP compliant)
1648
1890
  * Returns an array of active subscriptions. If subscriptionIds is not provided,
@@ -1655,6 +1897,8 @@ export const deepLinkToSubscriptionsIOS = async () => {
1655
1897
  *
1656
1898
  * @param subscriptionIds - Optional array of subscription IDs to filter by
1657
1899
  * @returns Promise<ActiveSubscription[]> - Array of active subscriptions
1900
+ *
1901
+ * @see {@link https://www.openiap.dev/docs/apis/get-active-subscriptions}
1658
1902
  */
1659
1903
  export const getActiveSubscriptions = async subscriptionIds => {
1660
1904
  try {
@@ -1801,6 +2045,8 @@ export const getActiveSubscriptions_OLD: QueryField<
1801
2045
  *
1802
2046
  * @param subscriptionIds - Optional array of subscription IDs to check
1803
2047
  * @returns Promise<boolean> - True if there are active subscriptions
2048
+ *
2049
+ * @see {@link https://www.openiap.dev/docs/apis/has-active-subscriptions}
1804
2050
  */
1805
2051
  export const hasActiveSubscriptions = async subscriptionIds => {
1806
2052
  try {
@@ -1903,6 +2149,8 @@ const normalizeProductQueryType = type => {
1903
2149
  * // Proceed with alternative billing flow
1904
2150
  * }
1905
2151
  * ```
2152
+ *
2153
+ * @see {@link https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android}
1906
2154
  */
1907
2155
  export const checkAlternativeBillingAvailabilityAndroid = async () => {
1908
2156
  if (Platform.OS !== 'android') {
@@ -1938,6 +2186,8 @@ export const checkAlternativeBillingAvailabilityAndroid = async () => {
1938
2186
  * }
1939
2187
  * }
1940
2188
  * ```
2189
+ *
2190
+ * @see {@link https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android}
1941
2191
  */
1942
2192
  export const showAlternativeBillingDialogAndroid = async () => {
1943
2193
  if (Platform.OS !== 'android') {
@@ -1973,6 +2223,8 @@ export const showAlternativeBillingDialogAndroid = async () => {
1973
2223
  * });
1974
2224
  * }
1975
2225
  * ```
2226
+ *
2227
+ * @see {@link https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android}
1976
2228
  */
1977
2229
  export const createAlternativeBillingTokenAndroid = async sku => {
1978
2230
  if (Platform.OS !== 'android') {
@@ -2040,6 +2292,8 @@ export const enableBillingProgramAndroid = program => {
2040
2292
  * // External offers are available for this user
2041
2293
  * }
2042
2294
  * ```
2295
+ *
2296
+ * @see {@link https://www.openiap.dev/docs/apis/android/is-billing-program-available-android}
2043
2297
  */
2044
2298
  export const isBillingProgramAvailableAndroid = async program => {
2045
2299
  if (Platform.OS !== 'android') {
@@ -2075,6 +2329,8 @@ export const isBillingProgramAvailableAndroid = async program => {
2075
2329
  * body: JSON.stringify({ token: details.externalTransactionToken })
2076
2330
  * });
2077
2331
  * ```
2332
+ *
2333
+ * @see {@link https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android}
2078
2334
  */
2079
2335
  export const createBillingProgramReportingDetailsAndroid = async program => {
2080
2336
  if (Platform.OS !== 'android') {
@@ -2112,6 +2368,8 @@ export const createBillingProgramReportingDetailsAndroid = async program => {
2112
2368
  * console.log('User accepted external link');
2113
2369
  * }
2114
2370
  * ```
2371
+ *
2372
+ * @see {@link https://www.openiap.dev/docs/apis/android/launch-external-link-android}
2115
2373
  */
2116
2374
  export const launchExternalLinkAndroid = async params => {
2117
2375
  if (Platform.OS !== 'android') {
@@ -2135,7 +2393,11 @@ export const launchExternalLinkAndroid = async params => {
2135
2393
  // ------------------------------
2136
2394
 
2137
2395
  /**
2138
- * Check if the device can present an external purchase notice sheet (iOS 18.2+).
2396
+ * Check if the device can present an external purchase notice sheet (iOS 17.4+).
2397
+ *
2398
+ * Wraps `ExternalPurchase.canPresent`, which Apple introduced in iOS 17.4.
2399
+ * Note: the notice sheet itself (`presentExternalPurchaseNoticeSheetIOS`)
2400
+ * still requires iOS 18.2+; only the eligibility check is available earlier.
2139
2401
  *
2140
2402
  * @returns Promise<boolean> - true if notice sheet can be presented
2141
2403
  * @platform iOS
@@ -2148,6 +2410,8 @@ export const launchExternalLinkAndroid = async params => {
2148
2410
  * const result = await presentExternalPurchaseNoticeSheetIOS();
2149
2411
  * }
2150
2412
  * ```
2413
+ *
2414
+ * @see {@link https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios}
2151
2415
  */
2152
2416
  export const canPresentExternalPurchaseNoticeIOS = async () => {
2153
2417
  if (Platform.OS !== 'ios') {
@@ -2176,6 +2440,8 @@ export const canPresentExternalPurchaseNoticeIOS = async () => {
2176
2440
  * await presentExternalPurchaseLinkIOS('https://your-website.com/purchase');
2177
2441
  * }
2178
2442
  * ```
2443
+ *
2444
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios}
2179
2445
  */
2180
2446
  export const presentExternalPurchaseNoticeSheetIOS = async () => {
2181
2447
  if (Platform.OS !== 'ios') {
@@ -2203,6 +2469,8 @@ export const presentExternalPurchaseNoticeSheetIOS = async () => {
2203
2469
  * console.log('User completed external purchase');
2204
2470
  * }
2205
2471
  * ```
2472
+ *
2473
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios}
2206
2474
  */
2207
2475
  export const presentExternalPurchaseLinkIOS = async url => {
2208
2476
  if (Platform.OS !== 'ios') {
@@ -2235,6 +2503,8 @@ export const presentExternalPurchaseLinkIOS = async url => {
2235
2503
  * // App can use custom external purchase links
2236
2504
  * }
2237
2505
  * ```
2506
+ *
2507
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios}
2238
2508
  */
2239
2509
  export const isEligibleForExternalPurchaseCustomLinkIOS = async () => {
2240
2510
  if (Platform.OS !== 'ios') {
@@ -2266,6 +2536,8 @@ export const isEligibleForExternalPurchaseCustomLinkIOS = async () => {
2266
2536
  * await reportToApple(result.token);
2267
2537
  * }
2268
2538
  * ```
2539
+ *
2540
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios}
2269
2541
  */
2270
2542
  export const getExternalPurchaseCustomLinkTokenIOS = async tokenType => {
2271
2543
  if (Platform.OS !== 'ios') {
@@ -2297,6 +2569,8 @@ export const getExternalPurchaseCustomLinkTokenIOS = async tokenType => {
2297
2569
  * await Linking.openURL('https://your-store.com/checkout');
2298
2570
  * }
2299
2571
  * ```
2572
+ *
2573
+ * @see {@link https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios}
2300
2574
  */
2301
2575
  export const showExternalPurchaseCustomLinkNoticeIOS = async noticeType => {
2302
2576
  if (Platform.OS !== 'ios') {