react-native-iap 14.6.1 → 14.6.3-rc.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.
@@ -43,6 +43,8 @@ namespace margelo::nitro::iap {
43
43
  jni::local_ref<jni::JDouble> quantity = this->getFieldValue(fieldQuantity);
44
44
  static const auto fieldWithOffer = clazz->getField<jni::JMap<jni::JString, jni::JString>>("withOffer");
45
45
  jni::local_ref<jni::JMap<jni::JString, jni::JString>> withOffer = this->getFieldValue(fieldWithOffer);
46
+ static const auto fieldAdvancedCommerceData = clazz->getField<jni::JString>("advancedCommerceData");
47
+ jni::local_ref<jni::JString> advancedCommerceData = this->getFieldValue(fieldAdvancedCommerceData);
46
48
  return NitroRequestPurchaseIos(
47
49
  sku->toStdString(),
48
50
  andDangerouslyFinishTransactionAutomatically != nullptr ? std::make_optional(static_cast<bool>(andDangerouslyFinishTransactionAutomatically->value())) : std::nullopt,
@@ -55,7 +57,8 @@ namespace margelo::nitro::iap {
55
57
  __map.emplace(__entry.first->toStdString(), __entry.second->toStdString());
56
58
  }
57
59
  return __map;
58
- }()) : std::nullopt
60
+ }()) : std::nullopt,
61
+ advancedCommerceData != nullptr ? std::make_optional(advancedCommerceData->toStdString()) : std::nullopt
59
62
  );
60
63
  }
61
64
 
@@ -65,7 +68,7 @@ namespace margelo::nitro::iap {
65
68
  */
66
69
  [[maybe_unused]]
67
70
  static jni::local_ref<JNitroRequestPurchaseIos::javaobject> fromCpp(const NitroRequestPurchaseIos& value) {
68
- using JSignature = JNitroRequestPurchaseIos(jni::alias_ref<jni::JString>, jni::alias_ref<jni::JBoolean>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JMap<jni::JString, jni::JString>>);
71
+ using JSignature = JNitroRequestPurchaseIos(jni::alias_ref<jni::JString>, jni::alias_ref<jni::JBoolean>, jni::alias_ref<jni::JString>, jni::alias_ref<jni::JDouble>, jni::alias_ref<jni::JMap<jni::JString, jni::JString>>, jni::alias_ref<jni::JString>);
69
72
  static const auto clazz = javaClassStatic();
70
73
  static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
71
74
  return create(
@@ -80,7 +83,8 @@ namespace margelo::nitro::iap {
80
83
  __map->put(jni::make_jstring(__entry.first), jni::make_jstring(__entry.second));
81
84
  }
82
85
  return __map;
83
- }() : nullptr
86
+ }() : nullptr,
87
+ value.advancedCommerceData.has_value() ? jni::make_jstring(value.advancedCommerceData.value()) : nullptr
84
88
  );
85
89
  }
86
90
  };
