@blocklet/payment-react 1.18.33 → 1.18.35
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/es/components/over-due-invoice-payment.js +7 -1
- package/es/history/invoice/list.js +2 -1
- package/es/libs/util.d.ts +1 -0
- package/es/libs/util.js +13 -0
- package/es/libs/validator.d.ts +1 -0
- package/es/libs/validator.js +14 -0
- package/es/locales/en.js +32 -5
- package/es/locales/zh.js +32 -5
- package/es/payment/form/address.d.ts +5 -1
- package/es/payment/form/address.js +26 -13
- package/es/payment/form/index.js +173 -41
- package/lib/components/over-due-invoice-payment.js +8 -1
- package/lib/history/invoice/list.js +3 -1
- package/lib/libs/util.d.ts +1 -0
- package/lib/libs/util.js +16 -1
- package/lib/libs/validator.d.ts +1 -0
- package/lib/libs/validator.js +14 -0
- package/lib/locales/en.js +32 -5
- package/lib/locales/zh.js +32 -5
- package/lib/payment/form/address.d.ts +5 -1
- package/lib/payment/form/address.js +21 -12
- package/lib/payment/form/index.js +230 -59
- package/package.json +6 -6
- package/src/components/over-due-invoice-payment.tsx +7 -1
- package/src/history/invoice/list.tsx +2 -1
- package/src/libs/util.ts +15 -0
- package/src/libs/validator.ts +14 -0
- package/src/locales/en.tsx +31 -1
- package/src/locales/zh.tsx +29 -1
- package/src/payment/form/address.tsx +25 -10
- package/src/payment/form/index.tsx +197 -35
package/src/locales/en.tsx
CHANGED
|
@@ -97,6 +97,12 @@ export default flat({
|
|
|
97
97
|
slashStakeAmount: 'Slash Stake Amount',
|
|
98
98
|
know: 'I know',
|
|
99
99
|
relatedSubscription: 'Subscription',
|
|
100
|
+
connect: {
|
|
101
|
+
defaultScan: 'Use following methods to complete this action',
|
|
102
|
+
scan: 'Use following methods to complete this {action}',
|
|
103
|
+
confirm: 'Confirm',
|
|
104
|
+
cancel: 'Cancel',
|
|
105
|
+
},
|
|
100
106
|
},
|
|
101
107
|
payment: {
|
|
102
108
|
checkout: {
|
|
@@ -169,7 +175,12 @@ export default flat({
|
|
|
169
175
|
donate: 'Thanks for your tip',
|
|
170
176
|
tip: 'A payment to {payee} has been completed. You can view the details of this payment in your account.',
|
|
171
177
|
},
|
|
172
|
-
confirm:
|
|
178
|
+
confirm: {
|
|
179
|
+
withStake:
|
|
180
|
+
'By confirming, you allow {payee} to charge your account for future payments and, if necessary, slash your stake. You can cancel your subscription or withdraw your stake at any time.',
|
|
181
|
+
withoutStake:
|
|
182
|
+
'By confirming, you allow {payee} to charge your account for future payments. You can cancel your subscription at any time.',
|
|
183
|
+
},
|
|
173
184
|
required: 'Required',
|
|
174
185
|
invalid: 'Invalid',
|
|
175
186
|
billing: {
|
|
@@ -215,6 +226,23 @@ export default flat({
|
|
|
215
226
|
orderSummary: 'Order Summary',
|
|
216
227
|
paymentDetails: 'Payment Details',
|
|
217
228
|
productListTotal: 'Includes {total} items',
|
|
229
|
+
connectModal: {
|
|
230
|
+
title: '{action}',
|
|
231
|
+
scan: 'Use following methods to complete this payment',
|
|
232
|
+
confirm: 'Confirm',
|
|
233
|
+
cancel: 'Cancel',
|
|
234
|
+
},
|
|
235
|
+
fastPay: {
|
|
236
|
+
title: 'Confirm Payment',
|
|
237
|
+
confirmMessage: 'You will pay {amount} {symbol} from {sourceType}.',
|
|
238
|
+
autoPaymentReason:
|
|
239
|
+
'This payment will be processed automatically due to prior delegation or sufficient balance.',
|
|
240
|
+
confirmPrompt: 'Please confirm the details before proceeding.',
|
|
241
|
+
payer: 'Account',
|
|
242
|
+
amount: 'Amount',
|
|
243
|
+
failed: 'Account changed, please pay manually.',
|
|
244
|
+
balanceLink: 'View Balance',
|
|
245
|
+
},
|
|
218
246
|
},
|
|
219
247
|
customer: {
|
|
220
248
|
payments: 'Payment History',
|
|
@@ -287,6 +315,7 @@ export default flat({
|
|
|
287
315
|
'By confirming this change, you allow {payee} to charge {symbol} from your account for future payments in accordance with their terms. You can always change your payment method.',
|
|
288
316
|
completed:
|
|
289
317
|
'Your payment method has been successfully updated, all future payments will use the new payment method unless you change it again.',
|
|
318
|
+
title: 'Payment Method Change',
|
|
290
319
|
},
|
|
291
320
|
invoice: {
|
|
292
321
|
summary: 'Summary',
|
|
@@ -308,6 +337,7 @@ export default flat({
|
|
|
308
337
|
invoiceNumber: 'Invoice Number',
|
|
309
338
|
emptyList: 'No Invoice',
|
|
310
339
|
noPaymentRequired: 'No Payment Required',
|
|
340
|
+
payBatch: 'Pay Due Invoices',
|
|
311
341
|
},
|
|
312
342
|
payment: {
|
|
313
343
|
empty: 'There are no payments',
|
package/src/locales/zh.tsx
CHANGED
|
@@ -97,6 +97,12 @@ export default flat({
|
|
|
97
97
|
slashStakeAmount: '罚没金额',
|
|
98
98
|
know: '我知道了',
|
|
99
99
|
relatedSubscription: '订阅',
|
|
100
|
+
connect: {
|
|
101
|
+
defaultScan: '使用以下方式完成本次操作',
|
|
102
|
+
scan: '使用以下方式完成本次{action}',
|
|
103
|
+
confirm: '确认',
|
|
104
|
+
cancel: '取消',
|
|
105
|
+
},
|
|
100
106
|
},
|
|
101
107
|
payment: {
|
|
102
108
|
checkout: {
|
|
@@ -168,7 +174,11 @@ export default flat({
|
|
|
168
174
|
donate: '感谢您的支持',
|
|
169
175
|
tip: '向{payee}的付款已完成。您可以在您的账户中查看此付款的详细信息。',
|
|
170
176
|
},
|
|
171
|
-
confirm:
|
|
177
|
+
confirm: {
|
|
178
|
+
withStake:
|
|
179
|
+
'确认订阅,即表示您授权 {payee} 从您的账户扣取未来款项,并在必要时罚没质押。您可随时取消订阅或撤销质押。',
|
|
180
|
+
withoutStake: '确认订阅,即表示您授权 {payee} 从您的账户扣取未来款项。您可随时取消订阅。',
|
|
181
|
+
},
|
|
172
182
|
required: '必填项',
|
|
173
183
|
invalid: '无效',
|
|
174
184
|
billing: {
|
|
@@ -212,6 +222,22 @@ export default flat({
|
|
|
212
222
|
orderSummary: '订单概览',
|
|
213
223
|
paymentDetails: '支付信息',
|
|
214
224
|
productListTotal: '包括 {total} 项',
|
|
225
|
+
connectModal: {
|
|
226
|
+
title: '{action}',
|
|
227
|
+
scan: '使用以下方式完成本次支付',
|
|
228
|
+
confirm: '确认',
|
|
229
|
+
cancel: '取消',
|
|
230
|
+
},
|
|
231
|
+
fastPay: {
|
|
232
|
+
title: '确认支付',
|
|
233
|
+
confirmMessage: '您将支付 {amount} {symbol},从{sourceType}扣除。',
|
|
234
|
+
autoPaymentReason: '由于授权或余额充足,系统将无需钱包确认自动完成支付。',
|
|
235
|
+
confirmPrompt: '请确认支付信息无误后继续。',
|
|
236
|
+
payer: '账户地址',
|
|
237
|
+
amount: '支付金额',
|
|
238
|
+
failed: '账户发生变化,无法自动完成支付,请手动支付。',
|
|
239
|
+
balanceLink: '查看余额',
|
|
240
|
+
},
|
|
215
241
|
},
|
|
216
242
|
customer: {
|
|
217
243
|
payments: '支付历史',
|
|
@@ -280,6 +306,7 @@ export default flat({
|
|
|
280
306
|
submit: '确认变更',
|
|
281
307
|
confirm: '确认变更方式意味着你允许 {payee} 使用新的支付方式支付你的未来账单。你可以随时再次变更支付方式。',
|
|
282
308
|
completed: '你的支付方式 已经更新成功。你可以在你的账户中查看此支付方式的详细信息。',
|
|
309
|
+
title: '支付方式变更',
|
|
283
310
|
},
|
|
284
311
|
invoice: {
|
|
285
312
|
summary: '摘要',
|
|
@@ -301,6 +328,7 @@ export default flat({
|
|
|
301
328
|
invoiceNumber: '账单编号',
|
|
302
329
|
emptyList: '没有账单',
|
|
303
330
|
noPaymentRequired: '无需支付',
|
|
331
|
+
payBatch: '支付欠款',
|
|
304
332
|
},
|
|
305
333
|
payment: {
|
|
306
334
|
empty: '没有支付记录',
|
|
@@ -4,19 +4,23 @@ import type { SxProps } from '@mui/material';
|
|
|
4
4
|
import { Controller, useFormContext, useWatch } from 'react-hook-form';
|
|
5
5
|
import FormInput from '../../components/input';
|
|
6
6
|
import CountrySelect from '../../components/country-select';
|
|
7
|
-
import { validatePostalCode } from '../../libs/validator';
|
|
7
|
+
import { getFieldValidation, validatePostalCode } from '../../libs/validator';
|
|
8
8
|
|
|
9
9
|
type Props = {
|
|
10
10
|
mode: string;
|
|
11
11
|
stripe: boolean;
|
|
12
12
|
sx?: SxProps;
|
|
13
|
+
fieldValidation?: Record<string, any>;
|
|
14
|
+
errorPosition?: 'right' | 'bottom';
|
|
13
15
|
};
|
|
14
16
|
|
|
15
17
|
AddressForm.defaultProps = {
|
|
16
18
|
sx: {},
|
|
19
|
+
fieldValidation: {},
|
|
20
|
+
errorPosition: 'right',
|
|
17
21
|
};
|
|
18
22
|
|
|
19
|
-
export default function AddressForm({ mode, stripe, sx = {} }: Props) {
|
|
23
|
+
export default function AddressForm({ mode, stripe, sx = {}, fieldValidation, errorPosition }: Props) {
|
|
20
24
|
const { t } = useLocaleContext();
|
|
21
25
|
const { control } = useFormContext();
|
|
22
26
|
const country = useWatch({ control, name: 'billing_address.country' });
|
|
@@ -28,24 +32,33 @@ export default function AddressForm({ mode, stripe, sx = {} }: Props) {
|
|
|
28
32
|
<FormLabel className="base-label">{t('payment.checkout.billing.line1')}</FormLabel>
|
|
29
33
|
<FormInput
|
|
30
34
|
name="billing_address.line1"
|
|
31
|
-
rules={{
|
|
32
|
-
|
|
35
|
+
rules={{
|
|
36
|
+
required: t('payment.checkout.required'),
|
|
37
|
+
...getFieldValidation('billing_address.line1', fieldValidation),
|
|
38
|
+
}}
|
|
39
|
+
errorPosition={errorPosition}
|
|
33
40
|
variant="outlined"
|
|
34
41
|
placeholder={t('payment.checkout.billing.line1')}
|
|
35
42
|
/>
|
|
36
43
|
<FormLabel className="base-label">{t('payment.checkout.billing.city')}</FormLabel>
|
|
37
44
|
<FormInput
|
|
38
45
|
name="billing_address.city"
|
|
39
|
-
rules={{
|
|
40
|
-
|
|
46
|
+
rules={{
|
|
47
|
+
required: t('payment.checkout.required'),
|
|
48
|
+
...getFieldValidation('billing_address.city', fieldValidation),
|
|
49
|
+
}}
|
|
50
|
+
errorPosition={errorPosition}
|
|
41
51
|
variant="outlined"
|
|
42
52
|
placeholder={t('payment.checkout.billing.city')}
|
|
43
53
|
/>
|
|
44
54
|
<FormLabel className="base-label">{t('payment.checkout.billing.state')}</FormLabel>
|
|
45
55
|
<FormInput
|
|
46
56
|
name="billing_address.state"
|
|
47
|
-
rules={{
|
|
48
|
-
|
|
57
|
+
rules={{
|
|
58
|
+
required: t('payment.checkout.required'),
|
|
59
|
+
...getFieldValidation('billing_address.state', fieldValidation),
|
|
60
|
+
}}
|
|
61
|
+
errorPosition={errorPosition}
|
|
49
62
|
variant="outlined"
|
|
50
63
|
placeholder={t('payment.checkout.billing.state')}
|
|
51
64
|
/>
|
|
@@ -58,8 +71,9 @@ export default function AddressForm({ mode, stripe, sx = {} }: Props) {
|
|
|
58
71
|
const isValid = validatePostalCode(x, country);
|
|
59
72
|
return isValid ? true : t('payment.checkout.invalid');
|
|
60
73
|
},
|
|
74
|
+
...getFieldValidation('billing_address.postal_code', fieldValidation),
|
|
61
75
|
}}
|
|
62
|
-
errorPosition=
|
|
76
|
+
errorPosition={errorPosition}
|
|
63
77
|
variant="outlined"
|
|
64
78
|
placeholder={t('payment.checkout.billing.postal_code')}
|
|
65
79
|
InputProps={{
|
|
@@ -104,8 +118,9 @@ export default function AddressForm({ mode, stripe, sx = {} }: Props) {
|
|
|
104
118
|
const isValid = validatePostalCode(x, country);
|
|
105
119
|
return isValid ? true : t('payment.checkout.invalid');
|
|
106
120
|
},
|
|
121
|
+
...getFieldValidation('billing_address.postal_code', fieldValidation),
|
|
107
122
|
}}
|
|
108
|
-
errorPosition=
|
|
123
|
+
errorPosition={errorPosition}
|
|
109
124
|
variant="outlined"
|
|
110
125
|
placeholder={t('payment.checkout.billing.postal_code')}
|
|
111
126
|
wrapperStyle={{ height: '40px' }}
|
|
@@ -5,7 +5,7 @@ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
|
5
5
|
// import { useTheme } from '@arcblock/ux/lib/Theme';
|
|
6
6
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
7
7
|
import type { TCheckoutSession, TCustomer, TPaymentIntent, TPaymentMethodExpanded } from '@blocklet/payment-types';
|
|
8
|
-
import { Box, Button, CircularProgress, Divider, Fade, FormLabel, Stack, Typography } from '@mui/material';
|
|
8
|
+
import { Box, Button, CircularProgress, Divider, Fade, FormLabel, Stack, Tooltip, Typography } from '@mui/material';
|
|
9
9
|
import { useMemoizedFn, useSetState } from 'ahooks';
|
|
10
10
|
import pWaitFor from 'p-wait-for';
|
|
11
11
|
import { useEffect, useMemo, useRef } from 'react';
|
|
@@ -13,8 +13,11 @@ import { Controller, useFormContext, useWatch } from 'react-hook-form';
|
|
|
13
13
|
import { joinURL } from 'ufo';
|
|
14
14
|
import { dispatch } from 'use-bus';
|
|
15
15
|
import isEmail from 'validator/es/lib/isEmail';
|
|
16
|
+
import { fromUnitToToken } from '@ocap/util';
|
|
17
|
+
import DID from '@arcblock/ux/lib/DID';
|
|
16
18
|
|
|
17
19
|
import isEmpty from 'lodash/isEmpty';
|
|
20
|
+
import { HelpOutline, OpenInNew } from '@mui/icons-material';
|
|
18
21
|
import FormInput from '../../components/input';
|
|
19
22
|
import { usePaymentContext } from '../../contexts/payment';
|
|
20
23
|
import { useSubscription } from '../../hooks/subscription';
|
|
@@ -25,6 +28,7 @@ import {
|
|
|
25
28
|
formatQuantityInventory,
|
|
26
29
|
getPrefix,
|
|
27
30
|
getStatementDescriptor,
|
|
31
|
+
getTokenBalanceLink,
|
|
28
32
|
isCrossOrigin,
|
|
29
33
|
} from '../../libs/util';
|
|
30
34
|
import type { CheckoutCallbacks, CheckoutContext } from '../../types';
|
|
@@ -37,6 +41,8 @@ import { formatPhone, validatePhoneNumber } from '../../libs/phone-validator';
|
|
|
37
41
|
import LoadingButton from '../../components/loading-button';
|
|
38
42
|
import OverdueInvoicePayment from '../../components/over-due-invoice-payment';
|
|
39
43
|
import { saveCurrencyPreference } from '../../libs/currency';
|
|
44
|
+
import ConfirmDialog from '../../components/confirm';
|
|
45
|
+
import { getFieldValidation } from '../../libs/validator';
|
|
40
46
|
|
|
41
47
|
export const waitForCheckoutComplete = async (sessionId: string) => {
|
|
42
48
|
let result: CheckoutContext;
|
|
@@ -101,6 +107,14 @@ type UserInfo = {
|
|
|
101
107
|
};
|
|
102
108
|
};
|
|
103
109
|
|
|
110
|
+
type FastCheckoutInfo = {
|
|
111
|
+
open: boolean;
|
|
112
|
+
loading: boolean;
|
|
113
|
+
sourceType: 'balance' | 'delegation';
|
|
114
|
+
amount: string;
|
|
115
|
+
payer?: string;
|
|
116
|
+
};
|
|
117
|
+
|
|
104
118
|
const setUserFormValues = (
|
|
105
119
|
userInfo: UserInfo,
|
|
106
120
|
currentValues: any,
|
|
@@ -159,10 +173,11 @@ export default function PaymentForm({
|
|
|
159
173
|
isDonation = false,
|
|
160
174
|
}: PageData) {
|
|
161
175
|
// const theme = useTheme();
|
|
162
|
-
const { t } = useLocaleContext();
|
|
176
|
+
const { t, locale } = useLocaleContext();
|
|
163
177
|
const { isMobile } = useMobile();
|
|
164
178
|
const { session, connect, payable } = usePaymentContext();
|
|
165
179
|
const subscription = useSubscription('events');
|
|
180
|
+
const formErrorPosition = isMobile ? 'bottom' : 'right';
|
|
166
181
|
const {
|
|
167
182
|
control,
|
|
168
183
|
getValues,
|
|
@@ -194,6 +209,7 @@ export default function PaymentForm({
|
|
|
194
209
|
customer?: TCustomer;
|
|
195
210
|
customerLimited?: boolean;
|
|
196
211
|
stripePaying: boolean;
|
|
212
|
+
fastCheckoutInfo: FastCheckoutInfo | null;
|
|
197
213
|
}>({
|
|
198
214
|
submitting: false,
|
|
199
215
|
paying: false,
|
|
@@ -203,6 +219,7 @@ export default function PaymentForm({
|
|
|
203
219
|
customer,
|
|
204
220
|
customerLimited: false,
|
|
205
221
|
stripePaying: false,
|
|
222
|
+
fastCheckoutInfo: null,
|
|
206
223
|
});
|
|
207
224
|
|
|
208
225
|
const currencies = flattenPaymentMethods(paymentMethods);
|
|
@@ -288,6 +305,7 @@ export default function PaymentForm({
|
|
|
288
305
|
}, [session?.user, checkoutSession.phone_number_collection?.enabled]);
|
|
289
306
|
|
|
290
307
|
const paymentMethod = useWatch({ control, name: 'payment_method' });
|
|
308
|
+
const paymentCurrencyId = useWatch({ control, name: 'payment_currency' });
|
|
291
309
|
|
|
292
310
|
// const domSize = useSize(document.body);
|
|
293
311
|
|
|
@@ -327,6 +345,9 @@ export default function PaymentForm({
|
|
|
327
345
|
buttonText = session?.user || isDonation ? buttonText : t('payment.checkout.connect', { action: buttonText });
|
|
328
346
|
|
|
329
347
|
const method = paymentMethods.find((x) => x.id === paymentMethod) as TPaymentMethodExpanded;
|
|
348
|
+
const paymentCurrency = currencies.find((x) => x.id === paymentCurrencyId);
|
|
349
|
+
const showStake = method.type === 'arcblock' && !checkoutSession.subscription_data?.no_stake;
|
|
350
|
+
|
|
330
351
|
const isDonationMode = checkoutSession?.submit_type === 'donate' && isDonation;
|
|
331
352
|
const showForm = !!session?.user;
|
|
332
353
|
const skipBindWallet = method.type === 'stripe';
|
|
@@ -364,6 +385,84 @@ export default function PaymentForm({
|
|
|
364
385
|
}
|
|
365
386
|
};
|
|
366
387
|
|
|
388
|
+
const handleFastCheckoutConfirm = async () => {
|
|
389
|
+
if (!state.fastCheckoutInfo) return;
|
|
390
|
+
|
|
391
|
+
setState({
|
|
392
|
+
fastCheckoutInfo: {
|
|
393
|
+
...state.fastCheckoutInfo,
|
|
394
|
+
loading: true,
|
|
395
|
+
},
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
try {
|
|
399
|
+
const result = await api.post(`/api/checkout-sessions/${checkoutSession.id}/fast-checkout-confirm`);
|
|
400
|
+
if (result.data.fastPaid) {
|
|
401
|
+
setState({
|
|
402
|
+
fastCheckoutInfo: null,
|
|
403
|
+
paying: true,
|
|
404
|
+
});
|
|
405
|
+
await handleConnected();
|
|
406
|
+
} else {
|
|
407
|
+
Toast.error(t('payment.checkout.fastPay.failed'));
|
|
408
|
+
setState({
|
|
409
|
+
fastCheckoutInfo: null,
|
|
410
|
+
paying: true,
|
|
411
|
+
});
|
|
412
|
+
openConnect();
|
|
413
|
+
}
|
|
414
|
+
} catch (err) {
|
|
415
|
+
console.error(err);
|
|
416
|
+
Toast.error(formatError(err));
|
|
417
|
+
setState({
|
|
418
|
+
fastCheckoutInfo: null,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const handleFastCheckoutCancel = () => {
|
|
424
|
+
setState({ fastCheckoutInfo: null });
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
const openConnect = () => {
|
|
428
|
+
try {
|
|
429
|
+
if (!['arcblock', 'ethereum', 'base'].includes(method.type)) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
setState({ paying: true });
|
|
433
|
+
connect.open({
|
|
434
|
+
locale,
|
|
435
|
+
containerEl: undefined as unknown as Element,
|
|
436
|
+
action: checkoutSession.mode,
|
|
437
|
+
prefix: joinURL(getPrefix(), '/api/did'),
|
|
438
|
+
saveConnect: false,
|
|
439
|
+
useSocket: isCrossOrigin() === false,
|
|
440
|
+
extraParams: { checkoutSessionId: checkoutSession.id, sessionUserDid: session?.user?.did },
|
|
441
|
+
onSuccess: async () => {
|
|
442
|
+
connect.close();
|
|
443
|
+
await handleConnected();
|
|
444
|
+
},
|
|
445
|
+
onClose: () => {
|
|
446
|
+
connect.close();
|
|
447
|
+
setState({ submitting: false, paying: false });
|
|
448
|
+
},
|
|
449
|
+
onError: (err: any) => {
|
|
450
|
+
console.error(err);
|
|
451
|
+
setState({ submitting: false, paying: false });
|
|
452
|
+
onError(err);
|
|
453
|
+
},
|
|
454
|
+
messages: {
|
|
455
|
+
title: t('payment.checkout.connectModal.title', { action: buttonText }),
|
|
456
|
+
scan: t('payment.checkout.connectModal.scan'),
|
|
457
|
+
confirm: t('payment.checkout.connectModal.confirm'),
|
|
458
|
+
cancel: t('payment.checkout.connectModal.cancel'),
|
|
459
|
+
},
|
|
460
|
+
} as any);
|
|
461
|
+
} catch (err) {
|
|
462
|
+
Toast.error(formatError(err));
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
|
|
367
466
|
const onFormSubmit = async (data: any) => {
|
|
368
467
|
setState({ submitting: true });
|
|
369
468
|
try {
|
|
@@ -383,36 +482,22 @@ export default function PaymentForm({
|
|
|
383
482
|
});
|
|
384
483
|
|
|
385
484
|
if (['arcblock', 'ethereum', 'base'].includes(method.type)) {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
connect.close();
|
|
399
|
-
await handleConnected();
|
|
400
|
-
},
|
|
401
|
-
onClose: () => {
|
|
402
|
-
connect.close();
|
|
403
|
-
setState({ submitting: false, paying: false });
|
|
404
|
-
},
|
|
405
|
-
onError: (err: any) => {
|
|
406
|
-
console.error(err);
|
|
407
|
-
setState({ submitting: false, paying: false });
|
|
408
|
-
onError(err);
|
|
409
|
-
},
|
|
410
|
-
messages: {
|
|
411
|
-
title: 'DID Connect',
|
|
412
|
-
scan: 'Use following methods to complete this payment',
|
|
413
|
-
confirm: 'Confirm',
|
|
485
|
+
if (
|
|
486
|
+
(result.data.balance?.sufficient || result.data.delegation?.sufficient) &&
|
|
487
|
+
!isDonationMode &&
|
|
488
|
+
result.data.fastPayInfo
|
|
489
|
+
) {
|
|
490
|
+
setState({
|
|
491
|
+
fastCheckoutInfo: {
|
|
492
|
+
open: true,
|
|
493
|
+
loading: false,
|
|
494
|
+
sourceType: result.data.fastPayInfo.type,
|
|
495
|
+
amount: result.data.fastPayInfo.amount,
|
|
496
|
+
payer: result.data.fastPayInfo.payer,
|
|
414
497
|
},
|
|
415
|
-
}
|
|
498
|
+
});
|
|
499
|
+
} else {
|
|
500
|
+
openConnect();
|
|
416
501
|
}
|
|
417
502
|
}
|
|
418
503
|
if (['stripe'].includes(method.type)) {
|
|
@@ -514,6 +599,56 @@ export default function PaymentForm({
|
|
|
514
599
|
};
|
|
515
600
|
}, [state.submitting, state.paying, state.stripePaying, quantityInventoryStatus, payable]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
516
601
|
|
|
602
|
+
const balanceLink = getTokenBalanceLink(method, state.fastCheckoutInfo?.payer || '');
|
|
603
|
+
const FastCheckoutConfirmDialog = state.fastCheckoutInfo && (
|
|
604
|
+
<ConfirmDialog
|
|
605
|
+
onConfirm={handleFastCheckoutConfirm}
|
|
606
|
+
onCancel={handleFastCheckoutCancel}
|
|
607
|
+
title={t('payment.checkout.fastPay.title')}
|
|
608
|
+
message={
|
|
609
|
+
<Stack>
|
|
610
|
+
<Typography>{t('payment.checkout.fastPay.autoPaymentReason')}</Typography>
|
|
611
|
+
<Typography>{t('payment.checkout.fastPay.confirmPrompt')}</Typography>
|
|
612
|
+
<Divider sx={{ mt: 1.5, mb: 1.5 }} />
|
|
613
|
+
<Stack spacing={1}>
|
|
614
|
+
<Stack flexDirection="row" alignItems="center" justifyContent="space-between">
|
|
615
|
+
<Typography color="text.primary" sx={{ whiteSpace: 'nowrap' }}>
|
|
616
|
+
{t('payment.checkout.fastPay.payer')}
|
|
617
|
+
</Typography>
|
|
618
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
|
619
|
+
<DID did={state.fastCheckoutInfo.payer || ''} compact responsive={false} />
|
|
620
|
+
{balanceLink && (
|
|
621
|
+
<Tooltip title={t('payment.checkout.fastPay.balanceLink')} placement="top">
|
|
622
|
+
<OpenInNew
|
|
623
|
+
sx={{
|
|
624
|
+
color: 'text.lighter',
|
|
625
|
+
fontSize: '0.85rem',
|
|
626
|
+
cursor: 'pointer',
|
|
627
|
+
'&:hover': { color: 'text.primary' },
|
|
628
|
+
}}
|
|
629
|
+
onClick={() => {
|
|
630
|
+
window.open(balanceLink, '_blank');
|
|
631
|
+
}}
|
|
632
|
+
/>
|
|
633
|
+
</Tooltip>
|
|
634
|
+
)}
|
|
635
|
+
</Box>
|
|
636
|
+
</Stack>
|
|
637
|
+
<Stack flexDirection="row" alignItems="center" justifyContent="space-between">
|
|
638
|
+
<Typography color="text.primary">{t('payment.checkout.fastPay.amount')}</Typography>
|
|
639
|
+
<Typography>
|
|
640
|
+
{fromUnitToToken(state.fastCheckoutInfo.amount, paymentCurrency?.decimal || 18).toString()}{' '}
|
|
641
|
+
{paymentCurrency?.symbol}
|
|
642
|
+
</Typography>
|
|
643
|
+
</Stack>
|
|
644
|
+
</Stack>
|
|
645
|
+
</Stack>
|
|
646
|
+
}
|
|
647
|
+
loading={state.fastCheckoutInfo.loading}
|
|
648
|
+
color="primary"
|
|
649
|
+
/>
|
|
650
|
+
);
|
|
651
|
+
|
|
517
652
|
if (onlyShowBtn) {
|
|
518
653
|
return (
|
|
519
654
|
<>
|
|
@@ -565,6 +700,7 @@ export default function PaymentForm({
|
|
|
565
700
|
}}
|
|
566
701
|
/>
|
|
567
702
|
)}
|
|
703
|
+
{FastCheckoutConfirmDialog}
|
|
568
704
|
</>
|
|
569
705
|
);
|
|
570
706
|
}
|
|
@@ -631,19 +767,25 @@ export default function PaymentForm({
|
|
|
631
767
|
<FormInput
|
|
632
768
|
name="customer_name"
|
|
633
769
|
variant="outlined"
|
|
634
|
-
errorPosition=
|
|
770
|
+
errorPosition={formErrorPosition}
|
|
635
771
|
rules={{
|
|
636
772
|
required: t('payment.checkout.required'),
|
|
773
|
+
...getFieldValidation('customer_name', checkoutSession.metadata?.page_info?.field_validation, locale),
|
|
637
774
|
}}
|
|
638
775
|
/>
|
|
639
776
|
<FormLabel className="base-label">{t('payment.checkout.customer.email')}</FormLabel>
|
|
640
777
|
<FormInput
|
|
641
778
|
name="customer_email"
|
|
642
779
|
variant="outlined"
|
|
643
|
-
errorPosition=
|
|
780
|
+
errorPosition={formErrorPosition}
|
|
644
781
|
rules={{
|
|
645
782
|
required: t('payment.checkout.required'),
|
|
646
783
|
validate: (x) => (isEmail(x) ? true : t('payment.checkout.invalid')),
|
|
784
|
+
...getFieldValidation(
|
|
785
|
+
'customer_email',
|
|
786
|
+
checkoutSession.metadata?.page_info?.field_validation,
|
|
787
|
+
locale
|
|
788
|
+
),
|
|
647
789
|
}}
|
|
648
790
|
/>
|
|
649
791
|
{checkoutSession.phone_number_collection?.enabled && (
|
|
@@ -652,7 +794,7 @@ export default function PaymentForm({
|
|
|
652
794
|
<PhoneInput
|
|
653
795
|
name="customer_phone"
|
|
654
796
|
variant="outlined"
|
|
655
|
-
errorPosition=
|
|
797
|
+
errorPosition={formErrorPosition}
|
|
656
798
|
placeholder="Phone number"
|
|
657
799
|
rules={{
|
|
658
800
|
required: t('payment.checkout.required'),
|
|
@@ -660,6 +802,11 @@ export default function PaymentForm({
|
|
|
660
802
|
const isValid = await validatePhoneNumber(x);
|
|
661
803
|
return isValid ? true : t('payment.checkout.invalid');
|
|
662
804
|
},
|
|
805
|
+
...getFieldValidation(
|
|
806
|
+
'customer_phone',
|
|
807
|
+
checkoutSession.metadata?.page_info?.field_validation,
|
|
808
|
+
locale
|
|
809
|
+
),
|
|
663
810
|
}}
|
|
664
811
|
/>
|
|
665
812
|
</>
|
|
@@ -668,6 +815,8 @@ export default function PaymentForm({
|
|
|
668
815
|
mode={checkoutSession.billing_address_collection as string}
|
|
669
816
|
stripe={method?.type === 'stripe'}
|
|
670
817
|
sx={{ marginTop: '0 !important' }}
|
|
818
|
+
fieldValidation={checkoutSession.metadata?.page_info?.field_validation}
|
|
819
|
+
errorPosition={formErrorPosition}
|
|
671
820
|
/>
|
|
672
821
|
</Stack>
|
|
673
822
|
)}
|
|
@@ -695,9 +844,21 @@ export default function PaymentForm({
|
|
|
695
844
|
|
|
696
845
|
{['subscription', 'setup'].includes(checkoutSession.mode) && (
|
|
697
846
|
<Typography sx={{ mt: 2.5, color: 'text.lighter', fontSize: '0.7875rem', lineHeight: '0.9625rem' }}>
|
|
698
|
-
{
|
|
847
|
+
{showStake
|
|
848
|
+
? t('payment.checkout.confirm.withStake', { payee })
|
|
849
|
+
: t('payment.checkout.confirm.withoutStake', { payee })}
|
|
699
850
|
</Typography>
|
|
700
851
|
)}
|
|
852
|
+
{checkoutSession.metadata?.page_info?.form_purpose_description && (
|
|
853
|
+
<Box sx={{ mt: 1, display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
|
854
|
+
<HelpOutline sx={{ color: 'text.lighter', fontSize: '0.75rem' }} />
|
|
855
|
+
<Typography variant="body2" sx={{ fontSize: '0.75rem', color: 'text.lighter' }}>
|
|
856
|
+
{locale === 'zh'
|
|
857
|
+
? checkoutSession.metadata.page_info.form_purpose_description.zh
|
|
858
|
+
: checkoutSession.metadata.page_info.form_purpose_description.en}
|
|
859
|
+
</Typography>
|
|
860
|
+
</Box>
|
|
861
|
+
)}
|
|
701
862
|
</Stack>
|
|
702
863
|
</Fade>
|
|
703
864
|
{state.customerLimited && (
|
|
@@ -725,6 +886,7 @@ export default function PaymentForm({
|
|
|
725
886
|
}}
|
|
726
887
|
/>
|
|
727
888
|
)}
|
|
889
|
+
{FastCheckoutConfirmDialog}
|
|
728
890
|
</>
|
|
729
891
|
);
|
|
730
892
|
}
|