@blocklet/payment-react 1.18.33 → 1.18.34
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/locales/en.js +31 -5
- package/es/locales/zh.js +31 -5
- package/es/payment/form/index.js +132 -33
- package/lib/components/over-due-invoice-payment.js +8 -1
- package/lib/history/invoice/list.js +3 -1
- package/lib/locales/en.js +31 -5
- package/lib/locales/zh.js +31 -5
- package/lib/payment/form/index.js +194 -52
- 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/locales/en.tsx +30 -1
- package/src/locales/zh.tsx +28 -1
- package/src/payment/form/index.tsx +161 -31
|
@@ -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 } 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';
|
|
@@ -37,6 +40,7 @@ import { formatPhone, validatePhoneNumber } from '../../libs/phone-validator';
|
|
|
37
40
|
import LoadingButton from '../../components/loading-button';
|
|
38
41
|
import OverdueInvoicePayment from '../../components/over-due-invoice-payment';
|
|
39
42
|
import { saveCurrencyPreference } from '../../libs/currency';
|
|
43
|
+
import ConfirmDialog from '../../components/confirm';
|
|
40
44
|
|
|
41
45
|
export const waitForCheckoutComplete = async (sessionId: string) => {
|
|
42
46
|
let result: CheckoutContext;
|
|
@@ -101,6 +105,14 @@ type UserInfo = {
|
|
|
101
105
|
};
|
|
102
106
|
};
|
|
103
107
|
|
|
108
|
+
type FastCheckoutInfo = {
|
|
109
|
+
open: boolean;
|
|
110
|
+
loading: boolean;
|
|
111
|
+
sourceType: 'balance' | 'delegation';
|
|
112
|
+
amount: string;
|
|
113
|
+
payer?: string;
|
|
114
|
+
};
|
|
115
|
+
|
|
104
116
|
const setUserFormValues = (
|
|
105
117
|
userInfo: UserInfo,
|
|
106
118
|
currentValues: any,
|
|
@@ -159,7 +171,7 @@ export default function PaymentForm({
|
|
|
159
171
|
isDonation = false,
|
|
160
172
|
}: PageData) {
|
|
161
173
|
// const theme = useTheme();
|
|
162
|
-
const { t } = useLocaleContext();
|
|
174
|
+
const { t, locale } = useLocaleContext();
|
|
163
175
|
const { isMobile } = useMobile();
|
|
164
176
|
const { session, connect, payable } = usePaymentContext();
|
|
165
177
|
const subscription = useSubscription('events');
|
|
@@ -194,6 +206,7 @@ export default function PaymentForm({
|
|
|
194
206
|
customer?: TCustomer;
|
|
195
207
|
customerLimited?: boolean;
|
|
196
208
|
stripePaying: boolean;
|
|
209
|
+
fastCheckoutInfo: FastCheckoutInfo | null;
|
|
197
210
|
}>({
|
|
198
211
|
submitting: false,
|
|
199
212
|
paying: false,
|
|
@@ -203,6 +216,7 @@ export default function PaymentForm({
|
|
|
203
216
|
customer,
|
|
204
217
|
customerLimited: false,
|
|
205
218
|
stripePaying: false,
|
|
219
|
+
fastCheckoutInfo: null,
|
|
206
220
|
});
|
|
207
221
|
|
|
208
222
|
const currencies = flattenPaymentMethods(paymentMethods);
|
|
@@ -288,6 +302,7 @@ export default function PaymentForm({
|
|
|
288
302
|
}, [session?.user, checkoutSession.phone_number_collection?.enabled]);
|
|
289
303
|
|
|
290
304
|
const paymentMethod = useWatch({ control, name: 'payment_method' });
|
|
305
|
+
const paymentCurrencyId = useWatch({ control, name: 'payment_currency' });
|
|
291
306
|
|
|
292
307
|
// const domSize = useSize(document.body);
|
|
293
308
|
|
|
@@ -327,6 +342,9 @@ export default function PaymentForm({
|
|
|
327
342
|
buttonText = session?.user || isDonation ? buttonText : t('payment.checkout.connect', { action: buttonText });
|
|
328
343
|
|
|
329
344
|
const method = paymentMethods.find((x) => x.id === paymentMethod) as TPaymentMethodExpanded;
|
|
345
|
+
const paymentCurrency = currencies.find((x) => x.id === paymentCurrencyId);
|
|
346
|
+
const showStake = method.type === 'arcblock' && !checkoutSession.subscription_data?.no_stake;
|
|
347
|
+
|
|
330
348
|
const isDonationMode = checkoutSession?.submit_type === 'donate' && isDonation;
|
|
331
349
|
const showForm = !!session?.user;
|
|
332
350
|
const skipBindWallet = method.type === 'stripe';
|
|
@@ -364,6 +382,84 @@ export default function PaymentForm({
|
|
|
364
382
|
}
|
|
365
383
|
};
|
|
366
384
|
|
|
385
|
+
const handleFastCheckoutConfirm = async () => {
|
|
386
|
+
if (!state.fastCheckoutInfo) return;
|
|
387
|
+
|
|
388
|
+
setState({
|
|
389
|
+
fastCheckoutInfo: {
|
|
390
|
+
...state.fastCheckoutInfo,
|
|
391
|
+
loading: true,
|
|
392
|
+
},
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
try {
|
|
396
|
+
const result = await api.post(`/api/checkout-sessions/${checkoutSession.id}/fast-checkout-confirm`);
|
|
397
|
+
if (result.data.fastPaid) {
|
|
398
|
+
setState({
|
|
399
|
+
fastCheckoutInfo: null,
|
|
400
|
+
paying: true,
|
|
401
|
+
});
|
|
402
|
+
await handleConnected();
|
|
403
|
+
} else {
|
|
404
|
+
Toast.error(t('payment.checkout.fastPay.failed'));
|
|
405
|
+
setState({
|
|
406
|
+
fastCheckoutInfo: null,
|
|
407
|
+
paying: true,
|
|
408
|
+
});
|
|
409
|
+
openConnect();
|
|
410
|
+
}
|
|
411
|
+
} catch (err) {
|
|
412
|
+
console.error(err);
|
|
413
|
+
Toast.error(formatError(err));
|
|
414
|
+
setState({
|
|
415
|
+
fastCheckoutInfo: null,
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
const handleFastCheckoutCancel = () => {
|
|
421
|
+
setState({ fastCheckoutInfo: null });
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
const openConnect = () => {
|
|
425
|
+
try {
|
|
426
|
+
if (!['arcblock', 'ethereum', 'base'].includes(method.type)) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
setState({ paying: true });
|
|
430
|
+
connect.open({
|
|
431
|
+
locale,
|
|
432
|
+
containerEl: undefined as unknown as Element,
|
|
433
|
+
action: checkoutSession.mode,
|
|
434
|
+
prefix: joinURL(getPrefix(), '/api/did'),
|
|
435
|
+
saveConnect: false,
|
|
436
|
+
useSocket: isCrossOrigin() === false,
|
|
437
|
+
extraParams: { checkoutSessionId: checkoutSession.id, sessionUserDid: session?.user?.did },
|
|
438
|
+
onSuccess: async () => {
|
|
439
|
+
connect.close();
|
|
440
|
+
await handleConnected();
|
|
441
|
+
},
|
|
442
|
+
onClose: () => {
|
|
443
|
+
connect.close();
|
|
444
|
+
setState({ submitting: false, paying: false });
|
|
445
|
+
},
|
|
446
|
+
onError: (err: any) => {
|
|
447
|
+
console.error(err);
|
|
448
|
+
setState({ submitting: false, paying: false });
|
|
449
|
+
onError(err);
|
|
450
|
+
},
|
|
451
|
+
messages: {
|
|
452
|
+
title: t('payment.checkout.connectModal.title', { action: buttonText }),
|
|
453
|
+
scan: t('payment.checkout.connectModal.scan'),
|
|
454
|
+
confirm: t('payment.checkout.connectModal.confirm'),
|
|
455
|
+
cancel: t('payment.checkout.connectModal.cancel'),
|
|
456
|
+
},
|
|
457
|
+
} as any);
|
|
458
|
+
} catch (err) {
|
|
459
|
+
Toast.error(formatError(err));
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
|
|
367
463
|
const onFormSubmit = async (data: any) => {
|
|
368
464
|
setState({ submitting: true });
|
|
369
465
|
try {
|
|
@@ -383,36 +479,22 @@ export default function PaymentForm({
|
|
|
383
479
|
});
|
|
384
480
|
|
|
385
481
|
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();
|
|
482
|
+
if (
|
|
483
|
+
(result.data.balance?.sufficient || result.data.delegation?.sufficient) &&
|
|
484
|
+
!isDonationMode &&
|
|
485
|
+
result.data.fastPayInfo
|
|
486
|
+
) {
|
|
487
|
+
setState({
|
|
488
|
+
fastCheckoutInfo: {
|
|
489
|
+
open: true,
|
|
490
|
+
loading: false,
|
|
491
|
+
sourceType: result.data.fastPayInfo.type,
|
|
492
|
+
amount: result.data.fastPayInfo.amount,
|
|
493
|
+
payer: result.data.fastPayInfo.payer,
|
|
400
494
|
},
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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',
|
|
414
|
-
},
|
|
415
|
-
} as any);
|
|
495
|
+
});
|
|
496
|
+
} else {
|
|
497
|
+
openConnect();
|
|
416
498
|
}
|
|
417
499
|
}
|
|
418
500
|
if (['stripe'].includes(method.type)) {
|
|
@@ -514,6 +596,40 @@ export default function PaymentForm({
|
|
|
514
596
|
};
|
|
515
597
|
}, [state.submitting, state.paying, state.stripePaying, quantityInventoryStatus, payable]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
516
598
|
|
|
599
|
+
const FastCheckoutConfirmDialog = state.fastCheckoutInfo && (
|
|
600
|
+
<ConfirmDialog
|
|
601
|
+
onConfirm={handleFastCheckoutConfirm}
|
|
602
|
+
onCancel={handleFastCheckoutCancel}
|
|
603
|
+
title={t('payment.checkout.fastPay.title')}
|
|
604
|
+
message={
|
|
605
|
+
<Stack>
|
|
606
|
+
<Typography>{t('payment.checkout.fastPay.autoPaymentReason')}</Typography>
|
|
607
|
+
<Typography>{t('payment.checkout.fastPay.confirmPrompt')}</Typography>
|
|
608
|
+
<Divider sx={{ mt: 1.5, mb: 1.5 }} />
|
|
609
|
+
<Stack spacing={1}>
|
|
610
|
+
<Stack flexDirection="row" alignItems="center" justifyContent="space-between">
|
|
611
|
+
<Typography color="text.primary" sx={{ whiteSpace: 'nowrap' }}>
|
|
612
|
+
{t('payment.checkout.fastPay.payer')}
|
|
613
|
+
</Typography>
|
|
614
|
+
<Typography>
|
|
615
|
+
<DID did={state.fastCheckoutInfo.payer || ''} compact responsive={false} />
|
|
616
|
+
</Typography>
|
|
617
|
+
</Stack>
|
|
618
|
+
<Stack flexDirection="row" alignItems="center" justifyContent="space-between">
|
|
619
|
+
<Typography color="text.primary">{t('payment.checkout.fastPay.amount')}</Typography>
|
|
620
|
+
<Typography>
|
|
621
|
+
{fromUnitToToken(state.fastCheckoutInfo.amount, paymentCurrency?.decimal || 18).toString()}{' '}
|
|
622
|
+
{paymentCurrency?.symbol}
|
|
623
|
+
</Typography>
|
|
624
|
+
</Stack>
|
|
625
|
+
</Stack>
|
|
626
|
+
</Stack>
|
|
627
|
+
}
|
|
628
|
+
loading={state.fastCheckoutInfo.loading}
|
|
629
|
+
color="primary"
|
|
630
|
+
/>
|
|
631
|
+
);
|
|
632
|
+
|
|
517
633
|
if (onlyShowBtn) {
|
|
518
634
|
return (
|
|
519
635
|
<>
|
|
@@ -565,6 +681,7 @@ export default function PaymentForm({
|
|
|
565
681
|
}}
|
|
566
682
|
/>
|
|
567
683
|
)}
|
|
684
|
+
{FastCheckoutConfirmDialog}
|
|
568
685
|
</>
|
|
569
686
|
);
|
|
570
687
|
}
|
|
@@ -695,9 +812,21 @@ export default function PaymentForm({
|
|
|
695
812
|
|
|
696
813
|
{['subscription', 'setup'].includes(checkoutSession.mode) && (
|
|
697
814
|
<Typography sx={{ mt: 2.5, color: 'text.lighter', fontSize: '0.7875rem', lineHeight: '0.9625rem' }}>
|
|
698
|
-
{
|
|
815
|
+
{showStake
|
|
816
|
+
? t('payment.checkout.confirm.withStake', { payee })
|
|
817
|
+
: t('payment.checkout.confirm.withoutStake', { payee })}
|
|
699
818
|
</Typography>
|
|
700
819
|
)}
|
|
820
|
+
{checkoutSession.metadata?.page_info?.form_purpose_description && (
|
|
821
|
+
<Box sx={{ mt: 1, display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
|
822
|
+
<HelpOutline sx={{ color: 'text.lighter', fontSize: '0.75rem' }} />
|
|
823
|
+
<Typography variant="body2" sx={{ fontSize: '0.75rem', color: 'text.lighter' }}>
|
|
824
|
+
{locale === 'zh'
|
|
825
|
+
? checkoutSession.metadata.page_info.form_purpose_description.zh
|
|
826
|
+
: checkoutSession.metadata.page_info.form_purpose_description.en}
|
|
827
|
+
</Typography>
|
|
828
|
+
</Box>
|
|
829
|
+
)}
|
|
701
830
|
</Stack>
|
|
702
831
|
</Fade>
|
|
703
832
|
{state.customerLimited && (
|
|
@@ -725,6 +854,7 @@ export default function PaymentForm({
|
|
|
725
854
|
}}
|
|
726
855
|
/>
|
|
727
856
|
)}
|
|
857
|
+
{FastCheckoutConfirmDialog}
|
|
728
858
|
</>
|
|
729
859
|
);
|
|
730
860
|
}
|