@@ -31,7 +31,10 @@ data class NitroRequestPurchaseIos(
31
31
  val quantity: Double?,
32
32
  @DoNotStrip
33
33
  @Keep
34
- val withOffer: Map<String, String>?
34
+ val withOffer: Map<String, String>?,
35
+ @DoNotStrip
36
+ @Keep
37
+ val advancedCommerceData: String?
35
38
  ) {
36
39
  private companion object {
37
40
  /**
@@ -41,8 +44,8 @@ data class NitroRequestPurchaseIos(
41
44
  @Keep
42
45
  @Suppress("unused")
43
46
  @JvmStatic
44
- private fun fromCpp(sku: String, andDangerouslyFinishTransactionAutomatically: Boolean?, appAccountToken: String?, quantity: Double?, withOffer: Map<String, String>?): NitroRequestPurchaseIos {
45
- return NitroRequestPurchaseIos(sku, andDangerouslyFinishTransactionAutomatically, appAccountToken, quantity, withOffer)
47
+ private fun fromCpp(sku: String, andDangerouslyFinishTransactionAutomatically: Boolean?, appAccountToken: String?, quantity: Double?, withOffer: Map<String, String>?, advancedCommerceData: String?): NitroRequestPurchaseIos {
48
+ return NitroRequestPurchaseIos(sku, andDangerouslyFinishTransactionAutomatically, appAccountToken, quantity, withOffer, advancedCommerceData)
46
49
  }
47
50
  }
48
51
  }
@@ -18,7 +18,7 @@ public extension NitroRequestPurchaseIos {
18
18
  /**
19
19
  * Create a new instance of `NitroRequestPurchaseIos`.
20
20
  */
21
- init(sku: String, andDangerouslyFinishTransactionAutomatically: Bool?, appAccountToken: String?, quantity: Double?, withOffer: Dictionary<String, String>?) {
21
+ init(sku: String, andDangerouslyFinishTransactionAutomatically: Bool?, appAccountToken: String?, quantity: Double?, withOffer: Dictionary<String, String>?, advancedCommerceData: String?) {
22
22
  self.init(std.string(sku), { () -> bridge.std__optional_bool_ in
23
23
  if let __unwrappedValue = andDangerouslyFinishTransactionAutomatically {
24
24
  return bridge.create_std__optional_bool_(__unwrappedValue)
@@ -49,6 +49,12 @@ public extension NitroRequestPurchaseIos {
49
49
  } else {
50
50
  return .init()
51
51
  }
52
+ }(), { () -> bridge.std__optional_std__string_ in
53
+ if let __unwrappedValue = advancedCommerceData {
54
+ return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
55
+ } else {
56
+ return .init()
57
+ }
52
58
  }())
53
59
  }
54
60
 
@@ -165,4 +171,28 @@ public extension NitroRequestPurchaseIos {
165
171
  }()
166
172
  }
167
173
  }
174
+
175
+ var advancedCommerceData: String? {
176
+ @inline(__always)
177
+ get {
178
+ return { () -> String? in
179
+ if bridge.has_value_std__optional_std__string_(self.__advancedCommerceData) {
180
+ let __unwrapped = bridge.get_std__optional_std__string_(self.__advancedCommerceData)
181
+ return String(__unwrapped)
182
+ } else {
183
+ return nil
184
+ }
185
+ }()
186
+ }
187
+ @inline(__always)
188
+ set {
189
+ self.__advancedCommerceData = { () -> bridge.std__optional_std__string_ in
190
+ if let __unwrappedValue = newValue {
191
+ return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
192
+ } else {
193
+ return .init()
194
+ }
195
+ }()
196
+ }
197
+ }
168
198
  }
@@ -41,10 +41,11 @@ namespace margelo::nitro::iap {
41
41
  std::optional<std::string> appAccountToken SWIFT_PRIVATE;
42
42
  std::optional<double> quantity SWIFT_PRIVATE;
43
43
  std::optional<std::unordered_map<std::string, std::string>> withOffer SWIFT_PRIVATE;
44
+ std::optional<std::string> advancedCommerceData SWIFT_PRIVATE;
44
45
 
45
46
  public:
46
47
  NitroRequestPurchaseIos() = default;
47
- explicit NitroRequestPurchaseIos(std::string sku, std::optional<bool> andDangerouslyFinishTransactionAutomatically, std::optional<std::string> appAccountToken, std::optional<double> quantity, std::optional<std::unordered_map<std::string, std::string>> withOffer): sku(sku), andDangerouslyFinishTransactionAutomatically(andDangerouslyFinishTransactionAutomatically), appAccountToken(appAccountToken), quantity(quantity), withOffer(withOffer) {}
48
+ explicit NitroRequestPurchaseIos(std::string sku, std::optional<bool> andDangerouslyFinishTransactionAutomatically, std::optional<std::string> appAccountToken, std::optional<double> quantity, std::optional<std::unordered_map<std::string, std::string>> withOffer, std::optional<std::string> advancedCommerceData): sku(sku), andDangerouslyFinishTransactionAutomatically(andDangerouslyFinishTransactionAutomatically), appAccountToken(appAccountToken), quantity(quantity), withOffer(withOffer), advancedCommerceData(advancedCommerceData) {}
48
49
  };
49
50
 
50
51
  } // namespace margelo::nitro::iap
@@ -61,7 +62,8 @@ namespace margelo::nitro {
61
62
  JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, "andDangerouslyFinishTransactionAutomatically")),
62
63
  JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "appAccountToken")),
63
64
  JSIConverter<std::optional<double>>::fromJSI(runtime, obj.getProperty(runtime, "quantity")),
