@tagadapay/plugin-sdk 3.0.14 → 3.1.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/README.md +1129 -1129
- package/build-cdn.js +113 -113
- package/dist/external-tracker.js +53 -5
- package/dist/external-tracker.min.js +2 -2
- package/dist/external-tracker.min.js.map +3 -3
- package/dist/react/providers/TagadaProvider.js +5 -5
- package/dist/v2/core/client.d.ts +1 -0
- package/dist/v2/core/client.js +25 -0
- package/dist/v2/core/funnelClient.d.ts +9 -0
- package/dist/v2/core/funnelClient.js +34 -6
- package/dist/v2/core/resources/checkout.d.ts +32 -0
- package/dist/v2/core/resources/checkout.js +38 -0
- package/dist/v2/core/resources/funnel.d.ts +1 -0
- package/dist/v2/react/components/ApplePayButton.js +105 -33
- package/dist/v2/react/components/FunnelScriptInjector.d.ts +14 -0
- package/dist/v2/react/components/FunnelScriptInjector.js +242 -0
- package/dist/v2/react/providers/TagadaProvider.js +8 -7
- package/package.json +112 -112
|
@@ -38,11 +38,11 @@ const InitializationLoader = () => (_jsxs("div", { style: {
|
|
|
38
38
|
borderTop: '1.5px solid #9ca3af',
|
|
39
39
|
borderRadius: '50%',
|
|
40
40
|
animation: 'tagada-spin 1s linear infinite',
|
|
41
|
-
} }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
|
|
42
|
-
@keyframes tagada-spin {
|
|
43
|
-
0% { transform: rotate(0deg); }
|
|
44
|
-
100% { transform: rotate(360deg); }
|
|
45
|
-
}
|
|
41
|
+
} }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
|
|
42
|
+
@keyframes tagada-spin {
|
|
43
|
+
0% { transform: rotate(0deg); }
|
|
44
|
+
100% { transform: rotate(360deg); }
|
|
45
|
+
}
|
|
46
46
|
` })] }));
|
|
47
47
|
const TagadaContext = createContext(null);
|
|
48
48
|
export function TagadaProvider({ children, environment, customApiConfig, debugMode, // Remove default, will be set based on environment
|
package/dist/v2/core/client.d.ts
CHANGED
package/dist/v2/core/client.js
CHANGED
|
@@ -26,6 +26,29 @@ export class TagadaClient {
|
|
|
26
26
|
this.config = config;
|
|
27
27
|
this.instanceId = Math.random().toString(36).substr(2, 9);
|
|
28
28
|
this.boundHandleStorageChange = this.handleStorageChange.bind(this);
|
|
29
|
+
this.boundHandlePageshow = (event) => {
|
|
30
|
+
if (event.persisted) {
|
|
31
|
+
if (this.state.debugMode) {
|
|
32
|
+
console.log(`[TagadaClient ${this.instanceId}] Page restored from BFcache (back button), re-initializing funnel...`);
|
|
33
|
+
}
|
|
34
|
+
// If we have an active session and store, we only need to re-initialize the funnel
|
|
35
|
+
// This ensures tracking is correct and the session is fresh on the backend
|
|
36
|
+
if (this.funnel && this.state.session && this.state.store) {
|
|
37
|
+
this.funnel.resetInitialization();
|
|
38
|
+
const accountId = this.getAccountId();
|
|
39
|
+
const urlParams = new URLSearchParams(typeof window !== 'undefined' ? window.location.search : '');
|
|
40
|
+
const funnelId = urlParams.get('funnelId') || undefined;
|
|
41
|
+
this.funnel.autoInitialize({ customerId: this.state.session.customerId, sessionId: this.state.session.sessionId }, { id: this.state.store.id, accountId }, funnelId).catch((err) => {
|
|
42
|
+
console.error('[TagadaClient] Funnel re-initialization failed:', err);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// If state is missing, perform a full initialization
|
|
47
|
+
this.sessionInitRetryCount = 0;
|
|
48
|
+
this.initialize();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
29
52
|
console.log(`[TagadaClient ${this.instanceId}] Initializing...`);
|
|
30
53
|
console.log(`[TagadaClient ${this.instanceId}] Config:`, {
|
|
31
54
|
debugMode: config.debugMode,
|
|
@@ -115,6 +138,7 @@ export class TagadaClient {
|
|
|
115
138
|
// Listen for storage changes (cross-tab sync)
|
|
116
139
|
if (typeof window !== 'undefined') {
|
|
117
140
|
window.addEventListener('storage', this.boundHandleStorageChange);
|
|
141
|
+
window.addEventListener('pageshow', this.boundHandlePageshow);
|
|
118
142
|
}
|
|
119
143
|
// Setup config hot-reload listener (for live config editing)
|
|
120
144
|
this.setupConfigHotReload();
|
|
@@ -127,6 +151,7 @@ export class TagadaClient {
|
|
|
127
151
|
destroy() {
|
|
128
152
|
if (typeof window !== 'undefined') {
|
|
129
153
|
window.removeEventListener('storage', this.boundHandleStorageChange);
|
|
154
|
+
window.removeEventListener('pageshow', this.boundHandlePageshow);
|
|
130
155
|
}
|
|
131
156
|
if (this.state.debugMode) {
|
|
132
157
|
console.log(`[TagadaClient ${this.instanceId}] Destroyed`);
|
|
@@ -50,6 +50,15 @@ export declare class FunnelClient {
|
|
|
50
50
|
* Get current state
|
|
51
51
|
*/
|
|
52
52
|
getState(): FunnelState;
|
|
53
|
+
/**
|
|
54
|
+
* Get the session ID that would be used for initialization (URL params or cookie)
|
|
55
|
+
* This allows getting the session ID even before the client is fully initialized.
|
|
56
|
+
*/
|
|
57
|
+
getDetectedSessionId(): string | null;
|
|
58
|
+
/**
|
|
59
|
+
* Reset initialization state (used for back-button restores)
|
|
60
|
+
*/
|
|
61
|
+
resetInitialization(): void;
|
|
53
62
|
/**
|
|
54
63
|
* Initialize session with automatic detection (cookies, URL, etc.)
|
|
55
64
|
*/
|
|
@@ -92,6 +92,37 @@ export class FunnelClient {
|
|
|
92
92
|
getState() {
|
|
93
93
|
return this.state;
|
|
94
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Get the session ID that would be used for initialization (URL params or cookie)
|
|
97
|
+
* This allows getting the session ID even before the client is fully initialized.
|
|
98
|
+
*/
|
|
99
|
+
getDetectedSessionId() {
|
|
100
|
+
// Priority 1: Already initialized session
|
|
101
|
+
if (this.state.context?.sessionId) {
|
|
102
|
+
return this.state.context.sessionId;
|
|
103
|
+
}
|
|
104
|
+
if (typeof window === 'undefined')
|
|
105
|
+
return null;
|
|
106
|
+
// Priority 2: URL params
|
|
107
|
+
const params = new URLSearchParams(window.location.search);
|
|
108
|
+
const urlSessionId = params.get('funnelSessionId');
|
|
109
|
+
if (urlSessionId)
|
|
110
|
+
return urlSessionId;
|
|
111
|
+
// Priority 3: Cookie
|
|
112
|
+
return getFunnelSessionCookie() || null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Reset initialization state (used for back-button restores)
|
|
116
|
+
*/
|
|
117
|
+
resetInitialization() {
|
|
118
|
+
this.initializationAttempted = false;
|
|
119
|
+
this.isInitializing = false;
|
|
120
|
+
// Clear context to force a fresh autoInitialize call to hit the backend
|
|
121
|
+
this.updateState({
|
|
122
|
+
context: null,
|
|
123
|
+
isInitialized: false,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
95
126
|
/**
|
|
96
127
|
* Initialize session with automatic detection (cookies, URL, etc.)
|
|
97
128
|
*/
|
|
@@ -106,15 +137,12 @@ export class FunnelClient {
|
|
|
106
137
|
this.isInitializing = true;
|
|
107
138
|
this.updateState({ isLoading: true, error: null });
|
|
108
139
|
try {
|
|
109
|
-
//
|
|
140
|
+
// 🎯 Get detected session ID
|
|
141
|
+
const existingSessionId = this.getDetectedSessionId();
|
|
142
|
+
// URL params for funnelId
|
|
110
143
|
const params = new URLSearchParams(typeof window !== 'undefined' ? window.location.search : '');
|
|
111
144
|
const urlFunnelId = params.get('funnelId');
|
|
112
145
|
const effectiveFunnelId = urlFunnelId || funnelId;
|
|
113
|
-
let existingSessionId = params.get('funnelSessionId');
|
|
114
|
-
// Cookie fallback
|
|
115
|
-
if (!existingSessionId) {
|
|
116
|
-
existingSessionId = getFunnelSessionCookie() || null;
|
|
117
|
-
}
|
|
118
146
|
// 🎯 Read funnel tracking data from injected HTML
|
|
119
147
|
const injectedFunnelId = getAssignedFunnelId(); // Funnel ID from server
|
|
120
148
|
const funnelVariantId = getAssignedFunnelVariant(); // A/B test variant ID
|
|
@@ -209,6 +209,38 @@ export declare class CheckoutResource {
|
|
|
209
209
|
customerId: string;
|
|
210
210
|
status: 'processing';
|
|
211
211
|
}>;
|
|
212
|
+
/**
|
|
213
|
+
* Preload checkout session (ultra-fast background pre-computation) ⚡⚡⚡
|
|
214
|
+
*
|
|
215
|
+
* This is the recommended way to handle cart changes or "Buy Now" intent.
|
|
216
|
+
* It pre-computes everything (checkoutToken, navigation URL, CMS session)
|
|
217
|
+
* before the user even clicks the checkout button.
|
|
218
|
+
*
|
|
219
|
+
* The SDK automatically gets funnelSessionId from FunnelClient if provided.
|
|
220
|
+
* Only FunnelClient knows how to properly extract funnelSessionId (from state, URL, cookies, etc.)
|
|
221
|
+
*
|
|
222
|
+
* @param params - Checkout and funnel parameters
|
|
223
|
+
* @param getFunnelSessionId - Optional function to get funnelSessionId from FunnelClient
|
|
224
|
+
* This maintains separation of concerns - only FunnelClient knows how to get it
|
|
225
|
+
*
|
|
226
|
+
* @returns { checkoutToken, customerId, navigationUrl }
|
|
227
|
+
*/
|
|
228
|
+
preloadCheckout(params: CheckoutInitParams & {
|
|
229
|
+
funnelSessionId?: string;
|
|
230
|
+
currentUrl?: string;
|
|
231
|
+
funnelStepId?: string;
|
|
232
|
+
funnelVariantId?: string;
|
|
233
|
+
navigationEvent?: string | {
|
|
234
|
+
type: string;
|
|
235
|
+
data?: any;
|
|
236
|
+
};
|
|
237
|
+
navigationOptions?: any;
|
|
238
|
+
}, getFunnelSessionId?: () => string | null | undefined): Promise<{
|
|
239
|
+
checkoutToken: string;
|
|
240
|
+
customerId: string;
|
|
241
|
+
navigationUrl: string | null;
|
|
242
|
+
funnelStepId?: string;
|
|
243
|
+
}>;
|
|
212
244
|
/**
|
|
213
245
|
* Check async checkout processing status (instant, no waiting)
|
|
214
246
|
* Perfect for polling or checking if background job completed
|
|
@@ -33,6 +33,44 @@ export class CheckoutResource {
|
|
|
33
33
|
async initCheckoutAsync(params) {
|
|
34
34
|
return this.apiClient.post('/api/v1/checkout/session/init-async', params);
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Preload checkout session (ultra-fast background pre-computation) ⚡⚡⚡
|
|
38
|
+
*
|
|
39
|
+
* This is the recommended way to handle cart changes or "Buy Now" intent.
|
|
40
|
+
* It pre-computes everything (checkoutToken, navigation URL, CMS session)
|
|
41
|
+
* before the user even clicks the checkout button.
|
|
42
|
+
*
|
|
43
|
+
* The SDK automatically gets funnelSessionId from FunnelClient if provided.
|
|
44
|
+
* Only FunnelClient knows how to properly extract funnelSessionId (from state, URL, cookies, etc.)
|
|
45
|
+
*
|
|
46
|
+
* @param params - Checkout and funnel parameters
|
|
47
|
+
* @param getFunnelSessionId - Optional function to get funnelSessionId from FunnelClient
|
|
48
|
+
* This maintains separation of concerns - only FunnelClient knows how to get it
|
|
49
|
+
*
|
|
50
|
+
* @returns { checkoutToken, customerId, navigationUrl }
|
|
51
|
+
*/
|
|
52
|
+
async preloadCheckout(params, getFunnelSessionId) {
|
|
53
|
+
// ⚡ GET FUNNEL SESSION ID: Only FunnelClient knows how to properly get it
|
|
54
|
+
// Priority: explicit param > FunnelClient > backend fallback (via currentUrl)
|
|
55
|
+
let funnelSessionId = params.funnelSessionId;
|
|
56
|
+
if (!funnelSessionId && getFunnelSessionId) {
|
|
57
|
+
// Let FunnelClient handle extraction (from state, URL, cookies, etc.)
|
|
58
|
+
funnelSessionId = getFunnelSessionId() || undefined;
|
|
59
|
+
}
|
|
60
|
+
// Format navigationEvent if it's a string
|
|
61
|
+
const navigationEvent = typeof params.navigationEvent === 'string'
|
|
62
|
+
? { type: params.navigationEvent }
|
|
63
|
+
: params.navigationEvent;
|
|
64
|
+
// Build request - backend will also try to extract from currentUrl if not provided
|
|
65
|
+
const requestParams = {
|
|
66
|
+
...params,
|
|
67
|
+
...(funnelSessionId && { funnelSessionId }),
|
|
68
|
+
...(navigationEvent && { navigationEvent }),
|
|
69
|
+
// Ensure currentUrl is always set for backend extraction fallback
|
|
70
|
+
currentUrl: params.currentUrl || (typeof window !== 'undefined' ? window.location.href : undefined),
|
|
71
|
+
};
|
|
72
|
+
return this.apiClient.post('/api/v1/checkout/session/preload', requestParams);
|
|
73
|
+
}
|
|
36
74
|
/**
|
|
37
75
|
* Check async checkout processing status (instant, no waiting)
|
|
38
76
|
* Perfect for polling or checking if background job completed
|
|
@@ -3,13 +3,37 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
* Apple Pay Button Component for v2 Architecture
|
|
4
4
|
* Uses v2 useExpressPaymentMethods hook and follows clean architecture principles
|
|
5
5
|
*/
|
|
6
|
-
import { useCallback, useEffect, useState } from 'react';
|
|
6
|
+
import { useCallback, useEffect, useState, useMemo } from 'react';
|
|
7
|
+
import { PaymentsResource } from '../../core/resources/payments';
|
|
8
|
+
import { OrdersResource } from '../../core/resources/orders';
|
|
7
9
|
import { useExpressPaymentMethods } from '../hooks/useExpressPaymentMethods';
|
|
10
|
+
import { getGlobalApiClient } from '../hooks/useApiQuery';
|
|
11
|
+
import { getBasisTheoryApiKey } from '../../../react/config/payment';
|
|
8
12
|
export const ApplePayButton = ({ className = '', disabled = false, onSuccess, onError, onCancel, storeName, currencyCode = 'USD', variant = 'default', size = 'lg', checkout, }) => {
|
|
9
13
|
const { applePayPaymentMethod, shippingMethods, lineItems, handleAddExpressId, updateCheckoutSessionValues, updateCustomerEmail, reComputeOrderSummary, setError: setContextError, } = useExpressPaymentMethods();
|
|
10
14
|
const [processingPayment, setProcessingPayment] = useState(false);
|
|
11
15
|
const [isApplePayAvailable, setIsApplePayAvailable] = useState(false);
|
|
12
16
|
const [applePayError, setApplePayError] = useState(null);
|
|
17
|
+
// Get Basis Theory API key from config (auto-detects environment)
|
|
18
|
+
const basistheoryPublicKey = useMemo(() => getBasisTheoryApiKey(), []);
|
|
19
|
+
// Create SDK resource clients
|
|
20
|
+
const paymentsResource = useMemo(() => {
|
|
21
|
+
try {
|
|
22
|
+
return new PaymentsResource(getGlobalApiClient());
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
throw new Error('Failed to initialize payments resource: ' +
|
|
26
|
+
(error instanceof Error ? error.message : 'Unknown error'));
|
|
27
|
+
}
|
|
28
|
+
}, []);
|
|
29
|
+
const ordersResource = useMemo(() => {
|
|
30
|
+
try {
|
|
31
|
+
return new OrdersResource(getGlobalApiClient());
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
throw new Error('Failed to initialize orders resource: ' + (error instanceof Error ? error.message : 'Unknown error'));
|
|
35
|
+
}
|
|
36
|
+
}, []);
|
|
13
37
|
// Don't render if no Apple Pay payment method is enabled
|
|
14
38
|
if (!applePayPaymentMethod) {
|
|
15
39
|
return null;
|
|
@@ -57,23 +81,55 @@ export const ApplePayButton = ({ className = '', disabled = false, onSuccess, on
|
|
|
57
81
|
email: contact.emailAddress || '',
|
|
58
82
|
};
|
|
59
83
|
}, []);
|
|
60
|
-
// Validate merchant with
|
|
61
|
-
const validateMerchant = useCallback(async (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
// Validate merchant with Basis Theory
|
|
85
|
+
const validateMerchant = useCallback(async () => {
|
|
86
|
+
try {
|
|
87
|
+
const response = await fetch('https://api.basistheory.com/apple-pay/session', {
|
|
88
|
+
method: 'POST',
|
|
89
|
+
headers: {
|
|
90
|
+
'Content-Type': 'application/json',
|
|
91
|
+
'BT-API-KEY': basistheoryPublicKey,
|
|
92
|
+
},
|
|
93
|
+
body: JSON.stringify({
|
|
94
|
+
display_name: checkout.checkoutSession.store?.name || 'Store',
|
|
95
|
+
domain: window.location.host,
|
|
96
|
+
}),
|
|
97
|
+
});
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
throw new Error(`Failed to validate merchant: ${response.status}`);
|
|
100
|
+
}
|
|
101
|
+
const merchantSession = await response.json();
|
|
102
|
+
return merchantSession;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.error('Merchant validation failed:', error);
|
|
106
|
+
throw error;
|
|
74
107
|
}
|
|
75
|
-
|
|
76
|
-
|
|
108
|
+
}, [checkout.checkoutSession.store?.name]);
|
|
109
|
+
// Tokenize Apple Pay payment with Basis Theory
|
|
110
|
+
const tokenizeApplePay = useCallback(async (token) => {
|
|
111
|
+
try {
|
|
112
|
+
const response = await fetch('https://api.basistheory.com/apple-pay', {
|
|
113
|
+
method: 'POST',
|
|
114
|
+
headers: {
|
|
115
|
+
'Content-Type': 'application/json',
|
|
116
|
+
'BT-API-KEY': basistheoryPublicKey,
|
|
117
|
+
},
|
|
118
|
+
body: JSON.stringify({
|
|
119
|
+
apple_payment_data: token,
|
|
120
|
+
}),
|
|
121
|
+
});
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
throw new Error(`Failed to tokenize Apple Pay: ${response.status}`);
|
|
124
|
+
}
|
|
125
|
+
const result = await response.json();
|
|
126
|
+
return result.apple_pay; // Basis Theory returns the Apple Pay token in the apple_pay field
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
console.error('Tokenization failed:', error);
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
}, []);
|
|
77
133
|
// Process Apple Pay payment
|
|
78
134
|
const processApplePayPayment = useCallback(async (token, billingContact, shippingContact) => {
|
|
79
135
|
try {
|
|
@@ -97,23 +153,35 @@ export const ApplePayButton = ({ className = '', disabled = false, onSuccess, on
|
|
|
97
153
|
},
|
|
98
154
|
});
|
|
99
155
|
}
|
|
100
|
-
//
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
156
|
+
// 1. Tokenize with Basis Theory
|
|
157
|
+
const applePayToken = await tokenizeApplePay(token);
|
|
158
|
+
// 2. Create payment instrument from the tokenized Apple Pay payment
|
|
159
|
+
const paymentInstrumentData = {
|
|
160
|
+
type: 'apple_pay',
|
|
161
|
+
token: applePayToken.id,
|
|
162
|
+
dpanType: applePayToken.type,
|
|
163
|
+
card: {
|
|
164
|
+
bin: applePayToken.card.bin,
|
|
165
|
+
last4: applePayToken.card.last4,
|
|
166
|
+
expirationMonth: applePayToken.card.expiration_month,
|
|
167
|
+
expirationYear: applePayToken.card.expiration_year,
|
|
168
|
+
brand: applePayToken.card.brand,
|
|
105
169
|
},
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (!
|
|
114
|
-
throw new Error('Failed to
|
|
170
|
+
};
|
|
171
|
+
const paymentInstrument = await paymentsResource.createPaymentInstrument(paymentInstrumentData);
|
|
172
|
+
if (!paymentInstrument?.id) {
|
|
173
|
+
throw new Error('Failed to create payment instrument');
|
|
174
|
+
}
|
|
175
|
+
// 3. Create order from checkout session
|
|
176
|
+
const orderResponse = await ordersResource.createOrder(checkout.checkoutSession.id);
|
|
177
|
+
if (!orderResponse?.success || !orderResponse?.order?.id) {
|
|
178
|
+
throw new Error('Failed to create order');
|
|
115
179
|
}
|
|
116
|
-
|
|
180
|
+
// 4. Process payment
|
|
181
|
+
const paymentResult = await paymentsResource.processPaymentDirect(checkout.checkoutSession.id, paymentInstrument.id, undefined, {
|
|
182
|
+
initiatedBy: 'customer',
|
|
183
|
+
source: 'checkout',
|
|
184
|
+
});
|
|
117
185
|
if (onSuccess) {
|
|
118
186
|
onSuccess(paymentResult);
|
|
119
187
|
}
|
|
@@ -137,6 +205,9 @@ export const ApplePayButton = ({ className = '', disabled = false, onSuccess, on
|
|
|
137
205
|
applePayContactToAddress,
|
|
138
206
|
updateCheckoutSessionValues,
|
|
139
207
|
updateCustomerEmail,
|
|
208
|
+
tokenizeApplePay,
|
|
209
|
+
paymentsResource,
|
|
210
|
+
ordersResource,
|
|
140
211
|
onSuccess,
|
|
141
212
|
onError,
|
|
142
213
|
setContextError,
|
|
@@ -174,7 +245,8 @@ export const ApplePayButton = ({ className = '', disabled = false, onSuccess, on
|
|
|
174
245
|
const session = new window.ApplePaySession(3, paymentRequest);
|
|
175
246
|
session.onvalidatemerchant = async (event) => {
|
|
176
247
|
try {
|
|
177
|
-
|
|
248
|
+
console.log('Merchant validation requested for:', event.validationURL);
|
|
249
|
+
const merchantSession = await validateMerchant();
|
|
178
250
|
session.completeMerchantValidation(merchantSession);
|
|
179
251
|
}
|
|
180
252
|
catch (error) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FunnelState } from '../../core';
|
|
2
|
+
interface FunnelScriptInjectorProps extends FunnelState {
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* FunnelScriptInjector - Handles injection of funnel scripts into the page.
|
|
6
|
+
*
|
|
7
|
+
* This component:
|
|
8
|
+
* - Sets up Tagada on the window object
|
|
9
|
+
* - Injects and manages funnel scripts from the context
|
|
10
|
+
* - Prevents duplicate script injection (handles React StrictMode)
|
|
11
|
+
* - Cleans up scripts when context changes or component unmounts
|
|
12
|
+
*/
|
|
13
|
+
export declare function FunnelScriptInjector({ context, isInitialized }: FunnelScriptInjectorProps): null;
|
|
14
|
+
export {};
|