react-native-iap 15.5.1 → 15.5.3

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 (61) hide show
  1. package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +26 -3
  2. package/ios/HybridRnIap.swift +16 -0
  3. package/lib/module/hooks/useIAP.js +6 -2
  4. package/lib/module/hooks/useIAP.js.map +1 -1
  5. package/lib/module/index.js +6 -0
  6. package/lib/module/index.js.map +1 -1
  7. package/lib/module/index.kepler.js.map +1 -1
  8. package/lib/module/kit-api.js +27 -0
  9. package/lib/module/kit-api.js.map +1 -1
  10. package/lib/module/types.js +7 -0
  11. package/lib/module/types.js.map +1 -1
  12. package/lib/module/vega-adapter.js +10 -6
  13. package/lib/module/vega-adapter.js.map +1 -1
  14. package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
  15. package/lib/typescript/src/index.d.ts +1 -1
  16. package/lib/typescript/src/index.d.ts.map +1 -1
  17. package/lib/typescript/src/index.kepler.d.ts +1 -0
  18. package/lib/typescript/src/index.kepler.d.ts.map +1 -1
  19. package/lib/typescript/src/kit-api.d.ts +60 -0
  20. package/lib/typescript/src/kit-api.d.ts.map +1 -1
  21. package/lib/typescript/src/specs/RnIap.nitro.d.ts +16 -0
  22. package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
  23. package/lib/typescript/src/types.d.ts +36 -1
  24. package/lib/typescript/src/types.d.ts.map +1 -1
  25. package/lib/typescript/src/vega-adapter.d.ts.map +1 -1
  26. package/nitrogen/generated/android/NitroIap+autolinking.cmake +1 -0
  27. package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +9 -0
  28. package/nitrogen/generated/android/c++/JIapkitClientPayloadFormat.hpp +61 -0
  29. package/nitrogen/generated/android/c++/JNitroIapkitProductClientPayload.hpp +71 -0
  30. package/nitrogen/generated/android/c++/JNitroVerifyPurchaseWithIapkitProps.hpp +7 -3
  31. package/nitrogen/generated/android/c++/JNitroVerifyPurchaseWithIapkitResult.hpp +20 -1
  32. package/nitrogen/generated/android/c++/JNitroVerifyPurchaseWithProviderResult.hpp +5 -0
  33. package/nitrogen/generated/android/c++/JVariant_NullType_NitroIapkitProductClientPayload.cpp +26 -0
  34. package/nitrogen/generated/android/c++/JVariant_NullType_NitroIapkitProductClientPayload.hpp +74 -0
  35. package/nitrogen/generated/android/c++/JVariant_NullType_NitroVerifyPurchaseWithIapkitResult.hpp +8 -0
  36. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/IapkitClientPayloadFormat.kt +24 -0
  37. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroIapkitProductClientPayload.kt +66 -0
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroVerifyPurchaseWithIapkitProps.kt +9 -4
  39. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroVerifyPurchaseWithIapkitResult.kt +14 -4
  40. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_NullType_NitroIapkitProductClientPayload.kt +62 -0
  41. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.hpp +50 -0
  42. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Umbrella.hpp +6 -0
  43. package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +6 -0
  44. package/nitrogen/generated/ios/swift/IapkitClientPayloadFormat.swift +44 -0
  45. package/nitrogen/generated/ios/swift/NitroIapkitProductClientPayload.swift +44 -0
  46. package/nitrogen/generated/ios/swift/NitroVerifyPurchaseWithIapkitProps.swift +38 -1
  47. package/nitrogen/generated/ios/swift/NitroVerifyPurchaseWithIapkitResult.swift +76 -2
  48. package/nitrogen/generated/ios/swift/Variant_NullType_NitroIapkitProductClientPayload.swift +30 -0
  49. package/nitrogen/generated/shared/c++/IapkitClientPayloadFormat.hpp +80 -0
  50. package/nitrogen/generated/shared/c++/NitroIapkitProductClientPayload.hpp +97 -0
  51. package/nitrogen/generated/shared/c++/NitroVerifyPurchaseWithIapkitProps.hpp +6 -2
  52. package/nitrogen/generated/shared/c++/NitroVerifyPurchaseWithIapkitResult.hpp +16 -1
  53. package/openiap-versions.json +3 -3
  54. package/package.json +1 -1
  55. package/src/hooks/useIAP.ts +6 -2
  56. package/src/index.kepler.ts +13 -0
  57. package/src/index.ts +13 -0
  58. package/src/kit-api.ts +107 -0
  59. package/src/specs/RnIap.nitro.ts +18 -0
  60. package/src/types.ts +38 -1
  61. package/src/vega-adapter.ts +14 -11
