react-native-iap 14.4.10 → 14.4.12

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 (94) hide show
  1. package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +195 -12
  2. package/ios/HybridRnIap.swift +115 -2
  3. package/ios/RnIapHelper.swift +32 -1
  4. package/lib/module/hooks/useIAP.js +24 -3
  5. package/lib/module/hooks/useIAP.js.map +1 -1
  6. package/lib/module/index.js +275 -2
  7. package/lib/module/index.js.map +1 -1
  8. package/lib/module/types.js +18 -0
  9. package/lib/module/types.js.map +1 -1
  10. package/lib/module/utils/type-bridge.js +39 -1
  11. package/lib/module/utils/type-bridge.js.map +1 -1
  12. package/lib/typescript/plugin/src/withIAP.d.ts +27 -0
  13. package/lib/typescript/plugin/src/withIAP.d.ts.map +1 -1
  14. package/lib/typescript/src/hooks/useIAP.d.ts +6 -1
  15. package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
  16. package/lib/typescript/src/index.d.ts +133 -0
  17. package/lib/typescript/src/index.d.ts.map +1 -1
  18. package/lib/typescript/src/specs/RnIap.nitro.d.ts +101 -2
  19. package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
  20. package/lib/typescript/src/types.d.ts +116 -13
  21. package/lib/typescript/src/types.d.ts.map +1 -1
  22. package/lib/typescript/src/utils/type-bridge.d.ts.map +1 -1
  23. package/nitrogen/generated/android/NitroIapOnLoad.cpp +2 -0
  24. package/nitrogen/generated/android/c++/JAlternativeBillingModeAndroid.hpp +62 -0
  25. package/nitrogen/generated/android/c++/JExternalPurchaseLinkResultIOS.hpp +58 -0
  26. package/nitrogen/generated/android/c++/JExternalPurchaseNoticeAction.hpp +59 -0
  27. package/nitrogen/generated/android/c++/JExternalPurchaseNoticeResultIOS.hpp +60 -0
  28. package/nitrogen/generated/android/c++/JFunc_void_NitroProduct.hpp +2 -0
  29. package/nitrogen/generated/android/c++/JFunc_void_UserChoiceBillingDetails.hpp +78 -0
  30. package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +136 -3
  31. package/nitrogen/generated/android/c++/JHybridRnIapSpec.hpp +9 -1
  32. package/nitrogen/generated/android/c++/JInitConnectionConfig.hpp +55 -0
  33. package/nitrogen/generated/android/c++/JNitroOneTimePurchaseOfferDetail.hpp +61 -0
  34. package/nitrogen/generated/android/c++/JNitroProduct.hpp +16 -2
  35. package/nitrogen/generated/android/c++/JNitroPurchase.hpp +74 -2
  36. package/nitrogen/generated/android/c++/JPurchaseAndroid.hpp +4 -0
  37. package/nitrogen/generated/android/c++/JPurchaseIOS.hpp +4 -0
  38. package/nitrogen/generated/android/c++/JUserChoiceBillingDetails.hpp +75 -0
  39. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/AlternativeBillingModeAndroid.kt +22 -0
  40. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/ExternalPurchaseLinkResultIOS.kt +32 -0
  41. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/ExternalPurchaseNoticeAction.kt +21 -0
  42. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/ExternalPurchaseNoticeResultIOS.kt +32 -0
  43. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Func_void_UserChoiceBillingDetails.kt +81 -0
  44. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/HybridRnIapSpec.kt +43 -1
  45. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/InitConnectionConfig.kt +29 -0
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroOneTimePurchaseOfferDetail.kt +35 -0
  47. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroProduct.kt +10 -1
  48. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroPurchase.kt +55 -1
  49. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseAndroid.kt +3 -0
  50. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/PurchaseIOS.kt +3 -0
  51. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/UserChoiceBillingDetails.kt +32 -0
  52. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.cpp +24 -0
  53. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.hpp +174 -0
  54. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Umbrella.hpp +21 -0
  55. package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +84 -3
  56. package/nitrogen/generated/ios/swift/AlternativeBillingModeAndroid.swift +44 -0
  57. package/nitrogen/generated/ios/swift/ExternalPurchaseLinkResultIOS.swift +65 -0
  58. package/nitrogen/generated/ios/swift/ExternalPurchaseNoticeAction.swift +40 -0
  59. package/nitrogen/generated/ios/swift/ExternalPurchaseNoticeResultIOS.swift +65 -0
  60. package/nitrogen/generated/ios/swift/Func_void_ExternalPurchaseLinkResultIOS.swift +47 -0
  61. package/nitrogen/generated/ios/swift/Func_void_ExternalPurchaseNoticeResultIOS.swift +47 -0
  62. package/nitrogen/generated/ios/swift/Func_void_UserChoiceBillingDetails.swift +47 -0
  63. package/nitrogen/generated/ios/swift/HybridRnIapSpec.swift +9 -1
  64. package/nitrogen/generated/ios/swift/HybridRnIapSpec_cxx.swift +168 -2
  65. package/nitrogen/generated/ios/swift/InitConnectionConfig.swift +47 -0
  66. package/nitrogen/generated/ios/swift/NitroOneTimePurchaseOfferDetail.swift +57 -0
  67. package/nitrogen/generated/ios/swift/NitroProduct.swift +91 -1
  68. package/nitrogen/generated/ios/swift/NitroPurchase.swift +520 -1
  69. package/nitrogen/generated/ios/swift/PurchaseAndroid.swift +31 -1
  70. package/nitrogen/generated/ios/swift/PurchaseIOS.swift +31 -1
  71. package/nitrogen/generated/ios/swift/UserChoiceBillingDetails.swift +58 -0
  72. package/nitrogen/generated/shared/c++/AlternativeBillingModeAndroid.hpp +80 -0
  73. package/nitrogen/generated/shared/c++/ExternalPurchaseLinkResultIOS.hpp +72 -0
  74. package/nitrogen/generated/shared/c++/ExternalPurchaseNoticeAction.hpp +76 -0
  75. package/nitrogen/generated/shared/c++/ExternalPurchaseNoticeResultIOS.hpp +74 -0
  76. package/nitrogen/generated/shared/c++/HybridRnIapSpec.cpp +8 -0
  77. package/nitrogen/generated/shared/c++/HybridRnIapSpec.hpp +22 -2
  78. package/nitrogen/generated/shared/c++/InitConnectionConfig.hpp +69 -0
  79. package/nitrogen/generated/shared/c++/NitroOneTimePurchaseOfferDetail.hpp +75 -0
  80. package/nitrogen/generated/shared/c++/NitroProduct.hpp +17 -2
  81. package/nitrogen/generated/shared/c++/NitroPurchase.hpp +74 -2
  82. package/nitrogen/generated/shared/c++/PurchaseAndroid.hpp +5 -1
  83. package/nitrogen/generated/shared/c++/PurchaseIOS.hpp +5 -1
  84. package/nitrogen/generated/shared/c++/UserChoiceBillingDetails.hpp +72 -0
  85. package/openiap-versions.json +3 -3
  86. package/package.json +3 -3
  87. package/plugin/build/withIAP.d.ts +27 -0
  88. package/plugin/build/withIAP.js +91 -1
  89. package/plugin/src/withIAP.ts +162 -0
  90. package/src/hooks/useIAP.ts +47 -1
  91. package/src/index.ts +313 -2
  92. package/src/specs/RnIap.nitro.ts +131 -1
  93. package/src/types.ts +124 -13
  94. package/src/utils/type-bridge.ts +76 -16