64
- JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::fromJSI(runtime, obj.getProperty(runtime, "withOffer"))
65
+ JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::fromJSI(runtime, obj.getProperty(runtime, "withOffer")),
66
+ JSIConverter<std::optional<std::string>>::fromJSI(runtime, obj.getProperty(runtime, "advancedCommerceData"))
65
67
  );
66
68
  }
67
69
  static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::iap::NitroRequestPurchaseIos& arg) {
@@ -71,6 +73,7 @@ namespace margelo::nitro {
71
73
  obj.setProperty(runtime, "appAccountToken", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.appAccountToken));
72
74
  obj.setProperty(runtime, "quantity", JSIConverter<std::optional<double>>::toJSI(runtime, arg.quantity));
73
75
  obj.setProperty(runtime, "withOffer", JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::toJSI(runtime, arg.withOffer));
76
+ obj.setProperty(runtime, "advancedCommerceData", JSIConverter<std::optional<std::string>>::toJSI(runtime, arg.advancedCommerceData));
74
77
  return obj;
75
78
  }
76
79
  static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
@@ -86,6 +89,7 @@ namespace margelo::nitro {
86
89
  if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "appAccountToken"))) return false;
87
90
  if (!JSIConverter<std::optional<double>>::canConvert(runtime, obj.getProperty(runtime, "quantity"))) return false;
88
91
  if (!JSIConverter<std::optional<std::unordered_map<std::string, std::string>>>::canConvert(runtime, obj.getProperty(runtime, "withOffer"))) return false;
92
+ if (!JSIConverter<std::optional<std::string>>::canConvert(runtime, obj.getProperty(runtime, "advancedCommerceData"))) return false;
89
93
  return true;
90
94
  }
91
95
  };
