react-native-iap 15.3.5 → 15.4.0-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.
Files changed (83) hide show
  1. package/README.md +1 -1
  2. package/android/build.gradle +13 -5
  3. package/android/src/main/java/com/margelo/nitro/iap/HybridRnIap.kt +16 -3
  4. package/ios/HybridRnIap.swift +12 -0
  5. package/lib/module/index.js +93 -75
  6. package/lib/module/index.js.map +1 -1
  7. package/lib/module/index.kepler.js +170 -0
  8. package/lib/module/index.kepler.js.map +1 -0
  9. package/lib/module/types/amazon-devices-kepler/index.d.js +2 -0
  10. package/lib/module/types/amazon-devices-kepler/index.d.js.map +1 -0
  11. package/lib/module/types.js +5 -2
  12. package/lib/module/types.js.map +1 -1
  13. package/lib/module/utils/error.js +98 -15
  14. package/lib/module/utils/error.js.map +1 -1
  15. package/lib/module/utils/type-bridge.js +4 -1
  16. package/lib/module/utils/type-bridge.js.map +1 -1
  17. package/lib/module/vega-adapter.js +981 -0
  18. package/lib/module/vega-adapter.js.map +1 -0
  19. package/lib/module/vega.js +10 -0
  20. package/lib/module/vega.js.map +1 -0
  21. package/lib/module/vega.kepler.js +18 -0
  22. package/lib/module/vega.kepler.js.map +1 -0
  23. package/lib/typescript/plugin/src/withIAP.d.ts +33 -0
  24. package/lib/typescript/plugin/src/withIAP.d.ts.map +1 -1
  25. package/lib/typescript/src/index.d.ts +9 -2
  26. package/lib/typescript/src/index.d.ts.map +1 -1
  27. package/lib/typescript/src/index.kepler.d.ts +55 -0
  28. package/lib/typescript/src/index.kepler.d.ts.map +1 -0
  29. package/lib/typescript/src/specs/RnIap.nitro.d.ts +10 -1
  30. package/lib/typescript/src/specs/RnIap.nitro.d.ts.map +1 -1
  31. package/lib/typescript/src/types.d.ts +16 -3
  32. package/lib/typescript/src/types.d.ts.map +1 -1
  33. package/lib/typescript/src/utils/error.d.ts +1 -1
  34. package/lib/typescript/src/utils/error.d.ts.map +1 -1
  35. package/lib/typescript/src/utils/type-bridge.d.ts.map +1 -1
  36. package/lib/typescript/src/vega-adapter.d.ts +76 -0
  37. package/lib/typescript/src/vega-adapter.d.ts.map +1 -0
  38. package/lib/typescript/src/vega.d.ts +4 -0
  39. package/lib/typescript/src/vega.d.ts.map +1 -0
  40. package/lib/typescript/src/vega.kepler.d.ts +4 -0
  41. package/lib/typescript/src/vega.kepler.d.ts.map +1 -0
  42. package/nitrogen/generated/android/NitroIap+autolinking.cmake +1 -0
  43. package/nitrogen/generated/android/c++/JHybridRnIapSpec.cpp +5 -0
  44. package/nitrogen/generated/android/c++/JIapStore.hpp +3 -0
  45. package/nitrogen/generated/android/c++/JNitroVerifyPurchaseWithIapkitAmazonProps.hpp +71 -0
  46. package/nitrogen/generated/android/c++/JNitroVerifyPurchaseWithIapkitProps.hpp +9 -1
  47. package/nitrogen/generated/android/c++/JNitroVerifyPurchaseWithProviderProps.hpp +4 -0
  48. package/nitrogen/generated/android/c++/JVariant_NullType_NitroVerifyPurchaseWithIapkitAmazonProps.cpp +26 -0
  49. package/nitrogen/generated/android/c++/JVariant_NullType_NitroVerifyPurchaseWithIapkitAmazonProps.hpp +75 -0
  50. package/nitrogen/generated/android/c++/JVariant_NullType_NitroVerifyPurchaseWithIapkitProps.hpp +4 -0
  51. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/IapStore.kt +2 -1
  52. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroVerifyPurchaseWithIapkitAmazonProps.kt +44 -0
  53. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/NitroVerifyPurchaseWithIapkitProps.kt +5 -2
  54. package/nitrogen/generated/android/kotlin/com/margelo/nitro/iap/Variant_NullType_NitroVerifyPurchaseWithIapkitAmazonProps.kt +53 -0
  55. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Bridge.hpp +47 -0
  56. package/nitrogen/generated/ios/NitroIap-Swift-Cxx-Umbrella.hpp +3 -0
  57. package/nitrogen/generated/ios/c++/HybridRnIapSpecSwift.hpp +3 -0
  58. package/nitrogen/generated/ios/swift/IapStore.swift +4 -0
  59. package/nitrogen/generated/ios/swift/NitroVerifyPurchaseWithIapkitAmazonProps.swift +103 -0
  60. package/nitrogen/generated/ios/swift/NitroVerifyPurchaseWithIapkitProps.swift +38 -1
  61. package/nitrogen/generated/ios/swift/Variant_NullType_NitroVerifyPurchaseWithIapkitAmazonProps.swift +18 -0
  62. package/nitrogen/generated/shared/c++/IapStore.hpp +4 -0
  63. package/nitrogen/generated/shared/c++/NitroVerifyPurchaseWithIapkitAmazonProps.hpp +94 -0
  64. package/nitrogen/generated/shared/c++/NitroVerifyPurchaseWithIapkitProps.hpp +8 -1
  65. package/openiap-versions.json +2 -2
  66. package/package.json +17 -4
  67. package/plugin/build/withIAP.d.ts +33 -0
  68. package/plugin/build/withIAP.js +109 -42
  69. package/plugin/src/withIAP.ts +185 -55
  70. package/src/index.kepler.ts +311 -0
  71. package/src/index.ts +187 -78
  72. package/src/specs/RnIap.nitro.ts +13 -2
  73. package/src/types/amazon-devices-kepler/index.d.ts +14 -0
  74. package/src/types.ts +17 -3
  75. package/src/utils/error.ts +127 -14
  76. package/src/utils/type-bridge.ts +4 -1
  77. package/src/vega-adapter.ts +1503 -0
  78. package/src/vega.kepler.ts +21 -0
  79. package/src/vega.ts +10 -0
  80. package/android/src/test/java/com/margelo/nitro/iap/ListenerThreadSafetyTest.kt +0 -154
  81. package/android/src/test/java/com/margelo/nitro/iap/OpenIapExceptionTest.kt +0 -93
  82. package/android/src/test/java/com/margelo/nitro/iap/ProductQueryHelpersTest.kt +0 -140
  83. package/plugin/tsconfig.tsbuildinfo +0 -1
