expo-iap 2.7.13 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.copilot-instructions.md +5 -5
- package/.cursorrules +31 -13
- package/CHANGELOG.md +16 -1
- package/CLAUDE.md +5 -1
- package/android/src/main/java/expo/modules/iap/ExpoIapModule.kt +2 -0
- package/build/ExpoIap.types.d.ts +24 -11
- package/build/ExpoIap.types.d.ts.map +1 -1
- package/build/ExpoIap.types.js.map +1 -1
- package/build/helpers/subscription.d.ts.map +1 -1
- package/build/helpers/subscription.js +24 -17
- package/build/helpers/subscription.js.map +1 -1
- package/build/index.d.ts +2 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +12 -17
- package/build/index.js.map +1 -1
- package/build/modules/ios.d.ts +10 -23
- package/build/modules/ios.d.ts.map +1 -1
- package/build/modules/ios.js +9 -23
- package/build/modules/ios.js.map +1 -1
- package/build/types/ExpoIapAndroid.types.d.ts +6 -0
- package/build/types/ExpoIapAndroid.types.d.ts.map +1 -1
- package/build/types/ExpoIapAndroid.types.js.map +1 -1
- package/build/types/{ExpoIapIos.types.d.ts → ExpoIapIOS.types.d.ts} +45 -33
- package/build/types/{ExpoIapIos.types.d.ts.map → ExpoIapIOS.types.d.ts.map} +1 -1
- package/build/types/ExpoIapIOS.types.js +2 -0
- package/build/types/ExpoIapIOS.types.js.map +1 -0
- package/build/{useIap.d.ts → useIAP.d.ts} +2 -2
- package/build/{useIap.d.ts.map → useIAP.d.ts.map} +1 -1
- package/build/{useIap.js → useIAP.js} +7 -6
- package/build/useIAP.js.map +1 -0
- package/bun.lock +677 -61
- package/ios/ExpoIapModule.swift +46 -45
- package/jest.config.js +43 -0
- package/package.json +8 -3
- package/src/ExpoIap.types.ts +34 -15
- package/src/helpers/subscription.ts +27 -20
- package/src/index.ts +16 -24
- package/src/modules/ios.ts +13 -40
- package/src/types/ExpoIapAndroid.types.ts +6 -0
- package/src/types/{ExpoIapIos.types.ts → ExpoIapIOS.types.ts} +46 -32
- package/src/{useIap.ts → useIAP.ts} +7 -6
- package/build/types/ExpoIapIos.types.js +0 -2
- package/build/types/ExpoIapIos.types.js.map +0 -1
- package/build/useIap.js.map +0 -1
package/src/modules/ios.ts
CHANGED
|
@@ -12,9 +12,9 @@ import {
|
|
|
12
12
|
SubscriptionPurchase,
|
|
13
13
|
} from '../ExpoIap.types';
|
|
14
14
|
import type {
|
|
15
|
-
|
|
15
|
+
ProductStatusIOS,
|
|
16
16
|
AppTransactionIOS,
|
|
17
|
-
} from '../types/
|
|
17
|
+
} from '../types/ExpoIapIOS.types';
|
|
18
18
|
import {Linking} from 'react-native';
|
|
19
19
|
|
|
20
20
|
export type TransactionEvent = {
|
|
@@ -36,7 +36,7 @@ export type TransactionEvent = {
|
|
|
36
36
|
* // Use:
|
|
37
37
|
* // purchaseUpdatedListener((purchase) => { ... });
|
|
38
38
|
*/
|
|
39
|
-
export const
|
|
39
|
+
export const transactionUpdatedIOS = (
|
|
40
40
|
listener: (event: TransactionEvent) => void,
|
|
41
41
|
) => {
|
|
42
42
|
const isProductPurchase = (item: unknown): item is ProductPurchase => {
|
|
@@ -74,7 +74,7 @@ export const transactionUpdatedIos = (
|
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
// Type guards
|
|
77
|
-
export function
|
|
77
|
+
export function isProductIOS<T extends {platform?: string}>(
|
|
78
78
|
item: unknown,
|
|
79
79
|
): item is T & {platform: 'ios'} {
|
|
80
80
|
return (
|
|
@@ -102,16 +102,16 @@ export const syncIOS = (): Promise<null> => {
|
|
|
102
102
|
/**
|
|
103
103
|
* Check if user is eligible for introductory offer
|
|
104
104
|
*
|
|
105
|
-
* @param
|
|
105
|
+
* @param groupId The subscription group ID
|
|
106
106
|
* @returns Promise resolving to true if eligible
|
|
107
107
|
* @throws Error if called on non-iOS platform
|
|
108
108
|
*
|
|
109
109
|
* @platform iOS
|
|
110
110
|
*/
|
|
111
111
|
export const isEligibleForIntroOfferIOS = (
|
|
112
|
-
|
|
112
|
+
groupId: string,
|
|
113
113
|
): Promise<boolean> => {
|
|
114
|
-
return ExpoIapModule.isEligibleForIntroOffer(
|
|
114
|
+
return ExpoIapModule.isEligibleForIntroOffer(groupId);
|
|
115
115
|
};
|
|
116
116
|
|
|
117
117
|
/**
|
|
@@ -125,7 +125,7 @@ export const isEligibleForIntroOfferIOS = (
|
|
|
125
125
|
*/
|
|
126
126
|
export const subscriptionStatusIOS = (
|
|
127
127
|
sku: string,
|
|
128
|
-
): Promise<
|
|
128
|
+
): Promise<ProductStatusIOS[]> => {
|
|
129
129
|
return ExpoIapModule.subscriptionStatus(sku);
|
|
130
130
|
};
|
|
131
131
|
|
|
@@ -176,7 +176,7 @@ export const beginRefundRequestIOS = (
|
|
|
176
176
|
/**
|
|
177
177
|
* Shows the system UI for managing subscriptions.
|
|
178
178
|
* When the user changes subscription renewal status, the system will emit events to
|
|
179
|
-
* purchaseUpdatedListener and
|
|
179
|
+
* purchaseUpdatedListener and transactionUpdatedIOS listeners.
|
|
180
180
|
*
|
|
181
181
|
* @returns Promise resolving to null on success
|
|
182
182
|
* @throws Error if called on non-iOS platform
|
|
@@ -321,7 +321,7 @@ export const buyPromotedProductIOS = (): Promise<void> => {
|
|
|
321
321
|
*
|
|
322
322
|
* @platform iOS
|
|
323
323
|
*/
|
|
324
|
-
export const
|
|
324
|
+
export const deepLinkToSubscriptionsIOS = (): Promise<void> =>
|
|
325
325
|
Linking.openURL('https://apps.apple.com/account/subscriptions');
|
|
326
326
|
|
|
327
327
|
// ============= DEPRECATED FUNCTIONS =============
|
|
@@ -340,11 +340,11 @@ export const sync = (): Promise<null> => {
|
|
|
340
340
|
/**
|
|
341
341
|
* @deprecated Use `isEligibleForIntroOfferIOS` instead. This function will be removed in version 3.0.0.
|
|
342
342
|
*/
|
|
343
|
-
export const isEligibleForIntroOffer = (
|
|
343
|
+
export const isEligibleForIntroOffer = (groupId: string): Promise<boolean> => {
|
|
344
344
|
console.warn(
|
|
345
345
|
'`isEligibleForIntroOffer` is deprecated. Use `isEligibleForIntroOfferIOS` instead. This function will be removed in version 3.0.0.',
|
|
346
346
|
);
|
|
347
|
-
return isEligibleForIntroOfferIOS(
|
|
347
|
+
return isEligibleForIntroOfferIOS(groupId);
|
|
348
348
|
};
|
|
349
349
|
|
|
350
350
|
/**
|
|
@@ -352,7 +352,7 @@ export const isEligibleForIntroOffer = (groupID: string): Promise<boolean> => {
|
|
|
352
352
|
*/
|
|
353
353
|
export const subscriptionStatus = (
|
|
354
354
|
sku: string,
|
|
355
|
-
): Promise<
|
|
355
|
+
): Promise<ProductStatusIOS[]> => {
|
|
356
356
|
console.warn(
|
|
357
357
|
'`subscriptionStatus` is deprecated. Use `subscriptionStatusIOS` instead. This function will be removed in version 3.0.0.',
|
|
358
358
|
);
|
|
@@ -401,16 +401,6 @@ export const showManageSubscriptions = (): Promise<null> => {
|
|
|
401
401
|
return showManageSubscriptionsIOS();
|
|
402
402
|
};
|
|
403
403
|
|
|
404
|
-
/**
|
|
405
|
-
* @deprecated Use `getReceiptIOS` instead. This function will be removed in version 3.0.0.
|
|
406
|
-
*/
|
|
407
|
-
export const getReceiptIos = (): Promise<string> => {
|
|
408
|
-
console.warn(
|
|
409
|
-
'`getReceiptIos` is deprecated. Use `getReceiptIOS` instead. This function will be removed in version 3.0.0.',
|
|
410
|
-
);
|
|
411
|
-
return getReceiptIOS();
|
|
412
|
-
};
|
|
413
|
-
|
|
414
404
|
/**
|
|
415
405
|
* @deprecated Use `isTransactionVerifiedIOS` instead. This function will be removed in version 3.0.0.
|
|
416
406
|
*/
|
|
@@ -431,23 +421,6 @@ export const getTransactionJws = (sku: string): Promise<string> => {
|
|
|
431
421
|
return getTransactionJwsIOS(sku);
|
|
432
422
|
};
|
|
433
423
|
|
|
434
|
-
/**
|
|
435
|
-
* @deprecated Use `validateReceiptIOS` instead. This function will be removed in version 3.0.0.
|
|
436
|
-
*/
|
|
437
|
-
export const validateReceiptIos = async (
|
|
438
|
-
sku: string,
|
|
439
|
-
): Promise<{
|
|
440
|
-
isValid: boolean;
|
|
441
|
-
receiptData: string;
|
|
442
|
-
jwsRepresentation: string;
|
|
443
|
-
latestTransaction?: ProductPurchase;
|
|
444
|
-
}> => {
|
|
445
|
-
console.warn(
|
|
446
|
-
'`validateReceiptIos` is deprecated. Use `validateReceiptIOS` instead. This function will be removed in version 3.0.0.',
|
|
447
|
-
);
|
|
448
|
-
return validateReceiptIOS(sku);
|
|
449
|
-
};
|
|
450
|
-
|
|
451
424
|
/**
|
|
452
425
|
* @deprecated Use `presentCodeRedemptionSheetIOS` instead. This function will be removed in version 3.0.0.
|
|
453
426
|
*/
|
|
@@ -68,6 +68,9 @@ type SubscriptionOffer = {
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
export type RequestSubscriptionAndroidProps = RequestPurchaseAndroidProps & {
|
|
71
|
+
/**
|
|
72
|
+
* @deprecated Use `purchaseToken` instead. This field will be removed in a future version.
|
|
73
|
+
*/
|
|
71
74
|
purchaseTokenAndroid?: string;
|
|
72
75
|
replacementModeAndroid?: ReplacementModesAndroid;
|
|
73
76
|
subscriptionOffers: SubscriptionOffer[];
|
|
@@ -115,6 +118,9 @@ export enum PurchaseStateAndroid {
|
|
|
115
118
|
|
|
116
119
|
export type ProductPurchaseAndroid = PurchaseBase & {
|
|
117
120
|
ids?: string[];
|
|
121
|
+
/**
|
|
122
|
+
* @deprecated Use `purchaseToken` instead. This field will be removed in a future version.
|
|
123
|
+
*/
|
|
118
124
|
purchaseTokenAndroid?: string;
|
|
119
125
|
dataAndroid?: string;
|
|
120
126
|
signatureAndroid?: string;
|
|
@@ -19,14 +19,14 @@ type SubscriptionOffer = {
|
|
|
19
19
|
type SubscriptionInfo = {
|
|
20
20
|
introductoryOffer?: SubscriptionOffer;
|
|
21
21
|
promotionalOffers?: SubscriptionOffer[];
|
|
22
|
-
|
|
22
|
+
subscriptionGroupId: string;
|
|
23
23
|
subscriptionPeriod: {
|
|
24
24
|
unit: SubscriptionIosPeriod;
|
|
25
25
|
value: number;
|
|
26
26
|
};
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
export type
|
|
29
|
+
export type ProductIOS = ProductBase & {
|
|
30
30
|
displayName: string;
|
|
31
31
|
isFamilyShareable: boolean;
|
|
32
32
|
jsonRepresentation: string;
|
|
@@ -45,7 +45,7 @@ export type Discount = {
|
|
|
45
45
|
subscriptionPeriod: string;
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
export type
|
|
48
|
+
export type SubscriptionProductIOS = ProductIOS & {
|
|
49
49
|
discounts?: Discount[];
|
|
50
50
|
introductoryPrice?: string;
|
|
51
51
|
introductoryPriceAsAmountIOS?: string;
|
|
@@ -79,7 +79,7 @@ export type PaymentDiscount = {
|
|
|
79
79
|
timestamp: number;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
-
export type
|
|
82
|
+
export type RequestPurchaseIOSProps = {
|
|
83
83
|
sku: string;
|
|
84
84
|
andDangerouslyFinishTransactionAutomaticallyIOS?: boolean;
|
|
85
85
|
/**
|
|
@@ -90,7 +90,17 @@ export type RequestPurchaseIosProps = {
|
|
|
90
90
|
withOffer?: PaymentDiscount;
|
|
91
91
|
};
|
|
92
92
|
|
|
93
|
-
export type
|
|
93
|
+
export type RequestSubscriptionIOSProps = RequestPurchaseIOSProps;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @deprecated Use RequestPurchaseIOSProps instead. This alias will be removed in v3.0.0.
|
|
97
|
+
*/
|
|
98
|
+
export type RequestPurchaseIosProps = RequestPurchaseIOSProps;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @deprecated Use RequestSubscriptionIOSProps instead. This alias will be removed in v3.0.0.
|
|
102
|
+
*/
|
|
103
|
+
export type RequestSubscriptionIosProps = RequestSubscriptionIOSProps;
|
|
94
104
|
|
|
95
105
|
type SubscriptionStatus =
|
|
96
106
|
| 'expired'
|
|
@@ -105,46 +115,50 @@ type RenewalInfo = {
|
|
|
105
115
|
autoRenewPreference?: string;
|
|
106
116
|
};
|
|
107
117
|
|
|
108
|
-
export type
|
|
118
|
+
export type ProductStatusIOS = {
|
|
109
119
|
state: SubscriptionStatus;
|
|
110
120
|
renewalInfo?: RenewalInfo;
|
|
111
121
|
};
|
|
112
122
|
|
|
113
|
-
export type
|
|
123
|
+
export type ProductPurchaseIOS = PurchaseBase & {
|
|
114
124
|
// iOS basic fields
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
125
|
+
quantityIOS?: number;
|
|
126
|
+
originalTransactionDateIOS?: number;
|
|
127
|
+
originalTransactionIdentifierIOS?: string;
|
|
118
128
|
appAccountToken?: string;
|
|
119
129
|
// iOS additional fields from StoreKit 2
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
130
|
+
expirationDateIOS?: number;
|
|
131
|
+
webOrderLineItemIdIOS?: number;
|
|
132
|
+
environmentIOS?: string;
|
|
133
|
+
storefrontCountryCodeIOS?: string;
|
|
134
|
+
appBundleIdIOS?: string;
|
|
135
|
+
productTypeIOS?: string;
|
|
136
|
+
subscriptionGroupIdIOS?: string;
|
|
137
|
+
isUpgradedIOS?: boolean;
|
|
138
|
+
ownershipTypeIOS?: string;
|
|
139
|
+
reasonIOS?: string;
|
|
140
|
+
reasonStringRepresentationIOS?: string;
|
|
141
|
+
transactionReasonIOS?: 'PURCHASE' | 'RENEWAL' | string;
|
|
142
|
+
revocationDateIOS?: number;
|
|
143
|
+
revocationReasonIOS?: string;
|
|
144
|
+
offerIOS?: {
|
|
135
145
|
id: string;
|
|
136
146
|
type: string;
|
|
137
147
|
paymentMode: string;
|
|
138
148
|
};
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
149
|
+
priceIOS?: number;
|
|
150
|
+
currencyIOS?: string;
|
|
151
|
+
/**
|
|
152
|
+
* @deprecated Use `purchaseToken` instead. This field will be removed in a future version.
|
|
153
|
+
* iOS 15+ JWS representation is now available through the `purchaseToken` field.
|
|
154
|
+
*/
|
|
155
|
+
jwsRepresentationIOS?: string;
|
|
142
156
|
};
|
|
143
157
|
|
|
144
158
|
export type AppTransactionIOS = {
|
|
145
|
-
|
|
159
|
+
appTransactionId?: string; // Only available in iOS 18.4+
|
|
146
160
|
originalPlatform?: string; // Only available in iOS 18.4+
|
|
147
|
-
|
|
161
|
+
bundleId: string;
|
|
148
162
|
appVersion: string;
|
|
149
163
|
originalAppVersion: string;
|
|
150
164
|
originalPurchaseDate: number;
|
|
@@ -152,7 +166,7 @@ export type AppTransactionIOS = {
|
|
|
152
166
|
deviceVerificationNonce: string;
|
|
153
167
|
environment: string;
|
|
154
168
|
signedDate: number;
|
|
155
|
-
|
|
156
|
-
|
|
169
|
+
appId?: number;
|
|
170
|
+
appVersionId?: number;
|
|
157
171
|
preorderDate?: number;
|
|
158
172
|
};
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
getActiveSubscriptions,
|
|
20
20
|
hasActiveSubscriptions,
|
|
21
21
|
type ActiveSubscription,
|
|
22
|
-
} from '
|
|
22
|
+
} from '.';
|
|
23
23
|
import {
|
|
24
24
|
syncIOS,
|
|
25
25
|
getPromotedProductIOS,
|
|
@@ -158,7 +158,7 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
158
158
|
const subscriptionsRef = useRef<{
|
|
159
159
|
purchaseUpdate?: EventSubscription;
|
|
160
160
|
purchaseError?: EventSubscription;
|
|
161
|
-
|
|
161
|
+
promotedProductsIOS?: EventSubscription;
|
|
162
162
|
promotedProductIOS?: EventSubscription;
|
|
163
163
|
}>({});
|
|
164
164
|
|
|
@@ -260,7 +260,8 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
260
260
|
return result;
|
|
261
261
|
} catch (error) {
|
|
262
262
|
console.error('Error getting active subscriptions:', error);
|
|
263
|
-
|
|
263
|
+
// Don't clear existing activeSubscriptions on error - preserve current state
|
|
264
|
+
// This prevents the UI from showing empty state when there are temporary network issues
|
|
264
265
|
return [];
|
|
265
266
|
}
|
|
266
267
|
},
|
|
@@ -385,7 +386,7 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
385
386
|
setCurrentPurchaseError(undefined);
|
|
386
387
|
setCurrentPurchase(purchase);
|
|
387
388
|
|
|
388
|
-
if ('
|
|
389
|
+
if ('expirationDateIOS' in purchase) {
|
|
389
390
|
await refreshSubscriptionStatus(purchase.id);
|
|
390
391
|
}
|
|
391
392
|
|
|
@@ -408,7 +409,7 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
408
409
|
|
|
409
410
|
if (Platform.OS === 'ios') {
|
|
410
411
|
// iOS promoted products listener
|
|
411
|
-
subscriptionsRef.current.
|
|
412
|
+
subscriptionsRef.current.promotedProductsIOS =
|
|
412
413
|
promotedProductListenerIOS((product: Product) => {
|
|
413
414
|
setPromotedProductIOS(product);
|
|
414
415
|
|
|
@@ -427,7 +428,7 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
427
428
|
return () => {
|
|
428
429
|
currentSubscriptions.purchaseUpdate?.remove();
|
|
429
430
|
currentSubscriptions.purchaseError?.remove();
|
|
430
|
-
currentSubscriptions.
|
|
431
|
+
currentSubscriptions.promotedProductsIOS?.remove();
|
|
431
432
|
currentSubscriptions.promotedProductIOS?.remove();
|
|
432
433
|
endConnection();
|
|
433
434
|
setConnected(false);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoIapIos.types.js","sourceRoot":"","sources":["../../src/types/ExpoIapIos.types.ts"],"names":[],"mappings":"","sourcesContent":["import {PurchaseBase, ProductBase} from '../ExpoIap.types';\n\ntype SubscriptionIosPeriod = 'DAY' | 'WEEK' | 'MONTH' | 'YEAR' | '';\ntype PaymentMode = '' | 'FREETRIAL' | 'PAYASYOUGO' | 'PAYUPFRONT';\n\ntype SubscriptionOffer = {\n displayPrice: string;\n id: string;\n paymentMode: PaymentMode;\n period: {\n unit: SubscriptionIosPeriod;\n value: number;\n };\n periodCount: number;\n price: number;\n type: 'introductory' | 'promotional';\n};\n\ntype SubscriptionInfo = {\n introductoryOffer?: SubscriptionOffer;\n promotionalOffers?: SubscriptionOffer[];\n subscriptionGroupID: string;\n subscriptionPeriod: {\n unit: SubscriptionIosPeriod;\n value: number;\n };\n};\n\nexport type ProductIos = ProductBase & {\n displayName: string;\n isFamilyShareable: boolean;\n jsonRepresentation: string;\n subscription?: SubscriptionInfo;\n introductoryPriceNumberOfPeriodsIOS?: string;\n introductoryPriceSubscriptionPeriodIOS?: SubscriptionIosPeriod;\n};\n\nexport type Discount = {\n identifier: string;\n type: string;\n numberOfPeriods: string;\n price: string;\n localizedPrice: string;\n paymentMode: PaymentMode;\n subscriptionPeriod: string;\n};\n\nexport type SubscriptionProductIos = ProductIos & {\n discounts?: Discount[];\n introductoryPrice?: string;\n introductoryPriceAsAmountIOS?: string;\n introductoryPricePaymentModeIOS?: PaymentMode;\n introductoryPriceNumberOfPeriodsIOS?: string;\n introductoryPriceSubscriptionPeriodIOS?: SubscriptionIosPeriod;\n subscriptionPeriodNumberIOS?: string;\n subscriptionPeriodUnitIOS?: SubscriptionIosPeriod;\n};\n\nexport type PaymentDiscount = {\n /**\n * A string used to uniquely identify a discount offer for a product.\n */\n identifier: string;\n /**\n * A string that identifies the key used to generate the signature.\n */\n keyIdentifier: string;\n /**\n * A universally unique ID (UUID) value that you define.\n */\n nonce: string;\n /**\n * A UTF-8 string representing the properties of a specific discount offer, cryptographically signed.\n */\n signature: string;\n /**\n * The date and time of the signature's creation in milliseconds, formatted in Unix epoch time.\n */\n timestamp: number;\n};\n\nexport type RequestPurchaseIosProps = {\n sku: string;\n andDangerouslyFinishTransactionAutomaticallyIOS?: boolean;\n /**\n * UUID representing user account\n */\n appAccountToken?: string;\n quantity?: number;\n withOffer?: PaymentDiscount;\n};\n\nexport type RequestSubscriptionIosProps = RequestPurchaseIosProps;\n\ntype SubscriptionStatus =\n | 'expired'\n | 'inBillingRetryPeriod'\n | 'inGracePeriod'\n | 'revoked'\n | 'subscribed';\n\ntype RenewalInfo = {\n jsonRepresentation?: string;\n willAutoRenew: boolean;\n autoRenewPreference?: string;\n};\n\nexport type ProductStatusIos = {\n state: SubscriptionStatus;\n renewalInfo?: RenewalInfo;\n};\n\nexport type ProductPurchaseIos = PurchaseBase & {\n // iOS basic fields\n quantityIos?: number;\n originalTransactionDateIos?: number;\n originalTransactionIdentifierIos?: string;\n appAccountToken?: string;\n // iOS additional fields from StoreKit 2\n expirationDateIos?: number;\n webOrderLineItemIdIos?: number;\n environmentIos?: string;\n storefrontCountryCodeIos?: string;\n appBundleIdIos?: string;\n productTypeIos?: string;\n subscriptionGroupIdIos?: string;\n isUpgradedIos?: boolean;\n ownershipTypeIos?: string;\n reasonIos?: string;\n reasonStringRepresentationIos?: string;\n transactionReasonIos?: 'PURCHASE' | 'RENEWAL' | string;\n revocationDateIos?: number;\n revocationReasonIos?: string;\n offerIos?: {\n id: string;\n type: string;\n paymentMode: string;\n };\n priceIos?: number;\n currencyIos?: string;\n jwsRepresentationIos?: string;\n};\n\nexport type AppTransactionIOS = {\n appTransactionID?: string; // Only available in iOS 18.4+\n originalPlatform?: string; // Only available in iOS 18.4+\n bundleID: string;\n appVersion: string;\n originalAppVersion: string;\n originalPurchaseDate: number;\n deviceVerification: string;\n deviceVerificationNonce: string;\n environment: string;\n signedDate: number;\n appID?: number;\n appVersionID?: number;\n preorderDate?: number;\n};\n"]}
|
package/build/useIap.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useIap.js","sourceRoot":"","sources":["../src/useIap.ts"],"names":[],"mappings":"AAAA,wBAAwB;AACxB,OAAO,EAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAC,MAAM,OAAO,CAAC;AAC/D,OAAO,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAC;AAGtC,mBAAmB;AACnB,OAAO,EACL,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,IAAI,yBAAyB,EAC9C,eAAe,IAAI,uBAAuB,EAC1C,eAAe,EACf,eAAe,IAAI,uBAAuB,EAC1C,sBAAsB,EACtB,sBAAsB,GAEvB,MAAM,IAAI,CAAC;AACZ,OAAO,EACL,OAAO,EACP,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAoFvB,MAAM,UAAU,MAAM,CAAC,OAAuB;IAC5C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC3D,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAY,EAAE,CAAC,CAAC;IACxD,MAAM,CAAC,mBAAmB,CAAC,GAAG,QAAQ,CAAoB,EAAE,CAAC,CAAC;IAC9D,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAwB,EAAE,CAAC,CAAC;IAC9E,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CACxD,EAAE,CACH,CAAC;IACF,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAAG,QAAQ,CAE1D,EAAE,CAAC,CAAC;IACN,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,EAAmB,CAAC;IAC1E,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAAG,QAAQ,EAAW,CAAC;IACxE,MAAM,CAAC,oBAAoB,EAAE,uBAAuB,CAAC,GACnD,QAAQ,EAAiB,CAAC;IAC5B,MAAM,CAAC,oBAAoB,CAAC,GAAG,QAAQ,EAAU,CAAC;IAClD,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAE5D,EAAE,CAAC,CAAC;IAEN,MAAM,UAAU,GAAG,MAAM,CAA4B,OAAO,CAAC,CAAC;IAE9D,0DAA0D;IAC1D,MAAM,uBAAuB,GAAG,WAAW,CACzC,CACE,aAAkB,EAClB,QAAa,EACb,MAA2B,EACtB,EAAE;QACP,MAAM,MAAM,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC;QAClC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC3B,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAC7B,CAAC,YAAY,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,CAC3D,CAAC;YACF,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC,EACD,EAAE,CACH,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAC/B,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,MAAM,gBAAgB,GAAG,MAAM,CAK5B,EAAE,CAAC,CAAC;IAEP,MAAM,qBAAqB,GAAG,MAAM,CAAwB,EAAE,CAAC,CAAC;IAEhE,SAAS,CAAC,GAAG,EAAE;QACb,qBAAqB,CAAC,OAAO,GAAG,aAAa,CAAC;IAChD,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,MAAM,oBAAoB,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5C,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,yBAAyB,GAAG,WAAW,CAAC,GAAG,EAAE;QACjD,uBAAuB,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,mBAAmB,GAAG,WAAW,CACrC,KAAK,EAAE,IAAc,EAAiB,EAAE;QACtC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAC,CAAC,CAAC;YAC5D,WAAW,CAAC,CAAC,YAAY,EAAE,EAAE,CAC3B,uBAAuB,CACrB,YAAY,EACZ,MAAmB,EACnB,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CACxB,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QACnD,CAAC;IACH,CAAC,EACD,CAAC,uBAAuB,CAAC,CAC1B,CAAC;IAEF,MAAM,wBAAwB,GAAG,WAAW,CAC1C,KAAK,EAAE,IAAc,EAAiB,EAAE;QACtC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;YAC3D,gBAAgB,CAAC,CAAC,iBAAiB,EAAE,EAAE,CACrC,uBAAuB,CACrB,iBAAiB,EACjB,MAA+B,EAC/B,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,CAClC,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,EACD,CAAC,uBAAuB,CAAC,CAC1B,CAAC;IAEF,MAAM,uBAAuB,GAAG,WAAW,CACzC,KAAK,EAAE,MAGN,EAAiB,EAAE;QAClB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;YAC7C,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC3B,gBAAgB,CAAC,CAAC,iBAAiB,EAAE,EAAE,CACrC,uBAAuB,CACrB,iBAAiB,EACjB,MAA+B,EAC/B,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,CAClC,CACF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,CAAC,YAAY,EAAE,EAAE,CAC3B,uBAAuB,CACrB,YAAY,EACZ,MAAmB,EACnB,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CACxB,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;QACnD,CAAC;IACH,CAAC,EACD,CAAC,uBAAuB,CAAC,CAC1B,CAAC;IAEF,MAAM,6BAA6B,GAAG,WAAW,CAAC,KAAK,IAAmB,EAAE;QAC1E,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,qBAAqB,EAAE,CAAC;YAC7C,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,8BAA8B,GAAG,WAAW,CAChD,KAAK,EAAE,eAA0B,EAAiC,EAAE;QAClE,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC,eAAe,CAAC,CAAC;YAC7D,sBAAsB,CAAC,MAAM,CAAC,CAAC;YAC/B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;YAC5D,sBAAsB,CAAC,EAAE,CAAC,CAAC;YAC3B,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,EACD,EAAE,CACH,CAAC;IAEF,MAAM,8BAA8B,GAAG,WAAW,CAChD,KAAK,EAAE,eAA0B,EAAoB,EAAE;QACrD,IAAI,CAAC;YACH,OAAO,MAAM,sBAAsB,CAAC,eAAe,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;YAC7D,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC,EACD,EAAE,CACH,CAAC;IAEF,MAAM,4BAA4B,GAAG,WAAW,CAAC,KAAK,IAAmB,EAAE;QACzE,oBAAoB,CAAC,MAAM,oBAAoB,EAAE,CAAC,CAAC;IACrD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,iBAAiB,GAAG,WAAW,CACnC,KAAK,EAAE,EACL,QAAQ,EACR,YAAY,GAIb,EAAqC,EAAE;QACtC,IAAI,CAAC;YACH,OAAO,MAAM,yBAAyB,CAAC;gBACrC,QAAQ;gBACR,YAAY;aACb,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,IAAI,QAAQ,CAAC,EAAE,KAAK,eAAe,EAAE,EAAE,EAAE,CAAC;gBACxC,oBAAoB,EAAE,CAAC;YACzB,CAAC;YACD,IAAI,QAAQ,CAAC,EAAE,KAAK,oBAAoB,EAAE,SAAS,EAAE,CAAC;gBACpD,yBAAyB,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC,EACD;QACE,eAAe,EAAE,EAAE;QACnB,oBAAoB,EAAE,SAAS;QAC/B,oBAAoB;QACpB,yBAAyB;KAC1B,CACF,CAAC;IAEF,MAAM,wBAAwB,GAAG,WAAW,CAC1C,KAAK,EAAE,UAAmD,EAAE,EAAE;QAC5D,oBAAoB,EAAE,CAAC;QACvB,yBAAyB,EAAE,CAAC;QAE5B,IAAI,CAAC;YACH,OAAO,MAAM,uBAAuB,CAAC,UAAU,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,EACD,CAAC,oBAAoB,EAAE,yBAAyB,CAAC,CAClD,CAAC;IAEF,MAAM,yBAAyB,GAAG,WAAW,CAC3C,KAAK,EAAE,SAAiB,EAAE,EAAE;QAC1B,IAAI,CAAC;YACH,IAAI,qBAAqB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,SAAS,CAAC,EAAE,CAAC;gBACtE,MAAM,wBAAwB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;gBAC5C,MAAM,6BAA6B,EAAE,CAAC;YACxC,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;QAChE,CAAC;IACH,CAAC,EACD,CAAC,6BAA6B,EAAE,wBAAwB,CAAC,CAC1D,CAAC;IAEF,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,IAAmB,EAAE;QAC7D,IAAI,CAAC;YACH,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;gBAC1B,MAAM,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;oBAC9B,IAAI,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC;wBACpC,UAAU,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;oBACxC,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,IAAI,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;oBACpD,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC;YACD,MAAM,6BAA6B,EAAE,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;QACtD,CAAC;IACH,CAAC,EAAE,CAAC,6BAA6B,CAAC,CAAC,CAAC;IAEpC,MAAM,eAAe,GAAG,WAAW,CACjC,KAAK,EACH,GAAW,EACX,cAKC,EACD,EAAE;QACF,OAAO,uBAAuB,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IACtD,CAAC,EACD,EAAE,CACH,CAAC;IAEF,MAAM,wBAAwB,GAAG,WAAW,CAAC,KAAK,IAAmB,EAAE;QACrE,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;QACtC,YAAY,CAAC,MAAM,CAAC,CAAC;QAErB,IAAI,MAAM,EAAE,CAAC;YACX,gBAAgB,CAAC,OAAO,CAAC,cAAc,GAAG,uBAAuB,CAC/D,KAAK,EAAE,QAAyC,EAAE,EAAE;gBAClD,uBAAuB,CAAC,SAAS,CAAC,CAAC;gBACnC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;gBAE7B,IAAI,mBAAmB,IAAI,QAAQ,EAAE,CAAC;oBACpC,MAAM,yBAAyB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC/C,CAAC;gBAED,IAAI,UAAU,CAAC,OAAO,EAAE,iBAAiB,EAAE,CAAC;oBAC1C,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;gBACjD,CAAC;YACH,CAAC,CACF,CAAC;YAEF,gBAAgB,CAAC,OAAO,CAAC,aAAa,GAAG,qBAAqB,CAC5D,CAAC,KAAoB,EAAE,EAAE;gBACvB,kBAAkB,CAAC,SAAS,CAAC,CAAC;gBAC9B,uBAAuB,CAAC,KAAK,CAAC,CAAC;gBAE/B,IAAI,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC;oBACxC,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC,CACF,CAAC;YAEF,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;gBAC1B,iCAAiC;gBACjC,gBAAgB,CAAC,OAAO,CAAC,mBAAmB;oBAC1C,0BAA0B,CAAC,CAAC,OAAgB,EAAE,EAAE;wBAC9C,qBAAqB,CAAC,OAAO,CAAC,CAAC;wBAE/B,IAAI,UAAU,CAAC,OAAO,EAAE,oBAAoB,EAAE,CAAC;4BAC7C,UAAU,CAAC,OAAO,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;wBACnD,CAAC;oBACH,CAAC,CAAC,CAAC;YACP,CAAC;QACH,CAAC;IACH,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,CAAC;IAEhC,SAAS,CAAC,GAAG,EAAE;QACb,wBAAwB,EAAE,CAAC;QAC3B,MAAM,oBAAoB,GAAG,gBAAgB,CAAC,OAAO,CAAC;QAEtD,OAAO,GAAG,EAAE;YACV,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,CAAC;YAC9C,oBAAoB,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;YAC7C,oBAAoB,CAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC;YACnD,oBAAoB,CAAC,kBAAkB,EAAE,MAAM,EAAE,CAAC;YAClD,aAAa,EAAE,CAAC;YAChB,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC;IAE/B,OAAO;QACL,SAAS;QACT,QAAQ;QACR,mBAAmB;QACnB,oBAAoB;QACpB,aAAa;QACb,iBAAiB;QACjB,iBAAiB;QACjB,kBAAkB;QAClB,eAAe;QACf,oBAAoB;QACpB,kBAAkB;QAClB,mBAAmB;QACnB,oBAAoB;QACpB,yBAAyB;QACzB,qBAAqB,EAAE,6BAA6B;QACpD,oBAAoB,EAAE,4BAA4B;QAClD,eAAe,EAAE,uBAAuB;QACxC,eAAe,EAAE,wBAAwB;QACzC,eAAe;QACf,gBAAgB;QAChB,WAAW,EAAE,mBAAmB;QAChC,gBAAgB,EAAE,wBAAwB;QAC1C,qBAAqB;QACrB,qBAAqB;QACrB,sBAAsB,EAAE,8BAA8B;QACtD,sBAAsB,EAAE,8BAA8B;KACvD,CAAC;AACJ,CAAC","sourcesContent":["// External dependencies\nimport {useCallback, useEffect, useState, useRef} from 'react';\nimport {Platform} from 'react-native';\nimport {EventSubscription} from 'expo-modules-core';\n\n// Internal modules\nimport {\n endConnection,\n initConnection,\n purchaseErrorListener,\n purchaseUpdatedListener,\n promotedProductListenerIOS,\n getAvailablePurchases,\n getPurchaseHistories,\n finishTransaction as finishTransactionInternal,\n requestPurchase as requestPurchaseInternal,\n requestProducts,\n validateReceipt as validateReceiptInternal,\n getActiveSubscriptions,\n hasActiveSubscriptions,\n type ActiveSubscription,\n} from './';\nimport {\n syncIOS,\n getPromotedProductIOS,\n buyPromotedProductIOS,\n} from './modules/ios';\n\n// Types\nimport {\n Product,\n ProductPurchase,\n Purchase,\n PurchaseError,\n PurchaseResult,\n SubscriptionProduct,\n SubscriptionPurchase,\n RequestPurchaseProps,\n RequestSubscriptionProps,\n} from './ExpoIap.types';\n\ntype UseIap = {\n connected: boolean;\n products: Product[];\n promotedProductsIOS: ProductPurchase[];\n promotedProductIdIOS?: string;\n subscriptions: SubscriptionProduct[];\n purchaseHistories: ProductPurchase[];\n availablePurchases: ProductPurchase[];\n currentPurchase?: ProductPurchase;\n currentPurchaseError?: PurchaseError;\n promotedProductIOS?: Product;\n activeSubscriptions: ActiveSubscription[];\n clearCurrentPurchase: () => void;\n clearCurrentPurchaseError: () => void;\n finishTransaction: ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }) => Promise<PurchaseResult | boolean>;\n getAvailablePurchases: (skus: string[]) => Promise<void>;\n getPurchaseHistories: (skus: string[]) => Promise<void>;\n requestProducts: (params: {\n skus: string[];\n type?: 'inapp' | 'subs';\n }) => Promise<void>;\n /**\n * @deprecated Use requestProducts({ skus, type: 'inapp' }) instead. This method will be removed in version 3.0.0.\n * Note: This method internally uses requestProducts, so no deprecation warning is shown.\n */\n getProducts: (skus: string[]) => Promise<void>;\n /**\n * @deprecated Use requestProducts({ skus, type: 'subs' }) instead. This method will be removed in version 3.0.0.\n * Note: This method internally uses requestProducts, so no deprecation warning is shown.\n */\n getSubscriptions: (skus: string[]) => Promise<void>;\n requestPurchase: (params: {\n request: RequestPurchaseProps | RequestSubscriptionProps;\n type?: 'inapp' | 'subs';\n }) => Promise<any>;\n validateReceipt: (\n sku: string,\n androidOptions?: {\n packageName: string;\n productToken: string;\n accessToken: string;\n isSub?: boolean;\n },\n ) => Promise<any>;\n restorePurchases: () => Promise<void>; // 구매 복원 함수 추가\n getPromotedProductIOS: () => Promise<any | null>;\n buyPromotedProductIOS: () => Promise<void>;\n getActiveSubscriptions: (\n subscriptionIds?: string[],\n ) => Promise<ActiveSubscription[]>;\n hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise<boolean>;\n};\n\nexport interface UseIAPOptions {\n onPurchaseSuccess?: (\n purchase: ProductPurchase | SubscriptionPurchase,\n ) => void;\n onPurchaseError?: (error: PurchaseError) => void;\n onSyncError?: (error: Error) => void;\n shouldAutoSyncPurchases?: boolean; // New option to control auto-syncing\n onPromotedProductIOS?: (product: Product) => void;\n}\n\nexport function useIAP(options?: UseIAPOptions): UseIap {\n const [connected, setConnected] = useState<boolean>(false);\n const [products, setProducts] = useState<Product[]>([]);\n const [promotedProductsIOS] = useState<ProductPurchase[]>([]);\n const [subscriptions, setSubscriptions] = useState<SubscriptionProduct[]>([]);\n const [purchaseHistories, setPurchaseHistories] = useState<ProductPurchase[]>(\n [],\n );\n const [availablePurchases, setAvailablePurchases] = useState<\n ProductPurchase[]\n >([]);\n const [currentPurchase, setCurrentPurchase] = useState<ProductPurchase>();\n const [promotedProductIOS, setPromotedProductIOS] = useState<Product>();\n const [currentPurchaseError, setCurrentPurchaseError] =\n useState<PurchaseError>();\n const [promotedProductIdIOS] = useState<string>();\n const [activeSubscriptions, setActiveSubscriptions] = useState<\n ActiveSubscription[]\n >([]);\n\n const optionsRef = useRef<UseIAPOptions | undefined>(options);\n\n // Helper function to merge arrays with duplicate checking\n const mergeWithDuplicateCheck = useCallback(\n <T>(\n existingItems: T[],\n newItems: T[],\n getKey: (item: T) => string,\n ): T[] => {\n const merged = [...existingItems];\n newItems.forEach((newItem) => {\n const isDuplicate = merged.some(\n (existingItem) => getKey(existingItem) === getKey(newItem),\n );\n if (!isDuplicate) {\n merged.push(newItem);\n }\n });\n return merged;\n },\n [],\n );\n\n useEffect(() => {\n optionsRef.current = options;\n }, [options]);\n\n const subscriptionsRef = useRef<{\n purchaseUpdate?: EventSubscription;\n purchaseError?: EventSubscription;\n promotedProductsIos?: EventSubscription;\n promotedProductIOS?: EventSubscription;\n }>({});\n\n const subscriptionsRefState = useRef<SubscriptionProduct[]>([]);\n\n useEffect(() => {\n subscriptionsRefState.current = subscriptions;\n }, [subscriptions]);\n\n const clearCurrentPurchase = useCallback(() => {\n setCurrentPurchase(undefined);\n }, []);\n\n const clearCurrentPurchaseError = useCallback(() => {\n setCurrentPurchaseError(undefined);\n }, []);\n\n const getProductsInternal = useCallback(\n async (skus: string[]): Promise<void> => {\n try {\n const result = await requestProducts({skus, type: 'inapp'});\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n result as Product[],\n (product) => product.id,\n ),\n );\n } catch (error) {\n console.error('Error fetching products:', error);\n }\n },\n [mergeWithDuplicateCheck],\n );\n\n const getSubscriptionsInternal = useCallback(\n async (skus: string[]): Promise<void> => {\n try {\n const result = await requestProducts({skus, type: 'subs'});\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n result as SubscriptionProduct[],\n (subscription) => subscription.id,\n ),\n );\n } catch (error) {\n console.error('Error fetching subscriptions:', error);\n }\n },\n [mergeWithDuplicateCheck],\n );\n\n const requestProductsInternal = useCallback(\n async (params: {\n skus: string[];\n type?: 'inapp' | 'subs';\n }): Promise<void> => {\n try {\n const result = await requestProducts(params);\n if (params.type === 'subs') {\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n result as SubscriptionProduct[],\n (subscription) => subscription.id,\n ),\n );\n } else {\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n result as Product[],\n (product) => product.id,\n ),\n );\n }\n } catch (error) {\n console.error('Error fetching products:', error);\n }\n },\n [mergeWithDuplicateCheck],\n );\n\n const getAvailablePurchasesInternal = useCallback(async (): Promise<void> => {\n try {\n const result = await getAvailablePurchases();\n setAvailablePurchases(result);\n } catch (error) {\n console.error('Error fetching available purchases:', error);\n }\n }, []);\n\n const getActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<ActiveSubscription[]> => {\n try {\n const result = await getActiveSubscriptions(subscriptionIds);\n setActiveSubscriptions(result);\n return result;\n } catch (error) {\n console.error('Error getting active subscriptions:', error);\n setActiveSubscriptions([]);\n return [];\n }\n },\n [],\n );\n\n const hasActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<boolean> => {\n try {\n return await hasActiveSubscriptions(subscriptionIds);\n } catch (error) {\n console.error('Error checking active subscriptions:', error);\n return false;\n }\n },\n [],\n );\n\n const getPurchaseHistoriesInternal = useCallback(async (): Promise<void> => {\n setPurchaseHistories(await getPurchaseHistories());\n }, []);\n\n const finishTransaction = useCallback(\n async ({\n purchase,\n isConsumable,\n }: {\n purchase: ProductPurchase;\n isConsumable?: boolean;\n }): Promise<PurchaseResult | boolean> => {\n try {\n return await finishTransactionInternal({\n purchase,\n isConsumable,\n });\n } catch (err) {\n throw err;\n } finally {\n if (purchase.id === currentPurchase?.id) {\n clearCurrentPurchase();\n }\n if (purchase.id === currentPurchaseError?.productId) {\n clearCurrentPurchaseError();\n }\n }\n },\n [\n currentPurchase?.id,\n currentPurchaseError?.productId,\n clearCurrentPurchase,\n clearCurrentPurchaseError,\n ],\n );\n\n const requestPurchaseWithReset = useCallback(\n async (requestObj: {request: any; type?: 'inapp' | 'subs'}) => {\n clearCurrentPurchase();\n clearCurrentPurchaseError();\n\n try {\n return await requestPurchaseInternal(requestObj);\n } catch (error) {\n throw error;\n }\n },\n [clearCurrentPurchase, clearCurrentPurchaseError],\n );\n\n const refreshSubscriptionStatus = useCallback(\n async (productId: string) => {\n try {\n if (subscriptionsRefState.current.some((sub) => sub.id === productId)) {\n await getSubscriptionsInternal([productId]);\n await getAvailablePurchasesInternal();\n }\n } catch (error) {\n console.warn('Failed to refresh subscription status:', error);\n }\n },\n [getAvailablePurchasesInternal, getSubscriptionsInternal],\n );\n\n const restorePurchases = useCallback(async (): Promise<void> => {\n try {\n if (Platform.OS === 'ios') {\n await syncIOS().catch((error) => {\n if (optionsRef.current?.onSyncError) {\n optionsRef.current.onSyncError(error);\n } else {\n console.warn('Error restoring purchases:', error);\n }\n });\n }\n await getAvailablePurchasesInternal();\n } catch (error) {\n console.warn('Failed to restore purchases:', error);\n }\n }, [getAvailablePurchasesInternal]);\n\n const validateReceipt = useCallback(\n async (\n sku: string,\n androidOptions?: {\n packageName: string;\n productToken: string;\n accessToken: string;\n isSub?: boolean;\n },\n ) => {\n return validateReceiptInternal(sku, androidOptions);\n },\n [],\n );\n\n const initIapWithSubscriptions = useCallback(async (): Promise<void> => {\n const result = await initConnection();\n setConnected(result);\n\n if (result) {\n subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(\n async (purchase: Purchase | SubscriptionPurchase) => {\n setCurrentPurchaseError(undefined);\n setCurrentPurchase(purchase);\n\n if ('expirationDateIos' in purchase) {\n await refreshSubscriptionStatus(purchase.id);\n }\n\n if (optionsRef.current?.onPurchaseSuccess) {\n optionsRef.current.onPurchaseSuccess(purchase);\n }\n },\n );\n\n subscriptionsRef.current.purchaseError = purchaseErrorListener(\n (error: PurchaseError) => {\n setCurrentPurchase(undefined);\n setCurrentPurchaseError(error);\n\n if (optionsRef.current?.onPurchaseError) {\n optionsRef.current.onPurchaseError(error);\n }\n },\n );\n\n if (Platform.OS === 'ios') {\n // iOS promoted products listener\n subscriptionsRef.current.promotedProductsIos =\n promotedProductListenerIOS((product: Product) => {\n setPromotedProductIOS(product);\n\n if (optionsRef.current?.onPromotedProductIOS) {\n optionsRef.current.onPromotedProductIOS(product);\n }\n });\n }\n }\n }, [refreshSubscriptionStatus]);\n\n useEffect(() => {\n initIapWithSubscriptions();\n const currentSubscriptions = subscriptionsRef.current;\n\n return () => {\n currentSubscriptions.purchaseUpdate?.remove();\n currentSubscriptions.purchaseError?.remove();\n currentSubscriptions.promotedProductsIos?.remove();\n currentSubscriptions.promotedProductIOS?.remove();\n endConnection();\n setConnected(false);\n };\n }, [initIapWithSubscriptions]);\n\n return {\n connected,\n products,\n promotedProductsIOS,\n promotedProductIdIOS,\n subscriptions,\n purchaseHistories,\n finishTransaction,\n availablePurchases,\n currentPurchase,\n currentPurchaseError,\n promotedProductIOS,\n activeSubscriptions,\n clearCurrentPurchase,\n clearCurrentPurchaseError,\n getAvailablePurchases: getAvailablePurchasesInternal,\n getPurchaseHistories: getPurchaseHistoriesInternal,\n requestProducts: requestProductsInternal,\n requestPurchase: requestPurchaseWithReset,\n validateReceipt,\n restorePurchases,\n getProducts: getProductsInternal,\n getSubscriptions: getSubscriptionsInternal,\n getPromotedProductIOS,\n buyPromotedProductIOS,\n getActiveSubscriptions: getActiveSubscriptionsInternal,\n hasActiveSubscriptions: hasActiveSubscriptionsInternal,\n };\n}\n"]}
|