package/src/index.ts CHANGED
@@ -292,6 +292,82 @@ export const promotedProductListenerIOS = (
292
292
  };
293
293
  };
294
294
 
295
+ /**
296
+ * Add a listener for user choice billing events (Android only).
297
+ * Fires when a user selects alternative billing in the User Choice Billing dialog.
298
+ *
299
+ * @param listener - Function to call when user chooses alternative billing
300
+ * @returns EventSubscription with remove() method to unsubscribe
301
+ * @platform Android
302
+ *
303
+ * @example
304
+ * ```typescript
305
+ * const subscription = userChoiceBillingListenerAndroid((details) => {
306
+ * console.log('User chose alternative billing');
307
+ * console.log('Products:', details.products);
308
+ * console.log('Token:', details.externalTransactionToken);
309
+ *
310
+ * // Send token to backend for Google Play reporting
311
+ * await reportToGooglePlay(details.externalTransactionToken);
312
+ * });
313
+ *
314
+ * // Later, remove the listener
315
+ * subscription.remove();
316
+ * ```
317
+ */
318
+ type NitroUserChoiceBillingListener = Parameters<
319
+ RnIap['addUserChoiceBillingListenerAndroid']
320
+ >[0];
321
+ const userChoiceBillingListenerMap = new WeakMap<
322
+ (details: any) => void,
323
+ NitroUserChoiceBillingListener
324
+ >();
325
+
326
+ export const userChoiceBillingListenerAndroid = (
327
+ listener: (details: any) => void,
328
+ ): EventSubscription => {
329
+ if (Platform.OS !== 'android') {
330
+ RnIapConsole.warn(
331
+ 'userChoiceBillingListenerAndroid: This listener is only available on Android',
332
+ );
333
+ return {remove: () => {}};
334
+ }
335
+
336
+ const wrappedListener: NitroUserChoiceBillingListener = (details) => {
337
+ listener(details);
338
+ };
339
+
340
+ userChoiceBillingListenerMap.set(listener, wrappedListener);
341
+ let attached = false;
342
+ try {
343
+ IAP.instance.addUserChoiceBillingListenerAndroid(wrappedListener);
344
+ attached = true;
345
+ } catch (e) {
346
+ const msg = toErrorMessage(e);
347
+ if (msg.includes('Nitro runtime not installed')) {
348
+ RnIapConsole.warn(
349
+ '[userChoiceBillingListenerAndroid] Nitro not ready yet; listener inert until initConnection()',
350
+ );
351
+ } else {
352
+ throw e;
353
+ }
354
+ }
355
+
356
+ return {
357
+ remove: () => {
358
+ const wrapped = userChoiceBillingListenerMap.get(listener);
359
+ if (wrapped) {
360
+ if (attached) {
361
+ try {
362
+ IAP.instance.removeUserChoiceBillingListenerAndroid(wrapped);
363
+ } catch {}
364
+ }
365
+ userChoiceBillingListenerMap.delete(listener);
366
+ }
367
+ },
368
+ };
369
+ };
370
+
295
371
  // ------------------------------