@@ -1,5 +1,6 @@
1
1
  {
2
- "apple": "1.3.5",
3
- "google": "1.3.14",
4
- "gql": "1.3.5"
2
+ "apple": "1.3.7",
3
+ "google": "1.3.15",
4
+ "gql": "1.3.7",
5
+ "docs": "1.3.7"
5
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-iap",
3
- "version": "14.6.1",
3
+ "version": "14.6.3-rc.1",
4
4
  "description": "React Native In-App Purchases module for iOS and Android using Nitro",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -0,0 +1,3 @@
1
+ import type { ConfigPlugin } from 'expo/config-plugins';
2
+ declare const _default: ConfigPlugin<void>;
3
+ export default _default;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config_plugins_1 = require("expo/config-plugins");
4
+ const pkg = require('../../package.json');
5
+ // Global flag to prevent duplicate logs
6
+ let hasLoggedPluginExecution = false;
7
+ const addLineToGradle = (content, anchor, lineToAdd, offset = 1) => {
8
+ const lines = content.split('\n');
9
+ const index = lines.findIndex((line) => line.match(anchor));
10
+ if (index === -1) {
11
+ console.warn(`Anchor "${anchor}" not found in build.gradle. Appending to end.`);
12
+ lines.push(lineToAdd);
13
+ }
14
+ else {
15
+ lines.splice(index + offset, 0, lineToAdd);
16
+ }
17
+ return lines.join('\n');
18
+ };
19
+ const modifyAppBuildGradle = (gradle) => {
20
+ let modified = gradle;
21
+ // Add billing library dependencies to app-level build.gradle
22
+ const billingDep = ` implementation "com.android.billingclient:billing-ktx:8.0.0"`;
23
+ const gmsDep = ` implementation "com.google.android.gms:play-services-base:18.1.0"`;
24
+ let hasAddedDependency = false;
25
+ if (!modified.includes(billingDep)) {
26
+ modified = addLineToGradle(modified, /dependencies\s*{/, billingDep);
27
+ hasAddedDependency = true;
28
+ }
29
+ if (!modified.includes(gmsDep)) {
30
+ modified = addLineToGradle(modified, /dependencies\s*{/, gmsDep, 1);
31
+ hasAddedDependency = true;
32
+ }
33
+ // Log only once and only if we actually added dependencies
34
+ if (hasAddedDependency && !hasLoggedPluginExecution) {
35
+ console.log('🛠️ react-native-iap: Added billing dependencies to build.gradle');
36
+ }
37
+ return modified;
38
+ };
39
+ const withIapAndroid = (config) => {
40
+ // Add IAP dependencies to app build.gradle
41
+ config = (0, config_plugins_1.withAppBuildGradle)(config, (config) => {
42
+ config.modResults.contents = modifyAppBuildGradle(config.modResults.contents);
43
+ return config;
44
+ });
45
+ config = (0, config_plugins_1.withAndroidManifest)(config, (config) => {
46
+ const manifest = config.modResults;
47
+ if (!manifest.manifest['uses-permission']) {
48
+ manifest.manifest['uses-permission'] = [];
49
+ }
50
+ const permissions = manifest.manifest['uses-permission'];
51
+ const billingPerm = { $: { 'android:name': 'com.android.vending.BILLING' } };
52
+ const alreadyExists = permissions.some((p) => p.$['android:name'] === 'com.android.vending.BILLING');
53
+ if (!alreadyExists) {
54
+ permissions.push(billingPerm);
55
+ if (!hasLoggedPluginExecution) {
56
+ console.log('✅ Added com.android.vending.BILLING to AndroidManifest.xml');
57
+ }
58
+ }
59
+ else {
60
+ if (!hasLoggedPluginExecution) {
61
+ console.log('ℹ️ com.android.vending.BILLING already exists in AndroidManifest.xml');
62
+ }
63
+ }
64
+ return config;
65
+ });
66
+ return config;
67
+ };
68
+ const withIAP = (config, _props) => {
69
+ try {
70
+ const result = withIapAndroid(config);
71
+ // Set flag after first execution to prevent duplicate logs
72
+ hasLoggedPluginExecution = true;
73
+ return result;
74
+ }
75
+ catch (error) {
76
+ config_plugins_1.WarningAggregator.addWarningAndroid('react-native-iap', `react-native-iap plugin encountered an error: ${error}`);
77
+ console.error('react-native-iap plugin error:', error);
78
+ return config;
79
+ }
80
+ };
81
+ exports.default = (0, config_plugins_1.createRunOncePlugin)(withIAP, pkg.name, pkg.version);
@@ -0,0 +1 @@
1
+ {"root":["../src/withiap.ts"],"version":"5.9.2"}
@@ -1 +1 @@
1
- {"root":["./src/withIAP.ts"],"version":"5.9.2"}
1
+ {"root":["./src/withiap.ts"],"version":"5.9.2"}
package/src/index.ts CHANGED
@@ -1068,14 +1068,17 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
1068
1068
  }
1069
1069
 
1070
1070
  if (Platform.OS === 'ios') {
1071
- const iosRequest = perPlatformRequest.ios;
1071
+ // Support both 'apple' (recommended) and 'ios' (deprecated) fields
1072
+ const iosRequest = perPlatformRequest.apple ?? perPlatformRequest.ios;
1072
1073
  if (!iosRequest?.sku) {
1073
1074
  throw new Error(
1074
1075
  'Invalid request for iOS. The `sku` property is required.',
1075
1076
  );
1076
1077
  }
1077
1078
  } else if (Platform.OS === 'android') {
1078
- const androidRequest = perPlatformRequest.android;
1079
+ // Support both 'google' (recommended) and 'android' (deprecated) fields
1080
+ const androidRequest =
1081
+ perPlatformRequest.google ?? perPlatformRequest.android;
1079
1082
  if (!androidRequest?.skus?.length) {
1080
1083
  throw new Error(
1081
1084
  'Invalid request for Android. The `skus` property is required and must be a non-empty array.',
@@ -1087,10 +1090,12 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
1087
1090
 
1088
1091
  const unifiedRequest: NitroPurchaseRequest = {};
1089
1092
 
1090
- if (Platform.OS === 'ios' && perPlatformRequest.ios) {
1093
+ // Support both 'apple' (recommended) and 'ios' (deprecated) fields
1094
+ const iosRequestSource = perPlatformRequest.apple ?? perPlatformRequest.ios;
1095
+ if (Platform.OS === 'ios' && iosRequestSource) {
1091
1096
  const iosRequest = isSubs
1092
- ? (perPlatformRequest.ios as RequestSubscriptionIosProps)
1093
- : (perPlatformRequest.ios as RequestPurchaseIosProps);
1097
+ ? (iosRequestSource as RequestSubscriptionIosProps)
1098
+ : (iosRequestSource as RequestPurchaseIosProps);
1094
1099
 
1095
1100
  const iosPayload: NonNullable<NitroPurchaseRequest['ios']> = {
1096
1101
  sku: iosRequest.sku,
@@ -1117,14 +1122,20 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
1117
1122
  if (offerRecord) {
1118
1123
  iosPayload.withOffer = offerRecord;
1119
1124
  }
1125
+ if (iosRequest.advancedCommerceData) {
1126
+ iosPayload.advancedCommerceData = iosRequest.advancedCommerceData;
1127
+ }
1120
1128
 
1121
1129
  unifiedRequest.ios = iosPayload;
1122
1130
  }
1123
1131
 
1124
- if (Platform.OS === 'android' && perPlatformRequest.android) {
1132
+ // Support both 'google' (recommended) and 'android' (deprecated) fields
1133
+ const androidRequestSource =
1134
+ perPlatformRequest.google ?? perPlatformRequest.android;
1135
+ if (Platform.OS === 'android' && androidRequestSource) {
1125
1136
  const androidRequest = isSubs
1126
- ? (perPlatformRequest.android as RequestSubscriptionAndroidProps)
1127
- : (perPlatformRequest.android as RequestPurchaseAndroidProps);
1137
+ ? (androidRequestSource as RequestSubscriptionAndroidProps)
1138
+ : (androidRequestSource as RequestPurchaseAndroidProps);
1128
1139
 
1129
1140
  const androidPayload: NonNullable<NitroPurchaseRequest['android']> = {
1130
1141
  skus: androidRequest.skus,
@@ -1601,43 +1612,60 @@ export const presentCodeRedemptionSheetIOS: MutationField<
1601
1612
 
1602
1613
  /**
1603
1614
  * Buy promoted product on iOS
1615
+ * @deprecated In StoreKit 2, promoted products can be purchased directly via the standard `requestPurchase()` flow.
1616
+ * Use `promotedProductListenerIOS` to receive the product ID when a user taps a promoted product,
1617
+ * then call `requestPurchase()` with the received SKU directly.
1618
+ *
1619
+ * @example
1620
+ * ```typescript
1621
+ * // Recommended approach
1622
+ * promotedProductListenerIOS(async (product) => {
1623
+ * await requestPurchase({
1624
+ * request: { apple: { sku: product.id } },
1625
+ * type: 'in-app'
1626
+ * });
1627
+ * });
1628
+ * ```
1629
+ *
1604
1630
  * @returns Promise<boolean> - true when the request triggers successfully
1605
1631
  * @platform iOS
1606
1632
  */
1607
- export const requestPurchaseOnPromotedProductIOS: MutationField<
1608
- 'requestPurchaseOnPromotedProductIOS'
1609
- > = async () => {
1610
- if (Platform.OS !== 'ios') {
1611
- throw new Error(
1612
- 'requestPurchaseOnPromotedProductIOS is only available on iOS',
1613
- );
1614
- }
1615
-
1616
- try {
1617
- await IAP.instance.buyPromotedProductIOS();
1618
- const pending = await IAP.instance.getPendingTransactionsIOS();
1619
- const latest = pending.find((purchase) => purchase != null);
1620
- if (!latest) {
1621
- throw new Error('No promoted purchase available after request');
1633
+ export const requestPurchaseOnPromotedProductIOS =
1634
+ async (): Promise<boolean> => {
1635
+ if (Platform.OS !== 'ios') {
1636
+ throw new Error(
1637
+ 'requestPurchaseOnPromotedProductIOS is only available on iOS',
1638
+ );
1622
1639
  }
1623
1640
 
1624
- const converted = convertNitroPurchaseToPurchase(latest);
1625
- if (converted.platform !== 'ios') {
1626
- throw new Error('Promoted purchase result not available for iOS');
1627
- }
1641
+ try {
1642
+ await IAP.instance.buyPromotedProductIOS();
1643
+ const pending = await IAP.instance.getPendingTransactionsIOS();
1644
+ const latest = pending.find((purchase) => purchase != null);
1645
+ if (!latest) {
1646
+ throw new Error('No promoted purchase available after request');
1647
+ }
1628
1648
 
1629
- return true;
1630
- } catch (error) {
1631
- RnIapConsole.error('[requestPurchaseOnPromotedProductIOS] Failed:', error);
1632
- const parsedError = parseErrorStringToJsonObj(error);
1633
- throw createPurchaseError({
1634
- code: parsedError.code,
1635
- message: parsedError.message,
1636
- responseCode: parsedError.responseCode,
1637
- debugMessage: parsedError.debugMessage,
1638
- });
1639
- }
1640
- };
1649
+ const converted = convertNitroPurchaseToPurchase(latest);
1650
+ if (converted.platform !== 'ios') {
1651
+ throw new Error('Promoted purchase result not available for iOS');
1652
+ }
1653
+
1654
+ return true;
1655
+ } catch (error) {
1656
+ RnIapConsole.error(
1657
+ '[requestPurchaseOnPromotedProductIOS] Failed:',
1658
+ error,
1659
+ );
1660
+ const parsedError = parseErrorStringToJsonObj(error);
1661
+ throw createPurchaseError({
1662
+ code: parsedError.code,
1663
+ message: parsedError.message,
1664
+ responseCode: parsedError.responseCode,
1665
+ debugMessage: parsedError.debugMessage,
1666
+ });
1667
+ }
1668
+ };
1641
1669
 
1642
1670
  /**
1643
1671
  * Clear unfinished transactions on iOS
@@ -102,6 +102,13 @@ export interface NitroRequestPurchaseIos {
102
102
  appAccountToken?: RequestPurchaseIosProps['appAccountToken'];
103
103
  quantity?: RequestPurchaseIosProps['quantity'];
104
104
  withOffer?: Record<string, string> | null;
105
+ /**
106
+ * Advanced commerce data for StoreKit 2's Product.PurchaseOption.custom API.
107
+ * Used to pass attribution data (campaign tokens, affiliate IDs) during purchases.
108
+ * Data is formatted as JSON: {"signatureInfo": {"token": "<value>"}}
109
+ * @platform iOS
110
+ */
111
+ advancedCommerceData?: RequestPurchaseIosProps['advancedCommerceData'];
105
112
  }
106
113
 
107
114
  export interface NitroRequestPurchaseAndroid {
package/src/types.ts CHANGED
@@ -358,8 +358,15 @@ export interface Mutation {
358
358
  presentExternalPurchaseNoticeSheetIOS: Promise<ExternalPurchaseNoticeResultIOS>;
359
359
  /** Initiate a purchase flow; rely on events for final state */
360
360
  requestPurchase?: Promise<(Purchase | Purchase[] | null)>;
361
- /** Purchase the promoted product surfaced by the App Store */
362
- requestPurchaseOnPromotedProductIOS: Promise<boolean>;
361
+ /**
362
+ * Purchase the promoted product surfaced by the App Store.
363
+ *
364
+ * @deprecated Use promotedProductListenerIOS to receive the productId,
365
+ * then call requestPurchase with that SKU instead. In StoreKit 2,
366
+ * promoted products can be purchased directly via the standard purchase flow.
367
+ * @deprecated Use promotedProductListenerIOS + requestPurchase instead
368
+ */
369
+ requestPurchaseOnPromotedProductIOS: boolean;
363
370
  /** Restore completed purchases across platforms */
364
371
  restorePurchases: Promise<void>;
365
372
  /**
@@ -889,6 +896,13 @@ export interface RequestPurchaseAndroidProps {
889
896
  }
890
897
 
891
898
  export interface RequestPurchaseIosProps {
899
+ /**
900
+ * Advanced commerce data token (iOS 15+).
901
+ * Used with StoreKit 2's Product.PurchaseOption.custom API for passing
902
+ * campaign tokens, affiliate IDs, or other attribution data.
903
+ * The data is formatted as JSON: {"signatureInfo": {"token": "<value>"}}
904
+ */
905
+ advancedCommerceData?: (string | null);
892
906
  /** Auto-finish transaction (dangerous) */
893
907
  andDangerouslyFinishTransactionAutomatically?: (boolean | null);
894
908
  /** App account token for user tracking */
@@ -964,6 +978,13 @@ export interface RequestSubscriptionAndroidProps {
964
978
  }
965
979
 
966
980
  export interface RequestSubscriptionIosProps {
981
+ /**
982
+ * Advanced commerce data token (iOS 15+).
983
+ * Used with StoreKit 2's Product.PurchaseOption.custom API for passing
984
+ * campaign tokens, affiliate IDs, or other attribution data.
985
+ * The data is formatted as JSON: {"signatureInfo": {"token": "<value>"}}
986
+ */
987
+ advancedCommerceData?: (string | null);
967
988
  andDangerouslyFinishTransactionAutomatically?: (boolean | null);
968
989
  appAccountToken?: (string | null);
969
990
  quantity?: (number | null);