package/src/types.ts CHANGED
@@ -511,7 +511,7 @@ export type IapEvent = 'purchase-updated' | 'purchase-error' | 'promoted-product
511
511
 
512
512
  export type IapPlatform = 'ios' | 'android';
513
513
 
514
- export type IapStore = 'unknown' | 'apple' | 'google' | 'horizon';
514
+ export type IapStore = 'unknown' | 'apple' | 'google' | 'horizon' | 'amazon';
515
515
 
516
516
  /** Unified purchase states from IAPKit verification response. */
517
517
  export type IapkitPurchaseState = 'entitled' | 'pending-acknowledgment' | 'pending' | 'canceled' | 'expired' | 'ready-to-consume' | 'consumed' | 'unknown' | 'inauthentic';
@@ -1614,7 +1614,8 @@ export type RequestPurchaseProps =
1614
1614
  *
1615
1615
  * Note: "Platforms" refers to the SDK/OS level (apple, google), not the store.
1616
1616
  * - apple: Always targets App Store
1617
- * - google: Targets Play Store by default, or Horizon when built with horizon flavor
1617
+ * - google: Targets Play Store by default, Horizon when built with horizon flavor,
1618
+ * or Fire OS when built with amazon flavor
1618
1619
  * (determined at build time, not runtime)
1619
1620
  */
