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
package/src/index.ts CHANGED
@@ -124,6 +124,30 @@ export interface EventSubscription {
124
124
 
125
125
  // Export hooks
126
126
  export {useIAP} from './hooks/useIAP';
127
+ export {useWebhookEvents} from './hooks/useWebhookEvents';
128
+ export type {
129
+ UseWebhookEventsOptions,
130
+ UseWebhookEventsResult,
131
+ } from './hooks/useWebhookEvents';
132
+ export {
133
+ connectWebhookStream,
134
+ parseWebhookEventData,
135
+ } from './webhook-client';
136
+ export type {
137
+ WebhookEventPayload,
138
+ WebhookEventStream,
139
+ WebhookEventType as WebhookEventTypeName,
140
+ WebhookListener,
141
+ WebhookListenerError,
142
+ WebhookListenerOptions,
143
+ } from './webhook-client';
144
+ export {kitApi, KitApiError} from './kit-api';
145
+ export type {
146
+ KitApiOptions,
147
+ KitSubscription,
148
+ EntitlementsResponse,
149
+ StatusResponse,
150
+ } from './kit-api';
127
151
 
128
152
  // Restore completed transactions (cross-platform)
129
153
  // Development utilities removed - use type bridge functions directly if needed
@@ -279,12 +303,14 @@ export const resetListenerState = (): void => {
279
303
  promotedProductNativeAttached = false;
280
304
  userChoiceBillingNativeAttached = false;
281
305
  developerProvidedBillingNativeAttached = false;
306
+ subscriptionBillingIssueNativeAttached = false;
282
307
  // Clear all JS listeners since native side clears them in endConnection
283
308
  purchaseUpdateJsListeners.clear();
284
309
  purchaseErrorJsListeners.clear();
285
310
  promotedProductJsListeners.clear();
286
311
  userChoiceBillingJsListeners.clear();
287
312
  developerProvidedBillingJsListeners.clear();
313
+ subscriptionBillingIssueJsListeners.clear();
288
314
  };
289
315
 
290
316
  export const purchaseUpdatedListener = (
@@ -565,25 +591,123 @@ export const developerProvidedBillingListenerAndroid = (
565
591
  };
566
592
  };
567
593
 
594
+ /**
595
+ * Listen for subscription billing-issue events (cross-platform).
596
+ *
597
+ * Fires when an active subscription enters a billing-issue state:
598
+ * - iOS 18+ / Mac Catalyst 18+: via StoreKit 2 `Message.Reason.billingIssue`.
599
+ * - Android (Play Billing 8.1+): when `isSuspendedAndroid === true` is observed.
600
+ * - Horizon / iOS 17 / older platforms: never fires.
601
+ *
602
+ * Recommended UX: on fire, call `deepLinkToSubscriptions()` so the user can
603
+ * update their payment method in the platform subscription center.
604
+ *
605
+ * @param listener - Function to call with the affected Purchase
606
+ * @returns EventSubscription with remove() method to unsubscribe
607
+ *
608
+ * @example
609
+ * ```typescript
610
+ * const subscription = subscriptionBillingIssueListener((purchase) => {
611
+ * console.warn('Subscription needs attention:', purchase.productId);
612
+ * deepLinkToSubscriptions({skuAndroid: purchase.productId, packageNameAndroid: 'com.example.app'});
613
+ * });
614
+ *
615
+ * subscription.remove();
616
+ * ```
617
+ */
618
+ type NitroSubscriptionBillingIssueListener = Parameters<
619
+ RnIap['addSubscriptionBillingIssueListener']
620
+ >[0];
621
+
622
+ const subscriptionBillingIssueJsListeners = new Set<(purchase: Purchase) => void>();
623
+ let subscriptionBillingIssueNativeAttached = false;
624
+ const subscriptionBillingIssueNativeHandler: NitroSubscriptionBillingIssueListener =
625
+ (nitroPurchase) => {
626
+ if (!validateNitroPurchase(nitroPurchase)) {
627
+ RnIapConsole.warn(
628
+ '[subscriptionBillingIssueListener] dropped malformed native payload',
629
+ );
630
+ return;
631
+ }
632
+ const purchase = convertNitroPurchaseToPurchase(nitroPurchase);
633
+ for (const listener of subscriptionBillingIssueJsListeners) {
634
+ try {
635
+ listener(purchase);
636
+ } catch (e) {
637
+ RnIapConsole.error(
638
+ '[subscriptionBillingIssueListener] callback threw:',
639
+ e,
640
+ );
641
+ }
642
+ }
643
+ };
644
+
645
+ function tryAttachSubscriptionBillingIssueNative(): void {
646
+ if (subscriptionBillingIssueNativeAttached) return;
647
+ try {
648
+ IAP.instance.addSubscriptionBillingIssueListener(
649
+ subscriptionBillingIssueNativeHandler,
650
+ );
651
+ subscriptionBillingIssueNativeAttached = true;
652
+ } catch (e) {
653
+ const msg = toErrorMessage(e);
654
+ if (msg.includes('Nitro runtime not installed')) {
655
+ RnIapConsole.warn(
656
+ '[subscriptionBillingIssueListener] Nitro not ready yet; will retry on next registration after initConnection()',
657
+ );
658
+ } else {
659
+ throw e;
660
+ }
661
+ }
662
+ }
663
+
664
+ export const subscriptionBillingIssueListener = (
665
+ listener: (purchase: Purchase) => void,
666
+ ): EventSubscription => {
667
+ subscriptionBillingIssueJsListeners.add(listener);
668
+ // Retry attachment every call so a listener registered before initConnection()
669
+ // doesn't stay permanently inert once Nitro is ready.
670
+ try {
671
+ tryAttachSubscriptionBillingIssueNative();
672
+ } catch (error) {
673
+ subscriptionBillingIssueJsListeners.delete(listener);
674
+ throw error;
675
+ }
676
+
677
+ return {
678
+ remove: () => {
679
+ subscriptionBillingIssueJsListeners.delete(listener);
680
+ },
681
+ };
682
+ };
683
+
568
684
  // ------------------------------
569
685
  // Query API
570
686
  // ------------------------------
571
687
 
572
688
  /**
573
- * Fetch products from the store
574
- * @param params - Product request configuration
575
- * @param params.skus - Array of product SKUs to fetch
576
- * @param params.type - Optional filter: 'in-app' (default) for products, 'subs' for subscriptions, or 'all' for both.
577
- * @returns Promise<Product[]> - Array of products from the store
689
+ * Retrieve products or subscriptions from the store by SKU.
578
690
  *
579
- * @example
580
- * ```typescript
581
- * // Regular products
582
- * const products = await fetchProducts({ skus: ['product1', 'product2'] });
691
+ * @param request `ProductRequest` — `skus` (string[]) and optional `type`
692
+ * (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
693
+ * @returns Promise resolving to a `FetchProductsResult` union — `Product[]` for `'in-app'`,
694
+ * `ProductSubscription[]` for `'subs'`, a mixed array for `'all'`, or `null`
695
+ * (the schema retains the nullable branch for backwards compatibility).
696
+ * @throws When the store rejects the request (empty `skus`, not connected,
697
+ * network/store error). Unknown SKUs are simply omitted from the result, not thrown.
583
698
  *
584
- * // Subscriptions
585
- * const subscriptions = await fetchProducts({ skus: ['sub1', 'sub2'], type: 'subs' });
699
+ * @example
700
+ * ```ts
701
+ * const products = await fetchProducts({
702
+ * skus: ['com.app.coins_100', 'com.app.premium'],
703
+ * type: 'in-app',
704
+ * });
586
705
  * ```
706
+ *
707
+ * @remarks This is a regular promise-based call. Don't confuse with `request*` APIs
708
+ * (`requestPurchase`), which are event-based.
709
+ *
710
+ * @see {@link https://www.openiap.dev/docs/apis/fetch-products}
587
711
  */
588
712
  export const fetchProducts: QueryField<'fetchProducts'> = async (request) => {
589
713
  const {skus, type} = request;
@@ -692,22 +816,40 @@ export const fetchProducts: QueryField<'fetchProducts'> = async (request) => {
692
816
  return convertedProducts as FetchProductsResult;
693
817
  } catch (error) {
694
818
  RnIapConsole.error('[fetchProducts] Failed:', error);
695
- throw error;
819
+ const parsedError = parseErrorStringToJsonObj(error);
820
+ throw createPurchaseError({
821
+ code: parsedError.code,
822
+ message: parsedError.message,
823
+ responseCode: parsedError.responseCode,
824
+ debugMessage: parsedError.debugMessage,
825
+ productId: parsedError.productId,
826
+ productIds: parsedError.productIds,
827
+ productType: parsedError.productType,
828
+ isEmptyProductList: parsedError.isEmptyProductList,
829
+ platform: Platform.OS === 'ios' ? 'ios' : 'android',
830
+ });
696
831
  }
697
832
  };
698
833
 
699
834
  /**
700
- * Get available purchases (purchased items not yet consumed/finished)
701
- * @param params - Options for getting available purchases
702
- * @param params.alsoPublishToEventListener - Whether to also publish to event listener
703
- * @param params.onlyIncludeActiveItems - Whether to only include active items
835
+ * List the user's unfinished purchases non-consumables, active subscriptions, and any
836
+ * pending transactions not yet finished.
837
+ *
838
+ * @param options Optional `PurchaseOptions`.
839
+ * - iOS: `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.
840
+ * - Android: `includeSuspendedAndroid` (include subscriptions in a paused/grace state).
841
+ * @returns Promise resolving to an array of `Purchase` currently held by the store.
842
+ * @throws When the platform query fails.
704
843
  *
705
844
  * @example
706
- * ```typescript
707
- * const purchases = await getAvailablePurchases({
708
- * onlyIncludeActiveItemsIOS: true
709
- * });
845
+ * ```ts
846
+ * const purchases = await getAvailablePurchases();
847
+ * for (const p of purchases) {
848
+ * if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });
849
+ * }
710
850
  * ```
851
+ *
852
+ * @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}
711
853
  */
712
854
  export const getAvailablePurchases: QueryField<
713
855
  'getAvailablePurchases'
@@ -774,6 +916,8 @@ export const getAvailablePurchases: QueryField<
774
916
  * Request the promoted product from the App Store (iOS only)
775
917
  * @returns Promise<Product | null> - The promoted product or null if none available
776
918
  * @platform iOS
919
+ *
920
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios}
777
921
  */
