react-native-iap 16.2.3 → 16.3.0

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 (33) hide show
  1. package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +4 -0
  2. package/ios/HybridRnIap.swift +4 -0
  3. package/lib/module/index.js +18 -1
  4. package/lib/module/index.js.map +1 -1
  5. package/lib/module/kit-api.js +16 -38
  6. package/lib/module/kit-api.js.map +1 -1
  7. package/lib/module/types.js.map +1 -1
  8. package/lib/module/vega-adapter.js +10 -0
  9. package/lib/module/vega-adapter.js.map +1 -1
  10. package/lib/typescript/src/index.d.ts +3 -1
  11. package/lib/typescript/src/index.d.ts.map +1 -1
  12. package/lib/typescript/src/kit-api.d.ts.map +1 -1
  13. package/lib/typescript/src/specs/RnIap.nitro.d.ts +4 -0
  14. package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
  15. package/lib/typescript/src/types.d.ts +11 -0
  16. package/lib/typescript/src/types.d.ts.map +1 -1
  17. package/lib/typescript/src/vega-adapter.d.ts.map +1 -1
  18. package/nitrogen/generated/android/c++/JNitroVerifyPurchaseWithIapkitAmazonProps.hpp +5 -1
  19. package/nitrogen/generated/android/c++/JNitroVerifyPurchaseWithIapkitResult.hpp +5 -1
  20. package/nitrogen/generated/android/c++/JVariant_NullType_NitroVerifyPurchaseWithIapkitAmazonProps.hpp +1 -1
  21. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroVerifyPurchaseWithIapkitAmazonProps.kt +8 -3
  22. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroVerifyPurchaseWithIapkitResult.kt +7 -2
  23. package/nitrogen/generated/ios/swift/NitroVerifyPurchaseWithIapkitAmazonProps.swift +39 -2
  24. package/nitrogen/generated/ios/swift/NitroVerifyPurchaseWithIapkitResult.swift +38 -1
  25. package/nitrogen/generated/shared/c++/NitroVerifyPurchaseWithIapkitAmazonProps.hpp +6 -2
  26. package/nitrogen/generated/shared/c++/NitroVerifyPurchaseWithIapkitResult.hpp +5 -1
  27. package/openiap-versions.json +3 -3
  28. package/package.json +1 -1
  29. package/src/index.ts +26 -1
  30. package/src/kit-api.ts +23 -46
  31. package/src/specs/RnIap.nitro.ts +4 -0
  32. package/src/types.ts +11 -0
  33. package/src/vega-adapter.ts +15 -0
package/src/kit-api.ts CHANGED
@@ -121,19 +121,19 @@ type CachedClientPayload = KitClientPayloadResponse & {
121
121
  etag?: string;
122
122
  };
123
123
 
124
+ type InternalRequestInit = Omit<RequestInit, "headers"> & {
125
+ headers?: Record<string, string>;
126
+ };
127
+
124
128
  const DEFAULT_BASE_URL = "https://kit.openiap.dev";
125
129
 