1620
1621
  export interface RequestPurchasePropsByPlatforms {
@@ -1713,7 +1714,8 @@ export interface RequestSubscriptionIosProps {
1713
1714
  *
1714
1715
  * Note: "Platforms" refers to the SDK/OS level (apple, google), not the store.
1715
1716
  * - apple: Always targets App Store
1716
- * - google: Targets Play Store by default, or Horizon when built with horizon flavor
1717
+ * - google: Targets Play Store by default, Horizon when built with horizon flavor,
1718
+ * or Fire OS when built with amazon flavor
1717
1719
  * (determined at build time, not runtime)
1718
1720
  */
1719
1721
  export interface RequestSubscriptionPropsByPlatforms {
@@ -1727,6 +1729,15 @@ export interface RequestSubscriptionPropsByPlatforms {
1727
1729
  ios?: (RequestSubscriptionIosProps | null);
1728
1730
  }
1729
1731
 
1732
+ export interface RequestVerifyPurchaseWithIapkitAmazonProps {
1733
+ /** Amazon Appstore receipt id returned by PurchaseResponse.getReceipt().getReceiptId(). */
1734
+ receiptId: string;
1735
+ /** Use Amazon RVS Cloud Sandbox for App Tester receipts. */
1736
+ sandbox?: (boolean | null);
1737
+ /** Amazon Appstore user id returned by PurchaseResponse.getUserData().getUserId(). */
1738
+ userId?: (string | null);
1739
+ }
1740
+
1730
1741
  export interface RequestVerifyPurchaseWithIapkitAppleProps {
1731
1742
  /** The JWS token returned with the purchase response. */
1732
1743
  jws: string;
@@ -1742,8 +1753,11 @@ export interface RequestVerifyPurchaseWithIapkitGoogleProps {
1742
1753
  *
1743
1754
  * - apple: Verifies via App Store (JWS token)
1744
1755
  * - google: Verifies via Play Store (purchase token)
1756
+ * - amazon: Verifies via Amazon Appstore RVS (userId + receiptId)
1745
1757
  */
1746
1758
  export interface RequestVerifyPurchaseWithIapkitProps {
1759
+ /** Amazon Appstore verification parameters. */
1760
+ amazon?: (RequestVerifyPurchaseWithIapkitAmazonProps | null);
1747
1761
  /** API key used for the Authorization header (Bearer {apiKey}). */
1748
1762
  apiKey?: (string | null);
1749
1763
  /** Apple App Store verification parameters. */
@@ -16,12 +16,125 @@ export interface IapError {
16
16
  [key: string]: any; // Allow additional platform-specific fields
17
17
  }
18
18
 
19
+ const parseJsonPayload = (
20
+ payload: string,
21
+ fallbackMessage: string,
22
+ ): IapError | null => {
23
+ const trimmed = payload.trim();
24
+ const candidates = [trimmed];
25
+
26
+ if (trimmed.includes('\\"')) {
27
+ candidates.push(trimmed.replace(/\\"/g, '"'));
28
+ }
29
+
30
+ for (const candidate of candidates) {
31
+ try {
32
+ const parsed = JSON.parse(candidate);
33
+ if (typeof parsed === 'object' && parsed !== null) {
34
+ const parsedError = parsed as Partial<IapError>;
35
+ return {
36
+ code: parsedError.code || ErrorCode.Unknown,
37
+ message: parsedError.message || fallbackMessage,
38
+ ...parsedError,
39
+ };
40
+ }
41
+ } catch {
42
+ // Try the next candidate.
43
+ }
44
+ }
45
+
46
+ return null;
47
+ };
48
+
49
+ const extractBalancedJsonObject = (
50
+ value: string,
51
+ startIndex: number,
52
+ ): string | null => {
53
+ for (let index = startIndex; index < value.length; index += 1) {
54
+ if (value[index] !== '}') {
55
+ continue;
56
+ }
57
+
58
+ const candidate = value.substring(startIndex, index + 1);
59
+ if (parseJsonPayload(candidate, value)) {
60
+ return candidate;
61
+ }
62
+ }
63
+
64
+ return null;
65
+ };
66
+
67
+ const parseNSErrorJsonPayload = (rawString: string): IapError | null => {
68
+ const payloads: string[] = [];
69
+ const quotedPayloadMatch = /Code=-?\d+\s+"/.exec(rawString);
70
+
71
+ if (quotedPayloadMatch?.index !== undefined) {
72
+ const contentStart =
73
+ quotedPayloadMatch.index + quotedPayloadMatch[0].length;
74
+ const userInfoIndex = rawString.indexOf('UserInfo=', contentStart);
75
+ const contentEnd =
76
+ userInfoIndex > contentStart
77
+ ? rawString.lastIndexOf('"', userInfoIndex)
78
+ : rawString.lastIndexOf('"');
79
+
80
+ if (contentEnd > contentStart) {
81
+ payloads.push(rawString.substring(contentStart, contentEnd));
82
+ }
83
+ }
84
+
85
+ const localizedDescription = 'NSLocalizedDescription=';
86
+ const descriptionIndex = rawString.indexOf(localizedDescription);
87
+
88
+ if (descriptionIndex >= 0) {
89
+ let valueStart = descriptionIndex + localizedDescription.length;
90
+ while (/\s/.test(rawString[valueStart] ?? '')) {
91
+ valueStart += 1;
92
+ }
93
+
94
+ const firstBraceIndex = rawString.indexOf('{', valueStart);
95
+ if (firstBraceIndex >= 0 && firstBraceIndex <= valueStart + 2) {
96
+ const payload = extractBalancedJsonObject(rawString, firstBraceIndex);
97
+ if (payload) {
98
+ payloads.push(payload);
99
+ }
100
+ }
101
+ }
102
+
103
+ for (const payload of payloads) {
104
+ const parsed = parseJsonPayload(payload, rawString);
105
+ if (parsed?.code && parsed.code !== ErrorCode.Unknown) {
106
+ return parsed;
107
+ }
108
+ }
109
+
110
+ return null;
111
+ };
112
+
113
+ const parseStructuredError = (error: Error): IapError | null => {
114
+ const errorWithCode = error as Error & {code?: unknown} & Record<
115
+ string,
116
+ unknown
117
+ >;
118
+
119
+ if (errorWithCode.code != null) {
120
+ const {code, message, ...extraFields} = errorWithCode;
121
+
122
+ return {
123
+ ...extraFields,
124
+ code: String(code),
125
+ message: typeof message === 'string' ? message : error.message,
126
+ };
127
+ }
128
+
129
+ return null;
130
+ };
131
+
19
132
  /**
20
133
  * Parses error string from native modules into a structured error object
21
134
  *
22
135
  * Native modules return errors in different formats:
23
136
  * - Android: JSON string like '{"code":"E_USER_CANCELLED","message":"User cancelled the purchase","responseCode":1}'
24
- * - iOS: JSON string or plain message
137
+ * - iOS: JSON string, Nitro NSError string with embedded JSON, or plain message
25
138
  * - Legacy: "CODE: message" format
26
139
  *
27
140
  * @param errorString - The error string from native module
@@ -32,6 +145,11 @@ export function parseErrorStringToJsonObj(
32
145
  ): IapError {
33
146
  // Handle Error objects
34
147
  if (errorString instanceof Error) {
148
+ const structuredError = parseStructuredError(errorString);
149
+ if (structuredError) {
150
+ return structuredError;
151
+ }
152
+
35
153
  errorString = errorString.message;
36
154
  }
37
155
 
@@ -43,19 +161,14 @@ export function parseErrorStringToJsonObj(
43
161
  };
44
162
  }
45
163
 
46
- // Try to parse as JSON first
47
- try {
48
- const parsed = JSON.parse(errorString);
49
- if (typeof parsed === 'object' && parsed !== null) {
50
- // Ensure it has at least code and message
51
- return {
52
- code: parsed.code || ErrorCode.Unknown,
53
- message: parsed.message || errorString,
54
- ...parsed,
55
- };
56
- }
57
- } catch {
58
- // Not JSON, continue with other formats
164
+ const jsonPayload = parseJsonPayload(errorString, errorString);
165
+ if (jsonPayload) {
166
+ return jsonPayload;
167
+ }
168
+
169
+ const nsErrorPayload = parseNSErrorJsonPayload(errorString);
170
+ if (nsErrorPayload) {
171
+ return nsErrorPayload;
59
172
  }
60
173
 
61
174
  // Try to parse "CODE: message" format
@@ -35,6 +35,7 @@ const STORE_UNKNOWN: IapStore = 'unknown';
35
35
  const STORE_APPLE: IapStore = 'apple';
36
36
  const STORE_GOOGLE: IapStore = 'google';
37
37
  const STORE_HORIZON: IapStore = 'horizon';
38
+ const STORE_AMAZON: IapStore = 'amazon';
38
39
  const PRODUCT_TYPE_SUBS: ProductType = 'subs';
39
40
  const PRODUCT_TYPE_IN_APP: ProductType = 'in-app';
40
41
  const PURCHASE_STATE_PENDING: PurchaseState = 'pending';
@@ -67,6 +68,8 @@ function normalizeStore(value?: Nullable<string>): IapStore {
67
68
  return STORE_GOOGLE;
68
69
  case 'horizon':
69
70
  return STORE_HORIZON;
71
+ case 'amazon':
72
+ return STORE_AMAZON;
70
73
  default:
71
74
  return STORE_UNKNOWN;
72
75
  }
@@ -191,7 +194,7 @@ function toNullableBoolean(value: unknown): boolean | null {
191
194
  function parseSubscriptionOffers(value?: Nullable<string> | any[]) {
192
195
  if (!value) return undefined;
193
196
 
194
- // If it's already an array (from mocks), return it as-is
197
+ // Keep pre-normalized native values intact.
195
198
  if (Array.isArray(value)) {
196
199
  return value;
197
200
  }