778
922
  export const getPromotedProductIOS: QueryField<
779
923
  'getPromotedProductIOS'
@@ -806,6 +950,19 @@ export const getPromotedProductIOS: QueryField<
806
950
 
807
951
  export const requestPromotedProductIOS = getPromotedProductIOS;
808
952
 
953
+ /**
954
+ * Get the storefront identifier for the user's App Store account (iOS only)
955
+ * @returns Promise<string> - The storefront identifier (e.g., 'USA' for United States)
956
+ * @platform iOS
957
+ *
958
+ * @example
959
+ * ```typescript
960
+ * const storefront = await getStorefrontIOS();
961
+ * console.log('User storefront:', storefront); // e.g., 'USA', 'GBR', 'KOR'
962
+ * ```
963
+ *
964
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-storefront-ios}
965
+ */
809
966
  export const getStorefrontIOS: QueryField<'getStorefrontIOS'> = async () => {
810
967
  if (Platform.OS !== 'ios') {
811
968
  throw new Error('getStorefrontIOS is only available on iOS');
@@ -820,6 +977,11 @@ export const getStorefrontIOS: QueryField<'getStorefrontIOS'> = async () => {
820
977
  }
821
978
  };
822
979
 
980
+ /**
981
+ * Return the user's storefront country code.
982
+ *
983
+ * @see {@link https://www.openiap.dev/docs/apis/get-storefront}
984
+ */
823
985
  export const getStorefront: QueryField<'getStorefront'> = async () => {
824
986
  if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
825
987
  RnIapConsole.warn(
@@ -853,6 +1015,27 @@ export const getStorefront: QueryField<'getStorefront'> = async () => {
853
1015
  }
854
1016
  };
855
1017
 
1018
+ /**
1019
+ * iOS only - Gets the original app transaction ID if the app was purchased from the App Store
1020
+ * @platform iOS
1021
+ * @description
1022
+ * This function retrieves the original app transaction information if the app was purchased
1023
+ * from the App Store. Returns null if the app was not purchased (e.g., free app or TestFlight).
1024
+ *
1025
+ * @returns {Promise<string | null>} The original app transaction ID or null
1026
+ *
1027
+ * @example
1028
+ * ```typescript
1029
+ * const appTransaction = await getAppTransactionIOS();
1030
+ * if (appTransaction) {
1031
+ * console.log('App was purchased, transaction ID:', appTransaction);
1032
+ * } else {
1033
+ * console.log('App was not purchased from App Store');
1034
+ * }
1035
+ * ```
1036
+ *
1037
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios}
1038
+ */
856
1039
  export const getAppTransactionIOS: QueryField<
857
1040
  'getAppTransactionIOS'
858
1041
  > = async () => {
@@ -885,6 +1068,15 @@ export const getAppTransactionIOS: QueryField<
885
1068
  }
886
1069
  };
887
1070
 
1071
+ /**
1072
+ * Get subscription status for a product (iOS only)
1073
+ * @param sku - The product SKU
1074
+ * @returns Promise<SubscriptionStatusIOS[]> - Array of subscription status objects
1075
+ * @throws Error when called on non-iOS platforms or when IAP is not initialized
1076
+ * @platform iOS
1077
+ *
1078
+ * @see {@link https://www.openiap.dev/docs/apis/ios/subscription-status-ios}
1079
+ */
888
1080
  export const subscriptionStatusIOS: QueryField<
889
1081
  'subscriptionStatusIOS'
890
1082
  > = async (sku) => {
@@ -910,6 +1102,14 @@ export const subscriptionStatusIOS: QueryField<
910
1102
  }
911
1103
  };