126
- // Merge caller-supplied headers with kit defaults (`accept`,
127
- // optionally `content-type`). When the runtime exposes a global
128
- // `Headers` constructor we use it directly so callers passing a
129
- // `Headers` instance (a `HeadersInit`) keep that exact instance's
130
- // values. When `Headers` is missing older React Native builds where
131
- // the operator wires up `fetchImpl` without a `Headers` polyfill —
132
- // we fall back to a case-insensitive merge into a plain record so
133
- // the request still goes through. Either way, caller-set values take
134
- // precedence over kit defaults.
130
+ // Merge the request's internal headers with kit defaults (`accept`,
131
+ // optionally `content-type`). When `Headers` is missing older React
132
+ // Native builds where the operator wires up `fetchImpl` without a
133
+ // `Headers` polyfill the internal request sites use plain records,
134
+ // so a small case-insensitive merge is sufficient.
135
135
  function mergeHeaders(
136
- callerHeaders: HeadersInit | undefined,
136
+ callerHeaders: Record<string, string> | undefined,
137
137
  hasBody: boolean,
138
138
  ): HeadersInit {
139
139
  if (typeof Headers === "function") {
@@ -144,41 +144,16 @@ function mergeHeaders(
144
144
  }
145
145
  return merged;
146
146
  }
147
- // Plain-object fallback path. Build a case-insensitive name map
148
- // from whatever the caller passed (Headers-shaped, array-of-pairs,
149
- // or plain record) and re-emit as a record `fetchImpl` accepts.
147
+ // Plain-object fallback path. Build a case-insensitive name map and
148
+ // re-emit it as a record `fetchImpl` accepts.
150
149
  const lower = new Map<string, { name: string; value: string }>();
151
150
  const setIfAbsent = (name: string, value: string) => {
152
151
  const key = name.toLowerCase();
153
152
  if (!lower.has(key)) lower.set(key, { name, value });
154
153
  };
155
- const setForce = (name: string, value: string) => {
156
- const key = name.toLowerCase();
157
- lower.set(key, { name, value });
158
- };
159
154
  if (callerHeaders) {
160
- if (Array.isArray(callerHeaders)) {
161
- for (const [name, value] of callerHeaders) setForce(name, value);
162
- } else if (
163
- typeof (callerHeaders as { forEach?: unknown }).forEach === "function"
164
- ) {
165
- // `Headers`-like (without being our `typeof Headers === "function"`
166
- // global). RN polyfills sometimes attach `Headers` only to
167
- // request/response instances rather than the global scope.
168
- // Standard signature is `forEach((value, key, parent))`; we
169
- // bind the first two positionally so a polyfill that omits
170
- // the third argument still works. `key` is the header name.
171
- (
172
- callerHeaders as {
173
- forEach: (cb: (value: string, key: string) => void) => void;
174
- }
175
- ).forEach((value, key) => setForce(key, value));
176
- } else {
177
- for (const [name, value] of Object.entries(
178
- callerHeaders as Record<string, string>,
179
- )) {
180
- setForce(name, value);
181
- }
155
+ for (const [name, value] of Object.entries(callerHeaders)) {
156
+ lower.set(name.toLowerCase(), { name, value });
182
157
  }
183
158
  }
184
159
  setIfAbsent("accept", "application/json");
@@ -212,16 +187,18 @@ export function kitApi(options: KitApiOptions) {
212
187
  );
213
188
  })();
214
189
 
