@tagadapay/plugin-sdk 3.1.10 → 3.1.12

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 (38) hide show
  1. package/README.md +1129 -1129
  2. package/build-cdn.js +113 -223
  3. package/dist/external-tracker.js +2 -3
  4. package/dist/external-tracker.min.js +2 -2
  5. package/dist/external-tracker.min.js.map +3 -3
  6. package/dist/react/hooks/useShippingRates.d.ts +6 -0
  7. package/dist/react/hooks/useShippingRates.js +38 -0
  8. package/dist/react/providers/TagadaProvider.js +5 -5
  9. package/dist/react/services/apiService.d.ts +21 -0
  10. package/dist/react/services/apiService.js +10 -0
  11. package/dist/v2/core/funnelClient.d.ts +14 -15
  12. package/dist/v2/core/funnelClient.js +1 -1
  13. package/dist/v2/core/resources/shippingRates.d.ts +15 -0
  14. package/dist/v2/core/resources/shippingRates.js +11 -0
  15. package/dist/v2/core/utils/currency.d.ts +0 -14
  16. package/dist/v2/core/utils/currency.js +0 -40
  17. package/dist/v2/core/utils/index.d.ts +0 -1
  18. package/dist/v2/core/utils/index.js +0 -2
  19. package/dist/v2/core/utils/pluginConfig.d.ts +0 -8
  20. package/dist/v2/core/utils/pluginConfig.js +0 -28
  21. package/dist/v2/core/utils/previewModeIndicator.js +101 -101
  22. package/dist/v2/index.d.ts +1 -1
  23. package/dist/v2/react/components/ApplePayButton.js +13 -4
  24. package/dist/v2/react/components/FunnelScriptInjector.js +30 -30
  25. package/dist/v2/react/hooks/useFunnel.d.ts +1 -2
  26. package/dist/v2/react/hooks/useGoogleAutocomplete.js +82 -33
  27. package/dist/v2/react/hooks/usePixelTracking.d.ts +5 -0
  28. package/dist/v2/react/hooks/usePixelTracking.js +108 -0
  29. package/dist/v2/react/hooks/useShippingRatesQuery.d.ts +6 -0
  30. package/dist/v2/react/hooks/useShippingRatesQuery.js +36 -1
  31. package/dist/v2/react/hooks/useStepConfig.d.ts +2 -8
  32. package/dist/v2/react/hooks/useStepConfig.js +1 -1
  33. package/dist/v2/react/providers/TagadaProvider.js +5 -5
  34. package/dist/v2/standalone/index.js +1 -1
  35. package/package.json +112 -112
  36. package/dist/tagada-sdk.js +0 -10164
  37. package/dist/tagada-sdk.min.js +0 -45
  38. package/dist/tagada-sdk.min.js.map +0 -7