912
1104
 
1105
+ /**
1106
+ * Get current entitlement for a product (iOS only)
1107
+ * @param sku - The product SKU
1108
+ * @returns Promise<Purchase | null> - Current entitlement or null
1109
+ * @platform iOS
1110
+ *
1111
+ * @see {@link https://www.openiap.dev/docs/apis/ios/current-entitlement-ios}
1112
+ */
913
1113
  export const currentEntitlementIOS: QueryField<
914
1114
  'currentEntitlementIOS'
915
1115
  > = async (sku) => {
@@ -936,6 +1136,14 @@ export const currentEntitlementIOS: QueryField<
936
1136
  }
937
1137
  };
938
1138
 
1139
+ /**
1140
+ * Get latest transaction for a product (iOS only)
1141
+ * @param sku - The product SKU
1142
+ * @returns Promise<Purchase | null> - Latest transaction or null
1143
+ * @platform iOS
1144
+ *
1145
+ * @see {@link https://www.openiap.dev/docs/apis/ios/latest-transaction-ios}
1146
+ */
939
1147
  export const latestTransactionIOS: QueryField<'latestTransactionIOS'> = async (
940
1148
  sku,
941
1149
  ) => {
@@ -962,6 +1170,13 @@ export const latestTransactionIOS: QueryField<'latestTransactionIOS'> = async (
962
1170
  }
963
1171
  };
964
1172
 
1173
+ /**
1174
+ * Get pending transactions (iOS only)
1175
+ * @returns Promise<Purchase[]> - Array of pending transactions
1176
+ * @platform iOS
1177
+ *
1178
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios}
1179
+ */
965
1180
  export const getPendingTransactionsIOS: QueryField<
966
1181
  'getPendingTransactionsIOS'
967
1182
  > = async () => {
@@ -988,6 +1203,44 @@ export const getPendingTransactionsIOS: QueryField<
988
1203
  }
989
1204
  };
990
1205
 