215
- async function request(path: string, init?: RequestInit): Promise<Response> {
190
+ async function request(
191
+ path: string,
192
+ init?: InternalRequestInit,
193
+ ): Promise<Response> {
216
194
  // Normalize headers without depending on a global `Headers`
217
195
  // constructor: older React Native runtimes ship `fetch` (or a
218
196
  // polyfill via `fetchImpl`) without exposing `Headers` globally.
219
197
  // The prior implementation crashed before the first request on
220
- // those runtimes. We use `new Headers()` when available (preserves
221
- // caller-supplied `Headers` instances exactly), and otherwise fall
222
- // back to a small case-insensitive merge into a plain record.
223
- // Either way, kit defaults only apply when the caller hasn't set
224
- // the same name.
198
+ // those runtimes. We use `new Headers()` when available and
199
+ // otherwise fall back to a small case-insensitive merge into a
200
+ // plain record. Either way, kit defaults only apply when the
201
+ // internal request hasn't set the same name.
225
202
  const headers = mergeHeaders(init?.headers, init?.body != null);
226
203
  // Prepend a leading slash if `path` is missing one. Today's
227
204
  // call sites all hard-code the leading "/", but normalizing here
@@ -278,7 +255,7 @@ export function kitApi(options: KitApiOptions) {
278
255
  return parsed as T;
279
256
  }
280
257
 
281
- async function call<T>(path: string, init?: RequestInit): Promise<T> {
258
+ async function call<T>(path: string, init?: InternalRequestInit): Promise<T> {
282
259
  return parseResponse<T>(await request(path, init), path);
283
260
  }
284
261
 
@@ -441,6 +441,8 @@ export interface NitroVerifyPurchaseWithIapkitGoogleProps {
441
441
  }
442
442
 
443
443
  export interface NitroVerifyPurchaseWithIapkitAmazonProps {
444
+ /** Available in OpenIAP Spec 3.2.0 / openiap-apple 3.2.0 / openiap-google 3.3.0. Optional Amazon product id that must match the product id verified by RVS. */
445
+ expectedProductId?: string | null;
444
446
  /** Amazon Appstore receipt id returned by PurchaseResponse.getReceipt().getReceiptId(). */
445
447
  receiptId: string;
446
448
  /** Use Amazon RVS Cloud Sandbox for App Tester receipts. */
@@ -475,6 +477,8 @@ export interface NitroVerifyPurchaseWithProviderProps {
475
477
  export interface NitroVerifyPurchaseWithIapkitResult {
476
478
  /** Available in OpenIAP Spec 2.4.0 / openiap-apple 2.4.1 / openiap-google 2.4.1. */
477
479
  clientPayload?: NitroIapkitProductClientPayload | null;
480
+ /** Available in OpenIAP Spec 3.2.0 / openiap-apple 3.2.0 / openiap-google 3.3.0. Amazon RVS environment selected by IAPKit. */
481
+ environment?: string | null;
478
482
  isValid: boolean;
479
483
  /** Available in OpenIAP Spec 2.4.0 / openiap-apple 2.4.1 / openiap-google 2.4.1. */
480
484
  productId?: string | null;
package/src/types.ts CHANGED
@@ -1791,6 +1791,11 @@ export interface RequestSubscriptionPropsByPlatforms {
1791
1791
  }
1792
1792
 
1793
1793
  export interface RequestVerifyPurchaseWithIapkitAmazonProps {
1794
+ /**
1795
+ * Available in OpenIAP Spec 3.2.0 / openiap-apple 3.2.0 / openiap-google 3.3.0.
1796
+ * Optional Amazon product id that must match the product id verified by RVS.
1797
+ */
1798
+ expectedProductId?: (string | null);
1794
1799
  /** Amazon Appstore receipt id returned by PurchaseResponse.getReceipt().getReceiptId(). */
1795
1800
  receiptId: string;
1796
1801
  /** Use Amazon RVS Cloud Sandbox for App Tester receipts. */
@@ -1848,6 +1853,12 @@ export interface RequestVerifyPurchaseWithIapkitResult {
1848
1853
  * Apple or Google receipt is valid, and a payload exists for that product.
1849
1854
  */
1850
1855
  clientPayload?: (IapkitProductClientPayload | null);
1856
+ /**
1857
+ * Available in OpenIAP Spec 3.2.0 / openiap-apple 3.2.0 / openiap-google 3.3.0.
1858
+ * Amazon RVS environment selected by IAPKit. Present as `Sandbox` or
1859
+ * `Production` on handled Amazon verification results.
1860
+ */
1861
+ environment?: (string | null);
1851
1862
  /**
1852
1863
  * True when the purchase is valid and actionable.
1853
1864
  * Only entitled, pending-acknowledgment, or ready-to-consume return true.
@@ -1271,8 +1271,20 @@ export function createVegaIapModule(service: VegaPurchasingService): RnIap {
1271
1271
  `IAPKit returned malformed response (HTTP ${status}).`,
1272
1272
  );
1273
1273
  }
1274
+ const environment = json.environment;
1275
+ if (
1276
+ environment != null &&
1277
+ (typeof environment !== 'string' ||
1278
+ (environment !== 'Sandbox' && environment !== 'Production'))
1279
+ ) {
1280
+ throw createVegaError(
1281
+ ErrorCode.PurchaseVerificationFailed,
1282
+ `IAPKit returned malformed response (HTTP ${status}).`,
1283
+ );
1284
+ }
1274
1285
 
1275
1286
  return {
1287
+ ...(environment == null ? {} : {environment}),
1276
1288
  isValid: json.isValid,
1277
1289
  ...(productId == null ? {} : {productId}),
1278
1290
  state: normalizeIapkitState(json.state),
@@ -1341,6 +1353,9 @@ export function createVegaIapModule(service: VegaPurchasingService): RnIap {
1341
1353
  store: 'amazon',
1342
1354
  userId,
1343
1355
  receiptId,
1356
+ ...(amazon.expectedProductId == null
1357
+ ? {}
1358
+ : {expectedProductId: amazon.expectedProductId}),
1344
1359
  ...(amazon.sandbox == null ? {} : {sandbox: amazon.sandbox}),
1345
1360
  }),
1346
1361
  signal: controller.signal,