@tagadapay/plugin-sdk 2.3.9 → 2.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react/hooks/useApplePay.js +176 -84
- package/dist/react/hooks/usePluginConfig.js +2 -0
- package/dist/react/index.d.ts +1 -2
- package/dist/react/index.js +1 -1
- package/dist/react/types/apple-pay.d.ts +9 -11
- package/package.json +1 -1
- package/dist/react/components/ApplePayUniversalButton.d.ts +0 -16
- package/dist/react/components/ApplePayUniversalButton.example.d.ts +0 -3
- package/dist/react/components/ApplePayUniversalButton.example.js +0 -39
- package/dist/react/components/ApplePayUniversalButton.js +0 -62
|
@@ -1,15 +1,49 @@
|
|
|
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 [
|
|
8
|
+
const [isApplePayAvailable, setIsApplePayAvailable] = useState(false);
|
|
9
9
|
const { createApplePayPaymentInstrument, processApplePayPayment } = usePayment();
|
|
10
10
|
const { environment, apiService } = useTagadaContext();
|
|
11
11
|
// Get API key from environment
|
|
12
12
|
const apiKey = getBasisTheoryApiKey(environment?.environment || 'local');
|
|
13
|
+
// Check Apple Pay availability on mount
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
const checkApplePayAvailability = () => {
|
|
16
|
+
if (typeof window === 'undefined') {
|
|
17
|
+
setIsApplePayAvailable(false);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
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
|
+
}, []);
|
|
13
47
|
// Utility function to convert Apple Pay contact to address
|
|
14
48
|
const appleContactToAddress = useCallback((contact) => {
|
|
15
49
|
return {
|
|
@@ -25,68 +59,85 @@ export function useApplePay(options = {}) {
|
|
|
25
59
|
email: contact?.emailAddress || '',
|
|
26
60
|
};
|
|
27
61
|
}, []);
|
|
28
|
-
//
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(encodedData)}`;
|
|
41
|
-
}, []);
|
|
42
|
-
// Check if Apple Pay is available with enhanced cross-browser support
|
|
43
|
-
const isApplePayAvailable = (() => {
|
|
44
|
-
if (typeof window === 'undefined')
|
|
45
|
-
return false;
|
|
46
|
-
// Check if ApplePaySession is available
|
|
47
|
-
const hasApplePaySession = !!window.ApplePaySession;
|
|
48
|
-
if (!hasApplePaySession) {
|
|
49
|
-
// In development, simulate Apple Pay availability for UI testing
|
|
50
|
-
const isDevelopment = process.env.NODE_ENV === 'development' ||
|
|
51
|
-
window.location.hostname === 'localhost' ||
|
|
52
|
-
window.location.hostname.includes('127.0.0.1');
|
|
53
|
-
if (isDevelopment) {
|
|
54
|
-
console.log('Development mode: Simulating Apple Pay availability for UI testing');
|
|
55
|
-
return true;
|
|
56
|
-
}
|
|
57
|
-
return false;
|
|
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
|
+
});
|
|
58
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 () => {
|
|
59
99
|
try {
|
|
60
|
-
|
|
61
|
-
|
|
100
|
+
const response = await apiService.fetch(`/api/v1/checkout-sessions/${options.checkoutSessionId}/order-summary`, {
|
|
101
|
+
method: 'POST',
|
|
102
|
+
headers: {
|
|
103
|
+
'Content-Type': 'application/json',
|
|
104
|
+
},
|
|
105
|
+
body: { checkoutSessionId: options.checkoutSessionId }
|
|
106
|
+
});
|
|
107
|
+
return response;
|
|
62
108
|
}
|
|
63
109
|
catch (error) {
|
|
64
|
-
console.
|
|
65
|
-
|
|
110
|
+
console.error('Failed to recompute order summary:', error);
|
|
111
|
+
throw error;
|
|
66
112
|
}
|
|
67
|
-
})
|
|
68
|
-
//
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
})
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
113
|
+
}, [apiService, options.checkoutSessionId]);
|
|
114
|
+
// Get shipping rates for the checkout session
|
|
115
|
+
const getShippingRates = useCallback(async () => {
|
|
116
|
+
try {
|
|
117
|
+
const response = await apiService.fetch(`/api/v1/checkout-sessions/${options.checkoutSessionId}/shipping-rates`);
|
|
118
|
+
return response;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.error('Failed to get shipping rates:', error);
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
}, [apiService, options.checkoutSessionId]);
|
|
125
|
+
// Set shipping rate
|
|
126
|
+
const setShippingRate = useCallback(async (shippingRateId) => {
|
|
127
|
+
try {
|
|
128
|
+
await apiService.fetch(`/api/v1/checkout-sessions/${options.checkoutSessionId}/shipping-rate`, {
|
|
129
|
+
method: 'POST',
|
|
130
|
+
body: {
|
|
131
|
+
shippingRateId,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
console.error('Failed to set shipping rate:', error);
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
}, [apiService, options.checkoutSessionId]);
|
|
140
|
+
const validateMerchant = useCallback(async (storeName) => {
|
|
90
141
|
try {
|
|
91
142
|
const response = await fetch('https://api.basistheory.com/apple-pay/session', {
|
|
92
143
|
method: 'POST',
|
|
@@ -95,7 +146,7 @@ export function useApplePay(options = {}) {
|
|
|
95
146
|
'BT-API-KEY': apiKey,
|
|
96
147
|
},
|
|
97
148
|
body: JSON.stringify({
|
|
98
|
-
display_name: 'Tagada Pay Store',
|
|
149
|
+
display_name: storeName || 'Tagada Pay Store',
|
|
99
150
|
domain: typeof window !== 'undefined' ? window.location.host : 'localhost',
|
|
100
151
|
}),
|
|
101
152
|
});
|
|
@@ -133,21 +184,8 @@ export function useApplePay(options = {}) {
|
|
|
133
184
|
throw error;
|
|
134
185
|
}
|
|
135
186
|
}, [apiKey]);
|
|
136
|
-
const handleApplePayClick = useCallback((checkoutSessionId, lineItems, total, config = {}) => {
|
|
187
|
+
const handleApplePayClick = useCallback((checkoutSessionId, lineItems, total, config = {}, storeName, currencyCode, shippingMethods) => {
|
|
137
188
|
if (!isApplePayAvailable) {
|
|
138
|
-
if (shouldShowQRCode) {
|
|
139
|
-
// Generate QR code data for fallback
|
|
140
|
-
const qrData = {
|
|
141
|
-
checkoutSessionId,
|
|
142
|
-
lineItems,
|
|
143
|
-
total,
|
|
144
|
-
config,
|
|
145
|
-
qrCodeUrl: generateQRCode({ checkoutSessionId, lineItems, total, config }),
|
|
146
|
-
};
|
|
147
|
-
setQrCodeData(qrData);
|
|
148
|
-
options.onError?.('Apple Pay not available - QR code generated');
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
189
|
const errorMsg = 'Apple Pay is not available on this device';
|
|
152
190
|
setError(errorMsg);
|
|
153
191
|
options.onError?.(errorMsg);
|
|
@@ -155,11 +193,12 @@ export function useApplePay(options = {}) {
|
|
|
155
193
|
}
|
|
156
194
|
const request = {
|
|
157
195
|
countryCode: config.countryCode || 'US',
|
|
158
|
-
currencyCode: 'USD',
|
|
196
|
+
currencyCode: currencyCode || 'USD',
|
|
159
197
|
supportedNetworks: config.supportedNetworks || ['visa', 'masterCard', 'amex', 'discover'],
|
|
160
198
|
merchantCapabilities: config.merchantCapabilities || ['supports3DS'],
|
|
161
199
|
total,
|
|
162
200
|
lineItems,
|
|
201
|
+
shippingMethods: shippingMethods || [],
|
|
163
202
|
requiredShippingContactFields: ['name', 'phone', 'email', 'postalAddress'],
|
|
164
203
|
requiredBillingContactFields: ['postalAddress'],
|
|
165
204
|
};
|
|
@@ -168,8 +207,7 @@ export function useApplePay(options = {}) {
|
|
|
168
207
|
session.onvalidatemerchant = (event) => {
|
|
169
208
|
void (async () => {
|
|
170
209
|
try {
|
|
171
|
-
|
|
172
|
-
const merchantSession = await validateMerchant();
|
|
210
|
+
const merchantSession = await validateMerchant(storeName);
|
|
173
211
|
session.completeMerchantValidation(merchantSession);
|
|
174
212
|
}
|
|
175
213
|
catch (error) {
|
|
@@ -191,10 +229,17 @@ export function useApplePay(options = {}) {
|
|
|
191
229
|
const billingContact = event.payment.billingContact;
|
|
192
230
|
const shippingAddress = shippingContact ? appleContactToAddress(shippingContact) : null;
|
|
193
231
|
const billingAddress = billingContact ? appleContactToAddress(billingContact) : null;
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
232
|
+
// Update checkout session with addresses
|
|
233
|
+
if (shippingAddress || billingAddress) {
|
|
234
|
+
await updateCheckoutSessionValues({
|
|
235
|
+
shippingAddress: shippingAddress || undefined,
|
|
236
|
+
billingAddress: billingAddress || undefined,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
// Update customer email if available
|
|
240
|
+
if (shippingContact?.emailAddress) {
|
|
241
|
+
await updateCustomerEmail(shippingContact.emailAddress);
|
|
242
|
+
}
|
|
198
243
|
// Tokenize the Apple Pay payment
|
|
199
244
|
const applePayToken = await tokenizeApplePay(event);
|
|
200
245
|
// Complete the Apple Pay session
|
|
@@ -222,6 +267,48 @@ export function useApplePay(options = {}) {
|
|
|
222
267
|
}
|
|
223
268
|
})();
|
|
224
269
|
};
|
|
270
|
+
// Handle shipping method selection
|
|
271
|
+
session.onshippingmethodselected = (event) => {
|
|
272
|
+
void (async () => {
|
|
273
|
+
try {
|
|
274
|
+
await setShippingRate(event.shippingMethod.identifier);
|
|
275
|
+
const newOrderSummary = await reComputeOrderSummary();
|
|
276
|
+
if (!newOrderSummary) {
|
|
277
|
+
session.abort();
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
const { lineItems: newLineItems, total: newTotal } = newOrderSummary;
|
|
281
|
+
session.completeShippingMethodSelection(window.ApplePaySession.STATUS_SUCCESS, newTotal, newLineItems);
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
console.error('Shipping method selection failed:', error);
|
|
285
|
+
session.abort();
|
|
286
|
+
}
|
|
287
|
+
})();
|
|
288
|
+
};
|
|
289
|
+
// Handle shipping contact selection
|
|
290
|
+
session.onshippingcontactselected = (event) => {
|
|
291
|
+
void (async () => {
|
|
292
|
+
try {
|
|
293
|
+
const shippingContact = event.shippingContact;
|
|
294
|
+
await updateCheckoutSessionValues({
|
|
295
|
+
shippingAddress: appleContactToAddress(shippingContact),
|
|
296
|
+
});
|
|
297
|
+
const newOrderSummary = await reComputeOrderSummary();
|
|
298
|
+
if (!newOrderSummary) {
|
|
299
|
+
session.abort();
|
|
300
|
+
setError('Payment Failed');
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const { lineItems: newLineItems, total: newTotal, shippingMethods: newShippingMethods, } = newOrderSummary;
|
|
304
|
+
session.completeShippingContactSelection(window.ApplePaySession.STATUS_SUCCESS, newShippingMethods, newTotal, newLineItems);
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
console.error('Shipping contact selection failed:', error);
|
|
308
|
+
session.abort();
|
|
309
|
+
}
|
|
310
|
+
})();
|
|
311
|
+
};
|
|
225
312
|
session.onerror = (event) => {
|
|
226
313
|
console.error('Apple Pay Session Error:', event);
|
|
227
314
|
const errorMsg = 'Apple Pay session error';
|
|
@@ -233,6 +320,7 @@ export function useApplePay(options = {}) {
|
|
|
233
320
|
setProcessingPayment(false);
|
|
234
321
|
options.onCancel?.();
|
|
235
322
|
};
|
|
323
|
+
// Begin the Apple Pay session - this opens the modal
|
|
236
324
|
session.begin();
|
|
237
325
|
}
|
|
238
326
|
catch (error) {
|
|
@@ -246,6 +334,10 @@ export function useApplePay(options = {}) {
|
|
|
246
334
|
validateMerchant,
|
|
247
335
|
tokenizeApplePay,
|
|
248
336
|
processApplePayPayment,
|
|
337
|
+
updateCheckoutSessionValues,
|
|
338
|
+
updateCustomerEmail,
|
|
339
|
+
setShippingRate,
|
|
340
|
+
reComputeOrderSummary,
|
|
249
341
|
options,
|
|
250
342
|
]);
|
|
251
343
|
return {
|
|
@@ -253,8 +345,8 @@ export function useApplePay(options = {}) {
|
|
|
253
345
|
processingPayment,
|
|
254
346
|
applePayError: error,
|
|
255
347
|
isApplePayAvailable,
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
348
|
+
updateCheckoutSessionValues,
|
|
349
|
+
updateCustomerEmail,
|
|
350
|
+
setShippingRate,
|
|
259
351
|
};
|
|
260
352
|
}
|
|
@@ -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) {
|
package/dist/react/index.d.ts
CHANGED
|
@@ -40,6 +40,5 @@ export type { PostPurchaseOffer, PostPurchaseOfferItem, PostPurchaseOfferLineIte
|
|
|
40
40
|
export type { Payment, PaymentPollingHook, PollingOptions } from './hooks/usePaymentPolling';
|
|
41
41
|
export type { PaymentInstrument, ThreedsChallenge, ThreedsHook, ThreedsOptions, ThreedsProvider, ThreedsSession } from './hooks/useThreeds';
|
|
42
42
|
export type { ApplePayToken, CardPaymentMethod, PaymentHook, PaymentInstrumentResponse, PaymentOptions, PaymentResponse } from './hooks/usePayment';
|
|
43
|
-
export type { ApplePayConfig, ApplePayLineItem, ApplePayPaymentAuthorizedEvent, ApplePayPaymentRequest, ApplePayPaymentToken, ApplePayValidateMerchantEvent, BasisTheorySessionRequest, BasisTheoryTokenizeRequest, PayToken, UseApplePayOptions, UseApplePayResult
|
|
44
|
-
export { ApplePayUniversalButton } from './components/ApplePayUniversalButton';
|
|
43
|
+
export type { ApplePayAddress, ApplePayConfig, ApplePayLineItem, ApplePayPaymentAuthorizedEvent, ApplePayPaymentRequest, ApplePayPaymentToken, ApplePayValidateMerchantEvent, BasisTheorySessionRequest, BasisTheoryTokenizeRequest, PayToken, UseApplePayOptions, UseApplePayResult } from './types/apple-pay';
|
|
45
44
|
export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits } from './utils/money';
|
package/dist/react/index.js
CHANGED
|
@@ -36,6 +36,6 @@ export { useThreedsModal } from './hooks/useThreedsModal';
|
|
|
36
36
|
// Apple Pay hooks exports
|
|
37
37
|
export { useApplePay } from './hooks/useApplePay';
|
|
38
38
|
// Component exports
|
|
39
|
-
|
|
39
|
+
// Apple Pay components removed - use useApplePay hook directly
|
|
40
40
|
// Utility exports
|
|
41
41
|
export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits } from './utils/money';
|
|
@@ -64,6 +64,8 @@ export interface UseApplePayOptions {
|
|
|
64
64
|
onError?: (error: string) => void;
|
|
65
65
|
onCancel?: () => void;
|
|
66
66
|
config?: ApplePayConfig;
|
|
67
|
+
checkoutSessionId?: string;
|
|
68
|
+
customerId?: string;
|
|
67
69
|
}
|
|
68
70
|
export interface ApplePayAddress {
|
|
69
71
|
address1: string;
|
|
@@ -77,21 +79,17 @@ export interface ApplePayAddress {
|
|
|
77
79
|
phone?: string;
|
|
78
80
|
email?: string;
|
|
79
81
|
}
|
|
80
|
-
export interface ApplePayQRCodeData {
|
|
81
|
-
checkoutSessionId: string;
|
|
82
|
-
lineItems: ApplePayLineItem[];
|
|
83
|
-
total: ApplePayLineItem;
|
|
84
|
-
config?: ApplePayConfig;
|
|
85
|
-
qrCodeUrl?: string;
|
|
86
|
-
}
|
|
87
82
|
export interface UseApplePayResult {
|
|
88
|
-
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;
|
|
89
84
|
processingPayment: boolean;
|
|
90
85
|
applePayError: string | null;
|
|
91
86
|
isApplePayAvailable: boolean;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
updateCheckoutSessionValues: (data: {
|
|
88
|
+
shippingAddress?: ApplePayAddress;
|
|
89
|
+
billingAddress?: ApplePayAddress;
|
|
90
|
+
}) => Promise<void>;
|
|
91
|
+
updateCustomerEmail: (email: string) => Promise<void>;
|
|
92
|
+
setShippingRate: (shippingRateId: string) => Promise<void>;
|
|
95
93
|
}
|
|
96
94
|
declare global {
|
|
97
95
|
interface Window {
|
package/package.json
CHANGED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { ApplePayLineItem, ApplePayConfig } from '../types/apple-pay';
|
|
3
|
-
interface ApplePayUniversalButtonProps {
|
|
4
|
-
checkoutSessionId: string;
|
|
5
|
-
lineItems: ApplePayLineItem[];
|
|
6
|
-
total: ApplePayLineItem;
|
|
7
|
-
config?: ApplePayConfig;
|
|
8
|
-
onSuccess?: (payment: any) => void;
|
|
9
|
-
onError?: (error: string) => void;
|
|
10
|
-
onCancel?: () => void;
|
|
11
|
-
className?: string;
|
|
12
|
-
children?: React.ReactNode;
|
|
13
|
-
disabled?: boolean;
|
|
14
|
-
}
|
|
15
|
-
export declare const ApplePayUniversalButton: React.FC<ApplePayUniversalButtonProps>;
|
|
16
|
-
export default ApplePayUniversalButton;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { ApplePayUniversalButton } from './ApplePayUniversalButton';
|
|
3
|
-
// Example usage of ApplePayUniversalButton
|
|
4
|
-
export const ApplePayUniversalButtonExample = () => {
|
|
5
|
-
const checkoutSessionId = 'example-session-123';
|
|
6
|
-
const lineItems = [
|
|
7
|
-
{
|
|
8
|
-
label: 'Product 1',
|
|
9
|
-
amount: '29.99',
|
|
10
|
-
type: 'final',
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
label: 'Shipping',
|
|
14
|
-
amount: '5.99',
|
|
15
|
-
type: 'final',
|
|
16
|
-
},
|
|
17
|
-
];
|
|
18
|
-
const total = {
|
|
19
|
-
label: 'Total',
|
|
20
|
-
amount: '35.98',
|
|
21
|
-
type: 'final',
|
|
22
|
-
};
|
|
23
|
-
const config = {
|
|
24
|
-
countryCode: 'US',
|
|
25
|
-
supportedNetworks: ['visa', 'masterCard', 'amex', 'discover'],
|
|
26
|
-
merchantCapabilities: ['supports3DS'],
|
|
27
|
-
};
|
|
28
|
-
const handleSuccess = (payment) => {
|
|
29
|
-
console.log('Payment successful:', payment);
|
|
30
|
-
};
|
|
31
|
-
const handleError = (error) => {
|
|
32
|
-
console.error('Payment error:', error);
|
|
33
|
-
};
|
|
34
|
-
const handleCancel = () => {
|
|
35
|
-
console.log('Payment cancelled');
|
|
36
|
-
};
|
|
37
|
-
return (_jsxs("div", { className: "max-w-md mx-auto p-6 bg-white rounded-lg shadow-lg", children: [_jsx("h2", { className: "text-2xl font-bold mb-4", children: "Apple Pay Universal Button Example" }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "font-semibold mb-2", children: "Order Summary:" }), lineItems.map((item, index) => (_jsxs("div", { className: "flex justify-between text-sm", children: [_jsx("span", { children: item.label }), _jsxs("span", { children: ["$", item.amount] })] }, index))), _jsxs("div", { className: "flex justify-between font-bold border-t pt-2 mt-2", children: [_jsx("span", { children: total.label }), _jsxs("span", { children: ["$", total.amount] })] })] }), _jsx(ApplePayUniversalButton, { checkoutSessionId: checkoutSessionId, lineItems: lineItems, total: total, config: config, onSuccess: handleSuccess, onError: handleError, onCancel: handleCancel, className: "w-full" }), _jsxs("div", { className: "text-xs text-gray-500 mt-4", children: [_jsx("p", { children: "This button will:" }), _jsxs("ul", { className: "list-disc list-inside space-y-1", children: [_jsx("li", { children: "Show Apple Pay on supported devices (Safari iOS/macOS)" }), _jsx("li", { children: "Show QR code on other mobile browsers" }), _jsx("li", { children: "Show \"Unavailable\" on unsupported browsers" })] })] })] })] }));
|
|
38
|
-
};
|
|
39
|
-
export default ApplePayUniversalButtonExample;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { useApplePay } from '../hooks/useApplePay';
|
|
4
|
-
export const ApplePayUniversalButton = ({ checkoutSessionId, lineItems, total, config = {}, onSuccess, onError, onCancel, className = '', children, disabled = false, }) => {
|
|
5
|
-
const [showQRCode, setShowQRCode] = useState(false);
|
|
6
|
-
const { handleApplePayClick, processingPayment, applePayError, isApplePayAvailable, shouldShowQRCode, qrCodeData, generateQRCode, } = useApplePay({
|
|
7
|
-
onSuccess,
|
|
8
|
-
onError,
|
|
9
|
-
onCancel,
|
|
10
|
-
config,
|
|
11
|
-
});
|
|
12
|
-
const handleClick = () => {
|
|
13
|
-
if (isApplePayAvailable) {
|
|
14
|
-
handleApplePayClick(checkoutSessionId, lineItems, total, config);
|
|
15
|
-
}
|
|
16
|
-
else if (shouldShowQRCode) {
|
|
17
|
-
setShowQRCode(true);
|
|
18
|
-
// Generate QR code data
|
|
19
|
-
const qrData = {
|
|
20
|
-
checkoutSessionId,
|
|
21
|
-
lineItems,
|
|
22
|
-
total,
|
|
23
|
-
config,
|
|
24
|
-
qrCodeUrl: generateQRCode({ checkoutSessionId, lineItems, total, config }),
|
|
25
|
-
};
|
|
26
|
-
handleApplePayClick(checkoutSessionId, lineItems, total, config);
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
onError?.('Apple Pay is not available on this device');
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
const getButtonText = () => {
|
|
33
|
-
if (processingPayment)
|
|
34
|
-
return 'Processing...';
|
|
35
|
-
if (isApplePayAvailable)
|
|
36
|
-
return 'Pay with Apple Pay';
|
|
37
|
-
if (shouldShowQRCode)
|
|
38
|
-
return 'Show QR Code';
|
|
39
|
-
return 'Apple Pay Unavailable';
|
|
40
|
-
};
|
|
41
|
-
const getButtonIcon = () => {
|
|
42
|
-
if (isApplePayAvailable) {
|
|
43
|
-
return (_jsx("svg", { className: "h-6 w-6", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z" }) }));
|
|
44
|
-
}
|
|
45
|
-
if (shouldShowQRCode) {
|
|
46
|
-
return (_jsx("svg", { className: "h-6 w-6", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M3 3h7v7H3V3zm2 2v3h3V5H5zm8-2h7v7h-7V3zm2 2v3h3V5h-3zM3 13h7v7H3v-7zm2 2v3h3v-3H5zm8-2h7v7h-7v-7zm2 2v3h3v-3h-3z" }) }));
|
|
47
|
-
}
|
|
48
|
-
return (_jsx("svg", { className: "h-6 w-6", viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) }));
|
|
49
|
-
};
|
|
50
|
-
const getButtonStyle = () => {
|
|
51
|
-
const baseStyle = "h-10 w-full text-base shadow-sm transition-colors duration-200 flex items-center justify-center gap-2";
|
|
52
|
-
if (isApplePayAvailable) {
|
|
53
|
-
return `${baseStyle} bg-black text-white hover:bg-black/80 ${className}`;
|
|
54
|
-
}
|
|
55
|
-
if (shouldShowQRCode) {
|
|
56
|
-
return `${baseStyle} bg-blue-600 text-white hover:bg-blue-700 ${className}`;
|
|
57
|
-
}
|
|
58
|
-
return `${baseStyle} bg-gray-400 text-gray-600 cursor-not-allowed ${className}`;
|
|
59
|
-
};
|
|
60
|
-
return (_jsxs("div", { className: "w-full", children: [_jsxs("button", { onClick: handleClick, disabled: disabled || processingPayment || (!isApplePayAvailable && !shouldShowQRCode), className: getButtonStyle(), style: { margin: 0 }, children: [getButtonIcon(), children || getButtonText()] }), showQRCode && qrCodeData && (_jsx("div", { className: "mt-4 p-4 bg-white border border-gray-200 rounded-lg shadow-sm", children: _jsxs("div", { className: "text-center", children: [_jsx("h3", { className: "text-lg font-medium text-gray-900 mb-2", children: "Scan QR Code to Pay" }), _jsx("p", { className: "text-sm text-gray-600 mb-4", children: "Use your mobile device to scan this QR code and complete your Apple Pay payment" }), _jsx("div", { className: "flex justify-center", children: _jsx("img", { src: qrCodeData.qrCodeUrl, alt: "Apple Pay QR Code", className: "w-48 h-48 border border-gray-200 rounded" }) }), _jsxs("div", { className: "mt-4 text-xs text-gray-500", children: [_jsxs("p", { children: ["Total: ", total.amount, " ", total.label] }), _jsxs("p", { children: ["Session: ", checkoutSessionId.slice(0, 8), "..."] })] }), _jsx("button", { onClick: () => setShowQRCode(false), className: "mt-3 px-4 py-2 text-sm text-gray-600 hover:text-gray-800 underline", children: "Close QR Code" })] }) })), applePayError && (_jsx("div", { className: "mt-2 p-2 bg-red-50 border border-red-200 rounded text-sm text-red-600", children: applePayError }))] }));
|
|
61
|
-
};
|
|
62
|
-
export default ApplePayUniversalButton;
|