@blocklet/payment-react 1.18.24 → 1.18.26

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 (67) hide show
  1. package/es/checkout/donate.js +11 -1
  2. package/es/components/country-select.js +243 -21
  3. package/es/components/over-due-invoice-payment.d.ts +3 -1
  4. package/es/components/over-due-invoice-payment.js +6 -4
  5. package/es/contexts/payment.d.ts +2 -1
  6. package/es/contexts/payment.js +8 -1
  7. package/es/hooks/keyboard.js +3 -0
  8. package/es/index.d.ts +1 -0
  9. package/es/index.js +1 -0
  10. package/es/libs/api.js +4 -0
  11. package/es/libs/currency.d.ts +3 -0
  12. package/es/libs/currency.js +22 -0
  13. package/es/libs/phone-validator.js +2 -0
  14. package/es/libs/util.d.ts +2 -2
  15. package/es/libs/util.js +7 -4
  16. package/es/libs/validator.d.ts +1 -0
  17. package/es/libs/validator.js +70 -0
  18. package/es/payment/form/address.js +17 -3
  19. package/es/payment/form/index.js +10 -1
  20. package/es/payment/form/phone.js +12 -1
  21. package/es/payment/form/stripe/form.js +72 -15
  22. package/es/payment/index.js +33 -11
  23. package/es/payment/product-donation.js +110 -12
  24. package/es/types/shims.d.ts +2 -0
  25. package/lib/checkout/donate.js +11 -1
  26. package/lib/components/country-select.js +243 -39
  27. package/lib/components/over-due-invoice-payment.d.ts +3 -1
  28. package/lib/components/over-due-invoice-payment.js +7 -4
  29. package/lib/contexts/payment.d.ts +2 -1
  30. package/lib/contexts/payment.js +9 -1
  31. package/lib/hooks/keyboard.js +3 -0
  32. package/lib/index.d.ts +1 -0
  33. package/lib/index.js +12 -0
  34. package/lib/libs/api.js +4 -0
  35. package/lib/libs/currency.d.ts +3 -0
  36. package/lib/libs/currency.js +31 -0
  37. package/lib/libs/phone-validator.js +1 -0
  38. package/lib/libs/util.d.ts +2 -2
  39. package/lib/libs/util.js +7 -4
  40. package/lib/libs/validator.d.ts +1 -0
  41. package/lib/libs/validator.js +20 -0
  42. package/lib/payment/form/address.js +15 -2
  43. package/lib/payment/form/index.js +12 -1
  44. package/lib/payment/form/phone.js +13 -1
  45. package/lib/payment/form/stripe/form.js +98 -29
  46. package/lib/payment/index.js +34 -10
  47. package/lib/payment/product-donation.js +106 -15
  48. package/lib/types/shims.d.ts +2 -0
  49. package/package.json +8 -8
  50. package/src/checkout/donate.tsx +11 -1
  51. package/src/components/country-select.tsx +265 -20
  52. package/src/components/over-due-invoice-payment.tsx +6 -2
  53. package/src/contexts/payment.tsx +11 -1
  54. package/src/hooks/keyboard.ts +5 -3
  55. package/src/index.ts +1 -0
  56. package/src/libs/api.ts +4 -1
  57. package/src/libs/currency.ts +25 -0
  58. package/src/libs/phone-validator.ts +1 -0
  59. package/src/libs/util.ts +18 -4
  60. package/src/libs/validator.ts +70 -0
  61. package/src/payment/form/address.tsx +17 -4
  62. package/src/payment/form/index.tsx +11 -1
  63. package/src/payment/form/phone.tsx +15 -1
  64. package/src/payment/form/stripe/form.tsx +104 -32
  65. package/src/payment/index.tsx +45 -14
  66. package/src/payment/product-donation.tsx +129 -10
  67. package/src/types/shims.d.ts +2 -0
@@ -6,13 +6,15 @@ import { useFormContext, useWatch } from 'react-hook-form';
6
6
  import { defaultCountries, usePhoneInput } from 'react-international-phone';
7
7
  import type { CountryIso2 } from 'react-international-phone';
8
8
 
9
+ import { useMount } from 'ahooks';
9
10
  import FormInput from '../../components/input';
10
11
  import { isValidCountry } from '../../libs/util';