1206
+ /**
1207
+ * List every StoreKit transaction (finished + unfinished) for the current user.
1208
+ *
1209
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios}
1210
+ */
1211
+ export const getAllTransactionsIOS: QueryField<
1212
+ 'getAllTransactionsIOS'
1213
+ > = async () => {
1214
+ if (Platform.OS !== 'ios') {
1215
+ return [];
1216
+ }
1217
+
1218
+ try {
1219
+ const nitroPurchases = await IAP.instance.getAllTransactionsIOS();
1220
+ return nitroPurchases
1221
+ .map(convertNitroPurchaseToPurchase)
1222
+ .filter(
1223
+ (purchase): purchase is PurchaseIOS => purchase.platform === 'ios',
1224
+ );
1225
+ } catch (error) {
1226
+ RnIapConsole.error('[getAllTransactionsIOS] Failed:', error);
1227
+ const parsedError = parseErrorStringToJsonObj(error);
1228
+ throw createPurchaseError({
1229
+ code: parsedError.code,
1230
+ message: parsedError.message,
1231
+ responseCode: parsedError.responseCode,
1232
+ debugMessage: parsedError.debugMessage,
1233
+ });
1234
+ }
1235
+ };
1236
+
1237
+ /**
1238
+ * Show manage subscriptions screen (iOS only)
1239
+ * @returns Promise<Purchase[]> - Subscriptions where auto-renewal status changed
1240
+ * @platform iOS
1241
+ *
1242
+ * @see {@link https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios}
1243
+ */
991
1244
  export const showManageSubscriptionsIOS: MutationField<
992
1245
  'showManageSubscriptionsIOS'
993
1246
  > = async () => {
@@ -1014,6 +1267,14 @@ export const showManageSubscriptionsIOS: MutationField<
1014
1267
  }
1015
1268
  };
1016
1269
 
1270
+ /**
1271
+ * Check if user is eligible for intro offer (iOS only)
1272
+ * @param groupID - The subscription group ID
1273
+ * @returns Promise<boolean> - Eligibility status
1274
+ * @platform iOS
1275
+ *
1276
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios}
1277
+ */
1017
1278
  export const isEligibleForIntroOfferIOS: QueryField<
1018
1279
  'isEligibleForIntroOfferIOS'
1019
1280
  > = async (groupID) => {
@@ -1035,6 +1296,13 @@ export const isEligibleForIntroOfferIOS: QueryField<
1035
1296
  }
1036
1297
  };
1037
1298
 
1299
+ /**
1300
+ * Get receipt data (iOS only)
1301
+ * @returns Promise<string> - Base64 encoded receipt data
1302
+ * @platform iOS
1303
+ *
1304
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios}
1305
+ */
1038
1306
  export const getReceiptDataIOS: QueryField<'getReceiptDataIOS'> = async () => {
1039
1307
  if (Platform.OS !== 'ios') {
1040
1308
  throw new Error('getReceiptDataIOS is only available on iOS');
@@ -1116,6 +1384,14 @@ export const requestReceiptRefreshIOS = async (): Promise<string> => {
1116
1384
  }
1117
1385
  };
1118
1386
 
1387
+ /**
1388
+ * Check if transaction is verified (iOS only)
1389
+ * @param sku - The product SKU
1390
+ * @returns Promise<boolean> - Verification status
1391
+ * @platform iOS
1392
+ *
1393
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios}
1394
+ */
1119
1395
  export const isTransactionVerifiedIOS: QueryField<
1120
1396
  'isTransactionVerifiedIOS'
1121
1397
  > = async (sku) => {
@@ -1137,6 +1413,14 @@ export const isTransactionVerifiedIOS: QueryField<
1137
1413
  }
1138
1414
  };
1139
1415
 
