react-native-iap 14.4.7 → 14.4.9
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.
- package/lib/module/hooks/useIAP.js +21 -11
- package/lib/module/hooks/useIAP.js.map +1 -1
- package/lib/module/index.js +168 -49
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/debug.js +44 -0
- package/lib/module/utils/debug.js.map +1 -0
- package/lib/module/utils/type-bridge.js +13 -5
- package/lib/module/utils/type-bridge.js.map +1 -1
- package/lib/module/utils.js +3 -1
- package/lib/module/utils.js.map +1 -1
- package/lib/typescript/src/hooks/useIAP.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +12 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/debug.d.ts +13 -0
- package/lib/typescript/src/utils/debug.d.ts.map +1 -0
- package/lib/typescript/src/utils/type-bridge.d.ts.map +1 -1
- package/lib/typescript/src/utils.d.ts.map +1 -1
- package/openiap-versions.json +1 -1
- package/package.json +1 -1
- package/src/hooks/useIAP.ts +19 -15
- package/src/index.ts +232 -55
- package/src/utils/debug.ts +49 -0
- package/src/utils/type-bridge.ts +18 -7
- package/src/utils.ts +5 -1
- package/lib/module/helpers/subscription.js +0 -64
- package/lib/module/helpers/subscription.js.map +0 -1
- package/lib/typescript/src/helpers/subscription.d.ts +0 -14
- package/lib/typescript/src/helpers/subscription.d.ts.map +0 -1
- package/src/helpers/subscription.ts +0 -75
package/src/utils/type-bridge.ts
CHANGED
|
@@ -24,6 +24,7 @@ import type {
|
|
|
24
24
|
Purchase,
|
|
25
25
|
SubscriptionStatusIOS,
|
|
26
26
|
} from '../types';
|
|
27
|
+
import {RnIapConsole} from './debug';
|
|
27
28
|
|
|
28
29
|
const PLATFORM_IOS: IapPlatform = 'ios';
|
|
29
30
|
const PLATFORM_ANDROID: IapPlatform = 'android';
|
|
@@ -78,7 +79,7 @@ function normalizeProductTypeIOS(value?: Nullable<string>): ProductTypeIOS {
|
|
|
78
79
|
return 'non-renewing-subscription';
|
|
79
80
|
default:
|
|
80
81
|
if (value) {
|
|
81
|
-
|
|
82
|
+
RnIapConsole.warn(
|
|
82
83
|
`[react-native-iap] Unknown iOS product type "${value}", defaulting to NonConsumable.`,
|
|
83
84
|
);
|
|
84
85
|
}
|
|
@@ -170,15 +171,25 @@ function toNullableBoolean(value: unknown): boolean | null {
|
|
|
170
171
|
return null;
|
|
171
172
|
}
|
|
172
173
|
|
|
173
|
-
function parseSubscriptionOffers(value?: Nullable<string>) {
|
|
174
|
+
function parseSubscriptionOffers(value?: Nullable<string> | any[]) {
|
|
174
175
|
if (!value) return undefined;
|
|
176
|
+
|
|
177
|
+
// If it's already an array (from mocks), return it as-is
|
|
178
|
+
if (Array.isArray(value)) {
|
|
179
|
+
return value;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Otherwise, try to parse it as JSON string
|
|
175
183
|
try {
|
|
176
|
-
const parsed = JSON.parse(value);
|
|
184
|
+
const parsed = JSON.parse(value as string);
|
|
177
185
|
if (Array.isArray(parsed)) {
|
|
178
186
|
return parsed;
|
|
179
187
|
}
|
|
180
188
|
} catch (error) {
|
|
181
|
-
|
|
189
|
+
RnIapConsole.warn(
|
|
190
|
+
'Failed to parse subscriptionOfferDetailsAndroid:',
|
|
191
|
+
error,
|
|
192
|
+
);
|
|
182
193
|
}
|
|
183
194
|
return undefined;
|
|
184
195
|
}
|
|
@@ -270,7 +281,7 @@ export function convertProductToProductSubscription(
|
|
|
270
281
|
product: Product,
|
|
271
282
|
): ProductSubscription {
|
|
272
283
|
if (product.type !== PRODUCT_TYPE_SUBS) {
|
|
273
|
-
|
|
284
|
+
RnIapConsole.warn(
|
|
274
285
|
'Converting non-subscription product to ProductSubscription:',
|
|
275
286
|
product.id,
|
|
276
287
|
);
|
|
@@ -390,7 +401,7 @@ export function validateNitroProduct(nitroProduct: NitroProduct): boolean {
|
|
|
390
401
|
!(field in nitroProduct) ||
|
|
391
402
|
nitroProduct[field as keyof NitroProduct] == null
|
|
392
403
|
) {
|
|
393
|
-
|
|
404
|
+
RnIapConsole.error(
|
|
394
405
|
`NitroProduct missing required field: ${field}`,
|
|
395
406
|
nitroProduct,
|
|
396
407
|
);
|
|
@@ -415,7 +426,7 @@ export function validateNitroPurchase(nitroPurchase: NitroPurchase): boolean {
|
|
|
415
426
|
!(field in nitroPurchase) ||
|
|
416
427
|
nitroPurchase[field as keyof NitroPurchase] == null
|
|
417
428
|
) {
|
|
418
|
-
|
|
429
|
+
RnIapConsole.error(
|
|
419
430
|
`NitroPurchase missing required field: ${field}`,
|
|
420
431
|
nitroPurchase,
|
|
421
432
|
);
|
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {AppTransaction} from './types';
|
|
2
|
+
import {RnIapConsole} from './utils/debug';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Parse the string payload returned by the native getAppTransactionIOS call into
|
|
@@ -62,7 +63,10 @@ export const parseAppTransactionPayload = (
|
|
|
62
63
|
signedDate,
|
|
63
64
|
};
|
|
64
65
|
} catch (error) {
|
|
65
|
-
|
|
66
|
+
RnIapConsole.warn(
|
|
67
|
+
'[parseAppTransactionPayload] Failed to parse payload',
|
|
68
|
+
error,
|
|
69
|
+
);
|
|
66
70
|
return null;
|
|
67
71
|
}
|
|
68
72
|
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { getAvailablePurchases } from "../index.js";
|
|
4
|
-
/**
|
|
5
|
-
* Get active subscriptions
|
|
6
|
-
* @param subscriptionIds - Optional array of subscription IDs to filter by
|
|
7
|
-
* @returns Promise<ActiveSubscription[]> - Array of active subscriptions
|
|
8
|
-
*/
|
|
9
|
-
export const getActiveSubscriptions = async subscriptionIds => {
|
|
10
|
-
try {
|
|
11
|
-
// Get available purchases and filter for subscriptions
|
|
12
|
-
const purchases = await getAvailablePurchases();
|
|
13
|
-
|
|
14
|
-
// Filter for subscriptions and map to ActiveSubscription format
|
|
15
|
-
const subscriptions = purchases.filter(purchase => {
|
|
16
|
-
// Filter by subscription IDs if provided
|
|
17
|
-
if (subscriptionIds && subscriptionIds.length > 0) {
|
|
18
|
-
return subscriptionIds.includes(purchase.productId);
|
|
19
|
-
}
|
|
20
|
-
return true;
|
|
21
|
-
}).map(purchase => {
|
|
22
|
-
const iosPurchase = purchase;
|
|
23
|
-
const androidPurchase = purchase;
|
|
24
|
-
return {
|
|
25
|
-
productId: purchase.productId,
|
|
26
|
-
isActive: true,
|
|
27
|
-
// If it's in availablePurchases, it's active
|
|
28
|
-
// Backend validation fields
|
|
29
|
-
transactionId: purchase.id,
|
|
30
|
-
purchaseToken: purchase.purchaseToken,
|
|
31
|
-
transactionDate: purchase.transactionDate,
|
|
32
|
-
// Platform-specific fields
|
|
33
|
-
expirationDateIOS: iosPurchase.expirationDateIOS ?? null,
|
|
34
|
-
autoRenewingAndroid: androidPurchase.autoRenewingAndroid ?? androidPurchase.isAutoRenewing,
|
|
35
|
-
// deprecated - use isAutoRenewing instead
|
|
36
|
-
environmentIOS: iosPurchase.environmentIOS,
|
|
37
|
-
// Convenience fields
|
|
38
|
-
willExpireSoon: false,
|
|
39
|
-
// Would need to calculate based on expiration date
|
|
40
|
-
daysUntilExpirationIOS: iosPurchase.expirationDateIOS != null ? Math.ceil((iosPurchase.expirationDateIOS - Date.now()) / (1000 * 60 * 60 * 24)) : undefined
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
return subscriptions;
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.error('Failed to get active subscriptions:', error);
|
|
46
|
-
throw error;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Check if there are any active subscriptions
|
|
52
|
-
* @param subscriptionIds - Optional array of subscription IDs to check
|
|
53
|
-
* @returns Promise<boolean> - True if there are active subscriptions
|
|
54
|
-
*/
|
|
55
|
-
export const hasActiveSubscriptions = async subscriptionIds => {
|
|
56
|
-
try {
|
|
57
|
-
const activeSubscriptions = await getActiveSubscriptions(subscriptionIds);
|
|
58
|
-
return activeSubscriptions.length > 0;
|
|
59
|
-
} catch (error) {
|
|
60
|
-
console.error('Failed to check active subscriptions:', error);
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
//# sourceMappingURL=subscription.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["getAvailablePurchases","getActiveSubscriptions","subscriptionIds","purchases","subscriptions","filter","purchase","length","includes","productId","map","iosPurchase","androidPurchase","isActive","transactionId","id","purchaseToken","transactionDate","expirationDateIOS","autoRenewingAndroid","isAutoRenewing","environmentIOS","willExpireSoon","daysUntilExpirationIOS","Math","ceil","Date","now","undefined","error","console","hasActiveSubscriptions","activeSubscriptions"],"sourceRoot":"../../../src","sources":["helpers/subscription.ts"],"mappings":";;AAAA,SAAQA,qBAAqB,QAAO,aAAK;AAGzC;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,sBAAsB,GAAG,MACpCC,eAA0B,IACQ;EAClC,IAAI;IACF;IACA,MAAMC,SAAS,GAAG,MAAMH,qBAAqB,CAAC,CAAC;;IAE/C;IACA,MAAMI,aAAa,GAAGD,SAAS,CAC5BE,MAAM,CAAEC,QAAQ,IAAK;MACpB;MACA,IAAIJ,eAAe,IAAIA,eAAe,CAACK,MAAM,GAAG,CAAC,EAAE;QACjD,OAAOL,eAAe,CAACM,QAAQ,CAACF,QAAQ,CAACG,SAAS,CAAC;MACrD;MACA,OAAO,IAAI;IACb,CAAC,CAAC,CACDC,GAAG,CAAEJ,QAAQ,IAAyB;MACrC,MAAMK,WAAW,GAAGL,QAAuB;MAC3C,MAAMM,eAAe,GAAGN,QAA2B;MACnD,OAAO;QACLG,SAAS,EAAEH,QAAQ,CAACG,SAAS;QAC7BI,QAAQ,EAAE,IAAI;QAAE;QAChB;QACAC,aAAa,EAAER,QAAQ,CAACS,EAAE;QAC1BC,aAAa,EAAEV,QAAQ,CAACU,aAAa;QACrCC,eAAe,EAAEX,QAAQ,CAACW,eAAe;QACzC;QACAC,iBAAiB,EAAEP,WAAW,CAACO,iBAAiB,IAAI,IAAI;QACxDC,mBAAmB,EACjBP,eAAe,CAACO,mBAAmB,IACnCP,eAAe,CAACQ,cAAc;QAAE;QAClCC,cAAc,EAAEV,WAAW,CAACU,cAAc;QAC1C;QACAC,cAAc,EAAE,KAAK;QAAE;QACvBC,sBAAsB,EACpBZ,WAAW,CAACO,iBAAiB,IAAI,IAAI,GACjCM,IAAI,CAACC,IAAI,CACP,CAACd,WAAW,CAACO,iBAAiB,GAAGQ,IAAI,CAACC,GAAG,CAAC,CAAC,KACxC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CACxB,CAAC,GACDC;MACR,CAAC;IACH,CAAC,CAAC;IAEJ,OAAOxB,aAAa;EACtB,CAAC,CAAC,OAAOyB,KAAK,EAAE;IACdC,OAAO,CAACD,KAAK,CAAC,qCAAqC,EAAEA,KAAK,CAAC;IAC3D,MAAMA,KAAK;EACb;AACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,OAAO,MAAME,sBAAsB,GAAG,MACpC7B,eAA0B,IACL;EACrB,IAAI;IACF,MAAM8B,mBAAmB,GAAG,MAAM/B,sBAAsB,CAACC,eAAe,CAAC;IACzE,OAAO8B,mBAAmB,CAACzB,MAAM,GAAG,CAAC;EACvC,CAAC,CAAC,OAAOsB,KAAK,EAAE;IACdC,OAAO,CAACD,KAAK,CAAC,uCAAuC,EAAEA,KAAK,CAAC;IAC7D,OAAO,KAAK;EACd;AACF,CAAC","ignoreList":[]}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { ActiveSubscription } from '../types';
|
|
2
|
-
/**
|
|
3
|
-
* Get active subscriptions
|
|
4
|
-
* @param subscriptionIds - Optional array of subscription IDs to filter by
|
|
5
|
-
* @returns Promise<ActiveSubscription[]> - Array of active subscriptions
|
|
6
|
-
*/
|
|
7
|
-
export declare const getActiveSubscriptions: (subscriptionIds?: string[]) => Promise<ActiveSubscription[]>;
|
|
8
|
-
/**
|
|
9
|
-
* Check if there are any active subscriptions
|
|
10
|
-
* @param subscriptionIds - Optional array of subscription IDs to check
|
|
11
|
-
* @returns Promise<boolean> - True if there are active subscriptions
|
|
12
|
-
*/
|
|
13
|
-
export declare const hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise<boolean>;
|
|
14
|
-
//# sourceMappingURL=subscription.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../../../src/helpers/subscription.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,kBAAkB,EAA+B,MAAM,UAAU,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,kBAAkB,MAAM,EAAE,KACzB,OAAO,CAAC,kBAAkB,EAAE,CA+C9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,kBAAkB,MAAM,EAAE,KACzB,OAAO,CAAC,OAAO,CAQjB,CAAC"}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import {getAvailablePurchases} from '../';
|
|
2
|
-
import type {ActiveSubscription, PurchaseIOS, PurchaseAndroid} from '../types';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Get active subscriptions
|
|
6
|
-
* @param subscriptionIds - Optional array of subscription IDs to filter by
|
|
7
|
-
* @returns Promise<ActiveSubscription[]> - Array of active subscriptions
|
|
8
|
-
*/
|
|
9
|
-
export const getActiveSubscriptions = async (
|
|
10
|
-
subscriptionIds?: string[],
|
|
11
|
-
): Promise<ActiveSubscription[]> => {
|
|
12
|
-
try {
|
|
13
|
-
// Get available purchases and filter for subscriptions
|
|
14
|
-
const purchases = await getAvailablePurchases();
|
|
15
|
-
|
|
16
|
-
// Filter for subscriptions and map to ActiveSubscription format
|
|
17
|
-
const subscriptions = purchases
|
|
18
|
-
.filter((purchase) => {
|
|
19
|
-
// Filter by subscription IDs if provided
|
|
20
|
-
if (subscriptionIds && subscriptionIds.length > 0) {
|
|
21
|
-
return subscriptionIds.includes(purchase.productId);
|
|
22
|
-
}
|
|
23
|
-
return true;
|
|
24
|
-
})
|
|
25
|
-
.map((purchase): ActiveSubscription => {
|
|
26
|
-
const iosPurchase = purchase as PurchaseIOS;
|
|
27
|
-
const androidPurchase = purchase as PurchaseAndroid;
|
|
28
|
-
return {
|
|
29
|
-
productId: purchase.productId,
|
|
30
|
-
isActive: true, // If it's in availablePurchases, it's active
|
|
31
|
-
// Backend validation fields
|
|
32
|
-
transactionId: purchase.id,
|
|
33
|
-
purchaseToken: purchase.purchaseToken,
|
|
34
|
-
transactionDate: purchase.transactionDate,
|
|
35
|
-
// Platform-specific fields
|
|
36
|
-
expirationDateIOS: iosPurchase.expirationDateIOS ?? null,
|
|
37
|
-
autoRenewingAndroid:
|
|
38
|
-
androidPurchase.autoRenewingAndroid ??
|
|
39
|
-
androidPurchase.isAutoRenewing, // deprecated - use isAutoRenewing instead
|
|
40
|
-
environmentIOS: iosPurchase.environmentIOS,
|
|
41
|
-
// Convenience fields
|
|
42
|
-
willExpireSoon: false, // Would need to calculate based on expiration date
|
|
43
|
-
daysUntilExpirationIOS:
|
|
44
|
-
iosPurchase.expirationDateIOS != null
|
|
45
|
-
? Math.ceil(
|
|
46
|
-
(iosPurchase.expirationDateIOS - Date.now()) /
|
|
47
|
-
(1000 * 60 * 60 * 24),
|
|
48
|
-
)
|
|
49
|
-
: undefined,
|
|
50
|
-
};
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
return subscriptions;
|
|
54
|
-
} catch (error) {
|
|
55
|
-
console.error('Failed to get active subscriptions:', error);
|
|
56
|
-
throw error;
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Check if there are any active subscriptions
|
|
62
|
-
* @param subscriptionIds - Optional array of subscription IDs to check
|
|
63
|
-
* @returns Promise<boolean> - True if there are active subscriptions
|
|
64
|
-
*/
|
|
65
|
-
export const hasActiveSubscriptions = async (
|
|
66
|
-
subscriptionIds?: string[],
|
|
67
|
-
): Promise<boolean> => {
|
|
68
|
-
try {
|
|
69
|
-
const activeSubscriptions = await getActiveSubscriptions(subscriptionIds);
|
|
70
|
-
return activeSubscriptions.length > 0;
|
|
71
|
-
} catch (error) {
|
|
72
|
-
console.error('Failed to check active subscriptions:', error);
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
};
|