@tagadapay/plugin-sdk 2.4.39 → 2.5.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.
Files changed (106) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +2 -0
  3. package/dist/react/hooks/useCheckout.js +19 -2
  4. package/dist/react/hooks/useCheckoutSession.d.ts +19 -0
  5. package/dist/react/hooks/useCheckoutSession.js +108 -0
  6. package/dist/react/hooks/useCheckoutToken.d.ts +17 -0
  7. package/dist/react/hooks/useCheckoutToken.js +80 -0
  8. package/dist/react/hooks/useOrderBump.js +92 -13
  9. package/dist/react/hooks/useOrderBumpV2.d.ts +17 -0
  10. package/dist/react/hooks/useOrderBumpV2.js +95 -0
  11. package/dist/react/hooks/useOrderBumpV3.d.ts +23 -0
  12. package/dist/react/hooks/useOrderBumpV3.js +109 -0
  13. package/dist/react/hooks/usePostPurchases.js +11 -5
  14. package/dist/react/index.d.ts +8 -0
  15. package/dist/react/index.js +4 -0
  16. package/dist/react/services/apiService.d.ts +1 -0
  17. package/dist/react/services/apiService.js +3 -0
  18. package/dist/v2/core/googleAutocomplete.d.ts +65 -0
  19. package/dist/v2/core/googleAutocomplete.js +94 -0
  20. package/dist/v2/core/index.d.ts +8 -0
  21. package/dist/v2/core/index.js +11 -0
  22. package/dist/v2/core/isoData.d.ts +50 -0
  23. package/dist/v2/core/isoData.js +103 -0
  24. package/dist/v2/core/resources/apiClient.d.ts +25 -0
  25. package/dist/v2/core/resources/apiClient.js +95 -0
  26. package/dist/v2/core/resources/checkout.d.ts +189 -0
  27. package/dist/v2/core/resources/checkout.js +119 -0
  28. package/dist/v2/core/resources/index.d.ts +13 -0
  29. package/dist/v2/core/resources/index.js +13 -0
  30. package/dist/v2/core/resources/offers.d.ts +98 -0
  31. package/dist/v2/core/resources/offers.js +115 -0
  32. package/dist/v2/core/resources/orders.d.ts +40 -0
  33. package/dist/v2/core/resources/orders.js +59 -0
  34. package/dist/v2/core/resources/payments.d.ts +140 -0
  35. package/dist/v2/core/resources/payments.js +126 -0
  36. package/dist/v2/core/resources/postPurchases.d.ts +182 -0
  37. package/dist/v2/core/resources/postPurchases.js +116 -0
  38. package/dist/v2/core/resources/products.d.ts +29 -0
  39. package/dist/v2/core/resources/products.js +49 -0
  40. package/dist/v2/core/resources/promotions.d.ts +45 -0
  41. package/dist/v2/core/resources/promotions.js +87 -0
  42. package/dist/v2/core/resources/threeds.d.ts +23 -0
  43. package/dist/v2/core/resources/threeds.js +15 -0
  44. package/dist/v2/core/utils/checkout.d.ts +24 -0
  45. package/dist/v2/core/utils/checkout.js +30 -0
  46. package/dist/v2/core/utils/currency.d.ts +28 -0
  47. package/dist/v2/core/utils/currency.js +272 -0
  48. package/dist/v2/core/utils/index.d.ts +12 -0
  49. package/dist/v2/core/utils/index.js +12 -0
  50. package/dist/v2/core/utils/order.d.ts +159 -0
  51. package/dist/v2/core/utils/order.js +42 -0
  52. package/dist/v2/core/utils/orderBump.d.ts +40 -0
  53. package/dist/v2/core/utils/orderBump.js +47 -0
  54. package/dist/v2/core/utils/pluginConfig.d.ts +43 -0
  55. package/dist/v2/core/utils/pluginConfig.js +155 -0
  56. package/dist/v2/core/utils/postPurchases.d.ts +32 -0
  57. package/dist/v2/core/utils/postPurchases.js +42 -0
  58. package/dist/v2/core/utils/products.d.ts +58 -0
  59. package/dist/v2/core/utils/products.js +64 -0
  60. package/dist/v2/core/utils/promotions.d.ts +24 -0
  61. package/dist/v2/core/utils/promotions.js +30 -0
  62. package/dist/v2/index.d.ts +19 -0
  63. package/dist/v2/index.js +15 -0
  64. package/dist/v2/react/components/DebugDrawer.d.ts +7 -0
  65. package/dist/v2/react/components/DebugDrawer.js +383 -0
  66. package/dist/v2/react/hooks/useApiQuery.d.ts +28 -0
  67. package/dist/v2/react/hooks/useApiQuery.js +84 -0
  68. package/dist/v2/react/hooks/useCheckoutQuery.d.ts +39 -0
  69. package/dist/v2/react/hooks/useCheckoutQuery.js +194 -0
  70. package/dist/v2/react/hooks/useCheckoutToken.d.ts +17 -0
  71. package/dist/v2/react/hooks/useCheckoutToken.js +65 -0
  72. package/dist/v2/react/hooks/useCurrency.d.ts +9 -0
  73. package/dist/v2/react/hooks/useCurrency.js +21 -0
  74. package/dist/v2/react/hooks/useGeoLocation.d.ts +138 -0
  75. package/dist/v2/react/hooks/useGeoLocation.js +123 -0
  76. package/dist/v2/react/hooks/useGoogleAutocomplete.d.ts +74 -0
  77. package/dist/v2/react/hooks/useGoogleAutocomplete.js +196 -0
  78. package/dist/v2/react/hooks/useISOData.d.ts +61 -0
  79. package/dist/v2/react/hooks/useISOData.js +175 -0
  80. package/dist/v2/react/hooks/useOffersQuery.d.ts +65 -0
  81. package/dist/v2/react/hooks/useOffersQuery.js +342 -0
  82. package/dist/v2/react/hooks/useOrderBumpQuery.d.ts +20 -0
  83. package/dist/v2/react/hooks/useOrderBumpQuery.js +92 -0
  84. package/dist/v2/react/hooks/useOrderQuery.d.ts +29 -0
  85. package/dist/v2/react/hooks/useOrderQuery.js +98 -0
  86. package/dist/v2/react/hooks/usePaymentPolling.d.ts +45 -0
  87. package/dist/v2/react/hooks/usePaymentPolling.js +140 -0
  88. package/dist/v2/react/hooks/usePaymentQuery.d.ts +19 -0
  89. package/dist/v2/react/hooks/usePaymentQuery.js +272 -0
  90. package/dist/v2/react/hooks/usePluginConfig.d.ts +16 -0
  91. package/dist/v2/react/hooks/usePluginConfig.js +35 -0
  92. package/dist/v2/react/hooks/usePostPurchasesQuery.d.ts +63 -0
  93. package/dist/v2/react/hooks/usePostPurchasesQuery.js +343 -0
  94. package/dist/v2/react/hooks/useProductsQuery.d.ts +31 -0
  95. package/dist/v2/react/hooks/useProductsQuery.js +102 -0
  96. package/dist/v2/react/hooks/usePromotionsQuery.d.ts +28 -0
  97. package/dist/v2/react/hooks/usePromotionsQuery.js +97 -0
  98. package/dist/v2/react/hooks/useThreeds.d.ts +36 -0
  99. package/dist/v2/react/hooks/useThreeds.js +150 -0
  100. package/dist/v2/react/hooks/useThreedsModal.d.ts +13 -0
  101. package/dist/v2/react/hooks/useThreedsModal.js +343 -0
  102. package/dist/v2/react/index.d.ts +38 -0
  103. package/dist/v2/react/index.js +27 -0
  104. package/dist/v2/react/providers/TagadaProvider.d.ts +63 -0
  105. package/dist/v2/react/providers/TagadaProvider.js +680 -0
  106. package/package.json +10 -3