1416
+ /**
1417
+ * Get transaction JWS representation (iOS only)
1418
+ * @param sku - The product SKU
1419
+ * @returns Promise<string | null> - JWS representation or null
1420
+ * @platform iOS
1421
+ *
1422
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios}
1423
+ */
1140
1424
  export const getTransactionJwsIOS: QueryField<'getTransactionJwsIOS'> = async (
1141
1425
  sku,
1142
1426
  ) => {
@@ -1163,25 +1447,23 @@ export const getTransactionJwsIOS: QueryField<'getTransactionJwsIOS'> = async (
1163
1447
  // ------------------------------
1164
1448
 
1165
1449
  /**
1166
- * Initialize connection to the store
1167
- * @param config - Optional configuration including alternative billing mode for Android
1168
- * @param config.alternativeBillingModeAndroid - Alternative billing mode: 'none', 'user-choice', or 'alternative-only'
1450
+ * Initialize the store connection. Must be called before any other IAP API.
1451
+ *
1452
+ * @param config Optional connection config. Use `enableBillingProgramAndroid` (Android,
1453
+ * Play Billing 8.2.0+) to opt into External Payments etc. iOS ignores Android-specific fields.
1454
+ * @returns Promise resolving to `true` when the platform billing client is connected.
1455
+ * @throws When the platform billing client fails to initialize.
1169
1456
  *
1170
1457
  * @example
1171
- * ```typescript
1172
- * // Standard billing (default)
1458
+ * ```ts
1173
1459
  * await initConnection();
1460
+ * await initConnection({ enableBillingProgramAndroid: 'external-offer' });
1461
+ * ```
1174
1462
  *
1175
- * // User choice billing (Android)
1176
- * await initConnection({
1177
- * alternativeBillingModeAndroid: 'user-choice'
1178
- * });
1463
+ * @remarks When using `useIAP()`, connection is auto-managed on mount/unmount —
1464
+ * pass options to the hook instead of calling this directly.
1179
1465
  *
1180
- * // Alternative billing only (Android)
1181
- * await initConnection({
1182
- * alternativeBillingModeAndroid: 'alternative-only'
1183
- * });
1184
- * ```
1466
+ * @see {@link https://www.openiap.dev/docs/apis/init-connection}
1185
1467
  */
1186
1468
  export const initConnection: MutationField<'initConnection'> = async (
1187
1469
  config,
@@ -1203,7 +1485,9 @@ export const initConnection: MutationField<'initConnection'> = async (
1203
1485
  };
1204
1486
 
1205
1487
  /**
1206
- * End connection to the store
1488
+ * Close the store connection and release resources.
1489
+ *
1490
+ * @see {@link https://www.openiap.dev/docs/apis/end-connection}
1207
1491
  */
1208
1492
  export const endConnection: MutationField<'endConnection'> = async () => {
1209
1493
  try {
@@ -1223,6 +1507,11 @@ export const endConnection: MutationField<'endConnection'> = async () => {
1223
1507
  }
1224
1508
  };
1225
1509
 
1510
+ /**
1511
+ * Restore non-consumable and active subscription purchases.
1512
+ *
1513
+ * @see {@link https://www.openiap.dev/docs/apis/restore-purchases}
1514
+ */
1226
1515
  export const restorePurchases: MutationField<'restorePurchases'> = async () => {
1227
1516
  try {
1228
1517
  if (Platform.OS === 'ios') {
@@ -1246,9 +1535,30 @@ export const restorePurchases: MutationField<'restorePurchases'> = async () => {
1246
1535
  };
1247
1536
 
1248
1537
  /**
1249
- * Request a purchase for products or subscriptions
1250
- * ⚠️ Important: This is an event-based operation, not promise-based.
1251
- * Listen for events through purchaseUpdatedListener or purchaseErrorListener.
1538
+ * Initiate a purchase or subscription flow. The result is delivered through
1539
+ * `purchaseUpdatedListener` NOT the return value.
1540
+ *
1541
+ * @param request `RequestPurchaseProps`, discriminated by `type`:
1542
+ * - `type: 'in-app'` — pass `request.apple.sku` (iOS) and/or `request.google.skus` (Android).
1543
+ * - `type: 'subs'` — same shape, plus `request.google.subscriptionOffers: [{ sku, offerToken }]`.
1544
+ * @returns The dispatched purchase payload. **Do not rely on it** for the actual outcome.
1545
+ * @throws Synchronous rejection from the store (e.g. `E_NOT_PREPARED`, validation failure).
1546
+ *
1547
+ * @example
1548
+ * ```ts
1549
+ * await requestPurchase({
1550
+ * request: {
1551
+ * apple: { sku: 'com.app.premium' },
1552
+ * google: { skus: ['com.app.premium'] },
1553
+ * },
1554
+ * type: 'in-app',
1555
+ * });
1556
+ * ```
1557
+ *
1558
+ * @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /
1559
+ * {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.
1560
+ *
1561
+ * @see {@link https://www.openiap.dev/docs/apis/request-purchase}
1252
1562
  */
1253
1563
  export const requestPurchase: MutationField<'requestPurchase'> = async (
1254
1564
  request,
@@ -1395,19 +1705,28 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
1395
1705
  };
1396
1706
 
1397
1707
  /**
1398
- * Finish a transaction (consume or acknowledge)
1399
- * @param params - Transaction finish parameters
1400
- * @param params.purchase - The purchase to finish
1401
- * @param params.isConsumable - Whether this is a consumable product (Android only)
1402
- * @returns Promise<void> - Resolves when the transaction is successfully finished
1708
+ * Complete a purchase transaction. Call after server-side verification to remove it
1709
+ * from the queue.
1710
+ *
1711
+ * @param args.purchase The `Purchase` to finalize.
1712
+ * @param args.isConsumable `true` for consumables (consumes the token so the SKU can be
1713
+ * re-bought, e.g. coins); `false` (default) for non-consumables and subscriptions.
1714
+ * @returns Promise that resolves once the platform finalizes the transaction.
1715
+ * @throws When the platform finalize call fails.
1403
1716
  *
1404
1717
  * @example
1405
- * ```typescript
1406
- * await finishTransaction({
1407
- * purchase: myPurchase,
1408
- * isConsumable: true
1718
+ * ```ts
1719
+ * purchaseUpdatedListener(async (purchase) => {
1720
+ * if (await verifyOnServer(purchase)) {
1721
+ * await finishTransaction({ purchase, isConsumable: false });
1722
+ * }
1409
1723
  * });
1410
1724
  * ```
1725
+ *
1726
+ * @remarks **Critical:** Android purchases must be finalized within 3 days or Google
1727
+ * auto-refunds. iOS unfinished transactions replay on every app launch.
1728
+ *
1729
+ * @see {@link https://www.openiap.dev/docs/apis/finish-transaction}
1411
1730
  */
1412
1731
  export const finishTransaction: MutationField<'finishTransaction'> = async (
1413
1732
  args,
@@ -1475,6 +1794,8 @@ export const finishTransaction: MutationField<'finishTransaction'> = async (
1475
1794
  * ```typescript
1476
1795
  * await acknowledgePurchaseAndroid('purchase_token_here');
1477
1796
  * ```
1797
+ *
1798
+ * @see {@link https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android}
1478
1799
  */
1479
1800
  export const acknowledgePurchaseAndroid: MutationField<
1480
1801
  'acknowledgePurchaseAndroid'
@@ -1514,6 +1835,8 @@ export const acknowledgePurchaseAndroid: MutationField<
1514
1835
  * ```typescript
1515
1836
  * await consumePurchaseAndroid('purchase_token_here');
1516
1837
  * ```
1838
+ *
1839
+ * @see {@link https://www.openiap.dev/docs/apis/android/consume-purchase-android}
1517
1840
  */
1518
1841
  export const consumePurchaseAndroid: MutationField<
1519
1842
  'consumePurchaseAndroid'
@@ -1569,6 +1892,8 @@ export const consumePurchaseAndroid: MutationField<
1569
1892
  * }
1570
1893
  * });
1571
1894
  * ```
1895
+ *
1896
+ * @see {@link https://www.openiap.dev/docs/apis/validate-receipt}
1572
1897
  */
1573
1898
  export const validateReceipt: MutationField<'validateReceipt'> = async (
1574
1899
  options,
@@ -1698,9 +2023,30 @@ export const validateReceipt: MutationField<'validateReceipt'> = async (
1698
2023
  *
1699
2024
  * @param options - Receipt validation options containing the SKU
1700
2025
  * @returns Promise resolving to receipt validation result
2026
+ *
2027
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase}
1701
2028
  */
1702
2029
  export const verifyPurchase: MutationField<'verifyPurchase'> = validateReceipt;
1703
2030
 
2031
+ /**
2032
+ * iOS-only receipt validation alias.
2033
+ *
2034
+ * @deprecated Use `verifyPurchase` (or `validateReceipt`) instead. Kept so
2035
+ * consumers who imported `validateReceiptIOS` — which is still declared on the
2036
+ * OpenIAP Query interface — keep working. Throws on non-iOS platforms.
2037
+ *
2038
+ * @see {@link https://www.openiap.dev/docs/apis/ios/validate-receipt-ios}
2039
+ */
2040
+ export const validateReceiptIOS: QueryField<'validateReceiptIOS'> = async (
2041
+ options,
2042
+ ) => {
2043
+ if (Platform.OS !== 'ios') {
2044
+ throw new Error('validateReceiptIOS is only available on iOS');
2045
+ }
2046
+ const result = await validateReceipt(options);
2047
+ return result as VerifyPurchaseResultIOS;
2048
+ };
2049
+
1704
2050
  /**
1705
2051
  * Verify purchase with a specific provider (e.g., IAPKit)
1706
2052
  *
@@ -1721,6 +2067,8 @@ export const verifyPurchase: MutationField<'verifyPurchase'> = validateReceipt;
1721
2067
  * },
1722
2068
  * });
1723
2069
  * ```
2070
+ *
2071
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}
1724
2072
  */
1725
2073
  export const verifyPurchaseWithProvider: MutationField<
1726
2074
  'verifyPurchaseWithProvider'
@@ -1764,6 +2112,8 @@ export const verifyPurchaseWithProvider: MutationField<
1764
2112
  * Sync iOS purchases with App Store (iOS only)
1765
2113
  * @returns Promise<boolean>
1766
2114
  * @platform iOS
2115
+ *
2116
+ * @see {@link https://www.openiap.dev/docs/apis/ios/sync-ios}
1767
2117
  */
1768
2118
  export const syncIOS: MutationField<'syncIOS'> = async () => {
1769
2119
  if (Platform.OS !== 'ios') {
@@ -1789,6 +2139,8 @@ export const syncIOS: MutationField<'syncIOS'> = async () => {
1789
2139
  * Present the code redemption sheet for offer codes (iOS only)
1790
2140
  * @returns Promise<boolean> - Indicates whether the redemption sheet was presented
1791
2141
  * @platform iOS
2142
+ *
2143
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios}
1792
2144
  */
1793
2145
  export const presentCodeRedemptionSheetIOS: MutationField<
1794
2146
  'presentCodeRedemptionSheetIOS'
@@ -1831,6 +2183,8 @@ export const presentCodeRedemptionSheetIOS: MutationField<
1831
2183
  *
1832
2184
  * @returns Promise<boolean> - true when the request triggers successfully
1833
2185
  * @platform iOS
2186
+ *
2187
+ * @see {@link https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios}
1834
2188
  */
1835
2189
  export const requestPurchaseOnPromotedProductIOS =
1836
2190
  async (): Promise<boolean> => {
@@ -1873,6 +2227,8 @@ export const requestPurchaseOnPromotedProductIOS =
1873
2227
  * Clear unfinished transactions on iOS
1874
2228
  * @returns Promise<boolean>
1875
2229
  * @platform iOS
2230
+ *
2231
+ * @see {@link https://www.openiap.dev/docs/apis/ios/clear-transaction-ios}
1876
2232
  */
1877
2233
  export const clearTransactionIOS: MutationField<
1878
2234
  'clearTransactionIOS'
@@ -1901,6 +2257,8 @@ export const clearTransactionIOS: MutationField<
1901
2257
  * @param sku - The product SKU to refund
1902
2258
  * @returns Promise<string | null> - The refund status or null if not available
1903
2259
  * @platform iOS
2260
+ *
2261
+ * @see {@link https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios}
1904
2262
  */
1905
2263
  export const beginRefundRequestIOS: MutationField<
1906
2264
  'beginRefundRequestIOS'
@@ -1924,72 +2282,11 @@ export const beginRefundRequestIOS: MutationField<
1924
2282
  }
1925
2283
  };
1926
2284
 
1927
- /**
1928
- * Get subscription status for a product (iOS only)
1929
- * @param sku - The product SKU
1930
- * @returns Promise<SubscriptionStatusIOS[]> - Array of subscription status objects
1931
- * @throws Error when called on non-iOS platforms or when IAP is not initialized
1932
- * @platform iOS
1933
- */
1934
- /**
1935
- * Get current entitlement for a product (iOS only)
1936
- * @param sku - The product SKU
1937
- * @returns Promise<Purchase | null> - Current entitlement or null
1938
- * @platform iOS
1939
- */
1940
- /**
1941
- * Get latest transaction for a product (iOS only)
1942
- * @param sku - The product SKU
1943
- * @returns Promise<Purchase | null> - Latest transaction or null
1944
- * @platform iOS
1945
- */
1946
- /**
1947
- * Get pending transactions (iOS only)
1948
- * @returns Promise<Purchase[]> - Array of pending transactions
1949
- * @platform iOS
1950
- */
1951
- /**
1952
- * Show manage subscriptions screen (iOS only)
1953
- * @returns Promise<Purchase[]> - Subscriptions where auto-renewal status changed
1954
- * @platform iOS
1955
- */
1956
- /**
1957
- * Check if user is eligible for intro offer (iOS only)
1958
- * @param groupID - The subscription group ID
1959
- * @returns Promise<boolean> - Eligibility status
1960
- * @platform iOS
1961
- */
1962
- /**
1963
- * Get receipt data (iOS only)
1964
- * @returns Promise<string> - Base64 encoded receipt data
1965
- * @platform iOS
1966
- */
1967
- /**
1968
- * Check if transaction is verified (iOS only)
1969
- * @param sku - The product SKU
1970
- * @returns Promise<boolean> - Verification status
1971
- * @platform iOS
1972
- */
1973
- /**
1974
- * Get transaction JWS representation (iOS only)
1975
- * @param sku - The product SKU
1976
- * @returns Promise<string | null> - JWS representation or null
1977
- * @platform iOS
1978
- */
1979
- /**
1980
- * Get the storefront identifier for the user's App Store account (iOS only)
1981
- * @returns Promise<string> - The storefront identifier (e.g., 'USA' for United States)
1982
- * @platform iOS
1983
- *
1984
- * @example
1985
- * ```typescript
1986
- * const storefront = await getStorefrontIOS();
1987
- * console.log('User storefront:', storefront); // e.g., 'USA', 'GBR', 'KOR'
1988
- * ```
1989
- */
1990
2285
  /**
1991
2286
  * Deeplinks to native interface that allows users to manage their subscriptions
1992
2287
  * Cross-platform alias aligning with expo-iap
2288
+ *
2289
+ * @see {@link https://www.openiap.dev/docs/apis/deep-link-to-subscriptions}
1993
2290
  */
1994
2291
  export const deepLinkToSubscriptions: MutationField<
1995
2292
  'deepLinkToSubscriptions'
@@ -2039,25 +2336,6 @@ export const deepLinkToSubscriptionsIOS = async (): Promise<boolean> => {
2039
2336
  }
2040
2337
  };
2041
2338
 
2042
- /**
2043
- * iOS only - Gets the original app transaction ID if the app was purchased from the App Store
2044
- * @platform iOS
2045
- * @description
2046
- * This function retrieves the original app transaction information if the app was purchased
2047
- * from the App Store. Returns null if the app was not purchased (e.g., free app or TestFlight).
2048
- *
2049
- * @returns {Promise<string | null>} The original app transaction ID or null
2050
- *
2051
- * @example
2052
- * ```typescript
2053
- * const appTransaction = await getAppTransactionIOS();
2054
- * if (appTransaction) {
2055
- * console.log('App was purchased, transaction ID:', appTransaction);
2056
- * } else {
2057
- * console.log('App was not purchased from App Store');
2058
- * }
2059
- * ```
2060
- */
2061
2339
  /**
2062
2340
  * Get all active subscriptions with detailed information (OpenIAP compliant)
2063
2341
  * Returns an array of active subscriptions. If subscriptionIds is not provided,
@@ -2070,6 +2348,8 @@ export const deepLinkToSubscriptionsIOS = async (): Promise<boolean> => {
2070
2348
  *
2071
2349
  * @param subscriptionIds - Optional array of subscription IDs to filter by
2072
2350
  * @returns Promise<ActiveSubscription[]> - Array of active subscriptions
2351
+ *
2352
+ * @see {@link https://www.openiap.dev/docs/apis/get-active-subscriptions}
2073
2353
  */
2074
2354
  export const getActiveSubscriptions: QueryField<
2075
2355
  'getActiveSubscriptions'
@@ -2229,6 +2509,8 @@ export const getActiveSubscriptions_OLD: QueryField<
2229
2509
  *
2230
2510
  * @param subscriptionIds - Optional array of subscription IDs to check
2231
2511
  * @returns Promise<boolean> - True if there are active subscriptions
2512
+ *
2513
+ * @see {@link https://www.openiap.dev/docs/apis/has-active-subscriptions}
2232
2514
  */
2233
2515
  export const hasActiveSubscriptions: QueryField<
2234
2516
  'hasActiveSubscriptions'
@@ -2356,6 +2638,8 @@ const normalizeProductQueryType = (
2356
2638
  * // Proceed with alternative billing flow
2357
2639
  * }
2358
2640
  * ```
2641
+ *
2642
+ * @see {@link https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android}
2359
2643
  */
2360
2644
  export const checkAlternativeBillingAvailabilityAndroid: MutationField<
2361
2645
  'checkAlternativeBillingAvailabilityAndroid'
@@ -2396,6 +2680,8 @@ export const checkAlternativeBillingAvailabilityAndroid: MutationField<
2396
2680
  * }
2397
2681
  * }
2398
2682
  * ```
2683
+ *
2684
+ * @see {@link https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android}
2399
2685
  */
2400
2686
  export const showAlternativeBillingDialogAndroid: MutationField<
2401
2687
  'showAlternativeBillingDialogAndroid'
@@ -2433,6 +2719,8 @@ export const showAlternativeBillingDialogAndroid: MutationField<
2433
2719
  * });
2434
2720
  * }
2435
2721
  * ```
2722
+ *
2723
+ * @see {@link https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android}
2436
2724
  */
2437
2725
  export const createAlternativeBillingTokenAndroid: MutationField<
2438
2726
  'createAlternativeBillingTokenAndroid'
@@ -2528,6 +2816,8 @@ export const enableBillingProgramAndroid = (
2528
2816
  * // External offers are available for this user
2529
2817
  * }
2530
2818
  * ```
2819
+ *
2820
+ * @see {@link https://www.openiap.dev/docs/apis/android/is-billing-program-available-android}
2531
2821
  */
2532
2822
  export const isBillingProgramAvailableAndroid: MutationField<
2533
2823
  'isBillingProgramAvailableAndroid'
@@ -2567,6 +2857,8 @@ export const isBillingProgramAvailableAndroid: MutationField<
2567
2857
  * body: JSON.stringify({ token: details.externalTransactionToken })
2568
2858
  * });
2569
2859
  * ```
2860
+ *
2861
+ * @see {@link https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android}
2570
2862
  */
2571
2863
  export const createBillingProgramReportingDetailsAndroid: MutationField<
2572
2864
  'createBillingProgramReportingDetailsAndroid'
@@ -2612,6 +2904,8 @@ export const createBillingProgramReportingDetailsAndroid: MutationField<
2612
2904
  * console.log('User accepted external link');
2613
2905
  * }
2614
2906
  * ```
2907
+ *
2908
+ * @see {@link https://www.openiap.dev/docs/apis/android/launch-external-link-android}
2615
2909
  */
2616
2910
  export const launchExternalLinkAndroid: MutationField<
2617
2911
  'launchExternalLinkAndroid'
@@ -2637,7 +2931,11 @@ export const launchExternalLinkAndroid: MutationField<
2637
2931
  // ------------------------------
2638
2932
 
2639
2933
  /**
2640
- * Check if the device can present an external purchase notice sheet (iOS 18.2+).
2934
+ * Check if the device can present an external purchase notice sheet (iOS 17.4+).
2935
+ *
2936
+ * Wraps `ExternalPurchase.canPresent`, which Apple introduced in iOS 17.4.
2937
+ * Note: the notice sheet itself (`presentExternalPurchaseNoticeSheetIOS`)
2938
+ * still requires iOS 18.2+; only the eligibility check is available earlier.
2641
2939
  *
2642
2940
  * @returns Promise<boolean> - true if notice sheet can be presented
2643
2941
  * @platform iOS
@@ -2650,6 +2948,8 @@ export const launchExternalLinkAndroid: MutationField<
2650
2948
  * const result = await presentExternalPurchaseNoticeSheetIOS();
2651
2949
  * }
2652
2950
  * ```
2951
+ *
2952
+ * @see {@link https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios}
2653
2953
  */
2654
2954
  export const canPresentExternalPurchaseNoticeIOS: QueryField<
2655
2955
  'canPresentExternalPurchaseNoticeIOS'
@@ -2683,6 +2983,8 @@ export const canPresentExternalPurchaseNoticeIOS: QueryField<
2683
2983
  * await presentExternalPurchaseLinkIOS('https://your-website.com/purchase');
2684
2984
  * }
2685
2985
  * ```
2986
+ *
2987
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios}
2686
2988
  */
2687
2989
  export const presentExternalPurchaseNoticeSheetIOS =
2688
2990
  async (): Promise<ExternalPurchaseNoticeResultIOS> => {
@@ -2714,6 +3016,8 @@ export const presentExternalPurchaseNoticeSheetIOS =
2714
3016
  * console.log('User completed external purchase');
2715
3017
  * }
2716
3018
  * ```
3019
+ *
3020
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios}
2717
3021
  */
2718
3022
  export const presentExternalPurchaseLinkIOS: MutationField<
2719
3023
  'presentExternalPurchaseLinkIOS'
@@ -2748,6 +3052,8 @@ export const presentExternalPurchaseLinkIOS: MutationField<
2748
3052
  * // App can use custom external purchase links
2749
3053
  * }
2750
3054
  * ```
3055
+ *
3056
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios}
2751
3057
  */
2752
3058
  export const isEligibleForExternalPurchaseCustomLinkIOS =
2753
3059
  async (): Promise<boolean> => {
@@ -2783,6 +3089,8 @@ export const isEligibleForExternalPurchaseCustomLinkIOS =
2783
3089
  * await reportToApple(result.token);
2784
3090
  * }
2785
3091
  * ```
3092
+ *
3093
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios}
2786
3094
  */
2787
3095
  export const getExternalPurchaseCustomLinkTokenIOS = async (
2788
3096
  tokenType: ExternalPurchaseCustomLinkTokenTypeIOS,
@@ -2821,6 +3129,8 @@ export const getExternalPurchaseCustomLinkTokenIOS = async (
2821
3129
  * await Linking.openURL('https://your-store.com/checkout');
2822
3130
  * }
2823
3131
  * ```
3132
+ *
3133
+ * @see {@link https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios}
2824
3134
  */
2825
3135
  export const showExternalPurchaseCustomLinkNoticeIOS = async (
2826
3136
  noticeType: ExternalPurchaseCustomLinkNoticeTypeIOS,