@idealyst/payments 1.2.108 → 1.2.109
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/README.md +54 -56
- package/package.json +11 -11
- package/src/constants.ts +3 -4
- package/src/errors.ts +53 -21
- package/src/index.native.ts +30 -18
- package/src/index.ts +30 -18
- package/src/index.web.ts +30 -18
- package/src/payments.native.ts +249 -192
- package/src/payments.web.ts +47 -68
- package/src/types.ts +136 -122
- package/src/usePayments.ts +149 -85
package/src/usePayments.ts
CHANGED
|
@@ -1,90 +1,149 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
2
2
|
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
UseIAPOptions,
|
|
4
|
+
UseIAPResult,
|
|
5
|
+
IAPProviderStatus,
|
|
6
|
+
IAPConfig,
|
|
7
|
+
IAPError,
|
|
8
|
+
IAPProduct,
|
|
9
|
+
IAPSubscription,
|
|
10
|
+
IAPPurchase,
|
|
11
11
|
} from './types';
|
|
12
|
-
import { INITIAL_PROVIDER_STATUS } from './constants';
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
|
-
* Factory that creates a
|
|
14
|
+
* Factory that creates a useIAP hook bound to platform-specific functions.
|
|
16
15
|
* Each platform entry point calls this with the correct implementations.
|
|
17
16
|
*/
|
|
18
|
-
export function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
export function createUseIAPHook(fns: {
|
|
18
|
+
initializeIAP: (config?: IAPConfig) => Promise<void>;
|
|
19
|
+
getProducts: (skus: string[]) => Promise<IAPProduct[]>;
|
|
20
|
+
getSubscriptions: (skus: string[]) => Promise<IAPSubscription[]>;
|
|
21
|
+
purchaseProduct: (sku: string) => Promise<IAPPurchase>;
|
|
22
|
+
purchaseSubscription: (sku: string, offerToken?: string) => Promise<IAPPurchase>;
|
|
23
|
+
finishTransaction: (purchase: IAPPurchase, isConsumable?: boolean) => Promise<void>;
|
|
24
|
+
restorePurchases: () => Promise<IAPPurchase[]>;
|
|
25
|
+
getIAPStatus: () => IAPProviderStatus;
|
|
26
|
+
endConnection: () => Promise<void>;
|
|
24
27
|
}) {
|
|
25
|
-
return function
|
|
26
|
-
|
|
27
|
-
): UsePaymentsResult {
|
|
28
|
-
const { config, autoCheckAvailability = true } = options;
|
|
28
|
+
return function useIAP(options: UseIAPOptions = {}): UseIAPResult {
|
|
29
|
+
const { config, productSkus, subscriptionSkus } = options;
|
|
29
30
|
|
|
30
|
-
const [
|
|
31
|
-
INITIAL_PROVIDER_STATUS,
|
|
32
|
-
);
|
|
31
|
+
const [isReady, setIsReady] = useState(false);
|
|
33
32
|
const [isProcessing, setIsProcessing] = useState(false);
|
|
34
|
-
const [error, setError] = useState<
|
|
33
|
+
const [error, setError] = useState<IAPError | null>(null);
|
|
34
|
+
const [products, setProducts] = useState<IAPProduct[]>([]);
|
|
35
|
+
const [subscriptions, setSubscriptions] = useState<IAPSubscription[]>([]);
|
|
36
|
+
const [currentPurchase, setCurrentPurchase] = useState<IAPPurchase | null>(null);
|
|
35
37
|
const initializedRef = useRef(false);
|
|
36
38
|
|
|
37
|
-
// Auto-initialize
|
|
39
|
+
// Auto-initialize and fetch products/subscriptions
|
|
38
40
|
useEffect(() => {
|
|
39
|
-
if (
|
|
41
|
+
if (initializedRef.current) return;
|
|
42
|
+
if (config === undefined && !productSkus && !subscriptionSkus) return;
|
|
40
43
|
initializedRef.current = true;
|
|
41
44
|
|
|
42
45
|
const init = async () => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
try {
|
|
47
|
+
await fns.initializeIAP(config);
|
|
48
|
+
const status = fns.getIAPStatus();
|
|
49
|
+
|
|
50
|
+
if (status.state === 'ready') {
|
|
51
|
+
setIsReady(true);
|
|
52
|
+
|
|
53
|
+
if (productSkus?.length) {
|
|
54
|
+
const prods = await fns.getProducts(productSkus);
|
|
55
|
+
setProducts(prods);
|
|
56
|
+
}
|
|
57
|
+
if (subscriptionSkus?.length) {
|
|
58
|
+
const subs = await fns.getSubscriptions(subscriptionSkus);
|
|
59
|
+
setSubscriptions(subs);
|
|
60
|
+
}
|
|
61
|
+
} else if (status.error) {
|
|
62
|
+
setError(status.error);
|
|
63
|
+
}
|
|
64
|
+
} catch (err) {
|
|
65
|
+
setError(err as IAPError);
|
|
51
66
|
}
|
|
52
67
|
};
|
|
53
68
|
init();
|
|
54
|
-
}, [config, autoCheckAvailability]);
|
|
55
69
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
return () => {
|
|
71
|
+
fns.endConnection();
|
|
72
|
+
};
|
|
73
|
+
}, [config, productSkus, subscriptionSkus]);
|
|
74
|
+
|
|
75
|
+
const initialize = useCallback(async (initConfig?: IAPConfig) => {
|
|
76
|
+
setError(null);
|
|
77
|
+
try {
|
|
78
|
+
await fns.initializeIAP(initConfig);
|
|
79
|
+
const status = fns.getIAPStatus();
|
|
80
|
+
setIsReady(status.state === 'ready');
|
|
81
|
+
if (status.error) setError(status.error);
|
|
82
|
+
} catch (err) {
|
|
83
|
+
setError(err as IAPError);
|
|
84
|
+
}
|
|
85
|
+
}, []);
|
|
71
86
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
87
|
+
const getProductsAction = useCallback(async (skus: string[]) => {
|
|
88
|
+
setIsProcessing(true);
|
|
89
|
+
setError(null);
|
|
90
|
+
try {
|
|
91
|
+
const result = await fns.getProducts(skus);
|
|
92
|
+
setProducts(result);
|
|
93
|
+
return result;
|
|
94
|
+
} catch (err) {
|
|
95
|
+
const iapError = err as IAPError;
|
|
96
|
+
setError(iapError);
|
|
97
|
+
throw iapError;
|
|
98
|
+
} finally {
|
|
99
|
+
setIsProcessing(false);
|
|
100
|
+
}
|
|
76
101
|
}, []);
|
|
77
102
|
|
|
78
|
-
const
|
|
79
|
-
|
|
103
|
+
const getSubscriptionsAction = useCallback(async (skus: string[]) => {
|
|
104
|
+
setIsProcessing(true);
|
|
105
|
+
setError(null);
|
|
106
|
+
try {
|
|
107
|
+
const result = await fns.getSubscriptions(skus);
|
|
108
|
+
setSubscriptions(result);
|
|
109
|
+
return result;
|
|
110
|
+
} catch (err) {
|
|
111
|
+
const iapError = err as IAPError;
|
|
112
|
+
setError(iapError);
|
|
113
|
+
throw iapError;
|
|
114
|
+
} finally {
|
|
115
|
+
setIsProcessing(false);
|
|
116
|
+
}
|
|
117
|
+
}, []);
|
|
118
|
+
|
|
119
|
+
const purchaseProductAction = useCallback(async (sku: string) => {
|
|
120
|
+
setIsProcessing(true);
|
|
121
|
+
setError(null);
|
|
122
|
+
try {
|
|
123
|
+
const purchase = await fns.purchaseProduct(sku);
|
|
124
|
+
setCurrentPurchase(purchase);
|
|
125
|
+
return purchase;
|
|
126
|
+
} catch (err) {
|
|
127
|
+
const iapError = err as IAPError;
|
|
128
|
+
setError(iapError);
|
|
129
|
+
throw iapError;
|
|
130
|
+
} finally {
|
|
131
|
+
setIsProcessing(false);
|
|
132
|
+
}
|
|
133
|
+
}, []);
|
|
134
|
+
|
|
135
|
+
const purchaseSubscriptionAction = useCallback(
|
|
136
|
+
async (sku: string, offerToken?: string) => {
|
|
80
137
|
setIsProcessing(true);
|
|
81
138
|
setError(null);
|
|
82
139
|
try {
|
|
83
|
-
|
|
140
|
+
const purchase = await fns.purchaseSubscription(sku, offerToken);
|
|
141
|
+
setCurrentPurchase(purchase);
|
|
142
|
+
return purchase;
|
|
84
143
|
} catch (err) {
|
|
85
|
-
const
|
|
86
|
-
setError(
|
|
87
|
-
throw
|
|
144
|
+
const iapError = err as IAPError;
|
|
145
|
+
setError(iapError);
|
|
146
|
+
throw iapError;
|
|
88
147
|
} finally {
|
|
89
148
|
setIsProcessing(false);
|
|
90
149
|
}
|
|
@@ -92,45 +151,50 @@ export function createUsePaymentsHook(fns: {
|
|
|
92
151
|
[],
|
|
93
152
|
);
|
|
94
153
|
|
|
95
|
-
const
|
|
96
|
-
async (
|
|
97
|
-
setIsProcessing(true);
|
|
98
|
-
setError(null);
|
|
154
|
+
const finishTransactionAction = useCallback(
|
|
155
|
+
async (purchase: IAPPurchase, isConsumable?: boolean) => {
|
|
99
156
|
try {
|
|
100
|
-
|
|
157
|
+
await fns.finishTransaction(purchase, isConsumable);
|
|
101
158
|
} catch (err) {
|
|
102
|
-
const
|
|
103
|
-
setError(
|
|
104
|
-
throw
|
|
105
|
-
} finally {
|
|
106
|
-
setIsProcessing(false);
|
|
159
|
+
const iapError = err as IAPError;
|
|
160
|
+
setError(iapError);
|
|
161
|
+
throw iapError;
|
|
107
162
|
}
|
|
108
163
|
},
|
|
109
164
|
[],
|
|
110
165
|
);
|
|
111
166
|
|
|
112
|
-
const
|
|
167
|
+
const restorePurchasesAction = useCallback(async () => {
|
|
168
|
+
setIsProcessing(true);
|
|
169
|
+
setError(null);
|
|
170
|
+
try {
|
|
171
|
+
return await fns.restorePurchases();
|
|
172
|
+
} catch (err) {
|
|
173
|
+
const iapError = err as IAPError;
|
|
174
|
+
setError(iapError);
|
|
175
|
+
throw iapError;
|
|
176
|
+
} finally {
|
|
177
|
+
setIsProcessing(false);
|
|
178
|
+
}
|
|
179
|
+
}, []);
|
|
113
180
|
|
|
114
|
-
const
|
|
181
|
+
const clearError = useCallback(() => setError(null), []);
|
|
115
182
|
|
|
116
183
|
return {
|
|
117
|
-
|
|
118
|
-
isReady: status.state === 'ready',
|
|
184
|
+
isReady,
|
|
119
185
|
isProcessing,
|
|
120
|
-
availablePaymentMethods,
|
|
121
|
-
isApplePayAvailable: availablePaymentMethods.some(
|
|
122
|
-
(m) => m.type === 'apple_pay' && m.isAvailable,
|
|
123
|
-
),
|
|
124
|
-
isGooglePayAvailable: availablePaymentMethods.some(
|
|
125
|
-
(m) => m.type === 'google_pay' && m.isAvailable,
|
|
126
|
-
),
|
|
127
|
-
isPaymentAvailable: status.isPaymentAvailable,
|
|
128
186
|
error,
|
|
187
|
+
products,
|
|
188
|
+
subscriptions,
|
|
189
|
+
currentPurchase,
|
|
129
190
|
|
|
130
191
|
initialize,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
192
|
+
getProducts: getProductsAction,
|
|
193
|
+
getSubscriptions: getSubscriptionsAction,
|
|
194
|
+
purchaseProduct: purchaseProductAction,
|
|
195
|
+
purchaseSubscription: purchaseSubscriptionAction,
|
|
196
|
+
finishTransaction: finishTransactionAction,
|
|
197
|
+
restorePurchases: restorePurchasesAction,
|
|
134
198
|
clearError,
|
|
135
199
|
};
|
|
136
200
|
};
|