@tagadapay/plugin-sdk 3.1.8 → 3.1.10
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 +223 -113
- package/dist/external-tracker.js +135 -81
- package/dist/external-tracker.min.js +2 -2
- package/dist/external-tracker.min.js.map +4 -4
- package/dist/react/providers/TagadaProvider.js +5 -5
- package/dist/tagada-sdk.js +10164 -0
- package/dist/tagada-sdk.min.js +45 -0
- package/dist/tagada-sdk.min.js.map +7 -0
- package/dist/v2/core/funnelClient.d.ts +91 -4
- package/dist/v2/core/funnelClient.js +42 -3
- package/dist/v2/core/resources/funnel.d.ts +10 -0
- package/dist/v2/core/resources/payments.d.ts +21 -1
- package/dist/v2/core/resources/payments.js +34 -0
- package/dist/v2/core/utils/currency.d.ts +14 -0
- package/dist/v2/core/utils/currency.js +40 -0
- package/dist/v2/core/utils/index.d.ts +1 -0
- package/dist/v2/core/utils/index.js +2 -0
- package/dist/v2/core/utils/pluginConfig.d.ts +8 -0
- package/dist/v2/core/utils/pluginConfig.js +28 -0
- package/dist/v2/core/utils/previewMode.d.ts +4 -0
- package/dist/v2/core/utils/previewMode.js +28 -0
- package/dist/v2/core/utils/previewModeIndicator.js +101 -101
- package/dist/v2/index.d.ts +7 -6
- package/dist/v2/index.js +6 -6
- package/dist/v2/react/components/ApplePayButton.d.ts +1 -2
- package/dist/v2/react/components/ApplePayButton.js +57 -58
- package/dist/v2/react/components/FunnelScriptInjector.js +161 -172
- package/dist/v2/react/components/GooglePayButton.d.ts +2 -0
- package/dist/v2/react/components/GooglePayButton.js +80 -64
- package/dist/v2/react/hooks/useFunnel.d.ts +8 -2
- package/dist/v2/react/hooks/useFunnel.js +2 -2
- package/dist/v2/react/hooks/useGoogleAutocomplete.d.ts +10 -0
- package/dist/v2/react/hooks/useGoogleAutocomplete.js +48 -0
- package/dist/v2/react/hooks/useGooglePayCheckout.d.ts +21 -0
- package/dist/v2/react/hooks/useGooglePayCheckout.js +198 -0
- package/dist/v2/react/hooks/usePaymentPolling.d.ts +7 -1
- package/dist/v2/react/hooks/usePaymentQuery.d.ts +2 -0
- package/dist/v2/react/hooks/usePaymentQuery.js +435 -8
- package/dist/v2/react/hooks/usePixelTracking.d.ts +56 -0
- package/dist/v2/react/hooks/usePixelTracking.js +508 -0
- package/dist/v2/react/hooks/useStepConfig.d.ts +8 -6
- package/dist/v2/react/hooks/useStepConfig.js +3 -2
- package/dist/v2/react/index.d.ts +6 -2
- package/dist/v2/react/index.js +3 -1
- package/dist/v2/react/providers/ExpressPaymentMethodsProvider.d.ts +1 -0
- package/dist/v2/react/providers/ExpressPaymentMethodsProvider.js +33 -13
- package/dist/v2/react/providers/TagadaProvider.js +22 -21
- package/dist/v2/standalone/index.js +1 -1
- package/package.json +112 -112
|
@@ -1,9 +1,79 @@
|
|
|
1
1
|
import { ApiClient } from './resources/apiClient';
|
|
2
|
-
import {
|
|
2
|
+
import { FunnelAction, FunnelNavigationResult, SimpleFunnelContext } from './resources/funnel';
|
|
3
3
|
import { PluginConfig } from './utils/pluginConfig';
|
|
4
|
+
/**
|
|
5
|
+
* Tracking providers supported by the SDK.
|
|
6
|
+
* Mirrors `TrackingType` in `apps/crm-app/.../types/tracking.ts`.
|
|
7
|
+
*/
|
|
8
|
+
export declare enum TrackingProvider {
|
|
9
|
+
FACEBOOK = "facebook",
|
|
10
|
+
TIKTOK = "tiktok",
|
|
11
|
+
SNAPCHAT = "snapchat",
|
|
12
|
+
META_CONVERSION = "meta_conversion",
|
|
13
|
+
GTM = "gtm"
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Base tracking config (all providers)
|
|
17
|
+
*/
|
|
18
|
+
export interface BaseTrackingConfig {
|
|
19
|
+
enabled: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Pixel-based providers (Facebook, TikTok)
|
|
23
|
+
*/
|
|
24
|
+
export interface PixelTrackingConfig extends BaseTrackingConfig {
|
|
25
|
+
pixelId: string;
|
|
26
|
+
events: {
|
|
27
|
+
PageView: boolean;
|
|
28
|
+
InitiateCheckout: boolean;
|
|
29
|
+
Purchase: boolean;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Snapchat pixel config (extends base pixel events)
|
|
34
|
+
*/
|
|
35
|
+
export interface SnapchatTrackingConfig extends BaseTrackingConfig {
|
|
36
|
+
pixelId: string;
|
|
37
|
+
events: {
|
|
38
|
+
PageView: boolean;
|
|
39
|
+
InitiateCheckout: boolean;
|
|
40
|
+
Purchase: boolean;
|
|
41
|
+
AddToCart: boolean;
|
|
42
|
+
ViewContent: boolean;
|
|
43
|
+
Search: boolean;
|
|
44
|
+
AddToWishlist: boolean;
|
|
45
|
+
CompleteRegistration: boolean;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Meta Conversion API config
|
|
50
|
+
*/
|
|
51
|
+
export interface MetaConversionTrackingConfig extends BaseTrackingConfig {
|
|
52
|
+
accessToken: string;
|
|
53
|
+
pixelId: string;
|
|
54
|
+
publishPurchaseIfNewCustomerOnly: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Google Tag Manager config
|
|
58
|
+
*/
|
|
59
|
+
export interface GTMTrackingConfig extends BaseTrackingConfig {
|
|
60
|
+
containerId: string;
|
|
61
|
+
events: {
|
|
62
|
+
PageView: boolean;
|
|
63
|
+
InitiateCheckout: boolean;
|
|
64
|
+
Purchase: boolean;
|
|
65
|
+
AddToCart: boolean;
|
|
66
|
+
ViewContent: boolean;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Union of all tracking configs.
|
|
71
|
+
* This mirrors `TrackingFormValues` from the CRM.
|
|
72
|
+
*/
|
|
73
|
+
export type PixelConfig = PixelTrackingConfig | SnapchatTrackingConfig | MetaConversionTrackingConfig | GTMTrackingConfig;
|
|
4
74
|
/**
|
|
5
75
|
* Runtime step configuration injected from the CRM
|
|
6
|
-
* Contains payment flows, static resources, scripts, and
|
|
76
|
+
* Contains payment flows, static resources, scripts, and tracking configs
|
|
7
77
|
*/
|
|
8
78
|
export interface RuntimeStepConfig {
|
|
9
79
|
payment?: {
|
|
@@ -16,7 +86,13 @@ export interface RuntimeStepConfig {
|
|
|
16
86
|
content: string;
|
|
17
87
|
position?: 'head-start' | 'head-end' | 'body-start' | 'body-end';
|
|
18
88
|
}>;
|
|
19
|
-
pixels?:
|
|
89
|
+
pixels?: {
|
|
90
|
+
[TrackingProvider.FACEBOOK]?: PixelTrackingConfig[];
|
|
91
|
+
[TrackingProvider.TIKTOK]?: PixelTrackingConfig[];
|
|
92
|
+
[TrackingProvider.SNAPCHAT]?: SnapchatTrackingConfig[];
|
|
93
|
+
[TrackingProvider.META_CONVERSION]?: MetaConversionTrackingConfig[];
|
|
94
|
+
[TrackingProvider.GTM]?: GTMTrackingConfig[];
|
|
95
|
+
};
|
|
20
96
|
}
|
|
21
97
|
/**
|
|
22
98
|
* Local funnel configuration for development
|
|
@@ -34,7 +110,7 @@ export interface LocalFunnelConfig {
|
|
|
34
110
|
/** Custom scripts for local testing */
|
|
35
111
|
scripts?: RuntimeStepConfig['scripts'];
|
|
36
112
|
/** Pixel tracking config */
|
|
37
|
-
pixels?:
|
|
113
|
+
pixels?: RuntimeStepConfig['pixels'];
|
|
38
114
|
}
|
|
39
115
|
/**
|
|
40
116
|
* Load local funnel config from /config/funnel.local.json (for local dev only)
|
|
@@ -85,6 +161,17 @@ export declare function getAssignedStaticResources(): Record<string, string> | u
|
|
|
85
161
|
* Returns only enabled scripts, filtered by position if specified
|
|
86
162
|
*/
|
|
87
163
|
export declare function getAssignedScripts(position?: 'head-start' | 'head-end' | 'body-start' | 'body-end'): RuntimeStepConfig['scripts'];
|
|
164
|
+
/**
|
|
165
|
+
* Get assigned pixel tracking configuration (normalized to arrays)
|
|
166
|
+
* Always returns arrays of PixelConfig for consistent consumption.
|
|
167
|
+
*/
|
|
168
|
+
export declare function getAssignedPixels(): {
|
|
169
|
+
[TrackingProvider.FACEBOOK]?: PixelTrackingConfig[];
|
|
170
|
+
[TrackingProvider.TIKTOK]?: PixelTrackingConfig[];
|
|
171
|
+
[TrackingProvider.SNAPCHAT]?: SnapchatTrackingConfig[];
|
|
172
|
+
[TrackingProvider.META_CONVERSION]?: MetaConversionTrackingConfig[];
|
|
173
|
+
[TrackingProvider.GTM]?: GTMTrackingConfig[];
|
|
174
|
+
} | undefined;
|
|
88
175
|
export interface FunnelClientConfig {
|
|
89
176
|
apiClient: ApiClient;
|
|
90
177
|
debugMode?: boolean;
|
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
import { FunnelResource, FunnelActionType } from './resources/funnel';
|
|
2
|
-
import { EventDispatcher } from './utils/eventDispatcher';
|
|
3
|
-
import { getFunnelSessionCookie, setFunnelSessionCookie } from './utils/sessionStorage';
|
|
4
1
|
import { detectEnvironment } from './config/environment';
|
|
2
|
+
import { FunnelActionType, FunnelResource } from './resources/funnel';
|
|
3
|
+
import { EventDispatcher } from './utils/eventDispatcher';
|
|
5
4
|
import { getSDKParams } from './utils/previewMode';
|
|
6
5
|
import { injectPreviewModeIndicator } from './utils/previewModeIndicator';
|
|
6
|
+
import { getFunnelSessionCookie, setFunnelSessionCookie } from './utils/sessionStorage';
|
|
7
|
+
/**
|
|
8
|
+
* Tracking providers supported by the SDK.
|
|
9
|
+
* Mirrors `TrackingType` in `apps/crm-app/.../types/tracking.ts`.
|
|
10
|
+
*/
|
|
11
|
+
export var TrackingProvider;
|
|
12
|
+
(function (TrackingProvider) {
|
|
13
|
+
TrackingProvider["FACEBOOK"] = "facebook";
|
|
14
|
+
TrackingProvider["TIKTOK"] = "tiktok";
|
|
15
|
+
TrackingProvider["SNAPCHAT"] = "snapchat";
|
|
16
|
+
TrackingProvider["META_CONVERSION"] = "meta_conversion";
|
|
17
|
+
TrackingProvider["GTM"] = "gtm";
|
|
18
|
+
})(TrackingProvider || (TrackingProvider = {}));
|
|
7
19
|
/**
|
|
8
20
|
* Get the funnel ID from the injected HTML
|
|
9
21
|
* Returns undefined if not available
|
|
@@ -268,6 +280,31 @@ export function getAssignedScripts(position) {
|
|
|
268
280
|
}
|
|
269
281
|
return scripts.length > 0 ? scripts : undefined;
|
|
270
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* Get assigned pixel tracking configuration (normalized to arrays)
|
|
285
|
+
* Always returns arrays of PixelConfig for consistent consumption.
|
|
286
|
+
*/
|
|
287
|
+
export function getAssignedPixels() {
|
|
288
|
+
const stepConfig = getAssignedStepConfig();
|
|
289
|
+
const rawPixels = stepConfig?.pixels;
|
|
290
|
+
if (!rawPixels || typeof rawPixels !== 'object')
|
|
291
|
+
return undefined;
|
|
292
|
+
const normalized = {};
|
|
293
|
+
for (const [key, value] of Object.entries(rawPixels)) {
|
|
294
|
+
if (!value)
|
|
295
|
+
continue;
|
|
296
|
+
if (Array.isArray(value)) {
|
|
297
|
+
// Already an array
|
|
298
|
+
normalized[key] = value;
|
|
299
|
+
}
|
|
300
|
+
else if (typeof value === 'object') {
|
|
301
|
+
// Single object - wrap in array
|
|
302
|
+
normalized[key] = [value];
|
|
303
|
+
}
|
|
304
|
+
// Skip invalid entries
|
|
305
|
+
}
|
|
306
|
+
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
|
307
|
+
}
|
|
271
308
|
export class FunnelClient {
|
|
272
309
|
constructor(config) {
|
|
273
310
|
this.eventDispatcher = new EventDispatcher();
|
|
@@ -401,6 +438,8 @@ export class FunnelClient {
|
|
|
401
438
|
funnelEnv: funnelEnv || undefined, // 🎯 Pass funnel environment (staging/production)
|
|
402
439
|
tagadaClientEnv: sdkParams.tagadaClientEnv, // 🎯 Pass client environment override
|
|
403
440
|
tagadaClientBaseUrl: sdkParams.tagadaClientBaseUrl, // 🎯 Pass custom API base URL
|
|
441
|
+
currency: sdkParams.currency, // 🌍 Pass display currency override
|
|
442
|
+
locale: sdkParams.locale, // 🌍 Pass display locale override
|
|
404
443
|
});
|
|
405
444
|
if (response.success && response.context) {
|
|
406
445
|
const enriched = this.enrichContext(response.context);
|
|
@@ -485,6 +485,16 @@ export interface FunnelInitializeRequest {
|
|
|
485
485
|
* Forces custom API base URL (e.g., for local development with ngrok)
|
|
486
486
|
*/
|
|
487
487
|
tagadaClientBaseUrl?: string;
|
|
488
|
+
/**
|
|
489
|
+
* 🌍 Display currency override (e.g., 'USD', 'EUR')
|
|
490
|
+
* Forces specific currency for display purposes
|
|
491
|
+
*/
|
|
492
|
+
currency?: string;
|
|
493
|
+
/**
|
|
494
|
+
* 🌍 Display locale override (e.g., 'en', 'fr')
|
|
495
|
+
* Forces specific locale for display purposes
|
|
496
|
+
*/
|
|
497
|
+
locale?: string;
|
|
488
498
|
}
|
|
489
499
|
export interface FunnelInitializeResponse {
|
|
490
500
|
success: boolean;
|
|
@@ -9,7 +9,7 @@ export interface Payment {
|
|
|
9
9
|
subStatus: string;
|
|
10
10
|
requireAction: 'none' | 'redirect' | 'error' | 'radar';
|
|
11
11
|
requireActionData?: {
|
|
12
|
-
type: 'redirect' | 'threeds_auth' | 'processor_auth' | 'error' | 'stripe_radar' | 'finix_radar';
|
|
12
|
+
type: 'redirect' | 'threeds_auth' | 'processor_auth' | 'error' | 'stripe_radar' | 'finix_radar' | 'radar';
|
|
13
13
|
url?: string;
|
|
14
14
|
processed: boolean;
|
|
15
15
|
processorId?: string;
|
|
@@ -31,12 +31,18 @@ export interface Payment {
|
|
|
31
31
|
orderId?: string;
|
|
32
32
|
publishableKey?: string;
|
|
33
33
|
};
|
|
34
|
+
provider?: string;
|
|
35
|
+
isTest?: boolean;
|
|
34
36
|
};
|
|
35
37
|
redirectUrl?: string;
|
|
36
38
|
resumeToken?: string;
|
|
37
39
|
message?: string;
|
|
38
40
|
errorCode?: string;
|
|
39
41
|
};
|
|
42
|
+
order?: {
|
|
43
|
+
id: string;
|
|
44
|
+
checkoutSessionId: string;
|
|
45
|
+
};
|
|
40
46
|
}
|
|
41
47
|
export interface PaymentResponse {
|
|
42
48
|
paymentId: string;
|
|
@@ -149,6 +155,11 @@ export declare class PaymentsResource {
|
|
|
149
155
|
*/
|
|
150
156
|
createApplePayPaymentInstrument(basisTheory: any, // BasisTheory instance from @basis-theory/basis-theory-react
|
|
151
157
|
applePayToken: ApplePayToken): Promise<PaymentInstrumentResponse>;
|
|
158
|
+
/**
|
|
159
|
+
* Create Google Pay payment instrument
|
|
160
|
+
*/
|
|
161
|
+
createGooglePayPaymentInstrument(basisTheory: any, // BasisTheory instance from @basis-theory/basis-theory-react
|
|
162
|
+
googlePayToken: any): Promise<PaymentInstrumentResponse>;
|
|
152
163
|
/**
|
|
153
164
|
* Helper function to format expiry date
|
|
154
165
|
*/
|
|
@@ -198,6 +209,7 @@ export declare class PaymentsResource {
|
|
|
198
209
|
finixRadarSessionData?: Record<string, unknown>;
|
|
199
210
|
stripeRadarSessionId?: string;
|
|
200
211
|
stripeRadarSessionData?: Record<string, unknown>;
|
|
212
|
+
airwallexRadarSessionId?: string;
|
|
201
213
|
}): Promise<{
|
|
202
214
|
success: boolean;
|
|
203
215
|
radarSessionId: string;
|
|
@@ -207,4 +219,12 @@ export declare class PaymentsResource {
|
|
|
207
219
|
* This resumes the payment flow that was paused for additional authentication/verification
|
|
208
220
|
*/
|
|
209
221
|
completePaymentAfterAction(paymentId: string): Promise<Payment>;
|
|
222
|
+
/**
|
|
223
|
+
* Update 3DS session status (used for Airwallex 3DS return handling)
|
|
224
|
+
*/
|
|
225
|
+
updateThreedsStatus(data: {
|
|
226
|
+
paymentId: string;
|
|
227
|
+
status: 'succeeded' | 'failed' | 'pending';
|
|
228
|
+
paymentIntentId: string;
|
|
229
|
+
}): Promise<any>;
|
|
210
230
|
}
|
|
@@ -78,6 +78,34 @@ export class PaymentsResource {
|
|
|
78
78
|
const response = await this.apiClient.post('/api/v1/payment/create-payment-instrument', { paymentInstrumentData });
|
|
79
79
|
return response;
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Create Google Pay payment instrument
|
|
83
|
+
*/
|
|
84
|
+
async createGooglePayPaymentInstrument(basisTheory, // BasisTheory instance from @basis-theory/basis-theory-react
|
|
85
|
+
googlePayToken // Token from Basis Theory Google Pay tokenization
|
|
86
|
+
) {
|
|
87
|
+
if (!basisTheory) {
|
|
88
|
+
throw new Error('Payment processor not initialized');
|
|
89
|
+
}
|
|
90
|
+
if (!googlePayToken.id) {
|
|
91
|
+
throw new Error('Google Pay token is missing');
|
|
92
|
+
}
|
|
93
|
+
const paymentInstrumentData = {
|
|
94
|
+
type: 'google_pay',
|
|
95
|
+
token: googlePayToken.id,
|
|
96
|
+
dpanType: googlePayToken.type,
|
|
97
|
+
card: {
|
|
98
|
+
bin: googlePayToken.card.bin,
|
|
99
|
+
last4: googlePayToken.card.last4,
|
|
100
|
+
expirationMonth: googlePayToken.card.expiration_month,
|
|
101
|
+
expirationYear: googlePayToken.card.expiration_year,
|
|
102
|
+
brand: googlePayToken.card.brand,
|
|
103
|
+
},
|
|
104
|
+
authMethod: googlePayToken?.details?.auth_method,
|
|
105
|
+
};
|
|
106
|
+
const response = await this.apiClient.post('/api/v1/payment/create-payment-instrument', { paymentInstrumentData });
|
|
107
|
+
return response;
|
|
108
|
+
}
|
|
81
109
|
/**
|
|
82
110
|
* Helper function to format expiry date
|
|
83
111
|
*/
|
|
@@ -154,4 +182,10 @@ export class PaymentsResource {
|
|
|
154
182
|
paymentId,
|
|
155
183
|
});
|
|
156
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Update 3DS session status (used for Airwallex 3DS return handling)
|
|
187
|
+
*/
|
|
188
|
+
async updateThreedsStatus(data) {
|
|
189
|
+
return this.apiClient.post('/api/v1/threeds/status', data);
|
|
190
|
+
}
|
|
157
191
|
}
|
|
@@ -8,6 +8,20 @@ export interface Currency {
|
|
|
8
8
|
name: string;
|
|
9
9
|
decimalPlaces: number;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Format money amount from minor units (cents) to a formatted string
|
|
13
|
+
*
|
|
14
|
+
* @param amountMinorUnits - Amount in minor units (e.g., 12345 for $123.45)
|
|
15
|
+
* @param currencyCode - ISO 4217 currency code (e.g., "USD", "EUR")
|
|
16
|
+
* @param locale - Locale for formatting (default: "en-US")
|
|
17
|
+
* @returns Formatted money string (e.g., "$123.45")
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* formatMoney(12345, 'USD') // "$123.45"
|
|
21
|
+
* formatMoney(10000, 'EUR', 'de-DE') // "100,00 €"
|
|
22
|
+
* formatMoney(1000, 'JPY') // "¥1,000"
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatMoney(amountMinorUnits: number, currencyCode?: string, locale?: string): string;
|
|
11
25
|
export declare class CurrencyUtils {
|
|
12
26
|
/**
|
|
13
27
|
* Get currency from context or fallback to default
|
|
@@ -2,6 +2,46 @@
|
|
|
2
2
|
* Currency Utility Functions
|
|
3
3
|
* Pure functions for currency management
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* Format money amount from minor units (cents) to a formatted string
|
|
7
|
+
*
|
|
8
|
+
* @param amountMinorUnits - Amount in minor units (e.g., 12345 for $123.45)
|
|
9
|
+
* @param currencyCode - ISO 4217 currency code (e.g., "USD", "EUR")
|
|
10
|
+
* @param locale - Locale for formatting (default: "en-US")
|
|
11
|
+
* @returns Formatted money string (e.g., "$123.45")
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* formatMoney(12345, 'USD') // "$123.45"
|
|
15
|
+
* formatMoney(10000, 'EUR', 'de-DE') // "100,00 €"
|
|
16
|
+
* formatMoney(1000, 'JPY') // "¥1,000"
|
|
17
|
+
*/
|
|
18
|
+
export function formatMoney(amountMinorUnits, currencyCode = 'USD', locale = 'en-US') {
|
|
19
|
+
const decimalPlaces = CurrencyUtils.getDecimalPlaces(currencyCode);
|
|
20
|
+
// Convert minor units to major units
|
|
21
|
+
// Backend stores amounts with 2 decimal places for all currencies
|
|
22
|
+
// For currencies with 0 decimal places (JPY, KRW, etc.), divide by 100
|
|
23
|
+
let value;
|
|
24
|
+
if (decimalPlaces === 0) {
|
|
25
|
+
// For zero-decimal currencies, backend still stores with 2 decimals
|
|
26
|
+
value = amountMinorUnits / 100;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
value = amountMinorUnits / Math.pow(10, decimalPlaces);
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
return new Intl.NumberFormat(locale, {
|
|
33
|
+
style: 'currency',
|
|
34
|
+
currency: currencyCode,
|
|
35
|
+
minimumFractionDigits: decimalPlaces,
|
|
36
|
+
maximumFractionDigits: decimalPlaces,
|
|
37
|
+
}).format(value);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Fallback if Intl.NumberFormat fails
|
|
41
|
+
const symbol = CurrencyUtils.getCurrencySymbol(currencyCode);
|
|
42
|
+
return `${symbol}${value.toFixed(decimalPlaces)}`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
5
45
|
export class CurrencyUtils {
|
|
6
46
|
/**
|
|
7
47
|
* Get currency from context or fallback to default
|
|
@@ -22,6 +22,14 @@ export type RawPluginConfig<TConfig = Record<string, any>> = {
|
|
|
22
22
|
basePath?: string;
|
|
23
23
|
config?: any;
|
|
24
24
|
} & TConfig;
|
|
25
|
+
/**
|
|
26
|
+
* Synchronously get plugin config from meta tags
|
|
27
|
+
* This is a lightweight sync alternative to loadPluginConfig
|
|
28
|
+
* Use this when you need immediate config access (e.g., in CDN bundles)
|
|
29
|
+
*
|
|
30
|
+
* @returns Plugin config from meta tags or defaults
|
|
31
|
+
*/
|
|
32
|
+
export declare function getPluginConfig(): PluginConfig;
|
|
25
33
|
/**
|
|
26
34
|
* Core plugin config loading function
|
|
27
35
|
*
|
|
@@ -154,9 +154,37 @@ const loadStaticResources = async () => {
|
|
|
154
154
|
* Helper to get content from meta tag
|
|
155
155
|
*/
|
|
156
156
|
const getMetaContent = (name) => {
|
|
157
|
+
if (typeof document === 'undefined')
|
|
158
|
+
return undefined;
|
|
157
159
|
const metaTag = document.querySelector(`meta[name="${name}"]`);
|
|
158
160
|
return metaTag?.getAttribute('content') || undefined;
|
|
159
161
|
};
|
|
162
|
+
/**
|
|
163
|
+
* Synchronously get plugin config from meta tags
|
|
164
|
+
* This is a lightweight sync alternative to loadPluginConfig
|
|
165
|
+
* Use this when you need immediate config access (e.g., in CDN bundles)
|
|
166
|
+
*
|
|
167
|
+
* @returns Plugin config from meta tags or defaults
|
|
168
|
+
*/
|
|
169
|
+
export function getPluginConfig() {
|
|
170
|
+
if (typeof document === 'undefined') {
|
|
171
|
+
return { basePath: '/', config: {} };
|
|
172
|
+
}
|
|
173
|
+
const storeId = getMetaContent('x-plugin-store-id');
|
|
174
|
+
const accountId = getMetaContent('x-plugin-account-id');
|
|
175
|
+
const basePath = getMetaContent('x-plugin-base-path') || '/';
|
|
176
|
+
let config = {};
|
|
177
|
+
try {
|
|
178
|
+
const encodedConfig = getMetaContent('x-plugin-config');
|
|
179
|
+
if (encodedConfig) {
|
|
180
|
+
config = JSON.parse(decodeURIComponent(encodedConfig));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
console.warn('[TagadaSDK] Failed to parse plugin config from meta tag:', error);
|
|
185
|
+
}
|
|
186
|
+
return { storeId, accountId, basePath, config };
|
|
187
|
+
}
|
|
160
188
|
/**
|
|
161
189
|
* Load production config from meta tags (HIGHEST PRIORITY)
|
|
162
190
|
* Meta tags are injected by the plugin middleware during HTML serving
|
|
@@ -48,6 +48,10 @@ export interface SDKOverrideParams {
|
|
|
48
48
|
tagadaClientEnv?: 'production' | 'development' | 'local';
|
|
49
49
|
/** Force custom API base URL - overrides environment-based URL */
|
|
50
50
|
tagadaClientBaseUrl?: string;
|
|
51
|
+
/** Display currency override (e.g., 'USD', 'EUR') */
|
|
52
|
+
currency?: string;
|
|
53
|
+
/** Display locale override (e.g., 'en', 'fr') */
|
|
54
|
+
locale?: string;
|
|
51
55
|
}
|
|
52
56
|
/**
|
|
53
57
|
* Check if force reset is active (simulates hard refresh)
|
|
@@ -34,6 +34,8 @@ const STORAGE_KEYS = {
|
|
|
34
34
|
FORCE_RESET: 'tgd_force_reset',
|
|
35
35
|
CLIENT_ENV: 'tgd_client_env',
|
|
36
36
|
CLIENT_BASE_URL: 'tgd_client_base_url',
|
|
37
|
+
CURRENCY: 'tgd_currency',
|
|
38
|
+
LOCALE: 'tgd_locale',
|
|
37
39
|
};
|
|
38
40
|
/**
|
|
39
41
|
* Check if force reset is active (simulates hard refresh)
|
|
@@ -173,6 +175,30 @@ export function getSDKParams() {
|
|
|
173
175
|
tagadaClientBaseUrl = storageBaseUrl;
|
|
174
176
|
}
|
|
175
177
|
}
|
|
178
|
+
// Get display currency (URL > localStorage > cookie)
|
|
179
|
+
let currency;
|
|
180
|
+
const urlCurrency = urlParams.get('currency');
|
|
181
|
+
if (urlCurrency) {
|
|
182
|
+
currency = urlCurrency;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
const storageCurrency = getFromStorage(STORAGE_KEYS.CURRENCY) || getFromCookie(STORAGE_KEYS.CURRENCY);
|
|
186
|
+
if (storageCurrency) {
|
|
187
|
+
currency = storageCurrency;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Get display locale (URL > localStorage > cookie)
|
|
191
|
+
let locale;
|
|
192
|
+
const urlLocale = urlParams.get('locale');
|
|
193
|
+
if (urlLocale) {
|
|
194
|
+
locale = urlLocale;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
const storageLocale = getFromStorage(STORAGE_KEYS.LOCALE) || getFromCookie(STORAGE_KEYS.LOCALE);
|
|
198
|
+
if (storageLocale) {
|
|
199
|
+
locale = storageLocale;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
176
202
|
return {
|
|
177
203
|
forceReset,
|
|
178
204
|
token,
|
|
@@ -183,6 +209,8 @@ export function getSDKParams() {
|
|
|
183
209
|
funnelEnv,
|
|
184
210
|
tagadaClientEnv,
|
|
185
211
|
tagadaClientBaseUrl,
|
|
212
|
+
currency,
|
|
213
|
+
locale,
|
|
186
214
|
};
|
|
187
215
|
}
|
|
188
216
|
/**
|