11
12
  import CountrySelect from '../../components/country-select';
13
+ import { getPhoneUtil } from '../../libs/phone-validator';
12
14
 
13
15
  export default function PhoneInput({ ...props }) {
14
16
  const countryFieldName = props.countryFieldName || 'billing_address.country';
15
- const { control, getValues, setValue } = useFormContext();
17
+ const { control, getValues, setValue, trigger } = useFormContext();
16
18
  const values = getValues();
17
19
 
18
20
  const isUpdatingRef = useRef(false);
@@ -51,6 +53,12 @@ export default function PhoneInput({ ...props }) {
51
53
  });
52
54
  }, [userCountry, country, setCountry, safeUpdate]);
53
55
 
56
+ useMount(() => {
57
+ getPhoneUtil().catch((err) => {
58
+ console.error('Failed to preload phone validator:', err);
59
+ });
60
+ });
61
+
54
62
  const onCountryChange = useCallback(
55
63
  (v: CountryIso2) => {
56
64
  safeUpdate(() => {
@@ -60,6 +68,11 @@ export default function PhoneInput({ ...props }) {
60
68
  [setCountry, safeUpdate]
61
69
  );
62
70
 
71
+ const handleBlur = useCallback(() => {
72
+ trigger(props.name);
73
+ // eslint-disable-next-line react-hooks/exhaustive-deps
74
+ }, [props.name]);
75
+
63
76
  return (
64
77
  // @ts-ignore
65
78
  <FormInput
@@ -67,6 +80,7 @@ export default function PhoneInput({ ...props }) {
67
80
  onChange={handlePhoneValueChange}
68
81
  type="tel"
69
82
  inputRef={inputRef}
83
+ onBlur={handleBlur}
70
84
  InputProps={{
71
85
  startAdornment: (
72
86
  <InputAdornment position="start" style={{ marginRight: '2px', marginLeft: '-8px' }}>
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/indent */
1
2
  import Center from '@arcblock/ux/lib/Center';
2
3
  import Dialog from '@arcblock/ux/lib/Dialog';
3
4
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
@@ -21,6 +22,14 @@ export type StripeCheckoutFormProps = {
21
22
  returnUrl: string;
22
23
  };
23
24
 
25
+ const PaymentElementContainer = styled('div')`
26
+ opacity: 0;
27
+ transition: opacity 300ms ease;
28
+ &.visible {
29
+ opacity: 1;
30
+ }
31
+ `;
32
+
24
33
  // @doc https://stripe.com/docs/js/elements_object/create_payment_element
25
34
  function StripeCheckoutForm({
26
35
  clientSecret,
@@ -38,8 +47,39 @@ function StripeCheckoutForm({
38
47
  message: '',
39
48
  confirming: false,
40
49
  loaded: false,
50
+ showBillingForm: false,
51
+ isTransitioning: false,
52
+ paymentMethod: 'card',
41
53
  });
42
54
 
55
+ const handlePaymentMethodChange = (event: any) => {
56
+ const method = event.value?.type;
57
+ const needsBillingInfo = method === 'google_pay' || method === 'apple_pay';
58
+ const shouldShowForm = needsBillingInfo && !isCompleteBillingAddress(customer.address);
59
+
60
+ if (shouldShowForm && !state.showBillingForm) {
61
+ setState({ isTransitioning: true });
62
+ setTimeout(() => {
63
+ setState({
64
+ isTransitioning: false,
65
+ paymentMethod: method,
66
+ showBillingForm: true,
67
+ });
68
+ }, 300);
69
+ } else {
70
+ // if shouldShowForm is false, set showBillingForm to false immediately
71
+ setState({
72
+ showBillingForm: false,
73
+ paymentMethod: method,
74
+ isTransitioning: false,
75
+ });
76
+ }
77
+ };
78
+
79
+ const isCompleteBillingAddress = (address: any) => {
80
+ return address && address.line1 && address.city && address.state && address.postal_code && address.country;
81
+ };
82
+
43
83
  useEffect(() => {
44
84
  if (!stripe) {
45
85
  return;
@@ -76,29 +116,53 @@ function StripeCheckoutForm({
76
116
  }
77
117
 
78
118
  try {
79
- setState({ confirming: true });
119
+ setState({ confirming: true, message: '' });
80
120
  const method = intentType === 'payment_intent' ? 'confirmPayment' : 'confirmSetup';
81
- const { error } = await stripe[method]({
121
+
122
+ const { error: submitError } = await elements.submit();
123
+ if (submitError) {
124
+ setState({ confirming: false });
125
+ return;
126
+ }
127
+
128
+ const { error, paymentIntent, setupIntent } = await stripe[method]({
82
129
  elements,
83
130
  redirect: 'if_required',
84
131
  confirmParams: {
85
132
  return_url: returnUrl || window.location.href,
86
- payment_method_data: {
87
- billing_details: {
88
- name: customer.name,
89
- phone: customer.phone,
90
- email: customer.email,
91
- address: customer.address,
92
- },
93
- },
133
+ ...(!state.showBillingForm
134
+ ? {
135
+ payment_method_data: {
136
+ billing_details: {
137
+ name: customer.name,
138
+ phone: customer.phone,
139
+ email: customer.email,
140
+ address: {
141
+ ...(customer.address || {}),
142
+ country: customer.address?.country || 'us',
143
+ line1: customer.address?.line1 || '',
144
+ line2: customer.address?.line2 || '',
145
+ city: customer.address?.city || '',
146
+ state: customer.address?.state || '',
147
+ postal_code: customer.address?.postal_code || '00000',
148
+ },
149
+ },
150
+ },
151
+ }
152
+ : {}),
94
153
  },
95
154
  });
155
+ const intent = paymentIntent || setupIntent;
156
+ if (intent?.status === 'canceled' || intent?.status === 'requires_payment_method') {
157
+ setState({ confirming: false });
158
+ return;
159
+ }
160
+
96
161
  setState({ confirming: false });
97
162
  if (error) {
98
163
  if (error.type === 'validation_error') {
99
164
  return;
100
165
  }
101
-
102
166
  setState({ message: error.message as string });
103
167
  return;
104
168
  }
@@ -109,32 +173,40 @@ function StripeCheckoutForm({
109
173
  setState({ confirming: false, message: err.message as string });
110
174
  }
111
175
  },
112
- [customer, intentType, stripe] // eslint-disable-line
176
+ [customer, intentType, stripe, state.showBillingForm, returnUrl] // eslint-disable-line
113
177
  );
114
178
 
115
179
  return (
116
180
  <Content onSubmit={handleSubmit}>
117
- <LinkAuthenticationElement
118
- options={{
119
- defaultEmail: customer.email,
120
- }}
121
- />
122
- <PaymentElement
123
- options={{
124
- layout: 'auto',
125
- fields: { billingDetails: 'never' },
126
- readOnly: state.confirming,
127
- defaultValues: {
128
- billingDetails: {
129
- name: customer.name,
130
- phone: customer.phone,
131
- email: customer.email,
132
- address: customer.address,
181
+ {(!state.paymentMethod || state.paymentMethod === 'card') && (
182
+ <LinkAuthenticationElement
183
+ options={{
184
+ defaultEmail: customer.email,
185
+ }}
186
+ />
187
+ )}
188
+ <PaymentElementContainer className={!state.isTransitioning ? 'visible' : ''}>
189
+ <PaymentElement
190
+ options={{
191
+ layout: 'auto',
192
+ fields: {
193
+ billingDetails: state.showBillingForm ? 'auto' : 'never',
133
194
  },
134
- },
135
- }}
136
- onReady={() => setState({ loaded: true })}
137
- />
195
+ readOnly: state.confirming,
196
+ defaultValues: {
197
+ billingDetails: {
198
+ name: customer.name,
199
+ phone: customer.phone,
200
+ email: customer.email,
201
+ address: customer.address,
202
+ },
203
+ },
204
+ }}
205
+ onChange={handlePaymentMethodChange}
206
+ onReady={() => setState({ loaded: true })}
207
+ />
208
+ </PaymentElementContainer>
209
+
138
210
  {(!stripe || !elements || !state.loaded) && (
139
211
  <Center relative="parent">
140
212
  <CircularProgress />
@@ -16,7 +16,7 @@ import { Box, Fade, Stack, type BoxProps } from '@mui/material';
16
16
  import { styled } from '@mui/system';
17
17
  import { fromTokenToUnit } from '@ocap/util';
18
18
  import { useSetState } from 'ahooks';
19
- import { useEffect, useState } from 'react';
19
+ import { useEffect, useState, useMemo } from 'react';
20
20
  import { FormProvider, useForm, useWatch } from 'react-hook-form';
21
21
  import trim from 'lodash/trim';
22
22
  import type { LiteralUnion } from 'type-fest';
@@ -34,7 +34,7 @@ import {
34
34
  import type { CheckoutCallbacks, CheckoutContext, CheckoutFormData } from '../types';
35
35
  import PaymentError from './error';
36
36
  import CheckoutFooter from './footer';
37
- import PaymentForm from './form';
37
+ import PaymentForm, { hasDidWallet } from './form';
38
38
  // import PaymentHeader from './header';
39
39
  import OverviewSkeleton from './skeleton/overview';
40
40
  import PaymentSkeleton from './skeleton/payment';
@@ -42,6 +42,7 @@ import PaymentSuccess from './success';
42
42
  import PaymentSummary from './summary';
43
43
  import { useMobile } from '../hooks/mobile';
44
44
  import { formatPhone } from '../libs/phone-validator';
45
+ import { getCurrencyPreference } from '../libs/currency';
45
46
 
46
47
  // eslint-disable-next-line react/no-unused-prop-types
47
48
  type Props = CheckoutContext & CheckoutCallbacks & { completed?: boolean; error?: any; showCheckoutSummary?: boolean };
@@ -70,8 +71,48 @@ function PaymentInner({
70
71
  const { isMobile } = useMobile();
71
72
  const [state, setState] = useSetState<{ checkoutSession: TCheckoutSessionExpanded }>({ checkoutSession });
72
73
  const query = getQueryParams(window.location.href);
73
- const defaultCurrencyId =
74
- query.currencyId || state.checkoutSession.currency_id || state.checkoutSession.line_items[0]?.price.currency_id;
74
+
75
+ const availableCurrencyIds = useMemo(() => {
76
+ const currencyIds = new Set<string>();
77
+ paymentMethods.forEach((method) => {
78
+ method.payment_currencies.forEach((currency) => {
79
+ if (currency.active) {
80
+ currencyIds.add(currency.id);
81
+ }
82
+ });
83
+ });
84
+ return Array.from(currencyIds);
85
+ }, [paymentMethods]);
86
+
87
+ const defaultCurrencyId = useMemo(() => {
88
+ // 1. first check url currencyId
89
+ if (query.currencyId && availableCurrencyIds.includes(query.currencyId)) {
90
+ return query.currencyId;
91
+ }
92
+
93
+ // 2. if user has no wallet, use the first available currency of stripe payment method
94
+ if (session?.user && !hasDidWallet(session.user)) {
95
+ const stripeCurrencyId = paymentMethods
96
+ .find((m) => m.type === 'stripe')
97
+ ?.payment_currencies.find((c) => c.active)?.id;
98
+ if (stripeCurrencyId) {
99
+ return stripeCurrencyId;
100
+ }
101
+ }
102
+
103
+ // 3. then check user's saved currency preference
104
+ const savedPreference = getCurrencyPreference(session?.user?.did, availableCurrencyIds);
105
+ if (savedPreference) {
106
+ return savedPreference;
107
+ }
108
+
109
+ // 4. finally use the currency in checkoutSession or the first available currency
110
+ if (state.checkoutSession.currency_id && availableCurrencyIds.includes(state.checkoutSession.currency_id)) {
111
+ return state.checkoutSession.currency_id;
112
+ }
113
+ return availableCurrencyIds?.[0];
114
+ }, [query.currencyId, availableCurrencyIds, session?.user, state.checkoutSession.currency_id, paymentMethods]);
115
+
75
116
  const defaultMethodId = paymentMethods.find((m) => m.payment_currencies.some((c) => c.id === defaultCurrencyId))?.id;
76
117
  const hideSummaryCard = mode.endsWith('-minimal') || !showCheckoutSummary;
77
118
 
@@ -120,16 +161,6 @@ function PaymentInner({
120
161
  };
121
162
  }, []);
122
163
 
123
- useEffect(() => {
124
- if (!methods || query.currencyId) {
125
- return;
126
- }
127
- if (state.checkoutSession.currency_id !== defaultCurrencyId) {
128
- methods.setValue('payment_currency', state.checkoutSession.currency_id);
129
- }
130
- // eslint-disable-next-line react-hooks/exhaustive-deps
131
- }, [state.checkoutSession, defaultCurrencyId, query.currencyId]);
132
-
133
164
  const currencyId = useWatch({ control: methods.control, name: 'payment_currency', defaultValue: defaultCurrencyId });
134
165
  const currency =
135
166
  (findCurrency(paymentMethods as TPaymentMethodExpanded[], currencyId as string) as TPaymentCurrency) ||
@@ -1,6 +1,7 @@
1
1
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
2
  import type { DonationSettings, TLineItemExpanded, TPaymentCurrency } from '@blocklet/payment-types';
3
- import { Avatar, Box, Card, CardActionArea, Grid, Stack, TextField, Typography } from '@mui/material';
3
+ import { Avatar, Box, Card, CardActionArea, Grid, Stack, TextField, Typography, IconButton } from '@mui/material';
4
+ import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';
4
5
  import { useSetState } from 'ahooks';
5
6
  import { useEffect, useRef } from 'react';
6
7
 
@@ -78,6 +79,7 @@ export default function ProductDonation({
78
79
  input: defaultCustomAmount,
79
80
  custom: !supportPreset || defaultPreset === 'custom',
80
81
  error: '',
82
+ animating: false,
81
83
  });
82
84
 
83
85
  const customInputRef = useRef<HTMLInputElement>(null);
@@ -91,15 +93,98 @@ export default function ProductDonation({
91
93
  };
92
94
 
93
95
  const handleCustomSelect = () => {
94
- setState({ custom: true, selected: '', error: '' });
95
- const savedCustomAmount = getSavedCustomAmount();
96
- if (savedCustomAmount) {
97
- setState({ input: savedCustomAmount });
98
- onChange({ priceId: item.price_id, amount: savedCustomAmount });
99
- setPayable(true);
100
- } else if (!state.input) {
101
- setPayable(false);
96
+ // Set custom mode and prepare for random amount
97
+ setState({
98
+ custom: true,
99
+ selected: '',
100
+ animating: true,
101
+ });
102
+
103
+ // Prepare random amount range with correctly sorted presets
104
+ const hasPresets = presets.length > 0;
105
+ let sortedPresets: number[] = [];
106
+ if (hasPresets) {
107
+ sortedPresets = [...presets].map((p) => parseFloat(p)).sort((a, b) => a - b);
102
108
  }
109
+
110
+ // Get min and max values for random amount
111
+ const minPreset = hasPresets ? sortedPresets[0] : 1;
112
+ const middleIndex = Math.floor(sortedPresets.length / 2);
113
+ const maxPreset = hasPresets ? sortedPresets[middleIndex] : 10;
114
+
115
+ // Detect precision from existing presets
116
+ const detectPrecision = () => {
117
+ let maxPrecision = 2; // Default to 2 decimal places for currency
118
+
119
+ // If no presets, default to 0 precision (integers) for simplicity
120
+ if (!hasPresets) return 0;
121
+
122
+ const allIntegers = presets.every((preset) => {
123
+ const num = parseFloat(preset);
124
+ return num === Math.floor(num);
125
+ });
126
+
127
+ if (allIntegers) return 0;
128
+
129
+ presets.forEach((preset) => {
130
+ const decimalPart = preset.toString().split('.')[1];
131
+ if (decimalPart) {
132
+ maxPrecision = Math.max(maxPrecision, decimalPart.length);
133
+ }
134
+ });
135
+
136
+ return maxPrecision;
137
+ };
138
+
139
+ const precision = detectPrecision();
140
+
141
+ // Generate random amount with matching precision
142
+ let randomAmount;
143
+ if (precision === 0) {
144
+ randomAmount = (Math.round(Math.random() * (maxPreset - minPreset) + minPreset) || 1).toString();
145
+ } else {
146
+ randomAmount = (Math.random() * (maxPreset - minPreset) + minPreset).toFixed(precision);
147
+ }
148
+
149
+ // Get starting value for animation - use either current input, cached value, or 0
150
+ const startValue = state.input ? parseFloat(state.input) : 0;
151
+ const targetValue = parseFloat(randomAmount);
152
+ const difference = targetValue - startValue;
153
+
154
+ // Animate value change
155
+ const startTime = Date.now();
156
+ const duration = 800;
157
+
158
+ const updateCounter = () => {
159
+ const currentTime = Date.now();
160
+ const elapsed = currentTime - startTime;
161
+
162
+ if (elapsed < duration) {
163
+ const progress = elapsed / duration;
164
+ const intermediateValue = startValue + difference * progress;
165
+ const currentValue =
166
+ precision === 0 ? Math.floor(intermediateValue).toString() : intermediateValue.toFixed(precision);
167
+
168
+ setState({ input: currentValue });
169
+ requestAnimationFrame(updateCounter);
170
+ } else {
171
+ // Animation complete
172
+ setState({
173
+ input: randomAmount,
174
+ animating: false,
175
+ error: '',
176
+ });
177
+ onChange({ priceId: item.price_id, amount: formatAmount(randomAmount) });
178
+ setPayable(true);
179
+ localStorage.setItem(getUserStorageKey(DONATION_CUSTOM_AMOUNT_KEY_BASE), formatAmount(randomAmount));
180
+
181
+ setTimeout(() => {
182
+ customInputRef.current?.focus();
183
+ }, 200);
184
+ }
185
+ };
186
+
187
+ requestAnimationFrame(updateCounter);
103
188
  localStorage.setItem(getUserStorageKey(DONATION_PRESET_KEY_BASE), 'custom');
104
189
  };
105
190
 
@@ -111,7 +196,6 @@ export default function ProductDonation({
111
196
  }
112
197
  };
113
198
 
114
- // 使用useTabNavigation进行键盘导航
115
199
  const { handleKeyDown } = useTabNavigation(presets, handleTabSelect, {
116
200
  includeCustom: supportCustom,
117
201
  currentValue: state.custom ? undefined : state.selected,
@@ -286,14 +370,49 @@ export default function ProductDonation({
286
370
  InputProps={{
287
371
  endAdornment: (
288
372
  <Stack direction="row" spacing={0.5} alignItems="center" sx={{ ml: 1 }}>
373
+ <IconButton
374
+ size="small"
375
+ onClick={handleCustomSelect}
376
+ disabled={state.animating}
377
+ sx={{
378
+ mr: 0.5,
379
+ opacity: state.animating ? 0.5 : 1,
380
+ transition: 'all 0.2s ease',
381
+ '&:hover': {
382
+ transform: 'scale(1.2)',
383
+ transition: 'transform 0.3s ease',
384
+ },
385
+ }}
386
+ aria-label={t('common.random')}>
387
+ <AutoAwesomeIcon fontSize="small" />
388
+ </IconButton>
289
389
  <Avatar src={currency?.logo} sx={{ width: 16, height: 16 }} alt={currency?.symbol} />
290
390
  <Typography>{currency?.symbol}</Typography>
291
391
  </Stack>
292
392
  ),
293
393
  autoComplete: 'off',
394
+ sx: {
395
+ '& input': {
396
+ transition: 'all 0.25s ease',
397
+ },
398
+ },
294
399
  }}
295
400
  sx={{
296
401
  mt: defaultPreset !== '0' ? 0 : 1,
402
+ '& .MuiInputBase-root': {
403
+ transition: 'all 0.3s ease',
404
+ },
405
+ '& input[type=number]': {
406
+ MozAppearance: 'textfield',
407
+ },
408
+ '& input[type=number]::-webkit-outer-spin-button': {
409
+ WebkitAppearance: 'none',
410
+ margin: 0,
411
+ },
412
+ '& input[type=number]::-webkit-inner-spin-button': {
413
+ WebkitAppearance: 'none',
414
+ margin: 0,
415
+ },
297
416
  }}
298
417
  />
299
418
  )}
@@ -16,3 +16,5 @@ declare module 'pretty-ms-i18n';
16
16
  declare var blocklet: import('@blocklet/sdk').WindowBlocklet;
17
17
 
18
18
  declare var __PAYMENT_KIT_BASE_URL: string;
19
+
20
+ declare var __PAYMENT_KIT_AUTH_TOKEN: string;