296
372
  // Query API
297
373
  // ------------------------------
@@ -832,10 +908,32 @@ export const getTransactionJwsIOS: QueryField<'getTransactionJwsIOS'> = async (
832
908
 
833
909
  /**
834
910
  * Initialize connection to the store
911
+ * @param config - Optional configuration including alternative billing mode for Android
912
+ * @param config.alternativeBillingModeAndroid - Alternative billing mode: 'none', 'user-choice', or 'alternative-only'
913
+ *
914
+ * @example
915
+ * ```typescript
916
+ * // Standard billing (default)
917
+ * await initConnection();
918
+ *
919
+ * // User choice billing (Android)
920
+ * await initConnection({
921
+ * alternativeBillingModeAndroid: 'user-choice'
922
+ * });
923
+ *
924
+ * // Alternative billing only (Android)
925
+ * await initConnection({
926
+ * alternativeBillingModeAndroid: 'alternative-only'
927
+ * });
928
+ * ```
835
929
  */
836
- export const initConnection: MutationField<'initConnection'> = async () => {
930
+ export const initConnection: MutationField<'initConnection'> = async (
931
+ config,
932
+ ) => {
837
933
  try {
838
- return await IAP.instance.initConnection();
934
+ return await IAP.instance.initConnection(
935
+ config as Record<string, unknown> | undefined,
936
+ );
839
937
  } catch (error) {
840
938
  RnIapConsole.error('Failed to initialize IAP connection:', error);
841
939
  throw error;
@@ -1648,3 +1746,216 @@ const normalizeProductQueryType = (
1648
1746
  }
1649
1747
  return 'in-app';
1650
1748
  };
1749
+
1750
+ // ============================================================================
1751
+ // ALTERNATIVE BILLING APIs
1752
+ // ============================================================================
1753
+
1754
+ // ------------------------------
1755
+ // Android Alternative Billing
1756
+ // ------------------------------
1757
+
1758
+ /**
1759
+ * Check if alternative billing is available for this user/device (Android only).
1760
+ * Step 1 of alternative billing flow.
1761
+ *
1762
+ * @returns Promise<boolean> - true if available, false otherwise
1763
+ * @throws Error if billing client not ready
1764
+ * @platform Android
1765
+ *
1766
+ * @example
1767
+ * ```typescript
1768
+ * const isAvailable = await checkAlternativeBillingAvailabilityAndroid();
1769
+ * if (isAvailable) {
1770
+ * // Proceed with alternative billing flow
1771
+ * }
1772
+ * ```
1773
+ */
1774
+ export const checkAlternativeBillingAvailabilityAndroid: MutationField<
1775
+ 'checkAlternativeBillingAvailabilityAndroid'
1776
+ > = async () => {
1777
+ if (Platform.OS !== 'android') {
1778
+ throw new Error('Alternative billing is only supported on Android');
1779
+ }
1780
+ try {
1781
+ return await IAP.instance.checkAlternativeBillingAvailabilityAndroid();
1782
+ } catch (error) {
1783
+ RnIapConsole.error(
1784
+ 'Failed to check alternative billing availability:',
1785
+ error,
1786
+ );
1787
+ throw error;
1788
+ }
1789
+ };
1790
+
1791
+ /**
1792
+ * Show alternative billing information dialog to user (Android only).
1793
+ * Step 2 of alternative billing flow.
1794
+ * Must be called BEFORE processing payment in your payment system.
1795
+ *
1796
+ * @returns Promise<boolean> - true if user accepted, false if user canceled
1797
+ * @throws Error if billing client not ready
1798
+ * @platform Android
1799
+ *
1800
+ * @example
1801
+ * ```typescript
1802
+ * const userAccepted = await showAlternativeBillingDialogAndroid();
1803
+ * if (userAccepted) {
1804
+ * // Process payment in your payment system
1805
+ * const success = await processCustomPayment();
1806
+ * if (success) {
1807
+ * // Create reporting token
1808
+ * const token = await createAlternativeBillingTokenAndroid();
1809
+ * // Send token to your backend for Google Play reporting
1810
+ * }
1811
+ * }
1812
+ * ```
1813
+ */
1814
+ export const showAlternativeBillingDialogAndroid: MutationField<
1815
+ 'showAlternativeBillingDialogAndroid'
1816
+ > = async () => {
1817
+ if (Platform.OS !== 'android') {
1818
+ throw new Error('Alternative billing is only supported on Android');
1819
+ }
1820
+ try {
1821
+ return await IAP.instance.showAlternativeBillingDialogAndroid();
1822
+ } catch (error) {
1823
+ RnIapConsole.error('Failed to show alternative billing dialog:', error);
1824
+ throw error;
1825
+ }
1826
+ };
1827
+
1828
+ /**
1829
+ * Create external transaction token for Google Play reporting (Android only).
1830
+ * Step 3 of alternative billing flow.
1831
+ * Must be called AFTER successful payment in your payment system.
1832
+ * Token must be reported to Google Play backend within 24 hours.
1833
+ *
1834
+ * @param sku - Optional product SKU that was purchased
1835
+ * @returns Promise<string | null> - Token string or null if creation failed
1836
+ * @throws Error if billing client not ready
1837
+ * @platform Android
1838
+ *
1839
+ * @example
1840
+ * ```typescript
1841
+ * const token = await createAlternativeBillingTokenAndroid('premium_subscription');
1842
+ * if (token) {
1843
+ * // Send token to your backend
1844
+ * await fetch('/api/report-transaction', {
1845
+ * method: 'POST',
1846
+ * body: JSON.stringify({ token, sku: 'premium_subscription' })
1847
+ * });
1848
+ * }
1849
+ * ```
1850
+ */
1851
+ export const createAlternativeBillingTokenAndroid: MutationField<
1852
+ 'createAlternativeBillingTokenAndroid'
1853
+ > = async (sku?: string) => {
1854
+ if (Platform.OS !== 'android') {
1855
+ throw new Error('Alternative billing is only supported on Android');
1856
+ }
1857
+ try {
1858
+ return await IAP.instance.createAlternativeBillingTokenAndroid(sku ?? null);
1859
+ } catch (error) {
1860
+ RnIapConsole.error('Failed to create alternative billing token:', error);
1861
+ throw error;
1862
+ }
1863
+ };
1864
+
1865
+ // ------------------------------
1866
+ // iOS External Purchase
1867
+ // ------------------------------
1868
+
1869
+ /**
1870
+ * Check if the device can present an external purchase notice sheet (iOS 18.2+).
1871
+ *
1872
+ * @returns Promise<boolean> - true if notice sheet can be presented
1873
+ * @platform iOS
1874
+ *
1875
+ * @example
1876
+ * ```typescript
1877
+ * const canPresent = await canPresentExternalPurchaseNoticeIOS();
1878
+ * if (canPresent) {
1879
+ * // Present notice before external purchase
1880
+ * const result = await presentExternalPurchaseNoticeSheetIOS();
1881
+ * }
1882
+ * ```
1883
+ */
1884
+ export const canPresentExternalPurchaseNoticeIOS: QueryField<
1885
+ 'canPresentExternalPurchaseNoticeIOS'
1886
+ > = async () => {
1887
+ if (Platform.OS !== 'ios') {
1888
+ return false;
1889
+ }
1890
+ try {
1891
+ return await IAP.instance.canPresentExternalPurchaseNoticeIOS();
1892
+ } catch (error) {
1893
+ RnIapConsole.error(
1894
+ 'Failed to check external purchase notice availability:',
1895
+ error,
1896
+ );
1897
+ return false;
1898
+ }
1899
+ };
1900
+
1901
+ /**
1902
+ * Present an external purchase notice sheet to inform users about external purchases (iOS 18.2+).
1903
+ * This must be called before opening an external purchase link.
1904
+ *
1905
+ * @returns Promise<ExternalPurchaseNoticeResultIOS> - Result with action and error if any
1906
+ * @platform iOS
1907
+ *
1908
+ * @example
1909
+ * ```typescript
1910
+ * const result = await presentExternalPurchaseNoticeSheetIOS();
1911
+ * if (result.result === 'continue') {
1912
+ * // User chose to continue, open external purchase link
1913
+ * await presentExternalPurchaseLinkIOS('https://your-website.com/purchase');
1914
+ * }
1915
+ * ```
1916
+ */
1917
+ export const presentExternalPurchaseNoticeSheetIOS: MutationField<
1918
+ 'presentExternalPurchaseNoticeSheetIOS'
1919
+ > = async () => {
1920
+ if (Platform.OS !== 'ios') {
1921
+ throw new Error('External purchase is only supported on iOS');
1922
+ }
1923
+ try {
1924
+ return (await IAP.instance.presentExternalPurchaseNoticeSheetIOS()) as any;
1925
+ } catch (error) {
1926
+ RnIapConsole.error(
1927
+ 'Failed to present external purchase notice sheet:',
1928
+ error,
1929
+ );
1930
+ throw error;
1931
+ }
1932
+ };
1933
+
1934
+ /**
1935
+ * Present an external purchase link to redirect users to your website (iOS 16.0+).
1936
+ *
1937
+ * @param url - The external purchase URL to open
1938
+ * @returns Promise<ExternalPurchaseLinkResultIOS> - Result with success status and error if any
1939
+ * @platform iOS
1940
+ *
1941
+ * @example
1942
+ * ```typescript
1943
+ * const result = await presentExternalPurchaseLinkIOS('https://your-website.com/purchase');
1944
+ * if (result.success) {
1945
+ * console.log('User completed external purchase');
1946
+ * }
1947
+ * ```
1948
+ */
1949
+ export const presentExternalPurchaseLinkIOS: MutationField<
1950
+ 'presentExternalPurchaseLinkIOS'
1951
+ > = async (url) => {
1952
+ if (Platform.OS !== 'ios') {
1953
+ throw new Error('External purchase is only supported on iOS');
1954
+ }
1955
+ try {
1956
+ return (await IAP.instance.presentExternalPurchaseLinkIOS(url)) as any;
1957
+ } catch (error) {
1958
+ RnIapConsole.error('Failed to present external purchase link:', error);
1959
+ throw error;
1960
+ }
1961
+ };
@@ -6,6 +6,9 @@ import type {HybridObject} from 'react-native-nitro-modules';
6
6
  import type {
7
7
  AndroidSubscriptionOfferInput,
8
8
  DeepLinkOptions,
9
+ InitConnectionConfig,
10
+ ExternalPurchaseLinkResultIOS,
11
+ ExternalPurchaseNoticeResultIOS,
9
12
  MutationFinishTransactionArgs,
10
13
  ProductCommon,
11
14
  PurchaseCommon,
@@ -16,6 +19,7 @@ import type {
16
19
  RequestPurchaseIosProps,
17
20
  RequestPurchaseResult,
18
21
  RequestSubscriptionAndroidProps,
22
+ UserChoiceBillingDetails,
19
23
  } from '../types';
20
24
 
21
25
  // ╔══════════════════════════════════════════════════════════════════════════╗
@@ -179,6 +183,15 @@ export interface NitroReceiptValidationResultAndroid {
179
183
  testTransaction: ReceiptValidationResultAndroid['testTransaction'];
180
184
  }
181
185
 
186
+ /**
187
+ * Android one-time purchase offer details
188
+ */
189
+ export interface NitroOneTimePurchaseOfferDetail {
190
+ formattedPrice: string;
191
+ priceAmountMicros: string;
192
+ priceCurrencyCode: string;
193
+ }
194
+
182
195
  export interface NitroPurchase {
183
196
  id: PurchaseCommon['id'];
184
197
  productId: PurchaseCommon['productId'];
@@ -188,10 +201,29 @@ export interface NitroPurchase {
188
201
  quantity: PurchaseCommon['quantity'];
189
202
  purchaseState: PurchaseCommon['purchaseState'];
190
203
  isAutoRenewing: PurchaseCommon['isAutoRenewing'];
204
+ // iOS specific fields
191
205
  quantityIOS?: number | null;
192
206
  originalTransactionDateIOS?: number | null;
193
207
  originalTransactionIdentifierIOS?: string | null;
194
208
  appAccountToken?: string | null;
209
+ appBundleIdIOS?: string | null;
210
+ countryCodeIOS?: string | null;
211
+ currencyCodeIOS?: string | null;
212
+ currencySymbolIOS?: string | null;
213
+ environmentIOS?: string | null;
214
+ expirationDateIOS?: number | null;
215
+ isUpgradedIOS?: boolean | null;
216
+ offerIOS?: string | null;
217
+ ownershipTypeIOS?: string | null;
218
+ reasonIOS?: string | null;
219
+ reasonStringRepresentationIOS?: string | null;
220
+ revocationDateIOS?: number | null;
221
+ revocationReasonIOS?: string | null;
222
+ storefrontCountryCodeIOS?: string | null;
223
+ subscriptionGroupIdIOS?: string | null;
224
+ transactionReasonIOS?: string | null;
225
+ webOrderLineItemIdIOS?: string | null;
226
+ // Android specific fields
195
227
  purchaseTokenAndroid?: string | null;
196
228
  dataAndroid?: string | null;
197
229
  signatureAndroid?: string | null;
@@ -201,6 +233,7 @@ export interface NitroPurchase {
201
233
  packageNameAndroid?: string | null;
202
234
  obfuscatedAccountIdAndroid?: string | null;
203
235
  obfuscatedProfileIdAndroid?: string | null;
236
+ developerPayloadAndroid?: string | null;
204
237
  }
205
238
 
206
239
  export interface NitroProduct {
@@ -217,6 +250,7 @@ export interface NitroProduct {
217
250
  typeIOS?: string | null;
218
251
  isFamilyShareableIOS?: boolean | null;
219
252
  jsonRepresentationIOS?: string | null;
253
+ discountsIOS?: string | null;
220
254
  introductoryPriceIOS?: string | null;
221
255
  introductoryPriceAsAmountIOS?: number | null;
222
256
  introductoryPriceNumberOfPeriodsIOS?: number | null;
@@ -225,6 +259,7 @@ export interface NitroProduct {
225
259
  subscriptionPeriodNumberIOS?: number | null;
226
260
  subscriptionPeriodUnitIOS?: string | null;
227
261
  // Android specific fields
262
+ nameAndroid?: string | null;
228
263
  originalPriceAndroid?: string | null;
229
264
  originalPriceAmountMicrosAndroid?: number | null;
230
265
  introductoryPriceCyclesAndroid?: number | null;
@@ -233,6 +268,7 @@ export interface NitroProduct {
233
268
  subscriptionPeriodAndroid?: string | null;
234
269
  freeTrialPeriodAndroid?: string | null;
235
270
  subscriptionOfferDetailsAndroid?: string | null;
271
+ oneTimePurchaseOfferDetailsAndroid?: NitroOneTimePurchaseOfferDetail | null;
236
272
  }
237
273
 
238
274
  // ╔══════════════════════════════════════════════════════════════════════════╗
@@ -247,9 +283,10 @@ export interface RnIap extends HybridObject<{ios: 'swift'; android: 'kotlin'}> {
247
283
 
248
284
  /**
249
285
  * Initialize connection to the store
286
+ * @param config - Optional configuration including alternative billing mode for Android
250
287
  * @returns Promise<boolean> - true if connection successful
251
288
  */
252
- initConnection(): Promise<boolean>;
289
+ initConnection(config?: InitConnectionConfig | null): Promise<boolean>;
253
290
 
254
291
  /**
255
292
  * End connection to the store
@@ -527,4 +564,97 @@ export interface RnIap extends HybridObject<{ios: 'swift'; android: 'kotlin'}> {
527
564
  deepLinkToSubscriptionsAndroid?(
528
565
  options: NitroDeepLinkOptionsAndroid,
529
566
  ): Promise<void>;
567
+
568
+ // ╔════════════════════════════════════════════════════════════════════════╗
569
+ // ║ ALTERNATIVE BILLING (Android) ║
570
+ // ╚════════════════════════════════════════════════════════════════════════╝
571
+
572
+ /**
573
+ * Check if alternative billing is available for this user/device (Android only).
574
+ * Step 1 of alternative billing flow.
575
+ *
576
+ * @returns Promise<boolean> - true if available, false otherwise
577
+ * @throws Error if billing client not ready
578
+ * @platform Android
579
+ */
580
+ checkAlternativeBillingAvailabilityAndroid(): Promise<boolean>;
581
+
582
+ /**
583
+ * Show alternative billing information dialog to user (Android only).
584
+ * Step 2 of alternative billing flow.
585
+ * Must be called BEFORE processing payment in your payment system.
586
+ *
587
+ * @returns Promise<boolean> - true if user accepted, false if user canceled
588
+ * @throws Error if billing client not ready
589
+ * @platform Android
590
+ */
591
+ showAlternativeBillingDialogAndroid(): Promise<boolean>;
592
+
593
+ /**
594
+ * Create external transaction token for Google Play reporting (Android only).
595
+ * Step 3 of alternative billing flow.
596
+ * Must be called AFTER successful payment in your payment system.
597
+ * Token must be reported to Google Play backend within 24 hours.
598
+ *
599
+ * @param sku - Optional product SKU that was purchased
600
+ * @returns Promise<string | null> - Token string or null if creation failed
601
+ * @throws Error if billing client not ready
602
+ * @platform Android
603
+ */
604
+ createAlternativeBillingTokenAndroid(
605
+ sku?: string | null,
606
+ ): Promise<string | null>;
607
+
608
+ /**
609
+ * Add a listener for user choice billing events (Android only).
610
+ * Fires when a user selects alternative billing in the User Choice Billing dialog.
611
+ *
612
+ * @param listener - Function to call when user chooses alternative billing
613
+ * @platform Android
614
+ */
615
+ addUserChoiceBillingListenerAndroid(
616
+ listener: (details: UserChoiceBillingDetails) => void,
617
+ ): void;
618
+
619
+ /**
620
+ * Remove a user choice billing listener (Android only).
621
+ *
622
+ * @param listener - Function to remove from listeners
623
+ * @platform Android
624
+ */
625
+ removeUserChoiceBillingListenerAndroid(
626
+ listener: (details: UserChoiceBillingDetails) => void,
627
+ ): void;
628
+
629
+ // ╔════════════════════════════════════════════════════════════════════════╗
630
+ // ║ EXTERNAL PURCHASE LINKS (iOS 16.0+) ║
631
+ // ╚════════════════════════════════════════════════════════════════════════╝
632
+
633
+ /**
634
+ * Check if the device can present an external purchase notice sheet (iOS 18.2+).
635
+ *
636
+ * @returns Promise<boolean> - true if notice sheet can be presented
637
+ * @platform iOS
638
+ */
639
+ canPresentExternalPurchaseNoticeIOS(): Promise<boolean>;
640
+
641
+ /**
642
+ * Present an external purchase notice sheet to inform users about external purchases (iOS 18.2+).
643
+ * This must be called before opening an external purchase link.
644
+ *
645
+ * @returns Promise<ExternalPurchaseNoticeResultIOS> - Result with action and error if any
646
+ * @platform iOS
647
+ */
648
+ presentExternalPurchaseNoticeSheetIOS(): Promise<ExternalPurchaseNoticeResultIOS>;
649
+
650
+ /**
651
+ * Present an external purchase link to redirect users to your website (iOS 16.0+).
652
+ *
653
+ * @param url - The external purchase URL to open
654
+ * @returns Promise<ExternalPurchaseLinkResultIOS> - Result with success status and error if any
655
+ * @platform iOS
656
+ */
657
+ presentExternalPurchaseLinkIOS(
658
+ url: string,
659
+ ): Promise<ExternalPurchaseLinkResultIOS>;
530
660
  }