react-native-iap 14.4.0 → 14.4.2

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.
@@ -6,40 +6,40 @@
6
6
  // ============================================================================
7
7
 
8
8
  export let ErrorCode = /*#__PURE__*/function (ErrorCode) {
9
- ErrorCode["ActivityUnavailable"] = "ACTIVITY_UNAVAILABLE";
10
- ErrorCode["AlreadyOwned"] = "ALREADY_OWNED";
11
- ErrorCode["AlreadyPrepared"] = "ALREADY_PREPARED";
12
- ErrorCode["BillingResponseJsonParseError"] = "BILLING_RESPONSE_JSON_PARSE_ERROR";
13
- ErrorCode["BillingUnavailable"] = "BILLING_UNAVAILABLE";
14
- ErrorCode["ConnectionClosed"] = "CONNECTION_CLOSED";
15
- ErrorCode["DeferredPayment"] = "DEFERRED_PAYMENT";
16
- ErrorCode["DeveloperError"] = "DEVELOPER_ERROR";
17
- ErrorCode["EmptySkuList"] = "EMPTY_SKU_LIST";
18
- ErrorCode["FeatureNotSupported"] = "FEATURE_NOT_SUPPORTED";
19
- ErrorCode["IapNotAvailable"] = "IAP_NOT_AVAILABLE";
20
- ErrorCode["InitConnection"] = "INIT_CONNECTION";
21
- ErrorCode["Interrupted"] = "INTERRUPTED";
22
- ErrorCode["ItemNotOwned"] = "ITEM_NOT_OWNED";
23
- ErrorCode["ItemUnavailable"] = "ITEM_UNAVAILABLE";
24
- ErrorCode["NetworkError"] = "NETWORK_ERROR";
25
- ErrorCode["NotEnded"] = "NOT_ENDED";
26
- ErrorCode["NotPrepared"] = "NOT_PREPARED";
27
- ErrorCode["Pending"] = "PENDING";
28
- ErrorCode["PurchaseError"] = "PURCHASE_ERROR";
29
- ErrorCode["QueryProduct"] = "QUERY_PRODUCT";
30
- ErrorCode["ReceiptFailed"] = "RECEIPT_FAILED";
31
- ErrorCode["ReceiptFinished"] = "RECEIPT_FINISHED";
32
- ErrorCode["ReceiptFinishedFailed"] = "RECEIPT_FINISHED_FAILED";
33
- ErrorCode["RemoteError"] = "REMOTE_ERROR";
34
- ErrorCode["ServiceDisconnected"] = "SERVICE_DISCONNECTED";
35
- ErrorCode["ServiceError"] = "SERVICE_ERROR";
36
- ErrorCode["SkuNotFound"] = "SKU_NOT_FOUND";
37
- ErrorCode["SkuOfferMismatch"] = "SKU_OFFER_MISMATCH";
38
- ErrorCode["SyncError"] = "SYNC_ERROR";
39
- ErrorCode["TransactionValidationFailed"] = "TRANSACTION_VALIDATION_FAILED";
40
- ErrorCode["Unknown"] = "UNKNOWN";
41
- ErrorCode["UserCancelled"] = "USER_CANCELLED";
42
- ErrorCode["UserError"] = "USER_ERROR";
9
+ ErrorCode["ActivityUnavailable"] = "activity-unavailable";
10
+ ErrorCode["AlreadyOwned"] = "already-owned";
11
+ ErrorCode["AlreadyPrepared"] = "already-prepared";
12
+ ErrorCode["BillingResponseJsonParseError"] = "billing-response-json-parse-error";
13
+ ErrorCode["BillingUnavailable"] = "billing-unavailable";
14
+ ErrorCode["ConnectionClosed"] = "connection-closed";
15
+ ErrorCode["DeferredPayment"] = "deferred-payment";
16
+ ErrorCode["DeveloperError"] = "developer-error";
17
+ ErrorCode["EmptySkuList"] = "empty-sku-list";
18
+ ErrorCode["FeatureNotSupported"] = "feature-not-supported";
19
+ ErrorCode["IapNotAvailable"] = "iap-not-available";
20
+ ErrorCode["InitConnection"] = "init-connection";
21
+ ErrorCode["Interrupted"] = "interrupted";
22
+ ErrorCode["ItemNotOwned"] = "item-not-owned";
23
+ ErrorCode["ItemUnavailable"] = "item-unavailable";
24
+ ErrorCode["NetworkError"] = "network-error";
25
+ ErrorCode["NotEnded"] = "not-ended";
26
+ ErrorCode["NotPrepared"] = "not-prepared";
27
+ ErrorCode["Pending"] = "pending";
28
+ ErrorCode["PurchaseError"] = "purchase-error";
29
+ ErrorCode["QueryProduct"] = "query-product";
30
+ ErrorCode["ReceiptFailed"] = "receipt-failed";
31
+ ErrorCode["ReceiptFinished"] = "receipt-finished";
32
+ ErrorCode["ReceiptFinishedFailed"] = "receipt-finished-failed";
33
+ ErrorCode["RemoteError"] = "remote-error";
34
+ ErrorCode["ServiceDisconnected"] = "service-disconnected";
35
+ ErrorCode["ServiceError"] = "service-error";
36
+ ErrorCode["SkuNotFound"] = "sku-not-found";
37
+ ErrorCode["SkuOfferMismatch"] = "sku-offer-mismatch";
38
+ ErrorCode["SyncError"] = "sync-error";
39
+ ErrorCode["TransactionValidationFailed"] = "transaction-validation-failed";
40
+ ErrorCode["Unknown"] = "unknown";
41
+ ErrorCode["UserCancelled"] = "user-cancelled";
42
+ ErrorCode["UserError"] = "user-error";
43
43
  return ErrorCode;
44
44
  }({});
45
45
 
@@ -1,5 +1,11 @@
1
1
  "use strict";
2
2
 
3
+ /**
4
+ * Error mapping utilities for react-native-iap.
5
+ * Provides helpers for working with platform-specific error codes
6
+ * and constructing structured purchase errors.
7
+ */
8
+
3
9
  import { ErrorCode } from "../types.js";