@@ -0,0 +1,140 @@
1
+ import { useCallback, useRef, useEffect, useMemo } from 'react';
2
+ import { PaymentsResource } from '../../core/resources/payments';
3
+ import { getGlobalApiClient } from './useApiQuery';
4
+ export function usePaymentPolling() {
5
+ const pollIntervalRef = useRef(null);
6
+ const attemptsRef = useRef(0);
7
+ const isPollingRef = useRef(false);
8
+ const isMountedRef = useRef(true);
9
+ const currentPaymentIdRef = useRef(null);
10
+ // Create payments resource client
11
+ const paymentsResource = useMemo(() => {
12
+ try {
13
+ return new PaymentsResource(getGlobalApiClient());
14
+ }
15
+ catch (error) {
16
+ throw new Error('Failed to initialize payments resource: ' + (error instanceof Error ? error.message : 'Unknown error'));
17
+ }
18
+ }, []);
19
+ // Track mounted state and cleanup
20
+ useEffect(() => {
21
+ isMountedRef.current = true;
22
+ return () => {
23
+ isMountedRef.current = false;
24
+ stopPolling();
25
+ };
26
+ }, []);
27
+ const stopPolling = useCallback(() => {
28
+ if (pollIntervalRef.current) {
29
+ clearInterval(pollIntervalRef.current);
30
+ pollIntervalRef.current = null;
31
+ }
32
+ isPollingRef.current = false;
33
+ currentPaymentIdRef.current = null;
34
+ if (isMountedRef.current) {
35
+ // Component is still mounted
36
+ }
37
+ }, []);
38
+ const startPolling = useCallback((paymentId, options = {}) => {
39
+ if (!paymentId) {
40
+ return { stop: stopPolling, isPolling: () => false };
41
+ }
42
+ // Prevent multiple polling sessions for the same payment
43
+ if (currentPaymentIdRef.current === paymentId && isPollingRef.current) {
44
+ return { stop: stopPolling, isPolling: () => isPollingRef.current };
45
+ }
46
+ // Clean up any existing polling
47
+ stopPolling();
48
+ // Don't start polling if component is unmounted
49
+ if (!isMountedRef.current) {
50
+ return { stop: stopPolling, isPolling: () => false };
51
+ }
52
+ // Reset attempts counter and set current payment
53
+ attemptsRef.current = 0;
54
+ isPollingRef.current = true;
55
+ currentPaymentIdRef.current = paymentId;
56
+ const { onRequireAction, onSuccess, onFailure, maxAttempts = 20, pollInterval = 1500 } = options;
57
+ const checkPaymentStatus = async () => {
58
+ // Stop if component was unmounted or polling was stopped
59
+ if (!isMountedRef.current || !isPollingRef.current) {
60
+ return;
61
+ }
62
+ try {
63
+ attemptsRef.current++;
64
+ const payment = await paymentsResource.getPaymentStatus(paymentId);
65
+ // Check again after async operation
66
+ if (!isMountedRef.current || !isPollingRef.current) {
67
+ return;
68
+ }
69
+ // Type guard and validation
70
+ if (!payment?.id) {
71
+ return;
72
+ }
73
+ // Check if payment requires action
74
+ if (payment.requireAction !== 'none' && payment.requireActionData) {
75
+ stopPolling();
76
+ if (isMountedRef.current && onRequireAction) {
77
+ onRequireAction(payment, stopPolling);
78
+ }
79
+ return;
80
+ }
81
+ // Check for successful payment
82
+ if (payment.status === 'succeeded' ||
83
+ (payment.status === 'pending' && payment.subStatus === 'authorized')) {
84
+ stopPolling();
85
+ if (isMountedRef.current && onSuccess) {
86
+ onSuccess(payment);
87
+ }
88
+ return;
89
+ }
90
+ // Check for failed payment (non-succeeded and not pending)
91
+ if (payment.status !== 'succeeded' && payment.status !== 'pending') {
92
+ stopPolling();
93
+ if (isMountedRef.current && onFailure) {
94
+ onFailure(payment.status || 'Payment failed');
95
+ }
96
+ return;
97
+ }
98
+ // Stop after max attempts
99
+ if (attemptsRef.current >= maxAttempts) {
100
+ stopPolling();
101
+ if (isMountedRef.current && onFailure) {
102
+ onFailure('Payment verification timeout');
103
+ }
104
+ }
105
+ }
106
+ catch (_error) {
107
+ // Stop polling on repeated errors to prevent infinite loops
108
+ if (attemptsRef.current >= 3) {
109
+ stopPolling();
110
+ if (isMountedRef.current && onFailure) {
111
+ onFailure('Payment verification failed due to network errors');
112
+ }
113
+ }
114
+ // Continue polling for occasional errors
115
+ }
116
+ };
117
+ // Start polling immediately, but check if still mounted
118
+ if (isMountedRef.current && isPollingRef.current) {
119
+ void checkPaymentStatus();
120
+ pollIntervalRef.current = setInterval(() => {
121
+ if (isMountedRef.current && isPollingRef.current) {
122
+ void checkPaymentStatus();
123
+ }
124
+ else {
125
+ stopPolling();
126
+ }
127
+ }, pollInterval);
128
+ }
129
+ // Return control object
130
+ return {
131
+ stop: stopPolling,
132
+ isPolling: () => isPollingRef.current && isMountedRef.current,
133
+ };
134
+ }, [paymentsResource, stopPolling]);
135
+ return {
136
+ startPolling,
137
+ stopPolling,
138
+ isPolling: () => isPollingRef.current && isMountedRef.current,
139
+ };
140
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Payment Hook using TanStack Query (V2)
3
+ * Matches the old usePayment.ts implementation exactly for easy migration
4
+ */
5
+ import type { PaymentResponse, PaymentOptions, CardPaymentMethod, ApplePayToken, PaymentInstrumentResponse, PaymentInstrumentCustomerResponse } from '../../core/resources/payments';
6
+ export type { Payment as PaymentType, PaymentResponse, PaymentOptions, CardPaymentMethod, ApplePayToken, PaymentInstrumentResponse, PaymentInstrumentCustomerResponse, PaymentInstrumentCustomer } from '../../core/resources/payments';
7
+ export interface PaymentHook {
8
+ processCardPayment: (checkoutSessionId: string, cardData: CardPaymentMethod, options?: PaymentOptions) => Promise<PaymentResponse>;
9
+ processApplePayPayment: (checkoutSessionId: string, applePayToken: ApplePayToken, options?: PaymentOptions) => Promise<PaymentResponse>;
10
+ processPaymentWithInstrument: (checkoutSessionId: string, paymentInstrumentId: string, options?: PaymentOptions) => Promise<PaymentResponse>;
11
+ createCardPaymentInstrument: (cardData: CardPaymentMethod) => Promise<PaymentInstrumentResponse>;
12
+ createApplePayPaymentInstrument: (applePayToken: ApplePayToken) => Promise<PaymentInstrumentResponse>;
13
+ getCardPaymentInstruments: () => Promise<PaymentInstrumentCustomerResponse>;
14
+ isLoading: boolean;
15
+ error: string | null;
16
+ clearError: () => void;
17
+ currentPaymentId: string | null;
18
+ }
19
+ export declare function usePaymentQuery(): PaymentHook;
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Payment Hook using TanStack Query (V2)
3
+ * Matches the old usePayment.ts implementation exactly for easy migration
4
+ */
5
+ import { useState, useCallback, useMemo, useRef, useEffect } from 'react';
6
+ import { useBasisTheory } from '@basis-theory/basis-theory-react';
7
+ import { getBasisTheoryApiKey } from '../../../react/config/payment';
8
+ import { useTagadaContext } from '../providers/TagadaProvider';
9
+ import { PaymentsResource } from '../../core/resources/payments';
10
+ import { usePaymentPolling } from './usePaymentPolling';
11
+ import { useThreeds } from './useThreeds';
12
+ import { getGlobalApiClient } from './useApiQuery';
13
+ export function usePaymentQuery() {
14
+ const { environment } = useTagadaContext();
15
+ // Create payments resource client
16
+ const paymentsResource = useMemo(() => {
17
+ try {
18
+ return new PaymentsResource(getGlobalApiClient());
19
+ }
20
+ catch (error) {
21
+ throw new Error('Failed to initialize payments resource: ' + (error instanceof Error ? error.message : 'Unknown error'));
22
+ }
23
+ }, []);
24
+ const [isLoading, setIsLoading] = useState(false);
25
+ const [error, setError] = useState(null);
26
+ const [currentPaymentId, setCurrentPaymentId] = useState(null);
27
+ const { startPolling, stopPolling } = usePaymentPolling();
28
+ const { createSession, startChallenge } = useThreeds();
29
+ // Track challenge in progress to prevent multiple challenges
30
+ const challengeInProgressRef = useRef(false);
31
+ // Stabilize environment value to prevent re-renders
32
+ const currentEnvironment = useMemo(() => environment?.environment || 'local', [environment?.environment]);
33
+ // Get API key from embedded configuration with proper environment detection
34
+ const apiKey = useMemo(() => getBasisTheoryApiKey(currentEnvironment), [currentEnvironment]);
35
+ // Initialize BasisTheory using React wrapper
36
+ const { bt: basisTheory, error: btError } = useBasisTheory(apiKey, {
37
+ elements: false,
38
+ });
39
+ // Handle BasisTheory initialization errors (only log once when state changes)
40
+ useEffect(() => {
41
+ if (btError) {
42
+ setError('Failed to initialize payment processor: ' + btError.message);
43
+ }
44
+ else if (basisTheory && !error) {
45
+ setError(null); // Clear any previous errors
46
+ }
47
+ }, [basisTheory, btError]); // Removed error from dependency to prevent loops
48
+ // Clean up polling when component unmounts
49
+ useEffect(() => {
50
+ return () => {
51
+ stopPolling();
52
+ };
53
+ }, [stopPolling]);
54
+ // Handle payment actions (3DS, redirects, etc.) - matches old implementation
55
+ const handlePaymentAction = useCallback(async (payment, options = {}) => {
56
+ if (payment.requireAction === 'none')
57
+ return;
58
+ if (payment?.requireActionData?.processed)
59
+ return;
60
+ const actionData = payment.requireActionData;
61
+ if (!actionData)
62
+ return;
63
+ // Mark action as processed
64
+ try {
65
+ await paymentsResource.markPaymentActionProcessed(payment.id);
66
+ }
67
+ catch (_error) {
68
+ // Error handling removed
69
+ }
70
+ switch (actionData.type) {
71
+ case 'threeds_auth':
72
+ if (actionData.metadata?.threedsSession && !challengeInProgressRef.current) {
73
+ try {
74
+ challengeInProgressRef.current = true;
75
+ await startChallenge({
76
+ sessionId: actionData.metadata.threedsSession.externalSessionId,
77
+ acsChallengeUrl: actionData.metadata.threedsSession.acsChallengeUrl,
78
+ acsTransactionId: actionData.metadata.threedsSession.acsTransID,
79
+ threeDSVersion: actionData.metadata.threedsSession.messageVersion,
80
+ }, { provider: options.threedsProvider || 'basis_theory' });
81
+ challengeInProgressRef.current = false;
82
+ // Start polling after challenge completion
83
+ if (payment.id) {
84
+ startPolling(payment.id, {
85
+ onRequireAction: (updatedPayment) => {
86
+ void handlePaymentAction(updatedPayment, options);
87
+ },
88
+ onSuccess: (successPayment) => {
89
+ setIsLoading(false);
90
+ options.onSuccess?.({
91
+ paymentId: successPayment.id,
92
+ payment: successPayment,
93
+ });
94
+ },
95
+ onFailure: (errorMsg) => {
96
+ setError(errorMsg);
97
+ setIsLoading(false);
98
+ options.onFailure?.(errorMsg);
99
+ },
100
+ });
101
+ }
102
+ }
103
+ catch (_error) {
104
+ challengeInProgressRef.current = false;
105
+ const errorMsg = _error instanceof Error ? _error.message : 'Failed to start 3DS challenge';
106
+ setError(errorMsg);
107
+ setIsLoading(false);
108
+ options.onFailure?.(errorMsg);
109
+ }
110
+ }
111
+ break;
112
+ case 'processor_auth':
113
+ case 'redirect': {
114
+ if (actionData.metadata?.redirect?.redirectUrl) {
115
+ window.location.href = actionData.metadata.redirect.redirectUrl;
116
+ }
117
+ break;
118
+ }
119
+ case 'error': {
120
+ const errorMsg = actionData.message || 'Payment processing failed';
121
+ setError(errorMsg);
122
+ setIsLoading(false);
123
+ options.onFailure?.(errorMsg);
124
+ break;
125
+ }
126
+ }
127
+ options.onRequireAction?.(payment);
128
+ }, [paymentsResource, startPolling, startChallenge]);
129
+ // Create card payment instrument - matches old implementation
130
+ const createCardPaymentInstrument = useCallback((cardData) => {
131
+ return paymentsResource.createCardPaymentInstrument(basisTheory, cardData);
132
+ }, [basisTheory, paymentsResource]);
133
+ // Create Apple Pay payment instrument - matches old implementation
134
+ const createApplePayPaymentInstrument = useCallback((applePayToken) => {
135
+ return paymentsResource.createApplePayPaymentInstrument(basisTheory, applePayToken);
136
+ }, [basisTheory, paymentsResource]);
137
+ // Process payment directly with checkout session - matches old implementation
138
+ const processPaymentDirect = useCallback(async (checkoutSessionId, paymentInstrumentId, threedsSessionId, options = {}) => {
139
+ try {
140
+ const response = await paymentsResource.processPaymentDirect(checkoutSessionId, paymentInstrumentId, threedsSessionId, {
141
+ initiatedBy: options.initiatedBy,
142
+ source: options.source,
143
+ });
144
+ setCurrentPaymentId(response.payment?.id);
145
+ if (response.payment.requireAction !== 'none') {
146
+ await handlePaymentAction(response.payment, options);
147
+ }
148
+ else if (response.payment.status === 'succeeded') {
149
+ setIsLoading(false);
150
+ options.onSuccess?.(response);
151
+ }
152
+ else {
153
+ // Start polling for payment status
154
+ startPolling(response.payment?.id, {
155
+ onRequireAction: (payment) => {
156
+ void handlePaymentAction(payment, options);
157
+ },
158
+ onSuccess: (payment) => {
159
+ setIsLoading(false);
160
+ options.onSuccess?.({
161
+ paymentId: payment.id,
162
+ payment,
163
+ });
164
+ },
165
+ onFailure: (errorMsg) => {
166
+ setError(errorMsg);
167
+ setIsLoading(false);
168
+ options.onFailure?.(errorMsg);
169
+ },
170
+ });
171
+ }
172
+ return response;
173
+ }
174
+ catch (_error) {
175
+ const errorMsg = _error instanceof Error ? _error.message : 'Payment failed';
176
+ setError(errorMsg);
177
+ setIsLoading(false);
178
+ options.onFailure?.(errorMsg);
179
+ throw _error;
180
+ }
181
+ }, [paymentsResource, handlePaymentAction, startPolling]);
182
+ // Process card payment - matches old implementation
183
+ const processCardPayment = useCallback(async (checkoutSessionId, cardData, options = {}) => {
184
+ setIsLoading(true);
185
+ setError(null);
186
+ try {
187
+ // 1. Create payment instrument
188
+ const paymentInstrument = await createCardPaymentInstrument(cardData);
189
+ // 2. Create 3DS session if enabled
190
+ let threedsSessionId;
191
+ if (options.enableThreeds !== false) {
192
+ try {
193
+ const threedsSession = await createSession(paymentInstrument, {
194
+ provider: options.threedsProvider || 'basis_theory',
195
+ });
196
+ threedsSessionId = threedsSession.id;
197
+ }
198
+ catch (_error) {
199
+ }
200
+ }
201
+ // 3. Process payment directly
202
+ return await processPaymentDirect(checkoutSessionId, paymentInstrument.id, threedsSessionId, options);
203
+ }
204
+ catch (_error) {
205
+ setIsLoading(false);
206
+ const errorMsg = _error instanceof Error ? _error.message : 'Payment failed';
207
+ setError(errorMsg);
208
+ options.onFailure?.(errorMsg);
209
+ throw _error;
210
+ }
211
+ }, [createCardPaymentInstrument, createSession, processPaymentDirect]);
212
+ // Process Apple Pay payment - matches old implementation
213
+ const processApplePayPayment = useCallback(async (checkoutSessionId, applePayToken, options = {}) => {
214
+ setIsLoading(true);
215
+ setError(null);
216
+ try {
217
+ // 1. Create payment instrument
218
+ const paymentInstrument = await createApplePayPaymentInstrument(applePayToken);
219
+ // 2. Process payment directly (Apple Pay typically doesn't require 3DS)
220
+ return await processPaymentDirect(checkoutSessionId, paymentInstrument.id, undefined, options);
221
+ }
222
+ catch (_error) {
223
+ setIsLoading(false);
224
+ const errorMsg = _error instanceof Error ? _error.message : 'Apple Pay payment failed';
225
+ setError(errorMsg);
226
+ options.onFailure?.(errorMsg);
227
+ throw _error;
228
+ }
229
+ }, [createApplePayPaymentInstrument, processPaymentDirect]);
230
+ // Process payment with existing instrument - matches old implementation
231
+ const processPaymentWithInstrument = useCallback(async (checkoutSessionId, paymentInstrumentId, options = {}) => {
232
+ setIsLoading(true);
233
+ setError(null);
234
+ try {
235
+ return await processPaymentDirect(checkoutSessionId, paymentInstrumentId, undefined, options);
236
+ }
237
+ catch (_error) {
238
+ setIsLoading(false);
239
+ const errorMsg = _error instanceof Error ? _error.message : 'Payment failed';
240
+ setError(errorMsg);
241
+ options.onFailure?.(errorMsg);
242
+ throw _error;
243
+ }
244
+ }, [processPaymentDirect]);
245
+ // Get card payment instruments - matches old implementation
246
+ const getCardPaymentInstruments = useCallback(async () => {
247
+ try {
248
+ const response = await paymentsResource.getCardPaymentInstruments();
249
+ return response;
250
+ }
251
+ catch (error) {
252
+ const errorMsg = error instanceof Error ? error.message : 'Failed to fetch payment instruments';
253
+ setError(errorMsg);
254
+ throw error;
255
+ }
256
+ }, [paymentsResource]);
257
+ const clearError = useCallback(() => {
258
+ setError(null);
259
+ }, []);
260
+ return {
261
+ processCardPayment,
262
+ processApplePayPayment,
263
+ processPaymentWithInstrument,
264
+ createCardPaymentInstrument,
265
+ createApplePayPaymentInstrument,
266
+ getCardPaymentInstruments,
267
+ isLoading: isLoading || !basisTheory, // Indicate loading if BasisTheory is not initialized
268
+ error,
269
+ clearError,
270
+ currentPaymentId,
271
+ };
272
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Plugin Configuration Hook
3
+ * Uses PluginConfigUtils for business logic
4
+ */
5
+ import { PluginConfig, RawPluginConfig } from '../../core/utils/pluginConfig';
6
+ export interface UsePluginConfigOptions {
7
+ rawConfig?: RawPluginConfig;
8
+ }
9
+ export interface UsePluginConfigResult<TConfig = Record<string, any>> {
10
+ config: PluginConfig<TConfig>;
11
+ storeId?: string;
12
+ accountId?: string;
13
+ basePath?: string;
14
+ isValid: boolean;
15
+ }
16
+ export declare function usePluginConfig<TConfig = Record<string, any>>(options?: UsePluginConfigOptions): UsePluginConfigResult<TConfig>;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Plugin Configuration Hook
3
+ * Uses PluginConfigUtils for business logic
4
+ */
5
+ import { useMemo } from 'react';
6
+ import { useTagadaContext } from '../providers/TagadaProvider';
7
+ import { PluginConfigUtils } from '../../core/utils/pluginConfig';
8
+ export function usePluginConfig(options = {}) {
9
+ const { pluginConfig } = useTagadaContext();
10
+ const config = useMemo(() => {
11
+ const baseConfig = PluginConfigUtils.getPluginConfig(options.rawConfig, {
12
+ storeId: pluginConfig.storeId,
13
+ accountId: pluginConfig.accountId,
14
+ basePath: pluginConfig.basePath,
15
+ });
16
+ // Merge config properties from the loaded plugin config
17
+ return {
18
+ ...baseConfig,
19
+ ...pluginConfig.config,
20
+ storeId: pluginConfig.storeId,
21
+ accountId: pluginConfig.accountId,
22
+ basePath: pluginConfig.basePath,
23
+ };
24
+ }, [options.rawConfig, pluginConfig]);
25
+ const isValid = useMemo(() => {
26
+ return PluginConfigUtils.validateConfig(config);
27
+ }, [config]);
28
+ return {
29
+ config,
30
+ storeId: config.storeId,
31
+ accountId: config.accountId,
32
+ basePath: config.basePath,
33
+ isValid,
34
+ };
35
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Post Purchases Hook using TanStack Query
3
+ * Handles post-purchase offers with automatic caching
4
+ */
5
+ import { PostPurchaseOffer, PostPurchaseOfferItem, PostPurchaseOfferSummary, CheckoutSessionState, OrderSummary, CurrencyOptions } from '../../core/resources/postPurchases';
6
+ export interface UsePostPurchasesQueryOptions {
7
+ orderId: string;
8
+ enabled?: boolean;
9
+ autoInitializeCheckout?: boolean;
10
+ }
11
+ export interface UsePostPurchasesQueryResult {
12
+ offers: PostPurchaseOffer[];
13
+ isLoading: boolean;
14
+ error: Error | null;
15
+ acceptOffer: (offerId: string, items: PostPurchaseOfferItem[]) => Promise<{
16
+ success: boolean;
17
+ summary?: PostPurchaseOfferSummary;
18
+ error?: string;
19
+ }>;
20
+ declineOffer: (offerId: string) => Promise<{
21
+ success: boolean;
22
+ error?: string;
23
+ }>;
24
+ previewOffer: (offerId: string, items: PostPurchaseOfferItem[]) => Promise<{
25
+ success: boolean;
26
+ summary?: PostPurchaseOfferSummary;
27
+ error?: string;
28
+ }>;
29
+ refresh: () => void;
30
+ payWithCheckoutSession: (checkoutSessionId: string, orderId?: string) => Promise<void>;
31
+ initCheckoutSession: (offerId: string, orderId: string) => Promise<{
32
+ checkoutSessionId: string;
33
+ }>;
34
+ initCheckoutSessionWithVariants: (offerId: string, orderId: string, lineItems: {
35
+ variantId: string;
36
+ quantity: number;
37
+ }[]) => Promise<{
38
+ checkoutSessionId: string;
39
+ }>;
40
+ getOffer: (offerId: string) => PostPurchaseOffer | undefined;
41
+ getTotalValue: () => number;
42
+ getTotalSavings: () => number;
43
+ getCheckoutSessionState: (offerId: string) => CheckoutSessionState | null;
44
+ initializeOfferCheckout: (offerId: string) => Promise<void>;
45
+ getAvailableVariants: (offerId: string, productId: string) => {
46
+ variantId: string;
47
+ variantName: string;
48
+ variantSku: string | null;
49
+ variantDefault: boolean | null;
50
+ variantExternalId: string | null;
51
+ priceId: string;
52
+ currencyOptions: CurrencyOptions;
53
+ }[];
54
+ selectVariant: (offerId: string, productId: string, variantId: string) => Promise<void>;
55
+ getOrderSummary: (offerId: string) => OrderSummary | null;
56
+ isLoadingVariants: (offerId: string, productId: string) => boolean;
57
+ isUpdatingOrderSummary: (offerId: string) => boolean;
58
+ confirmPurchase: (offerId: string, options?: {
59
+ draft?: boolean;
60
+ returnUrl?: string;
61
+ }) => Promise<void>;
62
+ }
63
+ export declare function usePostPurchasesQuery(options: UsePostPurchasesQueryOptions): UsePostPurchasesQueryResult;