package/src/kit-api.ts CHANGED
@@ -40,6 +40,71 @@ export type StatusResponse = {
40
40
  subscription: KitSubscription | null;
41
41
  };
42
42
 
43
+ export type KitProductPlatform = "IOS" | "Android";
44
+
45
+ export type KitProductClientPayload = {
46
+ format: "toml" | "json" | "text";
47
+ body: string;
48
+ version: number;
49
+ updatedAt: number;
50
+ };
51
+
52
+ export type KitProductOffer = {
53
+ id: string;
54
+ kind:
55
+ | "FreeTrial"
56
+ | "IntroPayUpFront"
57
+ | "IntroPayAsYouGo"
58
+ | "PromotionalOffer"
59
+ | "BasePlan";
60
+ duration?: string;
61
+ numberOfPeriods?: number;
62
+ priceAmountMicros?: number;
63
+ currency?: string;
64
+ };
65
+
66
+ export type KitProduct = {
67
+ productId: string;
68
+ platform: KitProductPlatform;
69
+ type: "Subscription" | "NonConsumable" | "Consumable";
70
+ title: string;
71
+ description?: string;
72
+ priceAmountMicros?: number;
73
+ currency?: string;
74
+ state: "Draft" | "Ready" | "Active" | "Removed";
75
+ storeRef?: string;
76
+ subscriptionGroupId?: string;
77
+ subscriptionGroupName?: string;
78
+ billingPeriod?: "P1W" | "P1M" | "P2M" | "P3M" | "P6M" | "P1Y";
79
+ offers?: KitProductOffer[];
80
+ updatedAt: number;
81
+ clientPayload?: KitProductClientPayload;
82
+ };
83
+
84
+ export type KitProductsOptions = {
85
+ platform?: KitProductPlatform;
86
+ /** Include public client payload bodies in a bounded platform page. */
87
+ includeClientPayload?: boolean;
88
+ /** Page size for payload-inclusive reads (default 25, maximum 50).
89
+ * Ignored by the legacy non-payload catalog path. */
90
+ limit?: number;
91
+ /** Opaque cursor returned as `nextCursor` by the previous payload page.
92
+ * Ignored by the legacy non-payload catalog path. */
93
+ cursor?: string;
94
+ };
95
+
96
+ export type KitProductsResponse = {
97
+ products: KitProduct[];
98
+ /** Present on payload-inclusive catalog pages. */
99
+ hasMore?: boolean;
100
+ /** Present when a payload-inclusive catalog page has another page. */
101
+ nextCursor?: string;
102
+ };
103
+
104
+ export type KitClientPayloadResponse = {
105
+ clientPayload: KitProductClientPayload;
106
+ };
107
+
43
108
  const DEFAULT_BASE_URL = "https://kit.openiap.dev";
44
109
 
45
110
  // Merge caller-supplied headers with kit defaults (`accept`,
@@ -210,6 +275,48 @@ export function kitApi(options: KitApiOptions) {
210
275
  `/v1/subscriptions/entitlements/${encodeURIComponent(options.apiKey)}?userId=${encodeURIComponent(userId)}`,
211
276
  ),
212
277
 
278
+ /** GET /v1/products — read the store-synced catalog. Client payloads
279
+ * are excluded unless explicitly requested because they may add up to
280
+ * 16 KiB per product. */
281
+ products: (productOptions: KitProductsOptions = {}) => {
282
+ if (
283
+ productOptions.includeClientPayload === true &&
284
+ !productOptions.platform
285
+ ) {
286
+ throw new Error(
287
+ "kitApi.products requires platform when includeClientPayload is true",
288
+ );
289
+ }
290
+ const query = new URLSearchParams();
291
+ if (productOptions.platform) {
292
+ query.set("platform", productOptions.platform);
293
+ }
294
+ if (productOptions.includeClientPayload !== undefined) {
295
+ query.set(
296
+ "includeClientPayload",
297
+ String(productOptions.includeClientPayload),
298
+ );
299
+ }
300
+ if (productOptions.limit !== undefined) {
301
+ query.set("limit", String(productOptions.limit));
302
+ }
303
+ if (productOptions.cursor !== undefined) {
304
+ query.set("cursor", productOptions.cursor);
305
+ }
306
+ const encodedQuery = query.toString();
307
+ const suffix = encodedQuery ? `?${encodedQuery}` : "";
308
+ return call<KitProductsResponse>(
309
+ `/v1/products/${encodeURIComponent(options.apiKey)}${suffix}`,
310
+ );
311
+ },
312
+
313
+ /** GET one public client payload by its store-specific natural key.
314
+ * Payloads are app-facing data; never store secrets in them. */
315
+ clientPayload: (productId: string, platform: KitProductPlatform) =>
316
+ call<KitClientPayloadResponse>(
317
+ `/v1/products/${encodeURIComponent(options.apiKey)}/${encodeURIComponent(productId)}/client-payload?platform=${encodeURIComponent(platform)}`,
318
+ ),
319
+
213
320
  /** POST /v1/subscriptions/bind-user — call after a successful
214
321
  * verifyReceipt so kit knows which userId owns the verified
215
322
  * `purchaseToken`. Idempotent. */