4
10
  const ERROR_CODE_ALIASES = {
5
11
  E_USER_CANCELED: ErrorCode.UserCancelled,
@@ -7,51 +13,304 @@ const ERROR_CODE_ALIASES = {
7
13
  E_USER_CANCELLED: ErrorCode.UserCancelled,
8
14
  USER_CANCELLED: ErrorCode.UserCancelled
9
15
  };
10
- export const normalizeErrorCodeFromNative = code => {
11
- if (typeof code === 'string') {
12
- const upper = code.toUpperCase();
13
- const alias = ERROR_CODE_ALIASES[upper];
14
- if (alias) {
15
- return alias;
16
+ const toKebabCase = str => {
17
+ if (str.includes('_')) {
18
+ return str.split('_').map(word => word.toLowerCase()).join('-');
19
+ } else {
20
+ return str.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
21
+ }
22
+ };
23
+ const normalizePlatform = platform => typeof platform === 'string' && platform.toLowerCase() === 'ios' ? 'ios' : 'android';
24
+ const COMMON_ERROR_CODE_MAP = {
25
+ [ErrorCode.Unknown]: ErrorCode.Unknown,
26
+ [ErrorCode.UserCancelled]: ErrorCode.UserCancelled,
27
+ [ErrorCode.UserError]: ErrorCode.UserError,
28
+ [ErrorCode.ItemUnavailable]: ErrorCode.ItemUnavailable,
29
+ [ErrorCode.RemoteError]: ErrorCode.RemoteError,
30
+ [ErrorCode.NetworkError]: ErrorCode.NetworkError,
31
+ [ErrorCode.ServiceError]: ErrorCode.ServiceError,
32
+ [ErrorCode.ReceiptFailed]: ErrorCode.ReceiptFailed,
33
+ [ErrorCode.ReceiptFinished]: ErrorCode.ReceiptFinished,
34
+ [ErrorCode.ReceiptFinishedFailed]: ErrorCode.ReceiptFinishedFailed,
35
+ [ErrorCode.NotPrepared]: ErrorCode.NotPrepared,
36
+ [ErrorCode.NotEnded]: ErrorCode.NotEnded,
37
+ [ErrorCode.AlreadyOwned]: ErrorCode.AlreadyOwned,
38
+ [ErrorCode.DeveloperError]: ErrorCode.DeveloperError,
39
+ [ErrorCode.BillingResponseJsonParseError]: ErrorCode.BillingResponseJsonParseError,
40
+ [ErrorCode.DeferredPayment]: ErrorCode.DeferredPayment,
41
+ [ErrorCode.Interrupted]: ErrorCode.Interrupted,
42
+ [ErrorCode.IapNotAvailable]: ErrorCode.IapNotAvailable,
43
+ [ErrorCode.PurchaseError]: ErrorCode.PurchaseError,
44
+ [ErrorCode.SyncError]: ErrorCode.SyncError,
45
+ [ErrorCode.TransactionValidationFailed]: ErrorCode.TransactionValidationFailed,
46
+ [ErrorCode.ActivityUnavailable]: ErrorCode.ActivityUnavailable,
47
+ [ErrorCode.AlreadyPrepared]: ErrorCode.AlreadyPrepared,
48
+ [ErrorCode.Pending]: ErrorCode.Pending,
49
+ [ErrorCode.ConnectionClosed]: ErrorCode.ConnectionClosed,
50
+ [ErrorCode.InitConnection]: ErrorCode.InitConnection,
51
+ [ErrorCode.ServiceDisconnected]: ErrorCode.ServiceDisconnected,
52
+ [ErrorCode.QueryProduct]: ErrorCode.QueryProduct,
53
+ [ErrorCode.SkuNotFound]: ErrorCode.SkuNotFound,
54
+ [ErrorCode.SkuOfferMismatch]: ErrorCode.SkuOfferMismatch,
55
+ [ErrorCode.ItemNotOwned]: ErrorCode.ItemNotOwned,
56
+ [ErrorCode.BillingUnavailable]: ErrorCode.BillingUnavailable,
57
+ [ErrorCode.FeatureNotSupported]: ErrorCode.FeatureNotSupported,
58
+ [ErrorCode.EmptySkuList]: ErrorCode.EmptySkuList
59
+ };
60
+ export const ErrorCodeMapping = {
61
+ ios: COMMON_ERROR_CODE_MAP,
62
+ android: COMMON_ERROR_CODE_MAP
63
+ };
64
+ const OPENIAP_ERROR_CODE_SET = new Set(Object.values(ErrorCode));
65
+ export const createPurchaseError = props => {
66
+ const errorCode = props.code ? typeof props.code === 'string' || typeof props.code === 'number' ? ErrorCodeUtils.fromPlatformCode(props.code, props.platform || 'ios') : props.code : undefined;
67
+ const error = new Error(props.message ?? 'Unknown error occurred');
68
+ error.name = '[react-native-iap]: PurchaseError';
69
+ error.responseCode = props.responseCode;
70
+ error.debugMessage = props.debugMessage;
71
+ error.code = errorCode;
72
+ error.productId = props.productId;
73
+ error.platform = props.platform;
74
+ return error;
75
+ };
76
+ export const createPurchaseErrorFromPlatform = (errorData, platform) => {
77
+ const normalizedPlatform = normalizePlatform(platform);
78
+ const errorCode = errorData.code ? typeof errorData.code === 'string' || typeof errorData.code === 'number' ? ErrorCodeUtils.fromPlatformCode(errorData.code, normalizedPlatform) : errorData.code : ErrorCode.Unknown;
79
+ return createPurchaseError({
80
+ message: errorData.message ?? 'Unknown error occurred',
81
+ responseCode: errorData.responseCode,
82
+ debugMessage: errorData.debugMessage,
83
+ code: errorCode,
84
+ productId: errorData.productId,
85
+ platform
86
+ });
87
+ };
88
+ export const ErrorCodeUtils = {
89
+ getNativeErrorCode: errorCode => {
90
+ return errorCode;
91
+ },
92
+ fromPlatformCode: (platformCode, _platform) => {
93
+ if (typeof platformCode === 'string') {
94
+ // Handle direct ErrorCode enum values
95
+ if (OPENIAP_ERROR_CODE_SET.has(platformCode)) {
96
+ return platformCode;
97
+ }
98
+
99
+ // Handle E_ prefixed codes
100
+ if (platformCode.startsWith('E_')) {
101
+ const withoutE = platformCode.substring(2);
102
+ const kebabCase = toKebabCase(withoutE);
103
+ if (OPENIAP_ERROR_CODE_SET.has(kebabCase)) {
104
+ return kebabCase;
105
+ }
106
+ }
107
+
108
+ // Handle kebab-case codes
109
+ const kebabCase = toKebabCase(platformCode);
110
+ if (OPENIAP_ERROR_CODE_SET.has(kebabCase)) {
111
+ return kebabCase;
112
+ }
113
+
114
+ // Handle legacy formats like USER_CANCELED
115
+ const upperCase = platformCode.toUpperCase();
116
+ if (upperCase === 'USER_CANCELED' || upperCase === 'E_USER_CANCELED') {
117
+ return ErrorCode.UserCancelled;
118
+ }
16
119
  }
17
- const trimmed = upper.startsWith('E_') ? upper.slice(2) : upper;
18
- const camel = trimmed.toLowerCase().split('_').map(segment => {
19
- if (!segment) return segment;
20
- return segment.charAt(0).toUpperCase() + segment.slice(1);
21
- }).join('');
22
- if (ErrorCode[camel]) {
23
- return ErrorCode[camel];
120
+ return ErrorCode.Unknown;
121
+ },
122
+ toPlatformCode: (errorCode, _platform) => {
123
+ return COMMON_ERROR_CODE_MAP[errorCode] ?? 'E_UNKNOWN';
124
+ },
125
+ isValidForPlatform: (errorCode, platform) => {
126
+ return errorCode in ErrorCodeMapping[normalizePlatform(platform)];
127
+ }
128
+ };
129
+
130
+ // ---------------------------------------------------------------------------
131
+ // Convenience helpers for interpreting error objects
132
+ // ---------------------------------------------------------------------------
133
+
134
+ const ERROR_CODES = new Set(Object.values(ErrorCode));
135
+ const normalizeErrorCode = code => {
136
+ if (!code) {
137
+ return undefined;
138
+ }
139
+
140
+ // If it's already an ErrorCode enum value, return it as string
141
+ if (typeof code !== 'string' && ERROR_CODES.has(code)) {
142
+ return code;
143
+ }
144
+ if (ERROR_CODES.has(code)) {
145
+ return code;
146
+ }
147
+ const camelCased = toKebabCase(code);
148
+ if (ERROR_CODES.has(camelCased)) {
149
+ return camelCased;
150
+ }
151
+ if (typeof code === 'string' && code.startsWith('E_')) {
152
+ const trimmed = code.substring(2);
153
+ if (ERROR_CODES.has(trimmed)) {
154
+ return trimmed;
155
+ }
156
+ const camelTrimmed = toKebabCase(trimmed);
157
+ if (ERROR_CODES.has(camelTrimmed)) {
158
+ return camelTrimmed;
24
159
  }
25
160
  }
26
- return ErrorCode.Unknown;
161
+
162
+ // Handle legacy formats
163
+ if (code === 'E_USER_CANCELED') {
164
+ return ErrorCode.UserCancelled;
165
+ }
166
+ return code;
27
167
  };
168
+ function extractCode(error) {
169
+ if (typeof error === 'string') {
170
+ return normalizeErrorCode(error);
171
+ }
172
+ if (error && typeof error === 'object' && 'code' in error) {
173
+ const code = error.code;
174
+ return normalizeErrorCode(typeof code === 'string' ? code : code);
175
+ }
176
+ return undefined;
177
+ }
28
178
  export function isUserCancelledError(error) {
29
- return normalizeErrorCodeFromNative(error.code) === ErrorCode.UserCancelled;
179
+ return extractCode(error) === ErrorCode.UserCancelled;
180
+ }
181
+ export function isNetworkError(error) {
182
+ const networkErrors = [ErrorCode.NetworkError, ErrorCode.RemoteError, ErrorCode.ServiceError, ErrorCode.ServiceDisconnected, ErrorCode.BillingUnavailable];
183
+ const code = extractCode(error);
184
+ return !!code && networkErrors.includes(code);
30
185
  }
31
186
  export function isRecoverableError(error) {
32
- const recoverable = new Set([ErrorCode.NetworkError, ErrorCode.ServiceError, ErrorCode.RemoteError, ErrorCode.ConnectionClosed, ErrorCode.ServiceDisconnected, ErrorCode.InitConnection, ErrorCode.SyncError]);
33
- return recoverable.has(error.code);
187
+ const recoverableErrors = [ErrorCode.NetworkError, ErrorCode.RemoteError, ErrorCode.ServiceError, ErrorCode.Interrupted, ErrorCode.ServiceDisconnected, ErrorCode.BillingUnavailable, ErrorCode.QueryProduct, ErrorCode.InitConnection, ErrorCode.SyncError, ErrorCode.ConnectionClosed];
188
+ const code = extractCode(error);
189
+ return !!code && recoverableErrors.includes(code);
34
190
  }
35
191
  export function getUserFriendlyErrorMessage(error) {
36
- switch (error.code) {
192
+ const errorCode = extractCode(error);
193
+ switch (errorCode) {
37
194
  case ErrorCode.UserCancelled:
38
195
  return 'Purchase cancelled';
39
196
  case ErrorCode.NetworkError:
40
- return 'Network connection error';
197
+ return 'Network connection error. Please check your internet connection and try again.';
198
+ case ErrorCode.ReceiptFinished:
199
+ return 'Receipt already finished';
200
+ case ErrorCode.ServiceDisconnected:
201
+ return 'Billing service disconnected. Please try again.';
202
+ case ErrorCode.BillingUnavailable:
203
+ return 'Billing is unavailable on this device or account.';
204
+ case ErrorCode.ItemUnavailable:
205
+ return 'This item is not available for purchase';
206
+ case ErrorCode.ItemNotOwned:
207
+ return "You don't own this item";
208
+ case ErrorCode.AlreadyOwned:
209
+ return 'You already own this item';
210
+ case ErrorCode.SkuNotFound:
211
+ return 'Requested product could not be found';
212
+ case ErrorCode.SkuOfferMismatch:
213
+ return 'Selected offer does not match the SKU';
214
+ case ErrorCode.DeferredPayment:
215
+ return 'Payment is pending approval';
216
+ case ErrorCode.NotPrepared:
217
+ return 'In-app purchase is not ready. Please try again later.';
41
218
  case ErrorCode.ServiceError:
42
- return 'Store service error';
43
- case ErrorCode.RemoteError:
44
- return 'Remote service error';
219
+ return 'Store service error. Please try again later.';
220
+ case ErrorCode.FeatureNotSupported:
221
+ return 'This feature is not supported on this device.';
222
+ case ErrorCode.TransactionValidationFailed:
223
+ return 'Transaction could not be verified';
224
+ case ErrorCode.ReceiptFailed:
225
+ return 'Receipt processing failed';
226
+ case ErrorCode.EmptySkuList:
227
+ return 'No product IDs provided';
228
+ case ErrorCode.InitConnection:
229
+ return 'Failed to initialize billing connection';
45
230
  case ErrorCode.IapNotAvailable:
46
231
  return 'In-app purchases are not available on this device';
47
- case ErrorCode.DeferredPayment:
48
- return 'Payment was deferred (pending approval)';
49
- case ErrorCode.TransactionValidationFailed:
50
- return 'Transaction validation failed';
51
- case ErrorCode.SkuNotFound:
52
- return 'Product not found';
232
+ case ErrorCode.QueryProduct:
233
+ return 'Failed to query products. Please try again later.';
53
234
  default:
54
- return error.message || 'Unknown error occurred';
235
+ {
236
+ if (error && typeof error === 'object' && 'message' in error) {
237
+ return error.message ?? 'An unexpected error occurred';
238
+ }
239
+ return 'An unexpected error occurred';
240
+ }
55
241
  }
56
242
  }
243
+ export const normalizeErrorCodeFromNative = code => {
244
+ if (typeof code === 'string') {
245
+ const upper = code.toUpperCase();
246
+
247
+ // Check aliases first
248
+ const alias = ERROR_CODE_ALIASES[upper];
249
+ if (alias) {
250
+ return alias;
251
+ }
252
+
253
+ // Handle various user cancelled formats
254
+ if (upper === 'USER_CANCELLED' || upper === 'USER_CANCELED' || upper === 'E_USER_CANCELLED' || upper === 'E_USER_CANCELED' || upper === 'USER_CANCEL' || upper === 'CANCELLED' || upper === 'CANCELED' || code === 'user-cancelled' || code === 'user-canceled') {
255
+ return ErrorCode.UserCancelled;
256
+ }
257
+
258
+ // Handle E_ prefixed codes
259
+ if (upper.startsWith('E_')) {
260
+ const trimmed = upper.slice(2);
261
+ // Try direct match first
262
+ if (ErrorCode[trimmed]) {
263
+ return ErrorCode[trimmed];
264
+ }
265
+
266
+ // Try camelCase conversion
267
+ const camel = trimmed.toLowerCase().split('_').map(segment => {
268
+ if (!segment) return segment;
269
+ return segment.charAt(0).toUpperCase() + segment.slice(1);
270
+ }).join('');
271
+ if (ErrorCode[camel]) {
272
+ return ErrorCode[camel];
273
+ }
274
+
275
+ // Try kebab-case conversion
276
+ const kebab = trimmed.toLowerCase().replace(/_/g, '-');
277
+ if (ErrorCode[kebab]) {
278
+ return ErrorCode[kebab];
279
+ }
280
+ }
281
+
282
+ // Handle direct kebab-case codes
283
+ if (code.includes('-')) {
284
+ if (ErrorCode[code]) {
285
+ return ErrorCode[code];
286
+ }
287
+ }
288
+
289
+ // Handle snake_case codes
290
+ if (code.includes('_')) {
291
+ const camel = code.toLowerCase().split('_').map(segment => {
292
+ if (!segment) return segment;
293
+ return segment.charAt(0).toUpperCase() + segment.slice(1);
294
+ }).join('');
295
+ if (ErrorCode[camel]) {
296
+ return ErrorCode[camel];
297
+ }
298
+ const kebab = code.toLowerCase().replace(/_/g, '-');
299
+ if (ErrorCode[kebab]) {
300
+ return ErrorCode[kebab];
301
+ }
302
+ }
303
+
304
+ // Try direct match with ErrorCode enum
305
+ if (ErrorCode[code]) {
306
+ return ErrorCode[code];
307
+ }
308
+
309
+ // Try uppercase match
310
+ if (ErrorCode[upper]) {
311
+ return ErrorCode[upper];
312
+ }
313
+ }
314
+ return ErrorCode.Unknown;
315
+ };
57
316
  //# sourceMappingURL=errorMapping.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["ErrorCode","ERROR_CODE_ALIASES","E_USER_CANCELED","UserCancelled","USER_CANCELED","E_USER_CANCELLED","USER_CANCELLED","normalizeErrorCodeFromNative","code","upper","toUpperCase","alias","trimmed","startsWith","slice","camel","toLowerCase","split","map","segment","charAt","join","Unknown","isUserCancelledError","error","isRecoverableError","recoverable","Set","NetworkError","ServiceError","RemoteError","ConnectionClosed","ServiceDisconnected","InitConnection","SyncError","has","getUserFriendlyErrorMessage","IapNotAvailable","DeferredPayment","TransactionValidationFailed","SkuNotFound","message"],"sourceRoot":"../../../src","sources":["utils/errorMapping.ts"],"mappings":";;AAAA,SAAQA,SAAS,QAA2B,aAAU;AAEtD,MAAMC,kBAA6C,GAAG;EACpDC,eAAe,EAAEF,SAAS,CAACG,aAAa;EACxCC,aAAa,EAAEJ,SAAS,CAACG,aAAa;EACtCE,gBAAgB,EAAEL,SAAS,CAACG,aAAa;EACzCG,cAAc,EAAEN,SAAS,CAACG;AAC5B,CAAC;AAED,OAAO,MAAMI,4BAA4B,GAAIC,IAAa,IAAgB;EACxE,IAAI,OAAOA,IAAI,KAAK,QAAQ,EAAE;IAC5B,MAAMC,KAAK,GAAGD,IAAI,CAACE,WAAW,CAAC,CAAC;IAChC,MAAMC,KAAK,GAAGV,kBAAkB,CAACQ,KAAK,CAAC;IACvC,IAAIE,KAAK,EAAE;MACT,OAAOA,KAAK;IACd;IAEA,MAAMC,OAAO,GAAGH,KAAK,CAACI,UAAU,CAAC,IAAI,CAAC,GAAGJ,KAAK,CAACK,KAAK,CAAC,CAAC,CAAC,GAAGL,KAAK;IAC/D,MAAMM,KAAK,GAAGH,OAAO,CAClBI,WAAW,CAAC,CAAC,CACbC,KAAK,CAAC,GAAG,CAAC,CACVC,GAAG,CAAEC,OAAO,IAAK;MAChB,IAAI,CAACA,OAAO,EAAE,OAAOA,OAAO;MAC5B,OAAOA,OAAO,CAACC,MAAM,CAAC,CAAC,CAAC,CAACV,WAAW,CAAC,CAAC,GAAGS,OAAO,CAACL,KAAK,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CACDO,IAAI,CAAC,EAAE,CAAC;IACX,IAAKrB,SAAS,CAASe,KAAK,CAAC,EAAE;MAC7B,OAAQf,SAAS,CAASe,KAAK,CAAC;IAClC;EACF;EACA,OAAOf,SAAS,CAACsB,OAAO;AAC1B,CAAC;AAED,OAAO,SAASC,oBAAoBA,CAACC,KAAoB,EAAW;EAClE,OAAOjB,4BAA4B,CAACiB,KAAK,CAAChB,IAAI,CAAC,KAAKR,SAAS,CAACG,aAAa;AAC7E;AAEA,OAAO,SAASsB,kBAAkBA,CAACD,KAAoB,EAAW;EAChE,MAAME,WAAW,GAAG,IAAIC,GAAG,CAAS,CAClC3B,SAAS,CAAC4B,YAAY,EACtB5B,SAAS,CAAC6B,YAAY,EACtB7B,SAAS,CAAC8B,WAAW,EACrB9B,SAAS,CAAC+B,gBAAgB,EAC1B/B,SAAS,CAACgC,mBAAmB,EAC7BhC,SAAS,CAACiC,cAAc,EACxBjC,SAAS,CAACkC,SAAS,CACpB,CAAC;EACF,OAAOR,WAAW,CAACS,GAAG,CAACX,KAAK,CAAChB,IAAI,CAAC;AACpC;AAEA,OAAO,SAAS4B,2BAA2BA,CAACZ,KAAoB,EAAU;EACxE,QAAQA,KAAK,CAAChB,IAAI;IAChB,KAAKR,SAAS,CAACG,aAAa;MAC1B,OAAO,oBAAoB;IAC7B,KAAKH,SAAS,CAAC4B,YAAY;MACzB,OAAO,0BAA0B;IACnC,KAAK5B,SAAS,CAAC6B,YAAY;MACzB,OAAO,qBAAqB;IAC9B,KAAK7B,SAAS,CAAC8B,WAAW;MACxB,OAAO,sBAAsB;IAC/B,KAAK9B,SAAS,CAACqC,eAAe;MAC5B,OAAO,mDAAmD;IAC5D,KAAKrC,SAAS,CAACsC,eAAe;MAC5B,OAAO,yCAAyC;IAClD,KAAKtC,SAAS,CAACuC,2BAA2B;MACxC,OAAO,+BAA+B;IACxC,KAAKvC,SAAS,CAACwC,WAAW;MACxB,OAAO,mBAAmB;IAC5B;MACE,OAAOhB,KAAK,CAACiB,OAAO,IAAI,wBAAwB;EACpD;AACF","ignoreList":[]}
1
+ {"version":3,"names":["ErrorCode","ERROR_CODE_ALIASES","E_USER_CANCELED","UserCancelled","USER_CANCELED","E_USER_CANCELLED","USER_CANCELLED","toKebabCase","str","includes","split","map","word","toLowerCase","join","replace","normalizePlatform","platform","COMMON_ERROR_CODE_MAP","Unknown","UserError","ItemUnavailable","RemoteError","NetworkError","ServiceError","ReceiptFailed","ReceiptFinished","ReceiptFinishedFailed","NotPrepared","NotEnded","AlreadyOwned","DeveloperError","BillingResponseJsonParseError","DeferredPayment","Interrupted","IapNotAvailable","PurchaseError","SyncError","TransactionValidationFailed","ActivityUnavailable","AlreadyPrepared","Pending","ConnectionClosed","InitConnection","ServiceDisconnected","QueryProduct","SkuNotFound","SkuOfferMismatch","ItemNotOwned","BillingUnavailable","FeatureNotSupported","EmptySkuList","ErrorCodeMapping","ios","android","OPENIAP_ERROR_CODE_SET","Set","Object","values","createPurchaseError","props","errorCode","code","ErrorCodeUtils","fromPlatformCode","undefined","error","Error","message","name","responseCode","debugMessage","productId","createPurchaseErrorFromPlatform","errorData","normalizedPlatform","getNativeErrorCode","platformCode","_platform","has","startsWith","withoutE","substring","kebabCase","upperCase","toUpperCase","toPlatformCode","isValidForPlatform","ERROR_CODES","normalizeErrorCode","camelCased","trimmed","camelTrimmed","extractCode","isUserCancelledError","isNetworkError","networkErrors","isRecoverableError","recoverableErrors","getUserFriendlyErrorMessage","normalizeErrorCodeFromNative","upper","alias","slice","camel","segment","charAt","kebab"],"sourceRoot":"../../../src","sources":["utils/errorMapping.ts"],"mappings":"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","ignoreList":[]}
@@ -77,40 +77,40 @@ export interface EntitlementIOS {
77
77
  transactionId: string;
78
78
  }
79
79
  export declare enum ErrorCode {
80
- ActivityUnavailable = "ACTIVITY_UNAVAILABLE",
81
- AlreadyOwned = "ALREADY_OWNED",
82
- AlreadyPrepared = "ALREADY_PREPARED",
83
- BillingResponseJsonParseError = "BILLING_RESPONSE_JSON_PARSE_ERROR",
84
- BillingUnavailable = "BILLING_UNAVAILABLE",
85
- ConnectionClosed = "CONNECTION_CLOSED",
86
- DeferredPayment = "DEFERRED_PAYMENT",
87
- DeveloperError = "DEVELOPER_ERROR",
88
- EmptySkuList = "EMPTY_SKU_LIST",
89
- FeatureNotSupported = "FEATURE_NOT_SUPPORTED",
90
- IapNotAvailable = "IAP_NOT_AVAILABLE",
91
- InitConnection = "INIT_CONNECTION",
92
- Interrupted = "INTERRUPTED",
93
- ItemNotOwned = "ITEM_NOT_OWNED",
94
- ItemUnavailable = "ITEM_UNAVAILABLE",
95
- NetworkError = "NETWORK_ERROR",
96
- NotEnded = "NOT_ENDED",
97
- NotPrepared = "NOT_PREPARED",
98
- Pending = "PENDING",
99
- PurchaseError = "PURCHASE_ERROR",
100
- QueryProduct = "QUERY_PRODUCT",
101
- ReceiptFailed = "RECEIPT_FAILED",
102
- ReceiptFinished = "RECEIPT_FINISHED",
103
- ReceiptFinishedFailed = "RECEIPT_FINISHED_FAILED",
104
- RemoteError = "REMOTE_ERROR",
105
- ServiceDisconnected = "SERVICE_DISCONNECTED",
106
- ServiceError = "SERVICE_ERROR",
107
- SkuNotFound = "SKU_NOT_FOUND",
108
- SkuOfferMismatch = "SKU_OFFER_MISMATCH",
109
- SyncError = "SYNC_ERROR",
110
- TransactionValidationFailed = "TRANSACTION_VALIDATION_FAILED",
111
- Unknown = "UNKNOWN",
112
- UserCancelled = "USER_CANCELLED",
113
- UserError = "USER_ERROR"
80
+ ActivityUnavailable = "activity-unavailable",
81
+ AlreadyOwned = "already-owned",
82
+ AlreadyPrepared = "already-prepared",
83
+ BillingResponseJsonParseError = "billing-response-json-parse-error",
84
+ BillingUnavailable = "billing-unavailable",
85
+ ConnectionClosed = "connection-closed",
86
+ DeferredPayment = "deferred-payment",
87
+ DeveloperError = "developer-error",
88
+ EmptySkuList = "empty-sku-list",
89
+ FeatureNotSupported = "feature-not-supported",
90
+ IapNotAvailable = "iap-not-available",
91
+ InitConnection = "init-connection",
92
+ Interrupted = "interrupted",
93
+ ItemNotOwned = "item-not-owned",
94
+ ItemUnavailable = "item-unavailable",
95
+ NetworkError = "network-error",
96
+ NotEnded = "not-ended",
97
+ NotPrepared = "not-prepared",
98
+ Pending = "pending",
99
+ PurchaseError = "purchase-error",
100
+ QueryProduct = "query-product",
101
+ ReceiptFailed = "receipt-failed",
102
+ ReceiptFinished = "receipt-finished",
103
+ ReceiptFinishedFailed = "receipt-finished-failed",
104
+ RemoteError = "remote-error",
105
+ ServiceDisconnected = "service-disconnected",
106
+ ServiceError = "service-error",
107
+ SkuNotFound = "sku-not-found",
108
+ SkuOfferMismatch = "sku-offer-mismatch",
109
+ SyncError = "sync-error",
110
+ TransactionValidationFailed = "transaction-validation-failed",
111
+ Unknown = "unknown",
112
+ UserCancelled = "user-cancelled",
113
+ UserError = "user-error"
114
114
  }
115
115
  export type FetchProductsResult = Product[] | ProductSubscription[] | null;
116
116
  export type IapEvent = 'purchase-updated' | 'purchase-error' | 'promoted-product-ios';
@@ -1,6 +1,44 @@
1
- import { ErrorCode, type PurchaseError } from '../types';
1
+ /**
2
+ * Error mapping utilities for react-native-iap.
3
+ * Provides helpers for working with platform-specific error codes
4
+ * and constructing structured purchase errors.
5
+ */
6
+ import { ErrorCode, type IapPlatform } from '../types';
7
+ export interface PurchaseErrorProps {
8
+ message?: string;
9
+ responseCode?: number;
10
+ debugMessage?: string;
11
+ code?: ErrorCode | string | number;
12
+ productId?: string;
13
+ platform?: IapPlatform;
14
+ }
15
+ export interface PurchaseError extends Error {
16
+ responseCode?: number;
17
+ debugMessage?: string;
18
+ code?: ErrorCode;
19
+ productId?: string;
20
+ platform?: IapPlatform;
21
+ }
22
+ export declare const ErrorCodeMapping: {
23
+ readonly ios: Record<ErrorCode, string>;
24
+ readonly android: Record<ErrorCode, string>;
25
+ };
26
+ export declare const createPurchaseError: (props: PurchaseErrorProps) => PurchaseError;
27
+ export declare const createPurchaseErrorFromPlatform: (errorData: PurchaseErrorProps, platform: IapPlatform) => PurchaseError;
28
+ export declare const ErrorCodeUtils: {
29
+ getNativeErrorCode: (errorCode: ErrorCode) => string;
30
+ fromPlatformCode: (platformCode: string | number, _platform: IapPlatform) => ErrorCode;
31
+ toPlatformCode: (errorCode: ErrorCode, _platform: IapPlatform) => string | number;
32
+ isValidForPlatform: (errorCode: ErrorCode, platform: IapPlatform) => boolean;
33
+ };
34
+ type ErrorLike = string | {
35
+ code?: ErrorCode | string;
36
+ message?: string;
37
+ };
38
+ export declare function isUserCancelledError(error: unknown): boolean;
39
+ export declare function isNetworkError(error: unknown): boolean;
40
+ export declare function isRecoverableError(error: unknown): boolean;
41
+ export declare function getUserFriendlyErrorMessage(error: ErrorLike): string;
2
42
  export declare const normalizeErrorCodeFromNative: (code: unknown) => ErrorCode;
3
- export declare function isUserCancelledError(error: PurchaseError): boolean;
4
- export declare function isRecoverableError(error: PurchaseError): boolean;
5
- export declare function getUserFriendlyErrorMessage(error: PurchaseError): string;
43
+ export {};
6
44
  //# sourceMappingURL=errorMapping.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errorMapping.d.ts","sourceRoot":"","sources":["../../../../src/utils/errorMapping.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,KAAK,aAAa,EAAC,MAAM,UAAU,CAAC;AASvD,eAAO,MAAM,4BAA4B,GAAI,MAAM,OAAO,KAAG,SAsB5D,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAElE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAWhE;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAqBxE"}
1
+ {"version":3,"file":"errorMapping.d.ts","sourceRoot":"","sources":["../../../../src/utils/errorMapping.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAC,SAAS,EAAE,KAAK,WAAW,EAAC,MAAM,UAAU,CAAC;AAuBrD,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB;AAED,MAAM,WAAW,aAAc,SAAQ,KAAK;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC;CACxB;AA8CD,eAAO,MAAM,gBAAgB;;;CAGnB,CAAC;AAIX,eAAO,MAAM,mBAAmB,GAC9B,OAAO,kBAAkB,KACxB,aAiBF,CAAC;AAEF,eAAO,MAAM,+BAA+B,GAC1C,WAAW,kBAAkB,EAC7B,UAAU,WAAW,KACpB,aAgBF,CAAC;AAEF,eAAO,MAAM,cAAc;oCACO,SAAS,KAAG,MAAM;qCAIlC,MAAM,GAAG,MAAM,aAClB,WAAW,KACrB,SAAS;gCAgCC,SAAS,aACT,WAAW,KACrB,MAAM,GAAG,MAAM;oCAIL,SAAS,YACV,WAAW,KACpB,OAAO;CAGX,CAAC;AAMF,KAAK,SAAS,GAAG,MAAM,GAAG;IAAC,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,CAAC;AAyDxE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAE5D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAWtD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAgB1D;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAsDpE;AAED,eAAO,MAAM,4BAA4B,GAAI,MAAM,OAAO,KAAG,SA4F5D,CAAC"}
@@ -1,5 +1,5 @@
1
1
  {
2
- "apple": "1.2.2",
3
- "google": "1.2.6",
2
+ "apple": "1.2.3",
3
+ "google": "1.2.7",
4
4
  "gql": "1.0.8"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-iap",
3
- "version": "14.4.0",
3
+ "version": "14.4.2",
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",
@@ -164,7 +164,7 @@
164
164
  "prettier --write"
165
165
  ],
166
166
  "*.{json,md}": [
167
- "prettier --write"
167
+ "node -p \"process.argv.slice(2).filter(f => { try { return !require('fs').lstatSync(f).isSymbolicLink(); } catch { return false; } }).join(' ')\" | xargs prettier --write"
168
168
  ]
169
169
  },
170
170
  "packageManager": "yarn@3.6.1"
package/src/types.ts CHANGED
@@ -90,40 +90,40 @@ export interface EntitlementIOS {
90
90
  }
91
91
 
92
92
  export enum ErrorCode {
93
- ActivityUnavailable = 'ACTIVITY_UNAVAILABLE',
94
- AlreadyOwned = 'ALREADY_OWNED',
95
- AlreadyPrepared = 'ALREADY_PREPARED',
96
- BillingResponseJsonParseError = 'BILLING_RESPONSE_JSON_PARSE_ERROR',
97
- BillingUnavailable = 'BILLING_UNAVAILABLE',
98
- ConnectionClosed = 'CONNECTION_CLOSED',
99
- DeferredPayment = 'DEFERRED_PAYMENT',
100
- DeveloperError = 'DEVELOPER_ERROR',
101
- EmptySkuList = 'EMPTY_SKU_LIST',
102
- FeatureNotSupported = 'FEATURE_NOT_SUPPORTED',
103
- IapNotAvailable = 'IAP_NOT_AVAILABLE',
104
- InitConnection = 'INIT_CONNECTION',
105
- Interrupted = 'INTERRUPTED',
106
- ItemNotOwned = 'ITEM_NOT_OWNED',
107
- ItemUnavailable = 'ITEM_UNAVAILABLE',
108
- NetworkError = 'NETWORK_ERROR',
109
- NotEnded = 'NOT_ENDED',
110
- NotPrepared = 'NOT_PREPARED',
111
- Pending = 'PENDING',
112
- PurchaseError = 'PURCHASE_ERROR',
113
- QueryProduct = 'QUERY_PRODUCT',
114
- ReceiptFailed = 'RECEIPT_FAILED',
115
- ReceiptFinished = 'RECEIPT_FINISHED',
116
- ReceiptFinishedFailed = 'RECEIPT_FINISHED_FAILED',
117
- RemoteError = 'REMOTE_ERROR',
118
- ServiceDisconnected = 'SERVICE_DISCONNECTED',
119
- ServiceError = 'SERVICE_ERROR',
120
- SkuNotFound = 'SKU_NOT_FOUND',
121
- SkuOfferMismatch = 'SKU_OFFER_MISMATCH',
122
- SyncError = 'SYNC_ERROR',
123
- TransactionValidationFailed = 'TRANSACTION_VALIDATION_FAILED',
124
- Unknown = 'UNKNOWN',
125
- UserCancelled = 'USER_CANCELLED',
126
- UserError = 'USER_ERROR'
93
+ ActivityUnavailable = 'activity-unavailable',
94
+ AlreadyOwned = 'already-owned',
95
+ AlreadyPrepared = 'already-prepared',
96
+ BillingResponseJsonParseError = 'billing-response-json-parse-error',
97
+ BillingUnavailable = 'billing-unavailable',
98
+ ConnectionClosed = 'connection-closed',
99
+ DeferredPayment = 'deferred-payment',
100
+ DeveloperError = 'developer-error',
101
+ EmptySkuList = 'empty-sku-list',
102
+ FeatureNotSupported = 'feature-not-supported',
103
+ IapNotAvailable = 'iap-not-available',
104
+ InitConnection = 'init-connection',
105
+ Interrupted = 'interrupted',
106
+ ItemNotOwned = 'item-not-owned',
107
+ ItemUnavailable = 'item-unavailable',
108
+ NetworkError = 'network-error',
109
+ NotEnded = 'not-ended',
110
+ NotPrepared = 'not-prepared',
111
+ Pending = 'pending',
112
+ PurchaseError = 'purchase-error',
113
+ QueryProduct = 'query-product',
114
+ ReceiptFailed = 'receipt-failed',
115
+ ReceiptFinished = 'receipt-finished',
116
+ ReceiptFinishedFailed = 'receipt-finished-failed',
117
+ RemoteError = 'remote-error',
118
+ ServiceDisconnected = 'service-disconnected',
119
+ ServiceError = 'service-error',
120
+ SkuNotFound = 'sku-not-found',
121
+ SkuOfferMismatch = 'sku-offer-mismatch',
122
+ SyncError = 'sync-error',
123
+ TransactionValidationFailed = 'transaction-validation-failed',
124
+ Unknown = 'unknown',
125
+ UserCancelled = 'user-cancelled',
126
+ UserError = 'user-error'
127
127
  }
128
128
 
129
129
  export type FetchProductsResult = Product[] | ProductSubscription[] | null;
@@ -1,4 +1,10 @@
1
- import {ErrorCode, type PurchaseError} from '../types';
1
+ /**
2
+ * Error mapping utilities for react-native-iap.
3
+ * Provides helpers for working with platform-specific error codes
4
+ * and constructing structured purchase errors.
5
+ */
6
+
7
+ import {ErrorCode, type IapPlatform} from '../types';
2
8
 
3
9
  const ERROR_CODE_ALIASES: Record<string, ErrorCode> = {
4
10
  E_USER_CANCELED: ErrorCode.UserCancelled,
@@ -7,66 +13,424 @@ const ERROR_CODE_ALIASES: Record<string, ErrorCode> = {
7
13
  USER_CANCELLED: ErrorCode.UserCancelled,
8
14
  };
9
15
 
10
- export const normalizeErrorCodeFromNative = (code: unknown): ErrorCode => {
11
- if (typeof code === 'string') {
12
- const upper = code.toUpperCase();
13
- const alias = ERROR_CODE_ALIASES[upper];
14
- if (alias) {
15
- return alias;
16
+ const toKebabCase = (str: string): string => {
17
+ if (str.includes('_')) {
18
+ return str
19
+ .split('_')
20
+ .map((word) => word.toLowerCase())
21
+ .join('-');
22
+ } else {
23
+ return str
24
+ .replace(/([A-Z])/g, '-$1')
25
+ .toLowerCase()
26
+ .replace(/^-/, '');
27
+ }
28
+ };
29
+
30
+ export interface PurchaseErrorProps {
31
+ message?: string;
32
+ responseCode?: number;
33
+ debugMessage?: string;
34
+ code?: ErrorCode | string | number;
35
+ productId?: string;
36
+ platform?: IapPlatform;
37
+ }
38
+
39
+ export interface PurchaseError extends Error {
40
+ responseCode?: number;
41
+ debugMessage?: string;
42
+ code?: ErrorCode;
43
+ productId?: string;
44
+ platform?: IapPlatform;
45
+ }
46
+
47
+ const normalizePlatform = (platform: IapPlatform): 'ios' | 'android' =>
48
+ typeof platform === 'string' && platform.toLowerCase() === 'ios'
49
+ ? 'ios'
50
+ : 'android';
51
+
52
+ const COMMON_ERROR_CODE_MAP: Record<ErrorCode, string> = {
53
+ [ErrorCode.Unknown]: ErrorCode.Unknown,
54
+ [ErrorCode.UserCancelled]: ErrorCode.UserCancelled,
55
+ [ErrorCode.UserError]: ErrorCode.UserError,
56
+ [ErrorCode.ItemUnavailable]: ErrorCode.ItemUnavailable,
57
+ [ErrorCode.RemoteError]: ErrorCode.RemoteError,
58
+ [ErrorCode.NetworkError]: ErrorCode.NetworkError,
59
+ [ErrorCode.ServiceError]: ErrorCode.ServiceError,
60
+ [ErrorCode.ReceiptFailed]: ErrorCode.ReceiptFailed,
61
+ [ErrorCode.ReceiptFinished]: ErrorCode.ReceiptFinished,
62
+ [ErrorCode.ReceiptFinishedFailed]: ErrorCode.ReceiptFinishedFailed,
63
+ [ErrorCode.NotPrepared]: ErrorCode.NotPrepared,
64
+ [ErrorCode.NotEnded]: ErrorCode.NotEnded,
65
+ [ErrorCode.AlreadyOwned]: ErrorCode.AlreadyOwned,
66
+ [ErrorCode.DeveloperError]: ErrorCode.DeveloperError,
67
+ [ErrorCode.BillingResponseJsonParseError]:
68
+ ErrorCode.BillingResponseJsonParseError,
69
+ [ErrorCode.DeferredPayment]: ErrorCode.DeferredPayment,
70
+ [ErrorCode.Interrupted]: ErrorCode.Interrupted,
71
+ [ErrorCode.IapNotAvailable]: ErrorCode.IapNotAvailable,
72
+ [ErrorCode.PurchaseError]: ErrorCode.PurchaseError,
73
+ [ErrorCode.SyncError]: ErrorCode.SyncError,
74
+ [ErrorCode.TransactionValidationFailed]:
75
+ ErrorCode.TransactionValidationFailed,
76
+ [ErrorCode.ActivityUnavailable]: ErrorCode.ActivityUnavailable,
77
+ [ErrorCode.AlreadyPrepared]: ErrorCode.AlreadyPrepared,
78
+ [ErrorCode.Pending]: ErrorCode.Pending,
79
+ [ErrorCode.ConnectionClosed]: ErrorCode.ConnectionClosed,
80
+ [ErrorCode.InitConnection]: ErrorCode.InitConnection,
81
+ [ErrorCode.ServiceDisconnected]: ErrorCode.ServiceDisconnected,
82
+ [ErrorCode.QueryProduct]: ErrorCode.QueryProduct,
83
+ [ErrorCode.SkuNotFound]: ErrorCode.SkuNotFound,
84
+ [ErrorCode.SkuOfferMismatch]: ErrorCode.SkuOfferMismatch,
85
+ [ErrorCode.ItemNotOwned]: ErrorCode.ItemNotOwned,
86
+ [ErrorCode.BillingUnavailable]: ErrorCode.BillingUnavailable,
87
+ [ErrorCode.FeatureNotSupported]: ErrorCode.FeatureNotSupported,
88
+ [ErrorCode.EmptySkuList]: ErrorCode.EmptySkuList,
89
+ };
90
+
91
+ export const ErrorCodeMapping = {
92
+ ios: COMMON_ERROR_CODE_MAP,
93
+ android: COMMON_ERROR_CODE_MAP,
94
+ } as const;
95
+
96
+ const OPENIAP_ERROR_CODE_SET: Set<string> = new Set(Object.values(ErrorCode));
97
+
98
+ export const createPurchaseError = (
99
+ props: PurchaseErrorProps,
100
+ ): PurchaseError => {
101
+ const errorCode = props.code
102
+ ? typeof props.code === 'string' || typeof props.code === 'number'
103
+ ? ErrorCodeUtils.fromPlatformCode(props.code, props.platform || 'ios')
104
+ : props.code
105
+ : undefined;
106
+
107
+ const error = new Error(
108
+ props.message ?? 'Unknown error occurred',
109
+ ) as PurchaseError;
110
+ error.name = '[react-native-iap]: PurchaseError';
111
+ error.responseCode = props.responseCode;
112
+ error.debugMessage = props.debugMessage;
113
+ error.code = errorCode;
114
+ error.productId = props.productId;
115
+ error.platform = props.platform;
116
+ return error;
117
+ };
118
+
119
+ export const createPurchaseErrorFromPlatform = (
120
+ errorData: PurchaseErrorProps,
121
+ platform: IapPlatform,
122
+ ): PurchaseError => {
123
+ const normalizedPlatform = normalizePlatform(platform);
124
+ const errorCode = errorData.code
125
+ ? typeof errorData.code === 'string' || typeof errorData.code === 'number'
126
+ ? ErrorCodeUtils.fromPlatformCode(errorData.code, normalizedPlatform)
127
+ : errorData.code
128
+ : ErrorCode.Unknown;
129
+
130
+ return createPurchaseError({
131
+ message: errorData.message ?? 'Unknown error occurred',
132
+ responseCode: errorData.responseCode,
133
+ debugMessage: errorData.debugMessage,
134
+ code: errorCode,
135
+ productId: errorData.productId,
136
+ platform,
137
+ });
138
+ };
139
+
140
+ export const ErrorCodeUtils = {
141
+ getNativeErrorCode: (errorCode: ErrorCode): string => {
142
+ return errorCode;
143
+ },
144
+ fromPlatformCode: (
145
+ platformCode: string | number,
146
+ _platform: IapPlatform,
147
+ ): ErrorCode => {
148
+ if (typeof platformCode === 'string') {
149
+ // Handle direct ErrorCode enum values
150
+ if (OPENIAP_ERROR_CODE_SET.has(platformCode)) {
151
+ return platformCode as ErrorCode;
152
+ }
153
+
154
+ // Handle E_ prefixed codes
155
+ if (platformCode.startsWith('E_')) {
156
+ const withoutE = platformCode.substring(2);
157
+ const kebabCase = toKebabCase(withoutE);
158
+ if (OPENIAP_ERROR_CODE_SET.has(kebabCase)) {
159
+ return kebabCase as ErrorCode;
160
+ }
161
+ }
162
+
163
+ // Handle kebab-case codes
164
+ const kebabCase = toKebabCase(platformCode);
165
+ if (OPENIAP_ERROR_CODE_SET.has(kebabCase)) {
166
+ return kebabCase as ErrorCode;
167
+ }
168
+
169
+ // Handle legacy formats like USER_CANCELED
170
+ const upperCase = platformCode.toUpperCase();
171
+ if (upperCase === 'USER_CANCELED' || upperCase === 'E_USER_CANCELED') {
172
+ return ErrorCode.UserCancelled;
173
+ }
16
174
  }
17
175
 
18
- const trimmed = upper.startsWith('E_') ? upper.slice(2) : upper;
19
- const camel = trimmed
20
- .toLowerCase()
21
- .split('_')
22
- .map((segment) => {
23
- if (!segment) return segment;
24
- return segment.charAt(0).toUpperCase() + segment.slice(1);
25
- })
26
- .join('');
27
- if ((ErrorCode as any)[camel]) {
28
- return (ErrorCode as any)[camel];
176
+ return ErrorCode.Unknown;
177
+ },
178
+ toPlatformCode: (
179
+ errorCode: ErrorCode,
180
+ _platform: IapPlatform,
181
+ ): string | number => {
182
+ return COMMON_ERROR_CODE_MAP[errorCode] ?? 'E_UNKNOWN';
183
+ },
184
+ isValidForPlatform: (
185
+ errorCode: ErrorCode,
186
+ platform: IapPlatform,
187
+ ): boolean => {
188
+ return errorCode in ErrorCodeMapping[normalizePlatform(platform)];
189
+ },
190
+ };
191
+
192
+ // ---------------------------------------------------------------------------
193
+ // Convenience helpers for interpreting error objects
194
+ // ---------------------------------------------------------------------------
195
+
196
+ type ErrorLike = string | {code?: ErrorCode | string; message?: string};
197
+
198
+ const ERROR_CODES = new Set<string>(Object.values(ErrorCode));
199
+
200
+ const normalizeErrorCode = (
201
+ code?: string | ErrorCode | null,
202
+ ): string | undefined => {
203
+ if (!code) {
204
+ return undefined;
205
+ }
206
+
207
+ // If it's already an ErrorCode enum value, return it as string
208
+ if (typeof code !== 'string' && ERROR_CODES.has(code as string)) {
209
+ return code as string;
210
+ }
211
+
212
+ if (ERROR_CODES.has(code as string)) {
213
+ return code as string;
214
+ }
215
+
216
+ const camelCased = toKebabCase(code as string);
217
+ if (ERROR_CODES.has(camelCased)) {
218
+ return camelCased;
219
+ }
220
+
221
+ if (typeof code === 'string' && code.startsWith('E_')) {
222
+ const trimmed = code.substring(2);
223
+ if (ERROR_CODES.has(trimmed)) {
224
+ return trimmed;
225
+ }
226
+ const camelTrimmed = toKebabCase(trimmed);
227
+ if (ERROR_CODES.has(camelTrimmed)) {
228
+ return camelTrimmed;
29
229
  }
30
230
  }
31
- return ErrorCode.Unknown;
231
+
232
+ // Handle legacy formats
233
+ if (code === 'E_USER_CANCELED') {
234
+ return ErrorCode.UserCancelled;
235
+ }
236
+
237
+ return code as string;
32
238
  };
33
239
 
34
- export function isUserCancelledError(error: PurchaseError): boolean {
35
- return normalizeErrorCodeFromNative(error.code) === ErrorCode.UserCancelled;
240
+ function extractCode(error: unknown): string | undefined {
241
+ if (typeof error === 'string') {
242
+ return normalizeErrorCode(error);
243
+ }
244
+
245
+ if (error && typeof error === 'object' && 'code' in error) {
246
+ const code = (error as {code?: string | ErrorCode}).code;
247
+ return normalizeErrorCode(typeof code === 'string' ? code : code);
248
+ }
249
+
250
+ return undefined;
36
251
  }
37
252
 
38
- export function isRecoverableError(error: PurchaseError): boolean {
39
- const recoverable = new Set<string>([
253
+ export function isUserCancelledError(error: unknown): boolean {
254
+ return extractCode(error) === ErrorCode.UserCancelled;
255
+ }
256
+
257
+ export function isNetworkError(error: unknown): boolean {
258
+ const networkErrors: ErrorCode[] = [
40
259
  ErrorCode.NetworkError,
260
+ ErrorCode.RemoteError,
41
261
  ErrorCode.ServiceError,
262
+ ErrorCode.ServiceDisconnected,
263
+ ErrorCode.BillingUnavailable,
264
+ ];
265
+
266
+ const code = extractCode(error);
267
+ return !!code && (networkErrors as string[]).includes(code);
268
+ }
269
+
270
+ export function isRecoverableError(error: unknown): boolean {
271
+ const recoverableErrors: string[] = [
272
+ ErrorCode.NetworkError,
42
273
  ErrorCode.RemoteError,
43
- ErrorCode.ConnectionClosed,
274
+ ErrorCode.ServiceError,
275
+ ErrorCode.Interrupted,
44
276
  ErrorCode.ServiceDisconnected,
277
+ ErrorCode.BillingUnavailable,
278
+ ErrorCode.QueryProduct,
45
279
  ErrorCode.InitConnection,
46
280
  ErrorCode.SyncError,
47
- ]);
48
- return recoverable.has(error.code);
281
+ ErrorCode.ConnectionClosed,
282
+ ];
283
+
284
+ const code = extractCode(error);
285
+ return !!code && recoverableErrors.includes(code);
49
286
  }
50
287
 
51
- export function getUserFriendlyErrorMessage(error: PurchaseError): string {
52
- switch (error.code) {
288
+ export function getUserFriendlyErrorMessage(error: ErrorLike): string {
289
+ const errorCode = extractCode(error);
290
+
291
+ switch (errorCode) {
53
292
  case ErrorCode.UserCancelled:
54
293
  return 'Purchase cancelled';
55
294
  case ErrorCode.NetworkError:
56
- return 'Network connection error';
295
+ return 'Network connection error. Please check your internet connection and try again.';
296
+ case ErrorCode.ReceiptFinished:
297
+ return 'Receipt already finished';
298
+ case ErrorCode.ServiceDisconnected:
299
+ return 'Billing service disconnected. Please try again.';
300
+ case ErrorCode.BillingUnavailable:
301
+ return 'Billing is unavailable on this device or account.';
302
+ case ErrorCode.ItemUnavailable:
303
+ return 'This item is not available for purchase';
304
+ case ErrorCode.ItemNotOwned:
305
+ return "You don't own this item";
306
+ case ErrorCode.AlreadyOwned:
307
+ return 'You already own this item';
308
+ case ErrorCode.SkuNotFound:
309
+ return 'Requested product could not be found';
310
+ case ErrorCode.SkuOfferMismatch:
311
+ return 'Selected offer does not match the SKU';
312
+ case ErrorCode.DeferredPayment:
313
+ return 'Payment is pending approval';
314
+ case ErrorCode.NotPrepared:
315
+ return 'In-app purchase is not ready. Please try again later.';
57
316
  case ErrorCode.ServiceError:
58
- return 'Store service error';
59
- case ErrorCode.RemoteError:
60
- return 'Remote service error';
317
+ return 'Store service error. Please try again later.';
318
+ case ErrorCode.FeatureNotSupported:
319
+ return 'This feature is not supported on this device.';
320
+ case ErrorCode.TransactionValidationFailed:
321
+ return 'Transaction could not be verified';
322
+ case ErrorCode.ReceiptFailed:
323
+ return 'Receipt processing failed';
324
+ case ErrorCode.EmptySkuList:
325
+ return 'No product IDs provided';
326
+ case ErrorCode.InitConnection:
327
+ return 'Failed to initialize billing connection';
61
328
  case ErrorCode.IapNotAvailable:
62
329
  return 'In-app purchases are not available on this device';
63
- case ErrorCode.DeferredPayment:
64
- return 'Payment was deferred (pending approval)';
65
- case ErrorCode.TransactionValidationFailed:
66
- return 'Transaction validation failed';
67
- case ErrorCode.SkuNotFound:
68
- return 'Product not found';
69
- default:
70
- return error.message || 'Unknown error occurred';
330
+ case ErrorCode.QueryProduct:
331
+ return 'Failed to query products. Please try again later.';
332
+ default: {
333
+ if (error && typeof error === 'object' && 'message' in error) {
334
+ return (
335
+ (error as {message?: string}).message ??
336
+ 'An unexpected error occurred'
337
+ );
338
+ }
339
+ return 'An unexpected error occurred';
340
+ }
71
341
  }
72
342
  }
343
+
344
+ export const normalizeErrorCodeFromNative = (code: unknown): ErrorCode => {
345
+ if (typeof code === 'string') {
346
+ const upper = code.toUpperCase();
347
+
348
+ // Check aliases first
349
+ const alias = ERROR_CODE_ALIASES[upper];
350
+ if (alias) {
351
+ return alias;
352
+ }
353
+
354
+ // Handle various user cancelled formats
355
+ if (
356
+ upper === 'USER_CANCELLED' ||
357
+ upper === 'USER_CANCELED' ||
358
+ upper === 'E_USER_CANCELLED' ||
359
+ upper === 'E_USER_CANCELED' ||
360
+ upper === 'USER_CANCEL' ||
361
+ upper === 'CANCELLED' ||
362
+ upper === 'CANCELED' ||
363
+ code === 'user-cancelled' ||
364
+ code === 'user-canceled'
365
+ ) {
366
+ return ErrorCode.UserCancelled;
367
+ }
368
+
369
+ // Handle E_ prefixed codes
370
+ if (upper.startsWith('E_')) {
371
+ const trimmed = upper.slice(2);
372
+ // Try direct match first
373
+ if ((ErrorCode as any)[trimmed]) {
374
+ return (ErrorCode as any)[trimmed];
375
+ }
376
+
377
+ // Try camelCase conversion
378
+ const camel = trimmed
379
+ .toLowerCase()
380
+ .split('_')
381
+ .map((segment) => {
382
+ if (!segment) return segment;
383
+ return segment.charAt(0).toUpperCase() + segment.slice(1);
384
+ })
385
+ .join('');
386
+ if ((ErrorCode as any)[camel]) {
387
+ return (ErrorCode as any)[camel];
388
+ }
389
+
390
+ // Try kebab-case conversion
391
+ const kebab = trimmed.toLowerCase().replace(/_/g, '-');
392
+ if ((ErrorCode as any)[kebab]) {
393
+ return (ErrorCode as any)[kebab];
394
+ }
395
+ }
396
+
397
+ // Handle direct kebab-case codes
398
+ if (code.includes('-')) {
399
+ if ((ErrorCode as any)[code]) {
400
+ return (ErrorCode as any)[code];
401
+ }
402
+ }
403
+
404
+ // Handle snake_case codes
405
+ if (code.includes('_')) {
406
+ const camel = code
407
+ .toLowerCase()
408
+ .split('_')
409
+ .map((segment) => {
410
+ if (!segment) return segment;
411
+ return segment.charAt(0).toUpperCase() + segment.slice(1);
412
+ })
413
+ .join('');
414
+ if ((ErrorCode as any)[camel]) {
415
+ return (ErrorCode as any)[camel];
416
+ }
417
+
418
+ const kebab = code.toLowerCase().replace(/_/g, '-');
419
+ if ((ErrorCode as any)[kebab]) {
420
+ return (ErrorCode as any)[kebab];
421
+ }
422
+ }
423
+
424
+ // Try direct match with ErrorCode enum
425
+ if ((ErrorCode as any)[code]) {
426
+ return (ErrorCode as any)[code];
427
+ }
428
+
429
+ // Try uppercase match
430
+ if ((ErrorCode as any)[upper]) {
431
+ return (ErrorCode as any)[upper];
432
+ }
433
+ }
434
+
435
+ return ErrorCode.Unknown;
436
+ };