package/README.md CHANGED
@@ -1,1129 +1,1129 @@
1
- # TagadaPay Plugin SDK
2
-
3
- A comprehensive React SDK for building plugins on the TagadaPay platform. Create custom checkout experiences, landing pages, and interactive components with automatic configuration injection and advanced routing capabilities.
4
-
5
- > **🚀 V2 Now Available!** The new V2 architecture features TanStack Query integration, improved TypeScript support, and better performance. [See V2 Architecture](#-v2-architecture) for details.
6
- >
7
- > **Recommended**: Use `@tagadapay/plugin-sdk/v3` for new projects. V1 (`/react`) is still supported for existing projects.
8
-
9
- ## 📚 Documentation
10
-
11
- ### V2 Core APIs (Recommended)
12
-
13
- - **[V2 Architecture](#-v2-architecture)** - New TanStack Query-based architecture
14
- - **[V2 Examples](#-v2-examples)** - Complete examples using the new V2 hooks
15
- - **[useCheckout (V2)](#usecheckout)** - TanStack Query-based checkout management
16
- - **[useOffers (V2)](#useoffers)** - Dynamic pricing with automatic caching
17
- - **[useProducts (V2)](#useproducts)** - Product data management
18
- - **[useStoreConfig (V2)](#usestoreconfig)** - Store configuration with automatic caching
19
- - **[usePayment (V2)](#usepayment)** - Payment processing with 3DS support
20
- - **[V2 Utility Functions](#v2-utility-functions--advanced-features)** - Enhanced utilities and TanStack Query integration
21
-
22
- ### Legacy V1 APIs (Still Supported)
23
-
24
- - **[useCheckout (V1)](./docs/README-useCheckout.md)** - Legacy checkout state management
25
- - **[setCheckoutInfo](./docs/README-setCheckoutInfo.md)** - Customer information and validation
26
- - **[useOffers (V1)](./docs/README-useOffers.md)** - Legacy dynamic pricing
27
- - **[usePromotionCodes](./docs/README-usePromotionCodes.md)** - Legacy promotion code management
28
- - **[Money utilities](./docs/README-money.md)** - Currency formatting and calculations
29
- - **[URL utilities](./docs/README-urlUtils.md)** - Navigation and routing helpers
30
-
31
- ### Plugin Development
32
-
33
- - **[Plugin Configuration](./docs/PLUGIN_CONFIG.md)** - How to access store context, config, and branding
34
- - **[Initialization Modes](#-initialization-modes)** - Choose between blocking and non-blocking initialization
35
- - **[Google Autocomplete](./docs/README-google-autocomplete.md)** - Address autocomplete with Google Places API
36
- - **[ISO Data](./docs/README-iso-data.md)** - Country and region data with Google integration
37
-
38
- ### Examples
39
-
40
- - **[Vite Checkout Demo](../checkout-vite)** - Complete checkout implementation
41
-
42
- ## 🏗️ Building a Plugin
43
-
44
- ### Plugin Structure
45
-
46
- Every TagadaPay plugin follows this simple structure:
47
-
48
- ```
49
- my-plugin/
50
- ├── plugin.manifest.json # Plugin metadata & routing
51
- ├── .local.json # Local dev config (auto-injected in production)
52
- ├── config/ # Optional deployment configs
53
- │ ├── theme-green.json # Config variant A
54
- │ └── theme-blue.json # Config variant B
55
- ├── src/
56
- │ └── App.tsx # Your plugin code
57
- └── dist/ # Built plugin files
58
- ```
59
-
60
- ### Configuration Flow
61
-
62
- ```mermaid
63
- graph TD
64
- A[🛠️ Local Development] --> B[.local.json]
65
- A --> C[config/*.json]
66
- B --> D[usePluginConfig()]
67
- C --> D
68
-
69
- E[🚀 Production] --> F[Platform Injection]
70
- F --> G[HTTP Headers & Meta Tags]
71
- G --> D
72
-
73
- D --> H[Your Plugin Component]
74
-
75
- style A fill:#e1f5fe
76
- style E fill:#f3e5f5
77
- style D fill:#fff3e0
78
- style H fill:#e8f5e8
79
- ```
80
-
81
- ### Essential Files
82
-
83
- #### 1. **`plugin.manifest.json`** - Plugin Metadata
84
-
85
- ```json
86
- {
87
- "pluginId": "my-awesome-plugin",
88
- "name": "My Awesome Plugin",
89
- "version": "1.0.0",
90
- "mode": "direct-mode",
91
- "router": {
92
- "basePath": "/",
93
- "matcher": ".*",
94
- "excluder": "/checkout"
95
- }
96
- }
97
- ```
98
-
99
- #### 2. **`.local.json`** - Local Development Context
100
-
101
- ```json
102
- {
103
- "storeId": "store_abc123",
104
- "accountId": "acc_xyz789",
105
- "basePath": "/"
106
- }
107
- ```
108
-
109
- > ⚠️ **Auto-managed**: This file is only for local dev. In production, the platform injects this data automatically.
110
-
111
- #### 3. **`config/my-theme.json`** - Optional Deployment Config
112
-
113
- ```json
114
- {
115
- "configName": "green-theme",
116
- "branding": {
117
- "primaryColor": "#059669",
118
- "companyName": "My Store",
119
- "logoUrl": "https://example.com/logo.png"
120
- },
121
- "features": {
122
- "enableChat": true,
123
- "maxItems": 10
124
- }
125
- }
126
- ```
127
-
128
- > 📝 **Note**: Config can contain any keys you need - the SDK doesn't enforce a specific structure.
129
-
130
- ## 🚀 Quick Start
131
-
132
- ### Installation
133
-
134
- ```bash
135
- npm install @tagadapay/plugin-sdk
136
- ```
137
-
138
- ### Basic Plugin Setup
139
-
140
- ```tsx
141
- import React from 'react';
142
- import {
143
- TagadaProvider,
144
- usePluginConfig,
145
- useGoogleAutocomplete,
146
- useISOData,
147
- useCheckout,
148
- formatMoney,
149
- } from '@tagadapay/plugin-sdk/v3';
150
-
151
- function MyPlugin() {
152
- const { config, storeId, accountId, basePath, loading } = usePluginConfig();
153
-
154
- // Optional: Add address autocomplete
155
- const { searchPlaces, predictions } = useGoogleAutocomplete({
156
- apiKey: config?.googleMapsApiKey || 'YOUR_API_KEY',
157
- });
158
-
159
- // Optional: Add country/region data
160
- const { countries } = useISOData('en');
161
-
162
- // V2: Use TanStack Query-based checkout hook
163
- const { checkout, init, updateLineItems, isLoading } = useCheckout({
164
- checkoutToken: 'your-checkout-token',
165
- });
166
-
167
- if (loading) return <div>Loading...</div>;
168
-
169
- return (
170
- <div style={{ '--primary': config?.branding?.primaryColor }}>
171
- <h1>Welcome to {config?.branding?.companyName}</h1>
172
- <p>Store: {storeId}</p>
173
- <p>Base Path: {basePath}</p>
174
- <p>Available Countries: {Object.keys(countries).length}</p>
175
-
176
- {checkout && (
177
- <div>
178
- <h2>Checkout Total: {formatMoney(checkout.summary.total, checkout.currency)}</h2>
179
- <p>Items: {checkout.lineItems.length}</p>
180
- </div>
181
- )}
182
- </div>
183
- );
184
- }
185
-
186
- // Wrap your plugin with TagadaProvider
187
- function App() {
188
- return (
189
- <TagadaProvider>
190
- <MyPlugin />
191
- </TagadaProvider>
192
- );
193
- }
194
-
195
- export default App;
196
- ```
197
-
198
- ## 🏗️ V2 Architecture
199
-
200
- ### What's New in V2
201
-
202
- The TagadaPay Plugin SDK v3 introduces a clean architecture with significant improvements:
203
-
204
- #### **🔄 TanStack Query Integration**
205
-
206
- - **Automatic Caching**: All API calls are cached and synchronized across components
207
- - **Background Refetching**: Data stays fresh with automatic background updates
208
- - **Optimistic Updates**: Instant UI feedback with automatic rollback on errors
209
- - **Request Deduplication**: Multiple components can use the same data without duplicate requests
210
-
211
- #### **🏗️ Clean Architecture**
212
-
213
- - **Core Layer**: Pure functions and API clients without React dependencies
214
- - **React Layer**: Hooks and components that use core functions
215
- - **Better Testing**: Easier to test business logic separately from UI logic
216
-
217
- #### **📦 Import Paths**
218
-
219
- ```tsx
220
- // V2 (Recommended)
221
- import { useCheckout, useOffers, TagadaProvider } from '@tagadapay/plugin-sdk/v3';
222
-
223
- // Legacy (Still supported)
224
- import { useCheckout, useOffers, TagadaProvider } from '@tagadapay/plugin-sdk/react';
225
- ```
226
-
227
- #### **🔧 Enhanced Developer Experience**
228
-
229
- - **TypeScript First**: Better type inference and autocomplete
230
- - **Debug Tools**: Built-in debug drawer for development
231
- - **Performance**: Reduced bundle size and better performance
232
-
233
- ### Migration from V1
234
-
235
- Most hooks have the same names but improved APIs:
236
-
237
- ```tsx
238
- // V1 Pattern
239
- const { checkout, loading, error } = useCheckout();
240
-
241
- // V2 Pattern (TanStack Query)
242
- const { checkout, isLoading, error, refresh } = useCheckout({
243
- checkoutToken: 'token',
244
- enabled: true,
245
- });
246
- ```
247
-
248
- ### 📚 V2 Examples
249
-
250
- #### Complete Checkout Flow
251
-
252
- ```tsx
253
- import React, { useState } from 'react';
254
- import {
255
- TagadaProvider,
256
- useCheckout,
257
- useProducts,
258
- usePluginConfig,
259
- formatMoney,
260
- } from '@tagadapay/plugin-sdk/v3';
261
-
262
- function CheckoutPage() {
263
- const [checkoutToken, setCheckoutToken] = useState<string>();
264
- const { config } = usePluginConfig();
265
-
266
- // Load products
267
- const { products, isLoading: productsLoading } = useProducts({
268
- storeId: config.storeId,
269
- });
270
-
271
- // Initialize checkout when needed
272
- const {
273
- checkout,
274
- isLoading: checkoutLoading,
275
- init,
276
- updateLineItems,
277
- updateCustomer,
278
- applyPromotionCode,
279
- } = useCheckout({
280
- checkoutToken,
281
- enabled: !!checkoutToken,
282
- });
283
-
284
- const handleInitCheckout = async () => {
285
- if (!products?.length) return;
286
-
287
- const result = await init({
288
- lineItems: [
289
- {
290
- variantId: products[0].variants[0].id,
291
- quantity: 1,
292
- },
293
- ],
294
- });
295
-
296
- setCheckoutToken(result.checkoutToken);
297
- };
298
-
299
- const handleApplyPromo = async (code: string) => {
300
- try {
301
- await applyPromotionCode(code);
302
- // TanStack Query automatically refetches and updates the UI
303
- } catch (error) {
304
- console.error('Failed to apply promo:', error);
305
- }
306
- };
307
-
308
- if (productsLoading) return <div>Loading products...</div>;
309
-
310
- return (
311
- <div>
312
- <h1>Checkout</h1>
313
-
314
- {!checkoutToken ? (
315
- <button onClick={handleInitCheckout}>Start Checkout</button>
316
- ) : (
317
- <div>
318
- {checkoutLoading ? (
319
- <div>Loading checkout...</div>
320
- ) : checkout ? (
321
- <div>
322
- <h2>Order Summary</h2>
323
- <p>Total: {formatMoney(checkout.summary.total, checkout.currency)}</p>
324
- <p>Items: {checkout.lineItems.length}</p>
325
-
326
- <div>
327
- <input
328
- type="text"
329
- placeholder="Promo code"
330
- onKeyDown={(e) => {
331
- if (e.key === 'Enter') {
332
- handleApplyPromo(e.currentTarget.value);
333
- }
334
- }}
335
- />
336
- </div>
337
- </div>
338
- ) : null}
339
- </div>
340
- )}
341
- </div>
342
- );
343
- }
344
-
345
- function App() {
346
- return (
347
- <TagadaProvider>
348
- <CheckoutPage />
349
- </TagadaProvider>
350
- );
351
- }
352
- ```
353
-
354
- #### Multi-Component Data Sharing
355
-
356
- ```tsx
357
- import React from 'react';
358
- import { TagadaProvider, useCheckout, useOffers, formatMoney } from '@tagadapay/plugin-sdk/v3';
359
-
360
- // Component 1: Cart Summary
361
- function CartSummary({ checkoutToken }: { checkoutToken: string }) {
362
- const { checkout, isLoading } = useCheckout({ checkoutToken });
363
-
364
- if (isLoading) return <div>Loading...</div>;
365
- if (!checkout) return null;
366
-
367
- return (
368
- <div>
369
- <h3>Cart ({checkout.lineItems.length} items)</h3>
370
- <p>Total: {formatMoney(checkout.summary.total, checkout.currency)}</p>
371
- </div>
372
- );
373
- }
374
-
375
- // Component 2: Available Offers (shares same checkout data automatically)
376
- function OffersPanel({ checkoutToken }: { checkoutToken: string }) {
377
- const { checkout } = useCheckout({ checkoutToken }); // Same data, no extra request!
378
- const { offers, isLoading } = useOffers({
379
- storeId: checkout?.storeId,
380
- });
381
-
382
- if (isLoading) return <div>Loading offers...</div>;
383
-
384
- return (
385
- <div>
386
- <h3>Special Offers</h3>
387
- {offers?.map((offer) => (
388
- <div key={offer.id}>
389
- <p>{offer.title}</p>
390
- <p>Save {formatMoney(offer.discount, checkout?.currency || 'USD')}</p>
391
- </div>
392
- ))}
393
- </div>
394
- );
395
- }
396
-
397
- // Main component
398
- function CheckoutWithOffers() {
399
- const checkoutToken = 'your-checkout-token';
400
-
401
- return (
402
- <div style={{ display: 'flex', gap: '20px' }}>
403
- <CartSummary checkoutToken={checkoutToken} />
404
- <OffersPanel checkoutToken={checkoutToken} />
405
- </div>
406
- );
407
- }
408
- ```
409
-
410
- #### Optimistic Updates
411
-
412
- ```tsx
413
- import React from 'react';
414
- import { useCheckout } from '@tagadapay/plugin-sdk/v3';
415
-
416
- function QuantitySelector({
417
- checkoutToken,
418
- variantId,
419
- currentQuantity,
420
- }: {
421
- checkoutToken: string;
422
- variantId: string;
423
- currentQuantity: number;
424
- }) {
425
- const { checkout, setItemQuantity, updateLineItemsOptimistic } = useCheckout({ checkoutToken });
426
-
427
- const handleQuantityChange = async (newQuantity: number) => {
428
- // 1. Optimistic update (instant UI feedback)
429
- const updatedItems =
430
- checkout?.lineItems.map((item) =>
431
- item.variantId === variantId ? { ...item, quantity: newQuantity } : item,
432
- ) || [];
433
-
434
- updateLineItemsOptimistic(updatedItems);
435
-
436
- // 2. Server update (with automatic rollback on error)
437
- try {
438
- await setItemQuantity(variantId, newQuantity);
439
- // TanStack Query automatically syncs the real data
440
- } catch (error) {
441
- // Automatic rollback to previous state
442
- console.error('Failed to update quantity:', error);
443
- }
444
- };
445
-
446
- return (
447
- <div>
448
- <button onClick={() => handleQuantityChange(currentQuantity - 1)}>-</button>
449
- <span>{currentQuantity}</span>
450
- <button onClick={() => handleQuantityChange(currentQuantity + 1)}>+</button>
451
- </div>
452
- );
453
- }
454
- ```
455
-
456
- ## 🚀 Initialization Modes
457
-
458
- The TagadaProvider supports two initialization modes to give you control over when your components render:
459
-
460
- ### Non-Blocking Mode (Default - Recommended)
461
-
462
- ```tsx
463
- <TagadaProvider>
464
- {/* Children render immediately after config loads */}
465
- <YourApp />
466
- </TagadaProvider>
467
-
468
- // OR explicitly
469
- <TagadaProvider blockUntilSessionReady={false}>
470
- <YourApp />
471
- </TagadaProvider>
472
- ```
473
-
474
- **Flow:**
475
-
476
- 1. **Phase 1 & 2** ✅ Plugin config loads → Children render immediately
477
- 2. **Phase 3** 🔄 Session initialization runs in background
478
- 3. **API calls** 🔄 Hooks automatically wait for session to be ready
479
-
480
- **Benefits:**
481
-
482
- - ⚡ **Faster rendering** - UI appears immediately
483
- - 🎯 **Better UX** - Show loading states while session initializes
484
- - 🔄 **Automatic waiting** - Hooks handle session timing for you
485
-
486
- ### Blocking Mode (Legacy Behavior)
487
-
488
- ```tsx
489
- <TagadaProvider blockUntilSessionReady={true}>
490
- {/* Children render only after ALL initialization completes */}
491
- <YourApp />
492
- </TagadaProvider>
493
- ```
494
-
495
- **Flow:**
496
-
497
- 1. **All Phases** ⏳ Config + Session must complete before children render
498
- 2. **API calls** ✅ Work immediately (no waiting needed)
499
-
500
- **Use when:**
501
-
502
- - 🔄 **Migrating** from older SDK versions
503
- - 🎯 **Simple apps** that don't need progressive loading
504
-
505
- ### Console Logs
506
-
507
- The SDK logs help you understand which mode you're using:
508
-
509
- **Non-blocking mode:**
510
-
511
- ```
512
- ✅ Phase 1 & 2 Complete - Plugin config loaded
513
- 🚀 Non-blocking mode: Children can now render - Phase 3 will continue in background
514
- 🔄 [useCheckout] Waiting for session initialization to complete...
515
- ✅ Phase 3 Complete - Session initialization completed successfully
516
- ✅ [useCheckout] Session initialized, proceeding with checkout init
517
- ```
518
-
519
- **Blocking mode:**
520
-
521
- ```
522
- ✅ Phase 1 & 2 Complete - Plugin config loaded
523
- ⏳ Blocking mode: Children will render after Phase 3 completes
524
- ✅ Phase 3 Complete - Session initialization completed successfully
525
- ```
526
-
527
- ### TagadaProvider API
528
-
529
- ```tsx
530
- interface TagadaProviderProps {
531
- children: ReactNode;
532
- environment?: 'local' | 'development' | 'staging' | 'production';
533
- customApiConfig?: Partial<EnvironmentConfig>;
534
- debugMode?: boolean;
535
- localConfig?: string; // LOCAL DEV ONLY: Override config variant
536
- blockUntilSessionReady?: boolean; // Default: false
537
-
538
- // V2 Specific Options
539
- queryClientConfig?: QueryClientConfig; // TanStack Query configuration
540
- enableDevtools?: boolean; // Enable React Query Devtools
541
- }
542
- ```
543
-
544
- | Prop | Type | Default | Description |
545
- | ------------------------ | ----------- | -------------------- | ------------------------------ |
546
- | `children` | `ReactNode` | - | Your plugin components |
547
- | `environment` | `string` | auto-detect | Override environment detection |
548
- | `customApiConfig` | `object` | - | Custom API configuration |
549
- | `debugMode` | `boolean` | auto (false in prod) | Enable debug features & drawer |
550
- | `localConfig` | `string` | `'default'` | Config variant for local dev |
551
- | `blockUntilSessionReady` | `boolean` | `false` | Use legacy blocking behavior |
552
- | `queryClientConfig` | `object` | - | **V2**: TanStack Query config |
553
- | `enableDevtools` | `boolean` | `false` | **V2**: React Query Devtools |
554
-
555
- #### V2 Enhanced Provider Features
556
-
557
- ```tsx
558
- import { TagadaProvider } from '@tagadapay/plugin-sdk/v3';
559
-
560
- function App() {
561
- return (
562
- <TagadaProvider
563
- debugMode={true}
564
- enableDevtools={true} // Shows React Query Devtools
565
- queryClientConfig={{
566
- defaultOptions: {
567
- queries: {
568
- staleTime: 5 * 60 * 1000, // 5 minutes
569
- cacheTime: 10 * 60 * 1000, // 10 minutes
570
- },
571
- },
572
- }}
573
- >
574
- <YourApp />
575
- </TagadaProvider>
576
- );
577
- }
578
- ```
579
-
580
- > **Version Compatibility:** V2 features require `@tagadapay/plugin-sdk/v3`. The `blockUntilSessionReady` option was added in v2.3.0. For older versions, the blocking behavior was the default and only option.
581
-
582
- ### Development vs Production
583
-
584
- | Environment | Store/Account ID | Deployment Config | How it Works |
585
- | -------------- | ---------------- | ----------------- | ------------------ |
586
- | **Local Dev** | `.local.json` | `config/*.json` | Files on disk |
587
- | **Production** | HTTP Headers | Meta Tags | Platform injection |
588
-
589
- ```tsx
590
- // ✅ ALWAYS use hooks - works in both environments
591
- const { storeId, accountId, basePath, config } = usePluginConfig();
592
-
593
- // ❌ NEVER access directly
594
- // const config = window.__PLUGIN_CONFIG__; // Doesn't exist!
595
- ```
596
-
597
- ## 🎯 Key Features
598
-
599
- ### 🔧 **Plugin Configuration System**
600
-
601
- - **Automatic Context Injection** - Store ID, Account ID, and custom config
602
- - **Development & Production** - Seamless environment switching
603
- - **Generic Configuration** - Support for any JSON structure
604
- - **React Hooks** - Clean, type-safe configuration access
605
-
606
- ### 💳 **Payment Processing**
607
-
608
- - Secure tokenized payments
609
- - Multiple payment method support
610
- - Real-time validation
611
- - PCI compliance
612
-
613
- ### 🌍 **Address & Location**
614
-
615
- - **Google Places Autocomplete** - Automatic API loading and address parsing
616
- - **ISO Country/Region Data** - Complete ISO 3166-1/3166-2 database
617
- - **Address Validation** - Structured component extraction
618
- - **Multi-language Support** - 11+ languages for international users
619
-
620
- ### 🛒 **E-commerce Features**
621
-
622
- - Dynamic pricing and promotional offers
623
- - Cart management and tax calculations
624
- - Currency conversion and formatting
625
- - Customer profile management
626
-
627
- ### 🎨 **UI & Development**
628
-
629
- - Pre-built React components
630
- - Customizable themes with configuration
631
- - Mobile-optimized and accessible
632
- - TypeScript support throughout
633
-
634
- ## 📖 API Reference
635
-
636
- ### V2 Core Hooks (TanStack Query-based)
637
-
638
- #### useCheckout()
639
-
640
- Primary hook for checkout state management using TanStack Query for automatic caching and synchronization.
641
-
642
- ```typescript
643
- const {
644
- // Query data
645
- checkout, // CheckoutData | undefined
646
- isLoading, // boolean
647
- error, // Error | null
648
- isSuccess, // boolean
649
-
650
- // Actions
651
- init, // (params: CheckoutInitParams) => Promise<{checkoutUrl, checkoutSession, checkoutToken}>
652
- refresh, // () => Promise<void>
653
-
654
- // Checkout operations
655
- updateLineItems, // (lineItems: CheckoutLineItem[]) => Promise<any>
656
- updateLineItemsOptimistic, // (lineItems: CheckoutLineItem[]) => void
657
- setItemQuantity, // (variantId: string, quantity: number, priceId?: string) => Promise<any>
658
- updateCustomer, // (data: {email: string, acceptsMarketing?: boolean}) => Promise<any>
659
- applyPromotionCode, // (code: string) => Promise<any>
660
- removePromotion, // (promotionId: string) => Promise<any>
661
- } = useCheckout({ checkoutToken, enabled });
662
- ```
663
-
664
- #### useOffers()
665
-
666
- Hook for managing dynamic offers and pricing with automatic cache management.
667
-
668
- ```typescript
669
- const {
670
- // Query data
671
- offers, // Offer[] | undefined
672
- isLoading, // boolean
673
- error, // Error | null
674
-
675
- // Actions
676
- refresh, // () => Promise<void>
677
- } = useOffers({ storeId, enabled });
678
- ```
679
-
680
- #### usePromotions()
681
-
682
- Hook for managing promotion codes in checkout sessions with TanStack Query.
683
-
684
- ```typescript
685
- const {
686
- // Query data
687
- promotions, // Promotion[] | undefined
688
- isLoading, // boolean
689
- error, // Error | null
690
-
691
- // Actions
692
- refresh, // () => Promise<void>
693
- } = usePromotions({ checkoutToken, enabled });
694
- ```
695
-
696
- #### useProducts()
697
-
698
- Hook for product data management with caching.
699
-
700
- ```typescript
701
- const {
702
- // Query data
703
- products, // Product[] | undefined
704
- isLoading, // boolean
705
- error, // Error | null
706
-
707
- // Actions
708
- refresh, // () => Promise<void>
709
- } = useProducts({ storeId, enabled });
710
- ```
711
-
712
- #### useStoreConfig()
713
-
714
- Hook for fetching store configuration with automatic caching.
715
-
716
- ```typescript
717
- const {
718
- // Query data
719
- storeConfig, // StoreConfig | undefined
720
- isLoading, // boolean
721
- error, // Error | null
722
- isSuccess, // boolean
723
-
724
- // Actions
725
- refetch, // () => Promise<void>
726
- } = useStoreConfig({ storeId, enabled });
727
- ```
728
-
729
- **Example:**
730
-
731
- ```tsx
732
- import { useStoreConfig } from '@tagadapay/plugin-sdk/v3';
733
-
734
- function StoreInfo() {
735
- const { storeConfig, isLoading } = useStoreConfig();
736
-
737
- if (isLoading) return <div>Loading...</div>;
738
-
739
- return (
740
- <div>
741
- <h1>{storeConfig?.storeName}</h1>
742
- <p>Currency: {storeConfig?.currency}</p>
743
- </div>
744
- );
745
- }
746
- ```
747
-
748
- See [useStoreConfig documentation](./docs/README-useStoreConfig.md) for more details.
749
-
750
- #### useOrder()
751
-
752
- Hook for order management and tracking.
753
-
754
- ```typescript
755
- const {
756
- // Query data
757
- order, // Order | undefined
758
- isLoading, // boolean
759
- error, // Error | null
760
-
761
- // Actions
762
- refresh, // () => Promise<void>
763
- } = useOrder({ orderId, enabled });
764
- ```
765
-
766
- #### usePostPurchases()
767
-
768
- Hook for post-purchase offers management.
769
-
770
- ```typescript
771
- const {
772
- // Query data
773
- postPurchases, // PostPurchaseOffer[] | undefined
774
- isLoading, // boolean
775
- error, // Error | null
776
-
777
- // Actions
778
- refresh, // () => Promise<void>
779
- } = usePostPurchases({ orderId, enabled });
780
- ```
781
-
782
- #### usePayment()
783
-
784
- Hook for payment processing with 3DS support.
785
-
786
- ```typescript
787
- const {
788
- // Payment methods
789
- processPayment, // (options: PaymentOptions) => Promise<PaymentResponse>
790
- processApplePayPayment, // (token: ApplePayToken) => Promise<PaymentResponse>
791
-
792
- // State
793
- isProcessing, // boolean
794
- error, // Error | null
795
- } = usePayment();
796
- ```
797
-
798
- ### V2 Utility Functions & Advanced Features
799
-
800
- #### TanStack Query Integration
801
-
802
- V2 provides direct access to TanStack Query features for advanced use cases:
803
-
804
- ```typescript
805
- import {
806
- useApiQuery,
807
- useApiMutation,
808
- useInvalidateQuery,
809
- usePreloadQuery,
810
- queryKeys,
811
- } from '@tagadapay/plugin-sdk/v3';
812
-
813
- // Custom API queries
814
- const { data, isLoading } = useApiQuery({
815
- queryKey: ['custom', 'endpoint'],
816
- queryFn: () => apiClient.get('/custom-endpoint'),
817
- });
818
-
819
- // Mutations with automatic cache updates
820
- const mutation = useApiMutation({
821
- mutationFn: (data) => apiClient.post('/update', data),
822
- onSuccess: () => {
823
- // Invalidate related queries
824
- invalidateQuery(['checkout']);
825
- },
826
- });
827
-
828
- // Preload data for better UX
829
- const preloadCheckout = usePreloadQuery();
830
- preloadCheckout({
831
- queryKey: queryKeys.checkout(checkoutToken),
832
- queryFn: () => checkoutResource.get(checkoutToken),
833
- });
834
- ```
835
-
836
- #### Money Utilities
837
-
838
- Enhanced money formatting with better TypeScript support:
839
-
840
- ```typescript
841
- import { formatMoney, convertCurrency, getCurrencyInfo } from '@tagadapay/plugin-sdk/v3';
842
-
843
- // Format money with automatic currency detection
844
- const formatted = formatMoney(2999, 'USD'); // "$29.99"
845
- const simple = formatSimpleMoney(2999, 'EUR'); // "29.99"
846
- const withoutSymbol = formatMoneyWithoutSymbol(2999, 'GBP'); // "29.99"
847
-
848
- // Currency conversion (if rates available)
849
- const converted = convertCurrency(2999, 'USD', 'EUR'); // 2699
850
-
851
- // Get currency information
852
- const currencyInfo = getCurrencyInfo('USD');
853
- // { symbol: '$', code: 'USD', minorUnits: 2 }
854
-
855
- // Convert between major and minor units
856
- const major = minorUnitsToMajorUnits(2999); // 29.99
857
- const minor = moneyStringOrNumberToMinorUnits('29.99'); // 2999
858
- ```
859
-
860
- #### Core Functions (Pure Functions)
861
-
862
- V2 separates core business logic from React hooks:
863
-
864
- ```typescript
865
- import {
866
- CheckoutResource,
867
- ProductsResource,
868
- PaymentsResource,
869
- PluginConfigUtils,
870
- } from '@tagadapay/plugin-sdk/v3';
871
-
872
- // Use core functions directly (useful for server-side or non-React contexts)
873
- const checkoutResource = new CheckoutResource(apiClient);
874
- const checkout = await checkoutResource.get(checkoutToken);
875
-
876
- // Plugin config utilities
877
- const config = PluginConfigUtils.getPluginConfig(rawConfig, context);
878
- const isValid = PluginConfigUtils.validateConfig(config);
879
- ```
880
-
881
- #### Debug Tools
882
-
883
- V2 includes built-in debugging tools:
884
-
885
- ```tsx
886
- import { TagadaProvider } from '@tagadapay/plugin-sdk/v3';
887
-
888
- function App() {
889
- return (
890
- <TagadaProvider
891
- debugMode={true} // Shows debug drawer in development
892
- environment="development"
893
- >
894
- <YourApp />
895
- </TagadaProvider>
896
- );
897
- }
898
- ```
899
-
900
- ## 🛠️ Development
901
-
902
- ### Local Development
903
-
904
- ```bash
905
- # Install dependencies
906
- npm install
907
-
908
- # Start development server
909
- npm run dev
910
-
911
- # Build for production
912
- npm run build
913
- ```
914
-
915
- ### Testing
916
-
917
- ```bash
918
- # Run tests
919
- npm test
920
-
921
- # Run tests with coverage
922
- npm run test:coverage
923
- ```
924
-
925
- ### Linting
926
-
927
- ```bash
928
- # Check code style
929
- npm run lint
930
-
931
- # Fix linting issues
932
- npm run lint:fix
933
- ```
934
-
935
- ## 📦 Build & Deploy
936
-
937
- ### Building Your Plugin
938
-
939
- ```bash
940
- # Build optimized bundle
941
- npm run build
942
-
943
- # Analyze bundle size
944
- npm run analyze
945
- ```
946
-
947
- ### Deployment
948
-
949
- ```bash
950
- # Deploy using TagadaPay CLI
951
- npx @tagadapay/plugin-cli deploy
952
-
953
- # Deploy specific environment
954
- npx @tagadapay/plugin-cli deploy --env production
955
- ```
956
-
957
- ## 🔧 Configuration
958
-
959
- ### Plugin Configuration
960
-
961
- ```json
962
- {
963
- "name": "My Checkout Plugin",
964
- "version": "1.0.0",
965
- "description": "Custom checkout experience",
966
- "main": "dist/index.js",
967
- "tagadapay": {
968
- "type": "checkout",
969
- "mode": "direct",
970
- "framework": "react"
971
- }
972
- }
973
- ```
974
-
975
- ## 🔐 Security
976
-
977
- ### Best Practices
978
-
979
- - Never store sensitive payment data
980
- - Always validate user inputs
981
- - Use HTTPS in production
982
- - Implement proper error handling
983
- - Follow PCI DSS guidelines
984
-
985
- ### Token Management
986
-
987
- ```typescript
988
- // ✅ Good: Use tokenized payments
989
- const paymentToken = await tokenizePayment(cardData);
990
- await processPayment({ token: paymentToken });
991
-
992
- // ❌ Bad: Never store raw card data
993
- // const cardNumber = '4111111111111111'; // Don't do this
994
- ```
995
-
996
- ## 📱 Mobile Optimization
997
-
998
- ### Responsive Design
999
-
1000
- ```css
1001
- .checkout-container {
1002
- max-width: 600px;
1003
- margin: 0 auto;
1004
- padding: 16px;
1005
- }
1006
-
1007
- @media (max-width: 768px) {
1008
- .checkout-container {
1009
- padding: 8px;
1010
- }
1011
-
1012
- .checkout-form {
1013
- font-size: 16px; /* Prevent zoom on iOS */
1014
- }
1015
- }
1016
- ```
1017
-
1018
- ### Touch Interactions
1019
-
1020
- ```typescript
1021
- const handleTouchStart = (e) => {
1022
- // Optimize for touch devices
1023
- e.preventDefault();
1024
- // Handle touch interaction
1025
- };
1026
- ```
1027
-
1028
- ## 🌐 Internationalization
1029
-
1030
- ### Multi-language Support
1031
-
1032
- ```typescript
1033
- import { useTranslation } from '@tagadapay/plugin-sdk';
1034
-
1035
- function CheckoutForm() {
1036
- const { t } = useTranslation();
1037
-
1038
- return (
1039
- <form>
1040
- <label>{t('checkout.email')}</label>
1041
- <input type="email" placeholder={t('checkout.email_placeholder')} />
1042
- </form>
1043
- );
1044
- }
1045
- ```
1046
-
1047
- ### Currency Support
1048
-
1049
- ```typescript
1050
- import { useCurrency } from '@tagadapay/plugin-sdk';
1051
-
1052
- function PriceDisplay({ amount }) {
1053
- const { formatPrice, currency } = useCurrency();
1054
-
1055
- return <span>{formatPrice(amount, currency)}</span>;
1056
- }
1057
- ```
1058
-
1059
- ## 📊 Analytics & Monitoring
1060
-
1061
- ### Event Tracking
1062
-
1063
- ```typescript
1064
- import { trackEvent } from '@tagadapay/plugin-sdk';
1065
-
1066
- // Track user interactions
1067
- trackEvent('checkout_started', {
1068
- product_id: 'prod_123',
1069
- value: 2999,
1070
- currency: 'USD',
1071
- });
1072
-
1073
- // Track conversions
1074
- trackEvent('purchase_completed', {
1075
- transaction_id: 'txn_456',
1076
- value: 2999,
1077
- currency: 'USD',
1078
- });
1079
- ```
1080
-
1081
- ### Performance Monitoring
1082
-
1083
- ```typescript
1084
- import { performance } from '@tagadapay/plugin-sdk';
1085
-
1086
- // Measure load times
1087
- performance.mark('checkout-start');
1088
- // ... checkout logic
1089
- performance.mark('checkout-end');
1090
- performance.measure('checkout-duration', 'checkout-start', 'checkout-end');
1091
- ```
1092
-
1093
- ## 🤝 Contributing
1094
-
1095
- ### Development Setup
1096
-
1097
- ```bash
1098
- # Clone the repository
1099
- git clone https://github.com/tagadapay/plugin-sdk.git
1100
-
1101
- # Install dependencies
1102
- npm install
1103
-
1104
- # Start development
1105
- npm run dev
1106
- ```
1107
-
1108
- ### Submitting Changes
1109
-
1110
- 1. Fork the repository
1111
- 2. Create a feature branch
1112
- 3. Make your changes
1113
- 4. Add tests
1114
- 5. Submit a pull request
1115
-
1116
- ## 📄 License
1117
-
1118
- MIT License - see [LICENSE](./LICENSE) for details.
1119
-
1120
- ## 🆘 Support
1121
-
1122
- - **Documentation**: [docs.tagadapay.com](https://docs.tagadapay.com)
1123
- - **Discord**: [discord.gg/tagadapay](https://discord.gg/tagadapay)
1124
- - **Email**: support@tagadapay.com
1125
- - **GitHub Issues**: [github.com/tagadapay/plugin-sdk/issues](https://github.com/tagadapay/plugin-sdk/issues)
1126
-
1127
- ---
1128
-
1129
- Built with ❤️ by the TagadaPay team
1
+ # TagadaPay Plugin SDK
2
+
3
+ A comprehensive React SDK for building plugins on the TagadaPay platform. Create custom checkout experiences, landing pages, and interactive components with automatic configuration injection and advanced routing capabilities.
4
+
5
+ > **🚀 V2 Now Available!** The new V2 architecture features TanStack Query integration, improved TypeScript support, and better performance. [See V2 Architecture](#-v2-architecture) for details.
6
+ >
7
+ > **Recommended**: Use `@tagadapay/plugin-sdk/v3` for new projects. V1 (`/react`) is still supported for existing projects.
8
+
9
+ ## 📚 Documentation
10
+
11
+ ### V2 Core APIs (Recommended)
12
+
13
+ - **[V2 Architecture](#-v2-architecture)** - New TanStack Query-based architecture
14
+ - **[V2 Examples](#-v2-examples)** - Complete examples using the new V2 hooks
15
+ - **[useCheckout (V2)](#usecheckout)** - TanStack Query-based checkout management
16
+ - **[useOffers (V2)](#useoffers)** - Dynamic pricing with automatic caching
17
+ - **[useProducts (V2)](#useproducts)** - Product data management
18
+ - **[useStoreConfig (V2)](#usestoreconfig)** - Store configuration with automatic caching
19
+ - **[usePayment (V2)](#usepayment)** - Payment processing with 3DS support
20
+ - **[V2 Utility Functions](#v2-utility-functions--advanced-features)** - Enhanced utilities and TanStack Query integration
21
+
22
+ ### Legacy V1 APIs (Still Supported)
23
+
24
+ - **[useCheckout (V1)](./docs/README-useCheckout.md)** - Legacy checkout state management
25
+ - **[setCheckoutInfo](./docs/README-setCheckoutInfo.md)** - Customer information and validation
26
+ - **[useOffers (V1)](./docs/README-useOffers.md)** - Legacy dynamic pricing
27
+ - **[usePromotionCodes](./docs/README-usePromotionCodes.md)** - Legacy promotion code management
28
+ - **[Money utilities](./docs/README-money.md)** - Currency formatting and calculations
29
+ - **[URL utilities](./docs/README-urlUtils.md)** - Navigation and routing helpers
30
+
31
+ ### Plugin Development
32
+
33
+ - **[Plugin Configuration](./docs/PLUGIN_CONFIG.md)** - How to access store context, config, and branding
34
+ - **[Initialization Modes](#-initialization-modes)** - Choose between blocking and non-blocking initialization
35
+ - **[Google Autocomplete](./docs/README-google-autocomplete.md)** - Address autocomplete with Google Places API
36
+ - **[ISO Data](./docs/README-iso-data.md)** - Country and region data with Google integration
37
+
38
+ ### Examples
39
+
40
+ - **[Vite Checkout Demo](../checkout-vite)** - Complete checkout implementation
41
+
42
+ ## 🏗️ Building a Plugin
43
+
44
+ ### Plugin Structure
45
+
46
+ Every TagadaPay plugin follows this simple structure:
47
+
48
+ ```
49
+ my-plugin/
50
+ ├── plugin.manifest.json # Plugin metadata & routing
51
+ ├── .local.json # Local dev config (auto-injected in production)
52
+ ├── config/ # Optional deployment configs
53
+ │ ├── theme-green.json # Config variant A
54
+ │ └── theme-blue.json # Config variant B
55
+ ├── src/
56
+ │ └── App.tsx # Your plugin code
57
+ └── dist/ # Built plugin files
58
+ ```
59
+
60
+ ### Configuration Flow
61
+
62
+ ```mermaid
63
+ graph TD
64
+ A[🛠️ Local Development] --> B[.local.json]
65
+ A --> C[config/*.json]
66
+ B --> D[usePluginConfig()]
67
+ C --> D
68
+
69
+ E[🚀 Production] --> F[Platform Injection]
70
+ F --> G[HTTP Headers & Meta Tags]
71
+ G --> D
72
+
73
+ D --> H[Your Plugin Component]
74
+
75
+ style A fill:#e1f5fe
76
+ style E fill:#f3e5f5
77
+ style D fill:#fff3e0
78
+ style H fill:#e8f5e8
79
+ ```
80
+
81
+ ### Essential Files
82
+
83
+ #### 1. **`plugin.manifest.json`** - Plugin Metadata
84
+
85
+ ```json
86
+ {
87
+ "pluginId": "my-awesome-plugin",
88
+ "name": "My Awesome Plugin",
89
+ "version": "1.0.0",
90
+ "mode": "direct-mode",
91
+ "router": {
92
+ "basePath": "/",
93
+ "matcher": ".*",
94
+ "excluder": "/checkout"
95
+ }
96
+ }
97
+ ```
98
+
99
+ #### 2. **`.local.json`** - Local Development Context
100
+
101
+ ```json
102
+ {
103
+ "storeId": "store_abc123",
104
+ "accountId": "acc_xyz789",
105
+ "basePath": "/"
106
+ }
107
+ ```
108
+
109
+ > ⚠️ **Auto-managed**: This file is only for local dev. In production, the platform injects this data automatically.
110
+
111
+ #### 3. **`config/my-theme.json`** - Optional Deployment Config
112
+
113
+ ```json
114
+ {
115
+ "configName": "green-theme",
116
+ "branding": {
117
+ "primaryColor": "#059669",
118
+ "companyName": "My Store",
119
+ "logoUrl": "https://example.com/logo.png"
120
+ },
121
+ "features": {
122
+ "enableChat": true,
123
+ "maxItems": 10
124
+ }
125
+ }
126
+ ```
127
+
128
+ > 📝 **Note**: Config can contain any keys you need - the SDK doesn't enforce a specific structure.
129
+
130
+ ## 🚀 Quick Start
131
+
132
+ ### Installation
133
+
134
+ ```bash
135
+ npm install @tagadapay/plugin-sdk
136
+ ```
137
+
138
+ ### Basic Plugin Setup
139
+
140
+ ```tsx
141
+ import React from 'react';
142
+ import {
143
+ TagadaProvider,
144
+ usePluginConfig,
145
+ useGoogleAutocomplete,
146
+ useISOData,
147
+ useCheckout,
148
+ formatMoney,
149
+ } from '@tagadapay/plugin-sdk/v3';
150
+
151
+ function MyPlugin() {
152
+ const { config, storeId, accountId, basePath, loading } = usePluginConfig();
153
+
154
+ // Optional: Add address autocomplete
155
+ const { searchPlaces, predictions } = useGoogleAutocomplete({
156
+ apiKey: config?.googleMapsApiKey || 'YOUR_API_KEY',
157
+ });
158
+
159
+ // Optional: Add country/region data
160
+ const { countries } = useISOData('en');
161
+
162
+ // V2: Use TanStack Query-based checkout hook
163
+ const { checkout, init, updateLineItems, isLoading } = useCheckout({
164
+ checkoutToken: 'your-checkout-token',
165
+ });
166
+
167
+ if (loading) return <div>Loading...</div>;
168
+
169
+ return (
170
+ <div style={{ '--primary': config?.branding?.primaryColor }}>
171
+ <h1>Welcome to {config?.branding?.companyName}</h1>
172
+ <p>Store: {storeId}</p>
173
+ <p>Base Path: {basePath}</p>
174
+ <p>Available Countries: {Object.keys(countries).length}</p>
175
+
176
+ {checkout && (
177
+ <div>
178
+ <h2>Checkout Total: {formatMoney(checkout.summary.total, checkout.currency)}</h2>
179
+ <p>Items: {checkout.lineItems.length}</p>
180
+ </div>
181
+ )}
182
+ </div>
183
+ );
184
+ }
185
+
186
+ // Wrap your plugin with TagadaProvider
187
+ function App() {
188
+ return (
189
+ <TagadaProvider>
190
+ <MyPlugin />
191
+ </TagadaProvider>
192
+ );
193
+ }
194
+
195
+ export default App;
196
+ ```
197
+
198
+ ## 🏗️ V2 Architecture
199
+
200
+ ### What's New in V2
201
+
202
+ The TagadaPay Plugin SDK v3 introduces a clean architecture with significant improvements:
203
+
204
+ #### **🔄 TanStack Query Integration**
205
+
206
+ - **Automatic Caching**: All API calls are cached and synchronized across components
207
+ - **Background Refetching**: Data stays fresh with automatic background updates
208
+ - **Optimistic Updates**: Instant UI feedback with automatic rollback on errors
209
+ - **Request Deduplication**: Multiple components can use the same data without duplicate requests
210
+
211
+ #### **🏗️ Clean Architecture**
212
+
213
+ - **Core Layer**: Pure functions and API clients without React dependencies
214
+ - **React Layer**: Hooks and components that use core functions
215
+ - **Better Testing**: Easier to test business logic separately from UI logic
216
+
217
+ #### **📦 Import Paths**
218
+
219
+ ```tsx
220
+ // V2 (Recommended)
221
+ import { useCheckout, useOffers, TagadaProvider } from '@tagadapay/plugin-sdk/v3';
222
+
223
+ // Legacy (Still supported)
224
+ import { useCheckout, useOffers, TagadaProvider } from '@tagadapay/plugin-sdk/react';
225
+ ```
226
+
227
+ #### **🔧 Enhanced Developer Experience**
228
+
229
+ - **TypeScript First**: Better type inference and autocomplete
230
+ - **Debug Tools**: Built-in debug drawer for development
231
+ - **Performance**: Reduced bundle size and better performance
232
+
233
+ ### Migration from V1
234
+
235
+ Most hooks have the same names but improved APIs:
236
+
237
+ ```tsx
238
+ // V1 Pattern
239
+ const { checkout, loading, error } = useCheckout();
240
+
241
+ // V2 Pattern (TanStack Query)
242
+ const { checkout, isLoading, error, refresh } = useCheckout({
243
+ checkoutToken: 'token',
244
+ enabled: true,
245
+ });
246
+ ```
247
+
248
+ ### 📚 V2 Examples
249
+
250
+ #### Complete Checkout Flow
251
+
252
+ ```tsx
253
+ import React, { useState } from 'react';
254
+ import {
255
+ TagadaProvider,
256
+ useCheckout,
257
+ useProducts,
258
+ usePluginConfig,
259
+ formatMoney,
260
+ } from '@tagadapay/plugin-sdk/v3';
261
+
262
+ function CheckoutPage() {
263
+ const [checkoutToken, setCheckoutToken] = useState<string>();
264
+ const { config } = usePluginConfig();
265
+
266
+ // Load products
267
+ const { products, isLoading: productsLoading } = useProducts({
268
+ storeId: config.storeId,
269
+ });
270
+
271
+ // Initialize checkout when needed
272
+ const {
273
+ checkout,
274
+ isLoading: checkoutLoading,
275
+ init,
276
+ updateLineItems,
277
+ updateCustomer,
278
+ applyPromotionCode,
279
+ } = useCheckout({
280
+ checkoutToken,
281
+ enabled: !!checkoutToken,
282
+ });
283
+
284
+ const handleInitCheckout = async () => {
285
+ if (!products?.length) return;
286
+
287
+ const result = await init({
288
+ lineItems: [
289
+ {
290
+ variantId: products[0].variants[0].id,
291
+ quantity: 1,
292
+ },
293
+ ],
294
+ });
295
+
296
+ setCheckoutToken(result.checkoutToken);
297
+ };
298
+
299
+ const handleApplyPromo = async (code: string) => {
300
+ try {
301
+ await applyPromotionCode(code);
302
+ // TanStack Query automatically refetches and updates the UI
303
+ } catch (error) {
304
+ console.error('Failed to apply promo:', error);
305
+ }
306
+ };
307
+
308
+ if (productsLoading) return <div>Loading products...</div>;
309
+
310
+ return (
311
+ <div>
312
+ <h1>Checkout</h1>
313
+
314
+ {!checkoutToken ? (
315
+ <button onClick={handleInitCheckout}>Start Checkout</button>
316
+ ) : (
317
+ <div>
318
+ {checkoutLoading ? (
319
+ <div>Loading checkout...</div>
320
+ ) : checkout ? (
321
+ <div>
322
+ <h2>Order Summary</h2>
323
+ <p>Total: {formatMoney(checkout.summary.total, checkout.currency)}</p>
324
+ <p>Items: {checkout.lineItems.length}</p>
325
+
326
+ <div>
327
+ <input
328
+ type="text"
329
+ placeholder="Promo code"
330
+ onKeyDown={(e) => {
331
+ if (e.key === 'Enter') {
332
+ handleApplyPromo(e.currentTarget.value);
333
+ }
334
+ }}
335
+ />
336
+ </div>
337
+ </div>
338
+ ) : null}
339
+ </div>
340
+ )}
341
+ </div>
342
+ );
343
+ }
344
+
345
+ function App() {
346
+ return (
347
+ <TagadaProvider>
348
+ <CheckoutPage />
349
+ </TagadaProvider>
350
+ );
351
+ }
352
+ ```
353
+
354
+ #### Multi-Component Data Sharing
355
+
356
+ ```tsx
357
+ import React from 'react';
358
+ import { TagadaProvider, useCheckout, useOffers, formatMoney } from '@tagadapay/plugin-sdk/v3';
359
+
360
+ // Component 1: Cart Summary
361
+ function CartSummary({ checkoutToken }: { checkoutToken: string }) {
362
+ const { checkout, isLoading } = useCheckout({ checkoutToken });
363
+
364
+ if (isLoading) return <div>Loading...</div>;
365
+ if (!checkout) return null;
366
+
367
+ return (
368
+ <div>
369
+ <h3>Cart ({checkout.lineItems.length} items)</h3>
370
+ <p>Total: {formatMoney(checkout.summary.total, checkout.currency)}</p>
371
+ </div>
372
+ );
373
+ }
374
+
375
+ // Component 2: Available Offers (shares same checkout data automatically)
376
+ function OffersPanel({ checkoutToken }: { checkoutToken: string }) {
377
+ const { checkout } = useCheckout({ checkoutToken }); // Same data, no extra request!
378
+ const { offers, isLoading } = useOffers({
379
+ storeId: checkout?.storeId,
380
+ });
381
+
382
+ if (isLoading) return <div>Loading offers...</div>;
383
+
384
+ return (
385
+ <div>
386
+ <h3>Special Offers</h3>
387
+ {offers?.map((offer) => (
388
+ <div key={offer.id}>
389
+ <p>{offer.title}</p>
390
+ <p>Save {formatMoney(offer.discount, checkout?.currency || 'USD')}</p>
391
+ </div>
392
+ ))}
393
+ </div>
394
+ );
395
+ }
396
+
397
+ // Main component
398
+ function CheckoutWithOffers() {
399
+ const checkoutToken = 'your-checkout-token';
400
+
401
+ return (
402
+ <div style={{ display: 'flex', gap: '20px' }}>
403
+ <CartSummary checkoutToken={checkoutToken} />
404
+ <OffersPanel checkoutToken={checkoutToken} />
405
+ </div>
406
+ );
407
+ }
408
+ ```
409
+
410
+ #### Optimistic Updates
411
+
412
+ ```tsx
413
+ import React from 'react';
414
+ import { useCheckout } from '@tagadapay/plugin-sdk/v3';
415
+
416
+ function QuantitySelector({
417
+ checkoutToken,
418
+ variantId,
419
+ currentQuantity,
420
+ }: {
421
+ checkoutToken: string;
422
+ variantId: string;
423
+ currentQuantity: number;
424
+ }) {
425
+ const { checkout, setItemQuantity, updateLineItemsOptimistic } = useCheckout({ checkoutToken });
426
+
427
+ const handleQuantityChange = async (newQuantity: number) => {
428
+ // 1. Optimistic update (instant UI feedback)
429
+ const updatedItems =
430
+ checkout?.lineItems.map((item) =>
431
+ item.variantId === variantId ? { ...item, quantity: newQuantity } : item,
432
+ ) || [];
433
+
434
+ updateLineItemsOptimistic(updatedItems);
435
+
436
+ // 2. Server update (with automatic rollback on error)
437
+ try {
438
+ await setItemQuantity(variantId, newQuantity);
439
+ // TanStack Query automatically syncs the real data
440
+ } catch (error) {
441
+ // Automatic rollback to previous state
442
+ console.error('Failed to update quantity:', error);
443
+ }
444
+ };
445
+
446
+ return (
447
+ <div>
448
+ <button onClick={() => handleQuantityChange(currentQuantity - 1)}>-</button>
449
+ <span>{currentQuantity}</span>
450
+ <button onClick={() => handleQuantityChange(currentQuantity + 1)}>+</button>
451
+ </div>
452
+ );
453
+ }
454
+ ```
455
+
456
+ ## 🚀 Initialization Modes
457
+
458
+ The TagadaProvider supports two initialization modes to give you control over when your components render:
459
+
460
+ ### Non-Blocking Mode (Default - Recommended)
461
+
462
+ ```tsx
463
+ <TagadaProvider>
464
+ {/* Children render immediately after config loads */}
465
+ <YourApp />
466
+ </TagadaProvider>
467
+
468
+ // OR explicitly
469
+ <TagadaProvider blockUntilSessionReady={false}>
470
+ <YourApp />
471
+ </TagadaProvider>
472
+ ```
473
+
474
+ **Flow:**
475
+
476
+ 1. **Phase 1 & 2** ✅ Plugin config loads → Children render immediately
477
+ 2. **Phase 3** 🔄 Session initialization runs in background
478
+ 3. **API calls** 🔄 Hooks automatically wait for session to be ready
479
+
480
+ **Benefits:**
481
+
482
+ - ⚡ **Faster rendering** - UI appears immediately
483
+ - 🎯 **Better UX** - Show loading states while session initializes
484
+ - 🔄 **Automatic waiting** - Hooks handle session timing for you
485
+
486
+ ### Blocking Mode (Legacy Behavior)
487
+
488
+ ```tsx
489
+ <TagadaProvider blockUntilSessionReady={true}>
490
+ {/* Children render only after ALL initialization completes */}
491
+ <YourApp />
492
+ </TagadaProvider>
493
+ ```
494
+
495
+ **Flow:**
496
+
497
+ 1. **All Phases** ⏳ Config + Session must complete before children render
498
+ 2. **API calls** ✅ Work immediately (no waiting needed)
499
+
500
+ **Use when:**
501
+
502
+ - 🔄 **Migrating** from older SDK versions
503
+ - 🎯 **Simple apps** that don't need progressive loading
504
+
505
+ ### Console Logs
506
+
507
+ The SDK logs help you understand which mode you're using:
508
+
509
+ **Non-blocking mode:**
510
+
511
+ ```
512
+ ✅ Phase 1 & 2 Complete - Plugin config loaded
513
+ 🚀 Non-blocking mode: Children can now render - Phase 3 will continue in background
514
+ 🔄 [useCheckout] Waiting for session initialization to complete...
515
+ ✅ Phase 3 Complete - Session initialization completed successfully
516
+ ✅ [useCheckout] Session initialized, proceeding with checkout init
517
+ ```
518
+
519
+ **Blocking mode:**
520
+
521
+ ```
522
+ ✅ Phase 1 & 2 Complete - Plugin config loaded
523
+ ⏳ Blocking mode: Children will render after Phase 3 completes
524
+ ✅ Phase 3 Complete - Session initialization completed successfully
525
+ ```
526
+
527
+ ### TagadaProvider API
528
+
529
+ ```tsx
530
+ interface TagadaProviderProps {
531
+ children: ReactNode;
532
+ environment?: 'local' | 'development' | 'staging' | 'production';
533
+ customApiConfig?: Partial<EnvironmentConfig>;
534
+ debugMode?: boolean;
535
+ localConfig?: string; // LOCAL DEV ONLY: Override config variant
536
+ blockUntilSessionReady?: boolean; // Default: false
537
+
538
+ // V2 Specific Options
539
+ queryClientConfig?: QueryClientConfig; // TanStack Query configuration
540
+ enableDevtools?: boolean; // Enable React Query Devtools
541
+ }
542
+ ```
543
+
544
+ | Prop | Type | Default | Description |
545
+ | ------------------------ | ----------- | -------------------- | ------------------------------ |
546
+ | `children` | `ReactNode` | - | Your plugin components |
547
+ | `environment` | `string` | auto-detect | Override environment detection |
548
+ | `customApiConfig` | `object` | - | Custom API configuration |
549
+ | `debugMode` | `boolean` | auto (false in prod) | Enable debug features & drawer |
550
+ | `localConfig` | `string` | `'default'` | Config variant for local dev |
551
+ | `blockUntilSessionReady` | `boolean` | `false` | Use legacy blocking behavior |
552
+ | `queryClientConfig` | `object` | - | **V2**: TanStack Query config |
553
+ | `enableDevtools` | `boolean` | `false` | **V2**: React Query Devtools |
554
+
555
+ #### V2 Enhanced Provider Features
556
+
557
+ ```tsx
558
+ import { TagadaProvider } from '@tagadapay/plugin-sdk/v3';
559
+
560
+ function App() {
561
+ return (
562
+ <TagadaProvider
563
+ debugMode={true}
564
+ enableDevtools={true} // Shows React Query Devtools
565
+ queryClientConfig={{
566
+ defaultOptions: {
567
+ queries: {
568
+ staleTime: 5 * 60 * 1000, // 5 minutes
569
+ cacheTime: 10 * 60 * 1000, // 10 minutes
570
+ },
571
+ },
572
+ }}
573
+ >
574
+ <YourApp />
575
+ </TagadaProvider>
576
+ );
577
+ }
578
+ ```
579
+
580
+ > **Version Compatibility:** V2 features require `@tagadapay/plugin-sdk/v3`. The `blockUntilSessionReady` option was added in v2.3.0. For older versions, the blocking behavior was the default and only option.
581
+
582
+ ### Development vs Production
583
+
584
+ | Environment | Store/Account ID | Deployment Config | How it Works |
585
+ | -------------- | ---------------- | ----------------- | ------------------ |
586
+ | **Local Dev** | `.local.json` | `config/*.json` | Files on disk |
587
+ | **Production** | HTTP Headers | Meta Tags | Platform injection |
588
+
589
+ ```tsx
590
+ // ✅ ALWAYS use hooks - works in both environments
591
+ const { storeId, accountId, basePath, config } = usePluginConfig();
592
+
593
+ // ❌ NEVER access directly
594
+ // const config = window.__PLUGIN_CONFIG__; // Doesn't exist!
595
+ ```
596
+
597
+ ## 🎯 Key Features
598
+
599
+ ### 🔧 **Plugin Configuration System**
600
+
601
+ - **Automatic Context Injection** - Store ID, Account ID, and custom config
602
+ - **Development & Production** - Seamless environment switching
603
+ - **Generic Configuration** - Support for any JSON structure
604
+ - **React Hooks** - Clean, type-safe configuration access
605
+
606
+ ### 💳 **Payment Processing**
607
+
608
+ - Secure tokenized payments
609
+ - Multiple payment method support
610
+ - Real-time validation
611
+ - PCI compliance
612
+
613
+ ### 🌍 **Address & Location**
614
+
615
+ - **Google Places Autocomplete** - Automatic API loading and address parsing
616
+ - **ISO Country/Region Data** - Complete ISO 3166-1/3166-2 database
617
+ - **Address Validation** - Structured component extraction
618
+ - **Multi-language Support** - 11+ languages for international users
619
+
620
+ ### 🛒 **E-commerce Features**
621
+
622
+ - Dynamic pricing and promotional offers
623
+ - Cart management and tax calculations
624
+ - Currency conversion and formatting
625
+ - Customer profile management
626
+
627
+ ### 🎨 **UI & Development**
628
+
629
+ - Pre-built React components
630
+ - Customizable themes with configuration
631
+ - Mobile-optimized and accessible
632
+ - TypeScript support throughout
633
+
634
+ ## 📖 API Reference
635
+
636
+ ### V2 Core Hooks (TanStack Query-based)
637
+
638
+ #### useCheckout()
639
+
640
+ Primary hook for checkout state management using TanStack Query for automatic caching and synchronization.
641
+
642
+ ```typescript
643
+ const {
644
+ // Query data
645
+ checkout, // CheckoutData | undefined
646
+ isLoading, // boolean
647
+ error, // Error | null
648
+ isSuccess, // boolean
649
+
650
+ // Actions
651
+ init, // (params: CheckoutInitParams) => Promise<{checkoutUrl, checkoutSession, checkoutToken}>
652
+ refresh, // () => Promise<void>
653
+
654
+ // Checkout operations
655
+ updateLineItems, // (lineItems: CheckoutLineItem[]) => Promise<any>
656
+ updateLineItemsOptimistic, // (lineItems: CheckoutLineItem[]) => void
657
+ setItemQuantity, // (variantId: string, quantity: number, priceId?: string) => Promise<any>
658
+ updateCustomer, // (data: {email: string, acceptsMarketing?: boolean}) => Promise<any>
659
+ applyPromotionCode, // (code: string) => Promise<any>
660
+ removePromotion, // (promotionId: string) => Promise<any>
661
+ } = useCheckout({ checkoutToken, enabled });
662
+ ```
663
+
664
+ #### useOffers()
665
+
666
+ Hook for managing dynamic offers and pricing with automatic cache management.
667
+
668
+ ```typescript
669
+ const {
670
+ // Query data
671
+ offers, // Offer[] | undefined
672
+ isLoading, // boolean
673
+ error, // Error | null
674
+
675
+ // Actions
676
+ refresh, // () => Promise<void>
677
+ } = useOffers({ storeId, enabled });
678
+ ```
679
+
680
+ #### usePromotions()
681
+
682
+ Hook for managing promotion codes in checkout sessions with TanStack Query.
683
+
684
+ ```typescript
685
+ const {
686
+ // Query data
687
+ promotions, // Promotion[] | undefined
688
+ isLoading, // boolean
689
+ error, // Error | null
690
+
691
+ // Actions
692
+ refresh, // () => Promise<void>
693
+ } = usePromotions({ checkoutToken, enabled });
694
+ ```
695
+
696
+ #### useProducts()
697
+
698
+ Hook for product data management with caching.
699
+
700
+ ```typescript
701
+ const {
702
+ // Query data
703
+ products, // Product[] | undefined
704
+ isLoading, // boolean
705
+ error, // Error | null
706
+
707
+ // Actions
708
+ refresh, // () => Promise<void>
709
+ } = useProducts({ storeId, enabled });
710
+ ```
711
+
712
+ #### useStoreConfig()
713
+
714
+ Hook for fetching store configuration with automatic caching.
715
+
716
+ ```typescript
717
+ const {
718
+ // Query data
719
+ storeConfig, // StoreConfig | undefined
720
+ isLoading, // boolean
721
+ error, // Error | null
722
+ isSuccess, // boolean
723
+
724
+ // Actions
725
+ refetch, // () => Promise<void>
726
+ } = useStoreConfig({ storeId, enabled });
727
+ ```
728
+
729
+ **Example:**
730
+
731
+ ```tsx
732
+ import { useStoreConfig } from '@tagadapay/plugin-sdk/v3';
733
+
734
+ function StoreInfo() {
735
+ const { storeConfig, isLoading } = useStoreConfig();
736
+
737
+ if (isLoading) return <div>Loading...</div>;
738
+
739
+ return (
740
+ <div>
741
+ <h1>{storeConfig?.storeName}</h1>
742
+ <p>Currency: {storeConfig?.currency}</p>
743
+ </div>
744
+ );
745
+ }
746
+ ```
747
+
748
+ See [useStoreConfig documentation](./docs/README-useStoreConfig.md) for more details.
749
+
750
+ #### useOrder()
751
+
752
+ Hook for order management and tracking.
753
+
754
+ ```typescript
755
+ const {
756
+ // Query data
757
+ order, // Order | undefined
758
+ isLoading, // boolean
759
+ error, // Error | null
760
+
761
+ // Actions
762
+ refresh, // () => Promise<void>
763
+ } = useOrder({ orderId, enabled });
764
+ ```
765
+
766
+ #### usePostPurchases()
767
+
768
+ Hook for post-purchase offers management.
769
+
770
+ ```typescript
771
+ const {
772
+ // Query data
773
+ postPurchases, // PostPurchaseOffer[] | undefined
774
+ isLoading, // boolean
775
+ error, // Error | null
776
+
777
+ // Actions
778
+ refresh, // () => Promise<void>
779
+ } = usePostPurchases({ orderId, enabled });
780
+ ```
781
+
782
+ #### usePayment()
783
+
784
+ Hook for payment processing with 3DS support.
785
+
786
+ ```typescript
787
+ const {
788
+ // Payment methods
789
+ processPayment, // (options: PaymentOptions) => Promise<PaymentResponse>
790
+ processApplePayPayment, // (token: ApplePayToken) => Promise<PaymentResponse>
791
+
792
+ // State
793
+ isProcessing, // boolean
794
+ error, // Error | null
795
+ } = usePayment();
796
+ ```
797
+
798
+ ### V2 Utility Functions & Advanced Features
799
+
800
+ #### TanStack Query Integration
801
+
802
+ V2 provides direct access to TanStack Query features for advanced use cases:
803
+
804
+ ```typescript
805
+ import {
806
+ useApiQuery,
807
+ useApiMutation,
808
+ useInvalidateQuery,
809
+ usePreloadQuery,
810
+ queryKeys,
811
+ } from '@tagadapay/plugin-sdk/v3';
812
+
813
+ // Custom API queries
814
+ const { data, isLoading } = useApiQuery({
815
+ queryKey: ['custom', 'endpoint'],
816
+ queryFn: () => apiClient.get('/custom-endpoint'),
817
+ });
818
+
819
+ // Mutations with automatic cache updates
820
+ const mutation = useApiMutation({
821
+ mutationFn: (data) => apiClient.post('/update', data),
822
+ onSuccess: () => {
823
+ // Invalidate related queries
824
+ invalidateQuery(['checkout']);
825
+ },
826
+ });
827
+
828
+ // Preload data for better UX
829
+ const preloadCheckout = usePreloadQuery();
830
+ preloadCheckout({
831
+ queryKey: queryKeys.checkout(checkoutToken),
832
+ queryFn: () => checkoutResource.get(checkoutToken),
833
+ });
834
+ ```
835
+
836
+ #### Money Utilities
837
+
838
+ Enhanced money formatting with better TypeScript support:
839
+
840
+ ```typescript
841
+ import { formatMoney, convertCurrency, getCurrencyInfo } from '@tagadapay/plugin-sdk/v3';
842
+
843
+ // Format money with automatic currency detection
844
+ const formatted = formatMoney(2999, 'USD'); // "$29.99"
845
+ const simple = formatSimpleMoney(2999, 'EUR'); // "29.99"
846
+ const withoutSymbol = formatMoneyWithoutSymbol(2999, 'GBP'); // "29.99"
847
+
848
+ // Currency conversion (if rates available)
849
+ const converted = convertCurrency(2999, 'USD', 'EUR'); // 2699
850
+
851
+ // Get currency information
852
+ const currencyInfo = getCurrencyInfo('USD');
853
+ // { symbol: '$', code: 'USD', minorUnits: 2 }
854
+
855
+ // Convert between major and minor units
856
+ const major = minorUnitsToMajorUnits(2999); // 29.99
857
+ const minor = moneyStringOrNumberToMinorUnits('29.99'); // 2999
858
+ ```
859
+
860
+ #### Core Functions (Pure Functions)
861
+
862
+ V2 separates core business logic from React hooks:
863
+
864
+ ```typescript
865
+ import {
866
+ CheckoutResource,
867
+ ProductsResource,
868
+ PaymentsResource,
869
+ PluginConfigUtils,
870
+ } from '@tagadapay/plugin-sdk/v3';
871
+
872
+ // Use core functions directly (useful for server-side or non-React contexts)
873
+ const checkoutResource = new CheckoutResource(apiClient);
874
+ const checkout = await checkoutResource.get(checkoutToken);
875
+
876
+ // Plugin config utilities
877
+ const config = PluginConfigUtils.getPluginConfig(rawConfig, context);
878
+ const isValid = PluginConfigUtils.validateConfig(config);
879
+ ```
880
+
881
+ #### Debug Tools
882
+
883
+ V2 includes built-in debugging tools:
884
+
885
+ ```tsx
886
+ import { TagadaProvider } from '@tagadapay/plugin-sdk/v3';
887
+
888
+ function App() {
889
+ return (
890
+ <TagadaProvider
891
+ debugMode={true} // Shows debug drawer in development
892
+ environment="development"
893
+ >
894
+ <YourApp />
895
+ </TagadaProvider>
896
+ );
897
+ }
898
+ ```
899
+
900
+ ## 🛠️ Development
901
+
902
+ ### Local Development
903
+
904
+ ```bash
905
+ # Install dependencies
906
+ npm install
907
+
908
+ # Start development server
909
+ npm run dev
910
+
911
+ # Build for production
912
+ npm run build
913
+ ```
914
+
915
+ ### Testing
916
+
917
+ ```bash
918
+ # Run tests
919
+ npm test
920
+
921
+ # Run tests with coverage
922
+ npm run test:coverage
923
+ ```
924
+
925
+ ### Linting
926
+
927
+ ```bash
928
+ # Check code style
929
+ npm run lint
930
+
931
+ # Fix linting issues
932
+ npm run lint:fix
933
+ ```
934
+
935
+ ## 📦 Build & Deploy
936
+
937
+ ### Building Your Plugin
938
+
939
+ ```bash
940
+ # Build optimized bundle
941
+ npm run build
942
+
943
+ # Analyze bundle size
944
+ npm run analyze
945
+ ```
946
+
947
+ ### Deployment
948
+
949
+ ```bash
950
+ # Deploy using TagadaPay CLI
951
+ npx @tagadapay/plugin-cli deploy
952
+
953
+ # Deploy specific environment
954
+ npx @tagadapay/plugin-cli deploy --env production
955
+ ```
956
+
957
+ ## 🔧 Configuration
958
+
959
+ ### Plugin Configuration
960
+
961
+ ```json
962
+ {
963
+ "name": "My Checkout Plugin",
964
+ "version": "1.0.0",
965
+ "description": "Custom checkout experience",
966
+ "main": "dist/index.js",
967
+ "tagadapay": {
968
+ "type": "checkout",
969
+ "mode": "direct",
970
+ "framework": "react"
971
+ }
972
+ }
973
+ ```
974
+
975
+ ## 🔐 Security
976
+
977
+ ### Best Practices
978
+
979
+ - Never store sensitive payment data
980
+ - Always validate user inputs
981
+ - Use HTTPS in production
982
+ - Implement proper error handling
983
+ - Follow PCI DSS guidelines
984
+
985
+ ### Token Management
986
+
987
+ ```typescript
988
+ // ✅ Good: Use tokenized payments
989
+ const paymentToken = await tokenizePayment(cardData);
990
+ await processPayment({ token: paymentToken });
991
+
992
+ // ❌ Bad: Never store raw card data
993
+ // const cardNumber = '4111111111111111'; // Don't do this
994
+ ```
995
+
996
+ ## 📱 Mobile Optimization
997
+
998
+ ### Responsive Design
999
+
1000
+ ```css
1001
+ .checkout-container {
1002
+ max-width: 600px;
1003
+ margin: 0 auto;
1004
+ padding: 16px;
1005
+ }
1006
+
1007
+ @media (max-width: 768px) {
1008
+ .checkout-container {
1009
+ padding: 8px;
1010
+ }
1011
+
1012
+ .checkout-form {
1013
+ font-size: 16px; /* Prevent zoom on iOS */
1014
+ }
1015
+ }
1016
+ ```
1017
+
1018
+ ### Touch Interactions
1019
+
1020
+ ```typescript
1021
+ const handleTouchStart = (e) => {
1022
+ // Optimize for touch devices
1023
+ e.preventDefault();
1024
+ // Handle touch interaction
1025
+ };
1026
+ ```
1027
+
1028
+ ## 🌐 Internationalization
1029
+
1030
+ ### Multi-language Support
1031
+
1032
+ ```typescript
1033
+ import { useTranslation } from '@tagadapay/plugin-sdk';
1034
+
1035
+ function CheckoutForm() {
1036
+ const { t } = useTranslation();
1037
+
1038
+ return (
1039
+ <form>
1040
+ <label>{t('checkout.email')}</label>
1041
+ <input type="email" placeholder={t('checkout.email_placeholder')} />
1042
+ </form>
1043
+ );
1044
+ }
1045
+ ```
1046
+
1047
+ ### Currency Support
1048
+
1049
+ ```typescript
1050
+ import { useCurrency } from '@tagadapay/plugin-sdk';
1051
+
1052
+ function PriceDisplay({ amount }) {
1053
+ const { formatPrice, currency } = useCurrency();
1054
+
1055
+ return <span>{formatPrice(amount, currency)}</span>;
1056
+ }
1057
+ ```
1058
+
1059
+ ## 📊 Analytics & Monitoring
1060
+
1061
+ ### Event Tracking
1062
+
1063
+ ```typescript
1064
+ import { trackEvent } from '@tagadapay/plugin-sdk';
1065
+
1066
+ // Track user interactions
1067
+ trackEvent('checkout_started', {
1068
+ product_id: 'prod_123',
1069
+ value: 2999,
1070
+ currency: 'USD',
1071
+ });
1072
+
1073
+ // Track conversions
1074
+ trackEvent('purchase_completed', {
1075
+ transaction_id: 'txn_456',
1076
+ value: 2999,
1077
+ currency: 'USD',
1078
+ });
1079
+ ```
1080
+
1081
+ ### Performance Monitoring
1082
+
1083
+ ```typescript
1084
+ import { performance } from '@tagadapay/plugin-sdk';
1085
+
1086
+ // Measure load times
1087
+ performance.mark('checkout-start');
1088
+ // ... checkout logic
1089
+ performance.mark('checkout-end');
1090
+ performance.measure('checkout-duration', 'checkout-start', 'checkout-end');
1091
+ ```
1092
+
1093
+ ## 🤝 Contributing
1094
+
1095
+ ### Development Setup
1096
+
1097
+ ```bash
1098
+ # Clone the repository
1099
+ git clone https://github.com/tagadapay/plugin-sdk.git
1100
+
1101
+ # Install dependencies
1102
+ npm install
1103
+
1104
+ # Start development
1105
+ npm run dev
1106
+ ```
1107
+
1108
+ ### Submitting Changes
1109
+
1110
+ 1. Fork the repository
1111
+ 2. Create a feature branch
1112
+ 3. Make your changes
1113
+ 4. Add tests
1114
+ 5. Submit a pull request
1115
+
1116
+ ## 📄 License
1117
+
1118
+ MIT License - see [LICENSE](./LICENSE) for details.
1119
+
1120
+ ## 🆘 Support
1121
+
1122
+ - **Documentation**: [docs.tagadapay.com](https://docs.tagadapay.com)
1123
+ - **Discord**: [discord.gg/tagadapay](https://discord.gg/tagadapay)
1124
+ - **Email**: support@tagadapay.com
1125
+ - **GitHub Issues**: [github.com/tagadapay/plugin-sdk/issues](https://github.com/tagadapay/plugin-sdk/issues)
1126
+
1127
+ ---
1128
+
1129
+ Built with ❤️ by the TagadaPay team