@@ -100,6 +100,8 @@ export type IapkitPurchaseState =
100
100
  | 'unknown'
101
101
  | 'inauthentic';
102
102
 
103
+ export type IapkitClientPayloadFormat = 'toml' | 'json' | 'text';
104
+
103
105
  // Store identifier for purchase origin
104
106
  // Defined locally for Nitro codegen (not in GQL schema)
105
107
  export type IapStore = 'unknown' | 'apple' | 'google' | 'horizon' | 'amazon';
@@ -473,6 +475,11 @@ export interface NitroVerifyPurchaseWithIapkitProps {
473
475
  */
474
476
  baseUrl?: string | null;
475
477
  google?: NitroVerifyPurchaseWithIapkitGoogleProps | null;
478
+ /**
479
+ * Available in OpenIAP Spec 2.4.0 / openiap-apple 2.4.1 / openiap-google 2.4.1.
480
+ * Include the product's public IAPKit client payload when available.
481
+ */
482
+ includeClientPayload?: boolean | null;
476
483
  }
477
484
 
478
485
  export interface NitroVerifyPurchaseWithProviderProps {
@@ -481,11 +488,22 @@ export interface NitroVerifyPurchaseWithProviderProps {
481
488
  }
482
489
 
483
490
  export interface NitroVerifyPurchaseWithIapkitResult {
491
+ /** Available in OpenIAP Spec 2.4.0 / openiap-apple 2.4.1 / openiap-google 2.4.1. */
492
+ clientPayload?: NitroIapkitProductClientPayload | null;
484
493
  isValid: boolean;
494
+ /** Available in OpenIAP Spec 2.4.0 / openiap-apple 2.4.1 / openiap-google 2.4.1. */
495
+ productId?: string | null;
485
496
  state: IapkitPurchaseState;
486
497
  store: IapStore;
487
498
  }
488
499
 
500
+ export interface NitroIapkitProductClientPayload {
501
+ body: string;
502
+ format: IapkitClientPayloadFormat;
503
+ updatedAt: number;
504
+ version: number;
505
+ }
506
+
489
507
  export interface NitroVerifyPurchaseWithProviderError {
490
508
  code?: string | null;
491
509
  message: string;
package/src/types.ts CHANGED
@@ -617,6 +617,20 @@ export type IapPlatform = 'ios' | 'android';
617
617
 
618
618
  export type IapStore = 'unknown' | 'apple' | 'google' | 'horizon' | 'amazon';
619
619
 
620
+ /** Serialization format of a public IAPKit product client payload. */
621
+ export type IapkitClientPayloadFormat = 'toml' | 'json' | 'text';
622
+
623
+ /**
624
+ * Public app-facing data attached to one store product in IAPKit.
625
+ * Never place credentials, signing keys, or server-authoritative rules here.
626
+ */
627
+ export interface IapkitProductClientPayload {
628
+ body: string;
629
+ format: IapkitClientPayloadFormat;
630
+ updatedAt: number;
631
+ version: number;
632
+ }
633
+
620
634
  /** Unified purchase states from IAPKit verification response. */
621
635
  export type IapkitPurchaseState = 'entitled' | 'pending-acknowledgment' | 'pending' | 'canceled' | 'expired' | 'ready-to-consume' | 'consumed' | 'unknown' | 'inauthentic';
622
636
 
@@ -1987,11 +2001,34 @@ export interface RequestVerifyPurchaseWithIapkitProps {
1987
2001
  baseUrl?: (string | null);
1988
2002
  /** Google Play Store verification parameters. */
1989
2003
  google?: (RequestVerifyPurchaseWithIapkitGoogleProps | null);
2004
+ /**
2005
+ * Available in OpenIAP Spec 2.4.0 / openiap-apple 2.4.1 / openiap-google 2.4.1.
2006
+ * Include the product's public IAPKit client payload in a valid Apple or
2007
+ * Google verification response. Defaults to false so existing response
2008
+ * shapes and bandwidth remain unchanged.
2009
+ */
2010
+ includeClientPayload?: (boolean | null);
1990
2011
  }
1991
2012
 
1992
2013
  export interface RequestVerifyPurchaseWithIapkitResult {
1993
- /** Whether the purchase is valid (not falsified). */
2014
+ /**
2015
+ * Available in OpenIAP Spec 2.4.0 / openiap-apple 2.4.1 / openiap-google 2.4.1.
2016
+ * Public product payload when includeClientPayload was requested, the
2017
+ * Apple or Google receipt is valid, and a payload exists for that product.
2018
+ */
2019
+ clientPayload?: (IapkitProductClientPayload | null);
2020
+ /**
2021
+ * True when the purchase is valid and actionable.
2022
+ * Only entitled, pending-acknowledgment, or ready-to-consume return true.
2023
+ * Callers must still match productId and use the platform plus app-owned product
2024
+ * type to choose the fulfillment path.
2025
+ */
1994
2026
  isValid: boolean;
2027
+ /**
2028
+ * Available in OpenIAP Spec 2.4.0 / openiap-apple 2.4.1 / openiap-google 2.4.1.
2029
+ * Store-verified product identifier when the provider returns one.
2030
+ */
2031
+ productId?: (string | null);
1995
2032
  /** The current state of the purchase. */
1996
2033
  state: IapkitPurchaseState;
1997
2034
  store: IapStore;
@@ -4,6 +4,7 @@ import type {
4
4
  NitroProduct,
5
5
  NitroPurchase,
6
6
  NitroPurchaseResult,
7
+ NitroVerifyPurchaseWithIapkitResult,
7
8
  NitroVerifyPurchaseWithProviderProps,
8
9
  NitroVerifyPurchaseWithProviderResult,
9
10
  RnIap,
@@ -155,8 +156,7 @@ function isValidIpv4Address(address: string): boolean {
155
156
  return (
156
157
  octets.length === 4 &&
157
158
  octets.every(
158
- (octet) =>
159
- /^(?:0|[1-9]\d{0,2})$/.test(octet) && Number(octet) <= 255,
159
+ (octet) => /^(?:0|[1-9]\d{0,2})$/.test(octet) && Number(octet) <= 255,
160
160
  )
161
161
  );
162
162
  }
@@ -1236,10 +1236,7 @@ export function createVegaIapModule(service: VegaPurchasingService): RnIap {
1236
1236
  function readIapkitResult(
1237
1237
  json: Record<string, unknown>,
1238
1238
  status: number,
1239
- ): {
1240
- isValid: boolean;
1241
- state: IapkitPurchaseState;
1242
- } {
1239
+ ): NitroVerifyPurchaseWithIapkitResult {
1243
1240
  if (
1244
1241
  typeof json.isValid !== 'boolean' ||
1245
1242
  typeof json.state !== 'string' ||
@@ -1251,9 +1248,19 @@ export function createVegaIapModule(service: VegaPurchasingService): RnIap {
1251
1248
  );
1252
1249
  }
1253
1250
 
1251
+ const productId = json.productId;
1252
+ if (productId != null && typeof productId !== 'string') {
1253
+ throw createVegaError(
1254
+ ErrorCode.ReceiptFailed,
1255
+ `IAPKit returned malformed response (HTTP ${status}).`,
1256
+ );
1257
+ }
1258
+
1254
1259
  return {
1255
1260
  isValid: json.isValid,
1261
+ ...(productId == null ? {} : {productId}),
1256
1262
  state: normalizeIapkitState(json.state),
1263
+ store: 'amazon',
1257
1264
  };
1258
1265
  }
1259
1266
 
@@ -1374,11 +1381,7 @@ export function createVegaIapModule(service: VegaPurchasingService): RnIap {
1374
1381
  const result = readIapkitResult(json, response.status);
1375
1382
  return {
1376
1383
  provider: 'iapkit',
1377
- iapkit: {
1378
- isValid: result.isValid,
1379
- state: result.state,
1380
- store: 'amazon',
1381
- },
1384
+ iapkit: result,
1382
1385
  };
1383
1386
  };
1384
1387