@tagadapay/plugin-sdk 2.3.8 → 2.3.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.
@@ -1,51 +1,139 @@
1
- import { useCallback, useState } from 'react';
1
+ import { useCallback, useEffect, useState } from 'react';
2
2
  import { getBasisTheoryApiKey } from '../config/payment';
3
3
  import { useTagadaContext } from '../providers/TagadaProvider';
4
4
  import { usePayment } from './usePayment';
5
5
  export function useApplePay(options = {}) {
6
6
  const [processingPayment, setProcessingPayment] = useState(false);
7
7
  const [error, setError] = useState(null);
8
+ const [isApplePayAvailable, setIsApplePayAvailable] = useState(false);
8
9
  const { createApplePayPaymentInstrument, processApplePayPayment } = usePayment();
9
10
  const { environment, apiService } = useTagadaContext();
10
11
  // Get API key from environment
11
12
  const apiKey = getBasisTheoryApiKey(environment?.environment || 'local');
12
- // Check if Apple Pay is available
13
- const isApplePayAvailable = (() => {
14
- if (typeof window === 'undefined')
15
- return false;
16
- // Check if ApplePaySession is available
17
- const hasApplePaySession = !!window.ApplePaySession;
18
- if (!hasApplePaySession) {
19
- // In development, simulate Apple Pay availability for UI testing
20
- const isDevelopment = process.env.NODE_ENV === 'development' ||
21
- window.location.hostname === 'localhost' ||
22
- window.location.hostname.includes('127.0.0.1');
23
- if (isDevelopment) {
24
- console.log('Development mode: Simulating Apple Pay availability for UI testing');
25
- return true;
13
+ // Check Apple Pay availability on mount
14
+ useEffect(() => {
15
+ const checkApplePayAvailability = () => {
16
+ if (typeof window === 'undefined') {
17
+ setIsApplePayAvailable(false);
18
+ return;
26
19
  }
27
- return false;
20
+ // Check if ApplePaySession is available
21
+ const hasApplePaySession = !!window.ApplePaySession;
22
+ if (!hasApplePaySession) {
23
+ // In development, simulate Apple Pay availability for UI testing
24
+ const isDevelopment = process.env.NODE_ENV === 'development' ||
25
+ window.location.hostname === 'localhost' ||
26
+ window.location.hostname.includes('127.0.0.1');
27
+ if (isDevelopment) {
28
+ setIsApplePayAvailable(true);
29
+ return;
30
+ }
31
+ setIsApplePayAvailable(false);
32
+ return;
33
+ }
34
+ try {
35
+ // Check basic Apple Pay support
36
+ const canMakePayments = window.ApplePaySession.canMakePayments();
37
+ setIsApplePayAvailable(canMakePayments);
38
+ }
39
+ catch (error) {
40
+ console.warn('Apple Pay availability check failed:', error);
41
+ setIsApplePayAvailable(false);
42
+ }
43
+ };
44
+ checkApplePayAvailability();
45
+ // Debug logging
46
+ }, []);
47
+ // Utility function to convert Apple Pay contact to address
48
+ const appleContactToAddress = useCallback((contact) => {
49
+ return {
50
+ address1: contact?.addressLines?.[0] || '',
51
+ address2: contact?.addressLines?.[1] || '',
52
+ lastName: contact?.familyName || '',
53
+ firstName: contact?.givenName || '',
54
+ city: contact?.locality || '',
55
+ state: contact?.administrativeArea || '',
56
+ country: contact?.countryCode || '',
57
+ postal: contact?.postalCode || '',
58
+ phone: contact?.phoneNumber || '',
59
+ email: contact?.emailAddress || '',
60
+ };
61
+ }, []);
62
+ // Update checkout session with addresses and customer info
63
+ const updateCheckoutSessionValues = useCallback(async (data) => {
64
+ try {
65
+ await apiService.fetch(`/api/v1/checkout-sessions/${options.checkoutSessionId}/address`, {
66
+ method: 'POST',
67
+ body: {
68
+ data: {
69
+ shippingAddress: data.shippingAddress,
70
+ billingAddress: data.billingAddress,
71
+ },
72
+ },
73
+ });
74
+ }
75
+ catch (error) {
76
+ console.error('Failed to update checkout session addresses:', error);
77
+ throw error;
78
+ }
79
+ }, [apiService, options.checkoutSessionId]);
80
+ // Update customer email
81
+ const updateCustomerEmail = useCallback(async (email) => {
82
+ try {
83
+ await apiService.fetch(`/api/v1/customers/${options.customerId}`, {
84
+ method: 'POST',
85
+ body: {
86
+ data: {
87
+ email,
88
+ },
89
+ },
90
+ });
91
+ }
92
+ catch (error) {
93
+ console.error('Failed to update customer email:', error);
94
+ throw error;
95
+ }
96
+ }, [apiService, options.customerId]);
97
+ // Recompute order summary after address/shipping changes
98
+ const reComputeOrderSummary = useCallback(async () => {
99
+ try {
100
+ const response = await apiService.fetch(`/api/v1/checkout-sessions/${options.checkoutSessionId}/order-summary`, {
101
+ method: 'POST',
102
+ });
103
+ return response;
104
+ }
105
+ catch (error) {
106
+ console.error('Failed to recompute order summary:', error);
107
+ throw error;
28
108
  }
109
+ }, [apiService, options.checkoutSessionId]);
110
+ // Get shipping rates for the checkout session
111
+ const getShippingRates = useCallback(async () => {
29
112
  try {
30
- // Check basic Apple Pay support
31
- return window.ApplePaySession.canMakePayments();
113
+ const response = await apiService.fetch(`/api/v1/checkout-sessions/${options.checkoutSessionId}/shipping-rates`);
114
+ return response;
32
115
  }
33
116
  catch (error) {
34
- console.warn('Apple Pay availability check failed:', error);
35
- return false;
36
- }
37
- })();
38
- // Debug logging
39
- console.log('Apple Pay availability check:', {
40
- hasWindow: typeof window !== 'undefined',
41
- hasApplePaySession: typeof window !== 'undefined' && !!window.ApplePaySession,
42
- canMakePayments: typeof window !== 'undefined' && window.ApplePaySession && window.ApplePaySession.canMakePayments(),
43
- isDevelopment: process.env.NODE_ENV === 'development' ||
44
- (typeof window !== 'undefined' && (window.location.hostname === 'localhost' || window.location.hostname.includes('127.0.0.1'))),
45
- isAvailable: isApplePayAvailable,
46
- note: !window.ApplePaySession ? 'Apple Pay not available in this browser. Use Safari on iOS/macOS for real Apple Pay support.' : 'Apple Pay API detected'
47
- });
48
- const validateMerchant = useCallback(async () => {
117
+ console.error('Failed to get shipping rates:', error);
118
+ throw error;
119
+ }
120
+ }, [apiService, options.checkoutSessionId]);
121
+ // Set shipping rate
122
+ const setShippingRate = useCallback(async (shippingRateId) => {
123
+ try {
124
+ await apiService.fetch(`/api/v1/checkout-sessions/${options.checkoutSessionId}/shipping-rate`, {
125
+ method: 'POST',
126
+ body: {
127
+ shippingRateId,
128
+ },
129
+ });
130
+ }
131
+ catch (error) {
132
+ console.error('Failed to set shipping rate:', error);
133
+ throw error;
134
+ }
135
+ }, [apiService, options.checkoutSessionId]);
136
+ const validateMerchant = useCallback(async (storeName) => {
49
137
  try {
50
138
  const response = await fetch('https://api.basistheory.com/apple-pay/session', {
51
139
  method: 'POST',
@@ -54,7 +142,7 @@ export function useApplePay(options = {}) {
54
142
  'BT-API-KEY': apiKey,
55
143
  },
56
144
  body: JSON.stringify({
57
- display_name: 'Tagada Pay Store',
145
+ display_name: storeName || 'Tagada Pay Store',
58
146
  domain: typeof window !== 'undefined' ? window.location.host : 'localhost',
59
147
  }),
60
148
  });
@@ -92,7 +180,7 @@ export function useApplePay(options = {}) {
92
180
  throw error;
93
181
  }
94
182
  }, [apiKey]);
95
- const handleApplePayClick = useCallback((checkoutSessionId, lineItems, total, config = {}) => {
183
+ const handleApplePayClick = useCallback((checkoutSessionId, lineItems, total, config = {}, storeName, currencyCode, shippingMethods) => {
96
184
  if (!isApplePayAvailable) {
97
185
  const errorMsg = 'Apple Pay is not available on this device';
98
186
  setError(errorMsg);
@@ -101,19 +189,21 @@ export function useApplePay(options = {}) {
101
189
  }
102
190
  const request = {
103
191
  countryCode: config.countryCode || 'US',
104
- currencyCode: 'USD', // This should be passed as a parameter
192
+ currencyCode: currencyCode || 'USD',
105
193
  supportedNetworks: config.supportedNetworks || ['visa', 'masterCard', 'amex', 'discover'],
106
194
  merchantCapabilities: config.merchantCapabilities || ['supports3DS'],
107
195
  total,
108
196
  lineItems,
197
+ shippingMethods: shippingMethods || [],
198
+ requiredShippingContactFields: ['name', 'phone', 'email', 'postalAddress'],
199
+ requiredBillingContactFields: ['postalAddress'],
109
200
  };
110
201
  try {
111
202
  const session = new window.ApplePaySession(3, request);
112
203
  session.onvalidatemerchant = (event) => {
113
204
  void (async () => {
114
205
  try {
115
- console.log('Merchant validation requested for:', event.validationURL);
116
- const merchantSession = await validateMerchant();
206
+ const merchantSession = await validateMerchant(storeName);
117
207
  session.completeMerchantValidation(merchantSession);
118
208
  }
119
209
  catch (error) {
@@ -130,6 +220,22 @@ export function useApplePay(options = {}) {
130
220
  try {
131
221
  setProcessingPayment(true);
132
222
  setError(null);
223
+ // Extract address information
224
+ const shippingContact = event.payment.shippingContact;
225
+ const billingContact = event.payment.billingContact;
226
+ const shippingAddress = shippingContact ? appleContactToAddress(shippingContact) : null;
227
+ const billingAddress = billingContact ? appleContactToAddress(billingContact) : null;
228
+ // Update checkout session with addresses
229
+ if (shippingAddress || billingAddress) {
230
+ await updateCheckoutSessionValues({
231
+ shippingAddress: shippingAddress || undefined,
232
+ billingAddress: billingAddress || undefined,
233
+ });
234
+ }
235
+ // Update customer email if available
236
+ if (shippingContact?.emailAddress) {
237
+ await updateCustomerEmail(shippingContact.emailAddress);
238
+ }
133
239
  // Tokenize the Apple Pay payment
134
240
  const applePayToken = await tokenizeApplePay(event);
135
241
  // Complete the Apple Pay session
@@ -157,6 +263,48 @@ export function useApplePay(options = {}) {
157
263
  }
158
264
  })();
159
265
  };
266
+ // Handle shipping method selection
267
+ session.onshippingmethodselected = (event) => {
268
+ void (async () => {
269
+ try {
270
+ await setShippingRate(event.shippingMethod.identifier);
271
+ const newOrderSummary = await reComputeOrderSummary();
272
+ if (!newOrderSummary) {
273
+ session.abort();
274
+ return;
275
+ }
276
+ const { lineItems: newLineItems, total: newTotal } = newOrderSummary;
277
+ session.completeShippingMethodSelection(window.ApplePaySession.STATUS_SUCCESS, newTotal, newLineItems);
278
+ }
279
+ catch (error) {
280
+ console.error('Shipping method selection failed:', error);
281
+ session.abort();
282
+ }
283
+ })();
284
+ };
285
+ // Handle shipping contact selection
286
+ session.onshippingcontactselected = (event) => {
287
+ void (async () => {
288
+ try {
289
+ const shippingContact = event.shippingContact;
290
+ await updateCheckoutSessionValues({
291
+ shippingAddress: appleContactToAddress(shippingContact),
292
+ });
293
+ const newOrderSummary = await reComputeOrderSummary();
294
+ if (!newOrderSummary) {
295
+ session.abort();
296
+ setError('Payment Failed');
297
+ return;
298
+ }
299
+ const { lineItems: newLineItems, total: newTotal, shippingMethods: newShippingMethods, } = newOrderSummary;
300
+ session.completeShippingContactSelection(window.ApplePaySession.STATUS_SUCCESS, newShippingMethods, newTotal, newLineItems);
301
+ }
302
+ catch (error) {
303
+ console.error('Shipping contact selection failed:', error);
304
+ session.abort();
305
+ }
306
+ })();
307
+ };
160
308
  session.onerror = (event) => {
161
309
  console.error('Apple Pay Session Error:', event);
162
310
  const errorMsg = 'Apple Pay session error';
@@ -168,6 +316,7 @@ export function useApplePay(options = {}) {
168
316
  setProcessingPayment(false);
169
317
  options.onCancel?.();
170
318
  };
319
+ // Begin the Apple Pay session - this opens the modal
171
320
  session.begin();
172
321
  }
173
322
  catch (error) {
@@ -181,6 +330,10 @@ export function useApplePay(options = {}) {
181
330
  validateMerchant,
182
331
  tokenizeApplePay,
183
332
  processApplePayPayment,
333
+ updateCheckoutSessionValues,
334
+ updateCustomerEmail,
335
+ setShippingRate,
336
+ reComputeOrderSummary,
184
337
  options,
185
338
  ]);
186
339
  return {
@@ -188,5 +341,8 @@ export function useApplePay(options = {}) {
188
341
  processingPayment,
189
342
  applePayError: error,
190
343
  isApplePayAvailable,
344
+ updateCheckoutSessionValues,
345
+ updateCustomerEmail,
346
+ setShippingRate,
191
347
  };
192
348
  }
@@ -179,19 +179,10 @@ export function useCheckout(options = {}) {
179
179
  }
180
180
  }, [apiService, currentCurrency, isSessionInitialized]);
181
181
  const refresh = useCallback(async () => {
182
- console.log('🔄 [useCheckout] Refreshing checkout data...', {
183
- checkoutToken: currentCheckoutTokenRef.current?.substring(0, 8) + '...',
184
- timestamp: new Date().toISOString(),
185
- });
186
182
  if (!currentCheckoutTokenRef.current) {
187
183
  throw new Error('No checkout session to refresh');
188
184
  }
189
- console.log('🔄 [useCheckout] Refreshing checkout data...', {
190
- checkoutToken: currentCheckoutTokenRef.current.substring(0, 8) + '...',
191
- timestamp: new Date().toISOString(),
192
- });
193
185
  await getCheckout(currentCheckoutTokenRef.current);
194
- console.log('✅ [useCheckout] Refresh completed, debug data will be updated automatically');
195
186
  }, [getCheckout]);
196
187
  // Register refresh function with coordinator and cleanup on unmount
197
188
  useEffect(() => {
@@ -19,6 +19,7 @@ const loadLocalDevConfig = async (configVariant = 'default') => {
19
19
  // Use hostname-based detection for better Vite compatibility
20
20
  const isLocalDev = typeof window !== 'undefined' &&
21
21
  (window.location.hostname === 'localhost' ||
22
+ window.location.hostname.includes('ngrok-free.app') ||
22
23
  window.location.hostname.includes('.localhost') ||
23
24
  window.location.hostname.includes('127.0.0.1'));
24
25
  if (!isLocalDev) {
@@ -184,6 +185,7 @@ export const debugPluginConfig = async (configVariant = 'default') => {
184
185
  // Use hostname-based detection for better Vite compatibility
185
186
  const isLocalDev = typeof window !== 'undefined' &&
186
187
  (window.location.hostname === 'localhost' ||
188
+ window.location.hostname.includes('ngrok-free.app') ||
187
189
  window.location.hostname.includes('.localhost') ||
188
190
  window.location.hostname.includes('127.0.0.1'));
189
191
  if (!isLocalDev) {
@@ -0,0 +1,69 @@
1
+ export interface VipOffer {
2
+ id: string;
3
+ productId: string;
4
+ variantId: string;
5
+ }
6
+ export interface VipPreviewResponse {
7
+ savings: number;
8
+ currency: string;
9
+ selectedOffers: {
10
+ productId: string;
11
+ variantId: string;
12
+ isSelected: boolean;
13
+ }[];
14
+ savingsPct: number;
15
+ }
16
+ export interface UseVipOffersOptions {
17
+ /**
18
+ * Checkout session ID for VIP offers
19
+ */
20
+ checkoutSessionId: string;
21
+ /**
22
+ * Array of VIP offer IDs to manage
23
+ */
24
+ vipOfferIds: string[];
25
+ /**
26
+ * Whether to automatically fetch VIP preview on mount
27
+ * @default true
28
+ */
29
+ autoPreview?: boolean;
30
+ }
31
+ export interface UseVipOffersResult {
32
+ /**
33
+ * Array of VIP offers
34
+ */
35
+ vipOffers: VipOffer[];
36
+ /**
37
+ * VIP preview data including savings and selected offers
38
+ */
39
+ vipPreview: VipPreviewResponse | null;
40
+ /**
41
+ * Loading state for VIP preview
42
+ */
43
+ isLoadingVipPreview: boolean;
44
+ /**
45
+ * Whether any VIP offers are currently selected
46
+ */
47
+ hasVip: boolean;
48
+ /**
49
+ * Check if a specific VIP offer is selected
50
+ */
51
+ isOfferSelected: (offer: VipOffer) => boolean;
52
+ /**
53
+ * Select all VIP offers
54
+ */
55
+ selectVipOffers: () => Promise<void>;
56
+ /**
57
+ * Cancel/deselect all VIP offers
58
+ */
59
+ cancelVipOffers: () => Promise<void>;
60
+ /**
61
+ * Refresh VIP preview data
62
+ */
63
+ refreshVipPreview: () => Promise<void>;
64
+ /**
65
+ * Error state
66
+ */
67
+ error: Error | null;
68
+ }
69
+ export declare function useVipOffers(options: UseVipOffersOptions): UseVipOffersResult;
@@ -0,0 +1,144 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { useTagadaContext } from '../providers/TagadaProvider';
3
+ export function useVipOffers(options) {
4
+ const { apiService, refreshCoordinator } = useTagadaContext();
5
+ const { checkoutSessionId, vipOfferIds, autoPreview = true } = options;
6
+ const [vipOffers, setVipOffers] = useState([]);
7
+ const [vipPreview, setVipPreview] = useState(null);
8
+ const [isLoadingVipPreview, setIsLoadingVipPreview] = useState(false);
9
+ const [hasVip, setHasVip] = useState(false);
10
+ const [error, setError] = useState(null);
11
+ // Convert offer IDs to VipOffer objects
12
+ useEffect(() => {
13
+ const offers = vipOfferIds.map((id) => ({
14
+ id,
15
+ productId: '', // These will be populated from the checkout session data
16
+ variantId: '', // These will be populated from the checkout session data
17
+ }));
18
+ setVipOffers(offers);
19
+ }, [vipOfferIds]);
20
+ // Fetch VIP preview
21
+ const refreshVipPreview = useCallback(async () => {
22
+ if (!checkoutSessionId || vipOfferIds.length === 0)
23
+ return;
24
+ setIsLoadingVipPreview(true);
25
+ setError(null);
26
+ try {
27
+ const response = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/vip-preview`, {
28
+ method: 'POST',
29
+ body: {
30
+ orderBumpOfferIds: vipOfferIds,
31
+ orderBumpType: 'vip',
32
+ },
33
+ });
34
+ setVipPreview(response);
35
+ // Update hasVip based on selected offers
36
+ const hasSelectedVipOffers = response.selectedOffers?.some((offer) => offer.isSelected) ?? false;
37
+ setHasVip(hasSelectedVipOffers);
38
+ }
39
+ catch (err) {
40
+ const error = err instanceof Error ? err : new Error('Failed to fetch VIP preview');
41
+ setError(error);
42
+ console.error('VIP preview failed:', error);
43
+ }
44
+ finally {
45
+ setIsLoadingVipPreview(false);
46
+ }
47
+ }, [checkoutSessionId, vipOfferIds]);
48
+ // Check if a specific VIP offer is selected
49
+ const isOfferSelected = useCallback((offer) => {
50
+ if (!vipPreview?.selectedOffers)
51
+ return false;
52
+ return vipPreview.selectedOffers.some((selected) => selected.productId === offer.productId &&
53
+ selected.variantId === offer.variantId &&
54
+ selected.isSelected);
55
+ }, [vipPreview?.selectedOffers]);
56
+ // Keep hasVip in sync with actual selected offers
57
+ useEffect(() => {
58
+ const hasSelectedVipOffers = vipOffers.some(isOfferSelected);
59
+ if (hasSelectedVipOffers !== hasVip) {
60
+ setHasVip(hasSelectedVipOffers);
61
+ }
62
+ }, [vipOffers, isOfferSelected, hasVip, vipPreview?.selectedOffers]);
63
+ // Toggle VIP offers mutation
64
+ const toggleOrderBump = useCallback(async (orderBumpOfferId, selected) => {
65
+ try {
66
+ const response = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/toggle-order-bump`, {
67
+ method: 'POST',
68
+ body: {
69
+ orderBumpOfferId,
70
+ selected,
71
+ },
72
+ });
73
+ if (response.success) {
74
+ // Notify other hooks that checkout data changed
75
+ await refreshCoordinator.notifyCheckoutChanged();
76
+ }
77
+ return response;
78
+ }
79
+ catch (err) {
80
+ const error = err instanceof Error ? err : new Error('Failed to toggle order bump');
81
+ throw error;
82
+ }
83
+ }, [checkoutSessionId]);
84
+ // Handle selecting VIP offers
85
+ const selectVipOffers = useCallback(async () => {
86
+ try {
87
+ await Promise.all(vipOffers.map((offer) => {
88
+ if (!isOfferSelected(offer)) {
89
+ return toggleOrderBump(offer.id, true);
90
+ }
91
+ return Promise.resolve({ success: true });
92
+ }));
93
+ setHasVip(true);
94
+ await refreshVipPreview();
95
+ }
96
+ catch (err) {
97
+ const error = err instanceof Error ? err : new Error('Failed to select VIP offers');
98
+ setError(error);
99
+ console.error('Failed to select VIP offers:', error);
100
+ throw error;
101
+ }
102
+ }, [vipOffers, isOfferSelected, toggleOrderBump, refreshVipPreview]);
103
+ // Handle canceling VIP offers
104
+ const cancelVipOffers = useCallback(async () => {
105
+ try {
106
+ setHasVip(false);
107
+ await Promise.all(vipOffers.map((offer) => toggleOrderBump(offer.id, false)));
108
+ await refreshVipPreview();
109
+ }
110
+ catch (err) {
111
+ const error = err instanceof Error ? err : new Error('Failed to cancel VIP offers');
112
+ setError(error);
113
+ console.error('Failed to cancel VIP offers:', error);
114
+ setHasVip(true); // Revert optimistic update
115
+ throw error;
116
+ }
117
+ }, [vipOffers, toggleOrderBump, refreshVipPreview]);
118
+ // Auto-fetch preview on mount and when dependencies change
119
+ useEffect(() => {
120
+ if (autoPreview && checkoutSessionId && vipOfferIds.length > 0) {
121
+ refreshVipPreview().catch((error) => {
122
+ console.error('Auto-preview failed:', error);
123
+ });
124
+ }
125
+ }, [autoPreview, refreshVipPreview]);
126
+ // Register refresh function with coordinator and cleanup on unmount
127
+ useEffect(() => {
128
+ refreshCoordinator.registerOrderBumpRefresh(refreshVipPreview);
129
+ return () => {
130
+ refreshCoordinator.unregisterOrderBumpRefresh();
131
+ };
132
+ }, [refreshVipPreview]);
133
+ return {
134
+ vipOffers,
135
+ vipPreview,
136
+ isLoadingVipPreview,
137
+ hasVip,
138
+ isOfferSelected,
139
+ selectVipOffers,
140
+ cancelVipOffers,
141
+ refreshVipPreview,
142
+ error,
143
+ };
144
+ }
@@ -17,6 +17,7 @@ export { usePostPurchases } from './hooks/usePostPurchases';
17
17
  export { useProducts } from './hooks/useProducts';
18
18
  export { useSession } from './hooks/useSession';
19
19
  export { useTranslations } from './hooks/useTranslations';
20
+ export { useVipOffers } from './hooks/useVipOffers';
20
21
  export { useTagadaContext } from './providers/TagadaProvider';
21
22
  export { clearPluginConfigCache, debugPluginConfig, getPluginConfig, useBasePath, usePluginConfig } from './hooks/usePluginConfig';
22
23
  export type { PluginConfig } from './hooks/usePluginConfig';
@@ -34,9 +35,10 @@ export type { AuthState, Currency, Customer, Environment, EnvironmentConfig, Loc
34
35
  export type { CheckoutData, CheckoutInitParams, CheckoutLineItem, CheckoutSession, CheckoutSessionPreview, Promotion, UseCheckoutOptions, UseCheckoutResult } from './hooks/useCheckout';
35
36
  export type { Discount, DiscountCodeValidation, UseDiscountsOptions, UseDiscountsResult } from './hooks/useDiscounts';
36
37
  export type { OrderBumpPreview, UseOrderBumpOptions, UseOrderBumpResult } from './hooks/useOrderBump';
38
+ export type { UseVipOffersOptions, UseVipOffersResult, VipOffer, VipPreviewResponse } from './hooks/useVipOffers';
37
39
  export type { PostPurchaseOffer, PostPurchaseOfferItem, PostPurchaseOfferLineItem, PostPurchaseOfferSummary, UsePostPurchasesOptions, UsePostPurchasesResult } from './hooks/usePostPurchases';
38
40
  export type { Payment, PaymentPollingHook, PollingOptions } from './hooks/usePaymentPolling';
39
41
  export type { PaymentInstrument, ThreedsChallenge, ThreedsHook, ThreedsOptions, ThreedsProvider, ThreedsSession } from './hooks/useThreeds';
40
42
  export type { ApplePayToken, CardPaymentMethod, PaymentHook, PaymentInstrumentResponse, PaymentOptions, PaymentResponse } from './hooks/usePayment';
41
- export type { ApplePayConfig, ApplePayLineItem, ApplePayPaymentAuthorizedEvent, ApplePayPaymentRequest, ApplePayPaymentToken, ApplePayValidateMerchantEvent, BasisTheorySessionRequest, BasisTheoryTokenizeRequest, PayToken, UseApplePayOptions, UseApplePayResult } from './types/apple-pay';
43
+ export type { ApplePayAddress, ApplePayConfig, ApplePayLineItem, ApplePayPaymentAuthorizedEvent, ApplePayPaymentRequest, ApplePayPaymentToken, ApplePayValidateMerchantEvent, BasisTheorySessionRequest, BasisTheoryTokenizeRequest, PayToken, UseApplePayOptions, UseApplePayResult } from './types/apple-pay';
42
44
  export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits } from './utils/money';
@@ -20,6 +20,7 @@ export { usePostPurchases } from './hooks/usePostPurchases';
20
20
  export { useProducts } from './hooks/useProducts';
21
21
  export { useSession } from './hooks/useSession';
22
22
  export { useTranslations } from './hooks/useTranslations';
23
+ export { useVipOffers } from './hooks/useVipOffers';
23
24
  export { useTagadaContext } from './providers/TagadaProvider';
24
25
  // Plugin configuration hooks
25
26
  export { clearPluginConfigCache, debugPluginConfig, getPluginConfig, useBasePath, usePluginConfig } from './hooks/usePluginConfig';
@@ -34,7 +35,7 @@ export { useThreeds } from './hooks/useThreeds';
34
35
  export { useThreedsModal } from './hooks/useThreedsModal';
35
36
  // Apple Pay hooks exports
36
37
  export { useApplePay } from './hooks/useApplePay';
37
- // Component exports (if any)
38
- // export { SomeComponent } from './components/SomeComponent';
38
+ // Component exports
39
+ // Apple Pay components removed - use useApplePay hook directly
39
40
  // Utility exports
40
41
  export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits } from './utils/money';
@@ -8,6 +8,9 @@ export interface ApplePayPaymentRequest {
8
8
  merchantCapabilities: string[];
9
9
  total: ApplePayLineItem;
10
10
  lineItems: ApplePayLineItem[];
11
+ requiredShippingContactFields?: string[];
12
+ requiredBillingContactFields?: string[];
13
+ shippingMethods?: any[];
11
14
  }
12
15
  export interface ApplePayLineItem {
13
16
  label: string;
@@ -17,6 +20,8 @@ export interface ApplePayLineItem {
17
20
  export interface ApplePayPaymentAuthorizedEvent {
18
21
  payment: {
19
22
  token: ApplePayPaymentToken;
23
+ shippingContact?: any;
24
+ billingContact?: any;
20
25
  };
21
26
  }
22
27
  export interface ApplePayPaymentToken {
@@ -59,12 +64,32 @@ export interface UseApplePayOptions {
59
64
  onError?: (error: string) => void;
60
65
  onCancel?: () => void;
61
66
  config?: ApplePayConfig;
67
+ checkoutSessionId?: string;
68
+ customerId?: string;
69
+ }
70
+ export interface ApplePayAddress {
71
+ address1: string;
72
+ address2?: string;
73
+ lastName: string;
74
+ firstName: string;
75
+ city: string;
76
+ state: string;
77
+ country: string;
78
+ postal: string;
79
+ phone?: string;
80
+ email?: string;
62
81
  }
63
82
  export interface UseApplePayResult {
64
- handleApplePayClick: (checkoutSessionId: string, lineItems: ApplePayLineItem[], total: ApplePayLineItem, config?: ApplePayConfig) => void;
83
+ handleApplePayClick: (checkoutSessionId: string, lineItems: ApplePayLineItem[], total: ApplePayLineItem, config?: ApplePayConfig, storeName?: string, currencyCode?: string, shippingMethods?: any[]) => void;
65
84
  processingPayment: boolean;
66
85
  applePayError: string | null;
67
86
  isApplePayAvailable: boolean;
87
+ updateCheckoutSessionValues: (data: {
88
+ shippingAddress?: ApplePayAddress;
89
+ billingAddress?: ApplePayAddress;
90
+ }) => Promise<void>;
91
+ updateCustomerEmail: (email: string) => Promise<void>;
92
+ setShippingRate: (shippingRateId: string) => Promise<void>;
68
93
  }
69
94
  declare global {
70
95
  interface Window {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tagadapay/plugin-sdk",
3
- "version": "2.3.8",
3
+ "version": "2.3.10",
4
4
  "description": "Modern React SDK for building Tagada Pay plugins",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",