@blocklet/payment-react 1.26.3 → 1.26.5
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/checkout-v2/components/dialogs/checkout-dialogs.js +2 -1
- package/es/checkout-v2/components/right/customer-info-card.js +5 -0
- package/es/checkout-v2/utils/format.d.ts +1 -1
- package/es/checkout-v2/utils/format.js +3 -2
- package/es/components/service-suspended-dialog.js +8 -6
- package/es/libs/util.js +9 -20
- package/es/locales/en.js +4 -2
- package/es/locales/zh.js +2 -0
- package/es/payment/form/index.js +1 -10
- package/es/payment/form/stripe/form.d.ts +3 -1
- package/es/payment/form/stripe/form.js +32 -15
- package/lib/checkout-v2/components/dialogs/checkout-dialogs.js +2 -1
- package/lib/checkout-v2/components/right/customer-info-card.js +5 -0
- package/lib/checkout-v2/utils/format.d.ts +1 -1
- package/lib/checkout-v2/utils/format.js +6 -2
- package/lib/components/service-suspended-dialog.js +8 -6
- package/lib/libs/util.js +11 -7
- package/lib/locales/en.js +4 -2
- package/lib/locales/zh.js +2 -0
- package/lib/payment/form/index.js +4 -9
- package/lib/payment/form/stripe/form.d.ts +3 -1
- package/lib/payment/form/stripe/form.js +37 -17
- package/package.json +4 -4
- package/src/checkout-v2/components/dialogs/checkout-dialogs.tsx +6 -0
- package/src/checkout-v2/components/right/customer-info-card.tsx +7 -0
- package/src/checkout-v2/layouts/checkout-layout.tsx +13 -12
- package/src/checkout-v2/utils/format.ts +8 -3
- package/src/components/service-suspended-dialog.tsx +8 -6
- package/src/libs/util.ts +9 -20
- package/src/locales/en.tsx +4 -2
- package/src/locales/zh.tsx +2 -0
- package/src/payment/form/index.tsx +1 -9
- package/src/payment/form/stripe/form.tsx +29 -11
|
@@ -50,7 +50,8 @@ export default function CheckoutDialogs() {
|
|
|
50
50
|
},
|
|
51
51
|
returnUrl: getRedirectUrl(session),
|
|
52
52
|
onConfirm: submit.stripeConfirm,
|
|
53
|
-
onCancel: submit.stripeCancel
|
|
53
|
+
onCancel: submit.stripeCancel,
|
|
54
|
+
onSkip: stripeContext.noPaymentRequired && `${session?.metadata?.allow_skip_payment_method}` === "true" ? submit.stripeSkip : void 0
|
|
54
55
|
}
|
|
55
56
|
),
|
|
56
57
|
submit.status === "confirming_price" && submit.context?.type === "price_change" && /* @__PURE__ */ jsx(
|
|
@@ -36,6 +36,11 @@ export default function CustomerInfoCard({ form, isLoggedIn }) {
|
|
|
36
36
|
[form.onChange]
|
|
37
37
|
// eslint-disable-line react-hooks/exhaustive-deps
|
|
38
38
|
);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (ready && !showEditForm && Object.keys(form.errors).length > 0) {
|
|
41
|
+
setShowEditForm(true);
|
|
42
|
+
}
|
|
43
|
+
}, [form.errors]);
|
|
39
44
|
if (!isLoggedIn || !ready) return null;
|
|
40
45
|
if (!showEditForm) {
|
|
41
46
|
return /* @__PURE__ */ jsxs(Box, { sx: { mt: 2 }, children: [
|
|
@@ -43,7 +43,7 @@ export declare const whiteTooltipSx: {
|
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
45
|
};
|
|
46
|
-
export declare function formatTrialText(t: (key: string) => string, days: number, interval: string): string;
|
|
46
|
+
export declare function formatTrialText(t: (key: string, params?: Record<string, any>) => string, days: number, interval: string): string;
|
|
47
47
|
type TFn = (key: string, params?: Record<string, any>) => string;
|
|
48
48
|
export type ItemTypeBadge = 'subscription' | 'topup' | 'oneTime';
|
|
49
49
|
interface ItemMeta {
|
|
@@ -86,8 +86,9 @@ export const whiteTooltipSx = {
|
|
|
86
86
|
}
|
|
87
87
|
};
|
|
88
88
|
export function formatTrialText(t, days, interval) {
|
|
89
|
-
const
|
|
90
|
-
|
|
89
|
+
const key = interval || "day";
|
|
90
|
+
const intervalKey = days > 1 ? `common.${key}s` : `common.${key}`;
|
|
91
|
+
return t("payment.checkout.free", { count: days, interval: t(intervalKey) });
|
|
91
92
|
}
|
|
92
93
|
export function getSessionHeaderMeta(t, session, product, items) {
|
|
93
94
|
const mode = session?.mode || "payment";
|
|
@@ -10,12 +10,14 @@ export default function ServiceSuspendedDialog({ open, onClose }) {
|
|
|
10
10
|
{
|
|
11
11
|
open,
|
|
12
12
|
onClose,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
slotProps: {
|
|
14
|
+
paper: {
|
|
15
|
+
sx: {
|
|
16
|
+
borderRadius: 3,
|
|
17
|
+
maxWidth: 400,
|
|
18
|
+
mx: "auto",
|
|
19
|
+
overflow: "hidden"
|
|
20
|
+
}
|
|
19
21
|
}
|
|
20
22
|
},
|
|
21
23
|
children: /* @__PURE__ */ jsxs(DialogContent, { sx: { p: 0 }, children: [
|
package/es/libs/util.js
CHANGED
|
@@ -734,34 +734,23 @@ export function hasMultipleRecurringIntervals(items) {
|
|
|
734
734
|
}
|
|
735
735
|
export function getFreeTrialTime({ trialInDays, trialEnd }, locale = "en") {
|
|
736
736
|
const now = dayjs().unix();
|
|
737
|
+
const plural = (singular, count) => t(`common.${count > 1 ? `${singular}s` : singular}`, locale);
|
|
737
738
|
if (trialEnd > 0 && trialEnd > now) {
|
|
738
739
|
if (trialEnd - now < 3600) {
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
interval: t("common.minute", locale)
|
|
742
|
-
};
|
|
740
|
+
const count2 = Math.ceil((trialEnd - now) / 60);
|
|
741
|
+
return { count: count2, interval: plural("minute", count2) };
|
|
743
742
|
}
|
|
744
743
|
if (trialEnd - now < 86400) {
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
interval: t("common.hour", locale)
|
|
748
|
-
};
|
|
744
|
+
const count2 = Math.ceil((trialEnd - now) / 3600);
|
|
745
|
+
return { count: count2, interval: plural("hour", count2) };
|
|
749
746
|
}
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
interval: t("common.day", locale)
|
|
753
|
-
};
|
|
747
|
+
const count = Math.ceil((trialEnd - now) / 86400);
|
|
748
|
+
return { count, interval: plural("day", count) };
|
|
754
749
|
}
|
|
755
750
|
if (trialInDays > 0) {
|
|
756
|
-
return {
|
|
757
|
-
count: trialInDays,
|
|
758
|
-
interval: t("common.day", locale)
|
|
759
|
-
};
|
|
751
|
+
return { count: trialInDays, interval: plural("day", trialInDays) };
|
|
760
752
|
}
|
|
761
|
-
return {
|
|
762
|
-
count: 0,
|
|
763
|
-
interval: t("common.day", locale)
|
|
764
|
-
};
|
|
753
|
+
return { count: 0, interval: t("common.day", locale) };
|
|
765
754
|
}
|
|
766
755
|
export function formatCheckoutHeadlines(items, currency, { trialInDays, trialEnd }, locale = "en", { exchangeRate = null } = {}) {
|
|
767
756
|
const brand = getStatementDescriptor(items);
|
package/es/locales/en.js
CHANGED
|
@@ -98,7 +98,7 @@ export default flat({
|
|
|
98
98
|
continue: "Continue",
|
|
99
99
|
qty: "Qty {count}",
|
|
100
100
|
each: "{unit} each",
|
|
101
|
-
trial: "Free for {count} {interval}
|
|
101
|
+
trial: "Free for {count} {interval}",
|
|
102
102
|
billed: "billed {rule}",
|
|
103
103
|
metered: "based on usage",
|
|
104
104
|
minute: "minute",
|
|
@@ -115,6 +115,7 @@ export default flat({
|
|
|
115
115
|
month3: "every 3 months",
|
|
116
116
|
month6: "every 6 months",
|
|
117
117
|
recurring: "every {count} {interval}",
|
|
118
|
+
minutes: "minutes",
|
|
118
119
|
hours: "hours",
|
|
119
120
|
days: "days",
|
|
120
121
|
weeks: "weeks",
|
|
@@ -265,6 +266,7 @@ export default flat({
|
|
|
265
266
|
configTip: "Configure donation settings in Payment Kit"
|
|
266
267
|
},
|
|
267
268
|
cardPay: "{action} with bank card",
|
|
269
|
+
skipPaymentMethod: "Skip, bind later",
|
|
268
270
|
empty: "Nothing to pay",
|
|
269
271
|
per: "per",
|
|
270
272
|
pay: "Pay {payee}",
|
|
@@ -275,7 +277,7 @@ export default flat({
|
|
|
275
277
|
then: "Then {subscription} {recurring}",
|
|
276
278
|
meteredThen: "Then {recurring} based on usage",
|
|
277
279
|
metered: "{recurring} based on usage",
|
|
278
|
-
free: "{count} {interval}
|
|
280
|
+
free: "{count} {interval} free",
|
|
279
281
|
least: "continue with at least",
|
|
280
282
|
completed: {
|
|
281
283
|
payment: "Purchase successful",
|
package/es/locales/zh.js
CHANGED
|
@@ -115,6 +115,7 @@ export default flat({
|
|
|
115
115
|
month3: "\u6BCF\u5B63\u5EA6",
|
|
116
116
|
month6: "\u6BCF\u534A\u5E74",
|
|
117
117
|
recurring: "\u6BCF{count}{interval}",
|
|
118
|
+
minutes: "\u5206\u949F",
|
|
118
119
|
hours: "\u5C0F\u65F6",
|
|
119
120
|
days: "\u5929",
|
|
120
121
|
weeks: "\u5468",
|
|
@@ -265,6 +266,7 @@ export default flat({
|
|
|
265
266
|
configTip: "\u524D\u5F80 Payment Kit \u914D\u7F6E\u6253\u8D4F\u9009\u9879"
|
|
266
267
|
},
|
|
267
268
|
cardPay: "\u4F7F\u7528\u94F6\u884C\u5361{action}",
|
|
269
|
+
skipPaymentMethod: "\u8DF3\u8FC7\uFF0C\u7A0D\u540E\u7ED1\u5B9A",
|
|
268
270
|
empty: "\u6CA1\u6709\u53EF\u652F\u4ED8\u7684\u9879\u76EE",
|
|
269
271
|
per: "\u6BCF",
|
|
270
272
|
pay: "\u4ED8\u6B3E\u7ED9 {payee}",
|
package/es/payment/form/index.js
CHANGED
|
@@ -1451,16 +1451,7 @@ export default function PaymentForm({
|
|
|
1451
1451
|
}
|
|
1452
1452
|
}
|
|
1453
1453
|
),
|
|
1454
|
-
state.serviceSuspended && /* @__PURE__ */ jsx(
|
|
1455
|
-
ConfirmDialog,
|
|
1456
|
-
{
|
|
1457
|
-
onConfirm: () => setState({ serviceSuspended: false }),
|
|
1458
|
-
onCancel: () => setState({ serviceSuspended: false }),
|
|
1459
|
-
title: t("payment.checkout.stopAcceptingOrders.title"),
|
|
1460
|
-
message: t("payment.checkout.stopAcceptingOrders.description"),
|
|
1461
|
-
confirm: t("common.confirm")
|
|
1462
|
-
}
|
|
1463
|
-
),
|
|
1454
|
+
state.serviceSuspended && /* @__PURE__ */ jsx(ServiceSuspendedDialog, { open: true, onClose: () => setState({ serviceSuspended: false }) }),
|
|
1464
1455
|
FastCheckoutConfirmDialog,
|
|
1465
1456
|
CreditInsufficientDialog,
|
|
1466
1457
|
PriceUpdatedDialog,
|
|
@@ -5,6 +5,7 @@ export type StripeCheckoutFormProps = {
|
|
|
5
5
|
customer: TCustomer;
|
|
6
6
|
mode: string;
|
|
7
7
|
onConfirm: Function;
|
|
8
|
+
onSkip?: Function | null;
|
|
8
9
|
returnUrl?: string;
|
|
9
10
|
submitButtonText?: string;
|
|
10
11
|
};
|
|
@@ -16,8 +17,9 @@ export type StripeCheckoutProps = {
|
|
|
16
17
|
customer: TCustomer;
|
|
17
18
|
onConfirm: Function;
|
|
18
19
|
onCancel: Function;
|
|
20
|
+
onSkip?: Function | null;
|
|
19
21
|
returnUrl?: string;
|
|
20
22
|
title?: string;
|
|
21
23
|
submitButtonText?: string;
|
|
22
24
|
};
|
|
23
|
-
export default function StripeCheckout({ clientSecret, intentType, publicKey, mode, customer, onConfirm, onCancel, returnUrl, title, submitButtonText, }: StripeCheckoutProps): import("react").JSX.Element;
|
|
25
|
+
export default function StripeCheckout({ clientSecret, intentType, publicKey, mode, customer, onConfirm, onCancel, onSkip, returnUrl, title, submitButtonText, }: StripeCheckoutProps): import("react").JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import Center from "@arcblock/ux/lib/Center";
|
|
3
3
|
import Dialog from "@arcblock/ux/lib/Dialog";
|
|
4
4
|
import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
@@ -23,6 +23,7 @@ function StripeCheckoutForm({
|
|
|
23
23
|
customer,
|
|
24
24
|
mode,
|
|
25
25
|
onConfirm,
|
|
26
|
+
onSkip = null,
|
|
26
27
|
returnUrl = "",
|
|
27
28
|
submitButtonText = ""
|
|
28
29
|
}) {
|
|
@@ -191,20 +192,34 @@ function StripeCheckoutForm({
|
|
|
191
192
|
}
|
|
192
193
|
) }),
|
|
193
194
|
(!stripe || !elements || !state.loaded) && /* @__PURE__ */ jsx(Center, { relative: "parent", children: /* @__PURE__ */ jsx(CircularProgress, {}) }),
|
|
194
|
-
stripe && elements && state.loaded && /* @__PURE__ */
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
195
|
+
stripe && elements && state.loaded && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
196
|
+
/* @__PURE__ */ jsx(
|
|
197
|
+
LoadingButton,
|
|
198
|
+
{
|
|
199
|
+
fullWidth: true,
|
|
200
|
+
sx: { mt: 2, mb: 1, borderRadius: 0, fontSize: "0.875rem" },
|
|
201
|
+
type: "submit",
|
|
202
|
+
disabled: state.confirming || !state.loaded,
|
|
203
|
+
loading: state.confirming,
|
|
204
|
+
variant: "contained",
|
|
205
|
+
color: "primary",
|
|
206
|
+
size: "large",
|
|
207
|
+
children: submitButtonText || t("payment.checkout.continue", { action: t(`payment.checkout.${mode}`) })
|
|
208
|
+
}
|
|
209
|
+
),
|
|
210
|
+
onSkip && /* @__PURE__ */ jsx(
|
|
211
|
+
LoadingButton,
|
|
212
|
+
{
|
|
213
|
+
fullWidth: true,
|
|
214
|
+
sx: { mb: 1, borderRadius: 0, fontSize: "0.875rem", borderColor: "divider" },
|
|
215
|
+
disabled: state.confirming,
|
|
216
|
+
variant: "outlined",
|
|
217
|
+
color: "primary",
|
|
218
|
+
onClick: () => onSkip(),
|
|
219
|
+
children: t("payment.checkout.skipPaymentMethod", { defaultValue: "Skip, bind later" })
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
] }),
|
|
208
223
|
state.message && /* @__PURE__ */ jsx(Typography, { sx: { mt: 1, color: "error.main" }, children: state.message })
|
|
209
224
|
] });
|
|
210
225
|
}
|
|
@@ -225,6 +240,7 @@ export default function StripeCheckout({
|
|
|
225
240
|
customer,
|
|
226
241
|
onConfirm,
|
|
227
242
|
onCancel,
|
|
243
|
+
onSkip = null,
|
|
228
244
|
returnUrl = "",
|
|
229
245
|
title = "",
|
|
230
246
|
submitButtonText = ""
|
|
@@ -300,6 +316,7 @@ export default function StripeCheckout({
|
|
|
300
316
|
mode,
|
|
301
317
|
customer,
|
|
302
318
|
onConfirm,
|
|
319
|
+
onSkip,
|
|
303
320
|
returnUrl,
|
|
304
321
|
submitButtonText
|
|
305
322
|
}
|
|
@@ -56,7 +56,8 @@ function CheckoutDialogs() {
|
|
|
56
56
|
},
|
|
57
57
|
returnUrl: getRedirectUrl(session),
|
|
58
58
|
onConfirm: submit.stripeConfirm,
|
|
59
|
-
onCancel: submit.stripeCancel
|
|
59
|
+
onCancel: submit.stripeCancel,
|
|
60
|
+
onSkip: stripeContext.noPaymentRequired && `${session?.metadata?.allow_skip_payment_method}` === "true" ? submit.stripeSkip : void 0
|
|
60
61
|
}), submit.status === "confirming_price" && submit.context?.type === "price_change" && /* @__PURE__ */(0, _jsxRuntime.jsx)(_priceChangeConfirm.default, {
|
|
61
62
|
open: true,
|
|
62
63
|
changePercent: submit.context.changePercent,
|
|
@@ -46,6 +46,11 @@ function CustomerInfoCard({
|
|
|
46
46
|
const handleChange = (0, _react.useCallback)((field, value) => form.onChange(field, value), [form.onChange]
|
|
47
47
|
// eslint-disable-line react-hooks/exhaustive-deps
|
|
48
48
|
);
|
|
49
|
+
(0, _react.useEffect)(() => {
|
|
50
|
+
if (ready && !showEditForm && Object.keys(form.errors).length > 0) {
|
|
51
|
+
setShowEditForm(true);
|
|
52
|
+
}
|
|
53
|
+
}, [form.errors]);
|
|
49
54
|
if (!isLoggedIn || !ready) return null;
|
|
50
55
|
if (!showEditForm) {
|
|
51
56
|
return /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
@@ -43,7 +43,7 @@ export declare const whiteTooltipSx: {
|
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
45
|
};
|
|
46
|
-
export declare function formatTrialText(t: (key: string) => string, days: number, interval: string): string;
|
|
46
|
+
export declare function formatTrialText(t: (key: string, params?: Record<string, any>) => string, days: number, interval: string): string;
|
|
47
47
|
type TFn = (key: string, params?: Record<string, any>) => string;
|
|
48
48
|
export type ItemTypeBadge = 'subscription' | 'topup' | 'oneTime';
|
|
49
49
|
interface ItemMeta {
|
|
@@ -116,8 +116,12 @@ const whiteTooltipSx = exports.whiteTooltipSx = {
|
|
|
116
116
|
}
|
|
117
117
|
};
|
|
118
118
|
function formatTrialText(t, days, interval) {
|
|
119
|
-
const
|
|
120
|
-
|
|
119
|
+
const key = interval || "day";
|
|
120
|
+
const intervalKey = days > 1 ? `common.${key}s` : `common.${key}`;
|
|
121
|
+
return t("payment.checkout.free", {
|
|
122
|
+
count: days,
|
|
123
|
+
interval: t(intervalKey)
|
|
124
|
+
});
|
|
121
125
|
}
|
|
122
126
|
function getSessionHeaderMeta(t, session, product, items) {
|
|
123
127
|
const mode = session?.mode || "payment";
|
|
@@ -20,12 +20,14 @@ function ServiceSuspendedDialog({
|
|
|
20
20
|
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Dialog, {
|
|
21
21
|
open,
|
|
22
22
|
onClose,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
slotProps: {
|
|
24
|
+
paper: {
|
|
25
|
+
sx: {
|
|
26
|
+
borderRadius: 3,
|
|
27
|
+
maxWidth: 400,
|
|
28
|
+
mx: "auto",
|
|
29
|
+
overflow: "hidden"
|
|
30
|
+
}
|
|
29
31
|
}
|
|
30
32
|
},
|
|
31
33
|
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.DialogContent, {
|
package/lib/libs/util.js
CHANGED
|
@@ -891,28 +891,32 @@ function getFreeTrialTime({
|
|
|
891
891
|
trialEnd
|
|
892
892
|
}, locale = "en") {
|
|
893
893
|
const now = (0, _dayjs.default)().unix();
|
|
894
|
+
const plural = (singular, count) => (0, _locales.t)(`common.${count > 1 ? `${singular}s` : singular}`, locale);
|
|
894
895
|
if (trialEnd > 0 && trialEnd > now) {
|
|
895
896
|
if (trialEnd - now < 3600) {
|
|
897
|
+
const count2 = Math.ceil((trialEnd - now) / 60);
|
|
896
898
|
return {
|
|
897
|
-
count:
|
|
898
|
-
interval: (
|
|
899
|
+
count: count2,
|
|
900
|
+
interval: plural("minute", count2)
|
|
899
901
|
};
|
|
900
902
|
}
|
|
901
903
|
if (trialEnd - now < 86400) {
|
|
904
|
+
const count2 = Math.ceil((trialEnd - now) / 3600);
|
|
902
905
|
return {
|
|
903
|
-
count:
|
|
904
|
-
interval: (
|
|
906
|
+
count: count2,
|
|
907
|
+
interval: plural("hour", count2)
|
|
905
908
|
};
|
|
906
909
|
}
|
|
910
|
+
const count = Math.ceil((trialEnd - now) / 86400);
|
|
907
911
|
return {
|
|
908
|
-
count
|
|
909
|
-
interval: (
|
|
912
|
+
count,
|
|
913
|
+
interval: plural("day", count)
|
|
910
914
|
};
|
|
911
915
|
}
|
|
912
916
|
if (trialInDays > 0) {
|
|
913
917
|
return {
|
|
914
918
|
count: trialInDays,
|
|
915
|
-
interval: (
|
|
919
|
+
interval: plural("day", trialInDays)
|
|
916
920
|
};
|
|
917
921
|
}
|
|
918
922
|
return {
|
package/lib/locales/en.js
CHANGED
|
@@ -105,7 +105,7 @@ module.exports = (0, _flat.default)({
|
|
|
105
105
|
continue: "Continue",
|
|
106
106
|
qty: "Qty {count}",
|
|
107
107
|
each: "{unit} each",
|
|
108
|
-
trial: "Free for {count} {interval}
|
|
108
|
+
trial: "Free for {count} {interval}",
|
|
109
109
|
billed: "billed {rule}",
|
|
110
110
|
metered: "based on usage",
|
|
111
111
|
minute: "minute",
|
|
@@ -122,6 +122,7 @@ module.exports = (0, _flat.default)({
|
|
|
122
122
|
month3: "every 3 months",
|
|
123
123
|
month6: "every 6 months",
|
|
124
124
|
recurring: "every {count} {interval}",
|
|
125
|
+
minutes: "minutes",
|
|
125
126
|
hours: "hours",
|
|
126
127
|
days: "days",
|
|
127
128
|
weeks: "weeks",
|
|
@@ -272,6 +273,7 @@ module.exports = (0, _flat.default)({
|
|
|
272
273
|
configTip: "Configure donation settings in Payment Kit"
|
|
273
274
|
},
|
|
274
275
|
cardPay: "{action} with bank card",
|
|
276
|
+
skipPaymentMethod: "Skip, bind later",
|
|
275
277
|
empty: "Nothing to pay",
|
|
276
278
|
per: "per",
|
|
277
279
|
pay: "Pay {payee}",
|
|
@@ -282,7 +284,7 @@ module.exports = (0, _flat.default)({
|
|
|
282
284
|
then: "Then {subscription} {recurring}",
|
|
283
285
|
meteredThen: "Then {recurring} based on usage",
|
|
284
286
|
metered: "{recurring} based on usage",
|
|
285
|
-
free: "{count} {interval}
|
|
287
|
+
free: "{count} {interval} free",
|
|
286
288
|
least: "continue with at least",
|
|
287
289
|
completed: {
|
|
288
290
|
payment: "Purchase successful",
|
package/lib/locales/zh.js
CHANGED
|
@@ -122,6 +122,7 @@ module.exports = (0, _flat.default)({
|
|
|
122
122
|
month3: "\u6BCF\u5B63\u5EA6",
|
|
123
123
|
month6: "\u6BCF\u534A\u5E74",
|
|
124
124
|
recurring: "\u6BCF{count}{interval}",
|
|
125
|
+
minutes: "\u5206\u949F",
|
|
125
126
|
hours: "\u5C0F\u65F6",
|
|
126
127
|
days: "\u5929",
|
|
127
128
|
weeks: "\u5468",
|
|
@@ -272,6 +273,7 @@ module.exports = (0, _flat.default)({
|
|
|
272
273
|
configTip: "\u524D\u5F80 Payment Kit \u914D\u7F6E\u6253\u8D4F\u9009\u9879"
|
|
273
274
|
},
|
|
274
275
|
cardPay: "\u4F7F\u7528\u94F6\u884C\u5361{action}",
|
|
276
|
+
skipPaymentMethod: "\u8DF3\u8FC7\uFF0C\u7A0D\u540E\u7ED1\u5B9A",
|
|
275
277
|
empty: "\u6CA1\u6709\u53EF\u652F\u4ED8\u7684\u9879\u76EE",
|
|
276
278
|
per: "\u6BCF",
|
|
277
279
|
pay: "\u4ED8\u6B3E\u7ED9 {payee}",
|
|
@@ -1630,16 +1630,11 @@ function PaymentForm({
|
|
|
1630
1630
|
}),
|
|
1631
1631
|
title: t("payment.customer.pastDue.alert.title")
|
|
1632
1632
|
}
|
|
1633
|
-
}), state.serviceSuspended && /* @__PURE__ */(0, _jsxRuntime.jsx)(
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
}),
|
|
1637
|
-
onCancel: () => setState({
|
|
1633
|
+
}), state.serviceSuspended && /* @__PURE__ */(0, _jsxRuntime.jsx)(_serviceSuspendedDialog.default, {
|
|
1634
|
+
open: true,
|
|
1635
|
+
onClose: () => setState({
|
|
1638
1636
|
serviceSuspended: false
|
|
1639
|
-
})
|
|
1640
|
-
title: t("payment.checkout.stopAcceptingOrders.title"),
|
|
1641
|
-
message: t("payment.checkout.stopAcceptingOrders.description"),
|
|
1642
|
-
confirm: t("common.confirm")
|
|
1637
|
+
})
|
|
1643
1638
|
}), FastCheckoutConfirmDialog, CreditInsufficientDialog, PriceUpdatedDialog, state.priceChangeConfirm?.open && /* @__PURE__ */(0, _jsxRuntime.jsx)(_priceChangeConfirm.default, {
|
|
1644
1639
|
open: true,
|
|
1645
1640
|
changePercent: state.priceChangeConfirm.changePercent,
|
|
@@ -5,6 +5,7 @@ export type StripeCheckoutFormProps = {
|
|
|
5
5
|
customer: TCustomer;
|
|
6
6
|
mode: string;
|
|
7
7
|
onConfirm: Function;
|
|
8
|
+
onSkip?: Function | null;
|
|
8
9
|
returnUrl?: string;
|
|
9
10
|
submitButtonText?: string;
|
|
10
11
|
};
|
|
@@ -16,8 +17,9 @@ export type StripeCheckoutProps = {
|
|
|
16
17
|
customer: TCustomer;
|
|
17
18
|
onConfirm: Function;
|
|
18
19
|
onCancel: Function;
|
|
20
|
+
onSkip?: Function | null;
|
|
19
21
|
returnUrl?: string;
|
|
20
22
|
title?: string;
|
|
21
23
|
submitButtonText?: string;
|
|
22
24
|
};
|
|
23
|
-
export default function StripeCheckout({ clientSecret, intentType, publicKey, mode, customer, onConfirm, onCancel, returnUrl, title, submitButtonText, }: StripeCheckoutProps): import("react").JSX.Element;
|
|
25
|
+
export default function StripeCheckout({ clientSecret, intentType, publicKey, mode, customer, onConfirm, onCancel, onSkip, returnUrl, title, submitButtonText, }: StripeCheckoutProps): import("react").JSX.Element;
|
|
@@ -37,6 +37,7 @@ function StripeCheckoutForm({
|
|
|
37
37
|
customer,
|
|
38
38
|
mode,
|
|
39
39
|
onConfirm,
|
|
40
|
+
onSkip = null,
|
|
40
41
|
returnUrl = "",
|
|
41
42
|
submitButtonText = ""
|
|
42
43
|
}) {
|
|
@@ -234,23 +235,40 @@ function StripeCheckoutForm({
|
|
|
234
235
|
}), (!stripe || !elements || !state.loaded) && /* @__PURE__ */(0, _jsxRuntime.jsx)(_Center.default, {
|
|
235
236
|
relative: "parent",
|
|
236
237
|
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.CircularProgress, {})
|
|
237
|
-
}), stripe && elements && state.loaded && /* @__PURE__ */(0, _jsxRuntime.
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
238
|
+
}), stripe && elements && state.loaded && /* @__PURE__ */(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
239
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_loadingButton.default, {
|
|
240
|
+
fullWidth: true,
|
|
241
|
+
sx: {
|
|
242
|
+
mt: 2,
|
|
243
|
+
mb: 1,
|
|
244
|
+
borderRadius: 0,
|
|
245
|
+
fontSize: "0.875rem"
|
|
246
|
+
},
|
|
247
|
+
type: "submit",
|
|
248
|
+
disabled: state.confirming || !state.loaded,
|
|
249
|
+
loading: state.confirming,
|
|
250
|
+
variant: "contained",
|
|
251
|
+
color: "primary",
|
|
252
|
+
size: "large",
|
|
253
|
+
children: submitButtonText || t("payment.checkout.continue", {
|
|
254
|
+
action: t(`payment.checkout.${mode}`)
|
|
255
|
+
})
|
|
256
|
+
}), onSkip && /* @__PURE__ */(0, _jsxRuntime.jsx)(_loadingButton.default, {
|
|
257
|
+
fullWidth: true,
|
|
258
|
+
sx: {
|
|
259
|
+
mb: 1,
|
|
260
|
+
borderRadius: 0,
|
|
261
|
+
fontSize: "0.875rem",
|
|
262
|
+
borderColor: "divider"
|
|
263
|
+
},
|
|
264
|
+
disabled: state.confirming,
|
|
265
|
+
variant: "outlined",
|
|
266
|
+
color: "primary",
|
|
267
|
+
onClick: () => onSkip(),
|
|
268
|
+
children: t("payment.checkout.skipPaymentMethod", {
|
|
269
|
+
defaultValue: "Skip, bind later"
|
|
270
|
+
})
|
|
271
|
+
})]
|
|
254
272
|
}), state.message && /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
255
273
|
sx: {
|
|
256
274
|
mt: 1,
|
|
@@ -277,6 +295,7 @@ function StripeCheckout({
|
|
|
277
295
|
customer,
|
|
278
296
|
onConfirm,
|
|
279
297
|
onCancel,
|
|
298
|
+
onSkip = null,
|
|
280
299
|
returnUrl = "",
|
|
281
300
|
title = "",
|
|
282
301
|
submitButtonText = ""
|
|
@@ -355,6 +374,7 @@ function StripeCheckout({
|
|
|
355
374
|
mode,
|
|
356
375
|
customer,
|
|
357
376
|
onConfirm,
|
|
377
|
+
onSkip,
|
|
358
378
|
returnUrl,
|
|
359
379
|
submitButtonText
|
|
360
380
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/payment-react",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.5",
|
|
4
4
|
"description": "Reusable react components for payment kit v2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@arcblock/react-hooks": "^3.5.1",
|
|
60
60
|
"@arcblock/ux": "^3.5.1",
|
|
61
61
|
"@arcblock/ws": "^1.28.5",
|
|
62
|
-
"@blocklet/payment-react-headless": "1.26.
|
|
62
|
+
"@blocklet/payment-react-headless": "1.26.5",
|
|
63
63
|
"@blocklet/theme": "^3.5.1",
|
|
64
64
|
"@blocklet/ui-react": "^3.5.1",
|
|
65
65
|
"@mui/icons-material": "^7.1.2",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"@babel/core": "^7.27.4",
|
|
98
98
|
"@babel/preset-env": "^7.27.2",
|
|
99
99
|
"@babel/preset-react": "^7.27.1",
|
|
100
|
-
"@blocklet/payment-types": "1.26.
|
|
100
|
+
"@blocklet/payment-types": "1.26.5",
|
|
101
101
|
"@storybook/addon-essentials": "^7.6.20",
|
|
102
102
|
"@storybook/addon-interactions": "^7.6.20",
|
|
103
103
|
"@storybook/addon-links": "^7.6.20",
|
|
@@ -128,5 +128,5 @@
|
|
|
128
128
|
"vite-plugin-babel": "^1.3.1",
|
|
129
129
|
"vite-plugin-node-polyfills": "^0.23.0"
|
|
130
130
|
},
|
|
131
|
-
"gitHead": "
|
|
131
|
+
"gitHead": "2d208818d218494407989dd8cd460ab51d075952"
|
|
132
132
|
}
|
|
@@ -59,6 +59,12 @@ export default function CheckoutDialogs() {
|
|
|
59
59
|
returnUrl={getRedirectUrl(session)}
|
|
60
60
|
onConfirm={submit.stripeConfirm}
|
|
61
61
|
onCancel={submit.stripeCancel}
|
|
62
|
+
onSkip={
|
|
63
|
+
stripeContext!.noPaymentRequired &&
|
|
64
|
+
`${(session?.metadata as Record<string, any>)?.allow_skip_payment_method}` === 'true'
|
|
65
|
+
? submit.stripeSkip
|
|
66
|
+
: undefined
|
|
67
|
+
}
|
|
62
68
|
/>
|
|
63
69
|
)}
|
|
64
70
|
|
|
@@ -65,6 +65,13 @@ export default function CustomerInfoCard({ form, isLoggedIn }: CustomerInfoCardP
|
|
|
65
65
|
[form.onChange] // eslint-disable-line react-hooks/exhaustive-deps
|
|
66
66
|
);
|
|
67
67
|
|
|
68
|
+
// Auto-expand to edit mode when validation errors appear (e.g. after submit click)
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (ready && !showEditForm && Object.keys(form.errors).length > 0) {
|
|
71
|
+
setShowEditForm(true);
|
|
72
|
+
}
|
|
73
|
+
}, [form.errors]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
74
|
+
|
|
68
75
|
if (!isLoggedIn || !ready) return null;
|
|
69
76
|
|
|
70
77
|
// Summary view
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/indent */
|
|
1
2
|
import { Box } from '@mui/material';
|
|
2
3
|
import { alpha, useTheme } from '@mui/material/styles';
|
|
3
4
|
import Header from '@blocklet/ui-react/lib/Header';
|
|
@@ -34,19 +35,19 @@ const isSafari =
|
|
|
34
35
|
|
|
35
36
|
const slideInFromRight = isSafari
|
|
36
37
|
? ({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
'@keyframes panelFadeIn': {
|
|
39
|
+
from: { opacity: 0, transform: 'translateX(24px)' },
|
|
40
|
+
to: { opacity: 1, transform: 'none' },
|
|
41
|
+
},
|
|
42
|
+
animation: { xs: 'none', md: 'panelFadeIn 0.5s cubic-bezier(0.16, 1, 0.3, 1) both' },
|
|
43
|
+
} as const)
|
|
43
44
|
: ({
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
'@keyframes slideInRight': {
|
|
46
|
+
from: { transform: 'translateX(100%)' },
|
|
47
|
+
to: { transform: 'translateX(0)' },
|
|
48
|
+
},
|
|
49
|
+
animation: { xs: 'none', md: 'slideInRight 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards' },
|
|
50
|
+
} as const);
|
|
50
51
|
|
|
51
52
|
interface CheckoutLayoutProps {
|
|
52
53
|
left: React.ReactNode;
|
|
@@ -136,9 +136,14 @@ export const whiteTooltipSx = {
|
|
|
136
136
|
};
|
|
137
137
|
|
|
138
138
|
// Helper: format trial text
|
|
139
|
-
export function formatTrialText(
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
export function formatTrialText(
|
|
140
|
+
t: (key: string, params?: Record<string, any>) => string,
|
|
141
|
+
days: number,
|
|
142
|
+
interval: string
|
|
143
|
+
): string {
|
|
144
|
+
const key = interval || 'day';
|
|
145
|
+
const intervalKey = days > 1 ? `common.${key}s` : `common.${key}`;
|
|
146
|
+
return t('payment.checkout.free', { count: days, interval: t(intervalKey) });
|
|
142
147
|
}
|
|
143
148
|
|
|
144
149
|
// ── Item meta: badge / title / subtitle for the header area ──
|
|
@@ -10,12 +10,14 @@ export default function ServiceSuspendedDialog({ open, onClose }: { open: boolea
|
|
|
10
10
|
<Dialog
|
|
11
11
|
open={open}
|
|
12
12
|
onClose={onClose}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
slotProps={{
|
|
14
|
+
paper: {
|
|
15
|
+
sx: {
|
|
16
|
+
borderRadius: 3,
|
|
17
|
+
maxWidth: 400,
|
|
18
|
+
mx: 'auto',
|
|
19
|
+
overflow: 'hidden',
|
|
20
|
+
},
|
|
19
21
|
},
|
|
20
22
|
}}>
|
|
21
23
|
<DialogContent sx={{ p: 0 }}>
|
package/src/libs/util.ts
CHANGED
|
@@ -1062,34 +1062,23 @@ export function getFreeTrialTime(
|
|
|
1062
1062
|
interval: string;
|
|
1063
1063
|
} {
|
|
1064
1064
|
const now = dayjs().unix();
|
|
1065
|
+
const plural = (singular: string, count: number) => t(`common.${count > 1 ? `${singular}s` : singular}`, locale);
|
|
1065
1066
|
if (trialEnd > 0 && trialEnd > now) {
|
|
1066
1067
|
if (trialEnd - now < 3600) {
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
interval: t('common.minute', locale),
|
|
1070
|
-
};
|
|
1068
|
+
const count = Math.ceil((trialEnd - now) / 60);
|
|
1069
|
+
return { count, interval: plural('minute', count) };
|
|
1071
1070
|
}
|
|
1072
1071
|
if (trialEnd - now < 86400) {
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
interval: t('common.hour', locale),
|
|
1076
|
-
};
|
|
1072
|
+
const count = Math.ceil((trialEnd - now) / 3600);
|
|
1073
|
+
return { count, interval: plural('hour', count) };
|
|
1077
1074
|
}
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
interval: t('common.day', locale),
|
|
1081
|
-
};
|
|
1075
|
+
const count = Math.ceil((trialEnd - now) / 86400);
|
|
1076
|
+
return { count, interval: plural('day', count) };
|
|
1082
1077
|
}
|
|
1083
1078
|
if (trialInDays > 0) {
|
|
1084
|
-
return {
|
|
1085
|
-
count: trialInDays,
|
|
1086
|
-
interval: t('common.day', locale),
|
|
1087
|
-
};
|
|
1079
|
+
return { count: trialInDays, interval: plural('day', trialInDays) };
|
|
1088
1080
|
}
|
|
1089
|
-
return {
|
|
1090
|
-
count: 0,
|
|
1091
|
-
interval: t('common.day', locale),
|
|
1092
|
-
};
|
|
1081
|
+
return { count: 0, interval: t('common.day', locale) };
|
|
1093
1082
|
}
|
|
1094
1083
|
export function formatCheckoutHeadlines(
|
|
1095
1084
|
items: TLineItemExpanded[],
|
package/src/locales/en.tsx
CHANGED
|
@@ -100,7 +100,7 @@ export default flat({
|
|
|
100
100
|
continue: 'Continue',
|
|
101
101
|
qty: 'Qty {count}',
|
|
102
102
|
each: '{unit} each',
|
|
103
|
-
trial:
|
|
103
|
+
trial: 'Free for {count} {interval}',
|
|
104
104
|
billed: 'billed {rule}',
|
|
105
105
|
metered: 'based on usage',
|
|
106
106
|
minute: 'minute',
|
|
@@ -117,6 +117,7 @@ export default flat({
|
|
|
117
117
|
month3: 'every 3 months',
|
|
118
118
|
month6: 'every 6 months',
|
|
119
119
|
recurring: 'every {count} {interval}',
|
|
120
|
+
minutes: 'minutes',
|
|
120
121
|
hours: 'hours',
|
|
121
122
|
days: 'days',
|
|
122
123
|
weeks: 'weeks',
|
|
@@ -271,6 +272,7 @@ export default flat({
|
|
|
271
272
|
configTip: 'Configure donation settings in Payment Kit',
|
|
272
273
|
},
|
|
273
274
|
cardPay: '{action} with bank card',
|
|
275
|
+
skipPaymentMethod: 'Skip, bind later',
|
|
274
276
|
empty: 'Nothing to pay',
|
|
275
277
|
per: 'per',
|
|
276
278
|
pay: 'Pay {payee}',
|
|
@@ -281,7 +283,7 @@ export default flat({
|
|
|
281
283
|
then: 'Then {subscription} {recurring}',
|
|
282
284
|
meteredThen: 'Then {recurring} based on usage',
|
|
283
285
|
metered: '{recurring} based on usage',
|
|
284
|
-
free:
|
|
286
|
+
free: '{count} {interval} free',
|
|
285
287
|
least: 'continue with at least',
|
|
286
288
|
completed: {
|
|
287
289
|
payment: 'Purchase successful',
|
package/src/locales/zh.tsx
CHANGED
|
@@ -117,6 +117,7 @@ export default flat({
|
|
|
117
117
|
month3: '每季度',
|
|
118
118
|
month6: '每半年',
|
|
119
119
|
recurring: '每{count}{interval}',
|
|
120
|
+
minutes: '分钟',
|
|
120
121
|
hours: '小时',
|
|
121
122
|
days: '天',
|
|
122
123
|
weeks: '周',
|
|
@@ -267,6 +268,7 @@ export default flat({
|
|
|
267
268
|
configTip: '前往 Payment Kit 配置打赏选项',
|
|
268
269
|
},
|
|
269
270
|
cardPay: '使用银行卡{action}',
|
|
271
|
+
skipPaymentMethod: '跳过,稍后绑定',
|
|
270
272
|
empty: '没有可支付的项目',
|
|
271
273
|
per: '每',
|
|
272
274
|
pay: '付款给 {payee}',
|
|
@@ -1759,15 +1759,7 @@ export default function PaymentForm({
|
|
|
1759
1759
|
}}
|
|
1760
1760
|
/>
|
|
1761
1761
|
)}
|
|
1762
|
-
{state.serviceSuspended && (
|
|
1763
|
-
<ConfirmDialog
|
|
1764
|
-
onConfirm={() => setState({ serviceSuspended: false })}
|
|
1765
|
-
onCancel={() => setState({ serviceSuspended: false })}
|
|
1766
|
-
title={t('payment.checkout.stopAcceptingOrders.title')}
|
|
1767
|
-
message={t('payment.checkout.stopAcceptingOrders.description')}
|
|
1768
|
-
confirm={t('common.confirm')}
|
|
1769
|
-
/>
|
|
1770
|
-
)}
|
|
1762
|
+
{state.serviceSuspended && <ServiceSuspendedDialog open onClose={() => setState({ serviceSuspended: false })} />}
|
|
1771
1763
|
{FastCheckoutConfirmDialog}
|
|
1772
1764
|
{CreditInsufficientDialog}
|
|
1773
1765
|
{PriceUpdatedDialog}
|
|
@@ -19,6 +19,7 @@ export type StripeCheckoutFormProps = {
|
|
|
19
19
|
customer: TCustomer;
|
|
20
20
|
mode: string;
|
|
21
21
|
onConfirm: Function;
|
|
22
|
+
onSkip?: Function | null;
|
|
22
23
|
returnUrl?: string;
|
|
23
24
|
submitButtonText?: string;
|
|
24
25
|
};
|
|
@@ -39,6 +40,7 @@ function StripeCheckoutForm({
|
|
|
39
40
|
customer,
|
|
40
41
|
mode,
|
|
41
42
|
onConfirm,
|
|
43
|
+
onSkip = null,
|
|
42
44
|
returnUrl = '',
|
|
43
45
|
submitButtonText = '',
|
|
44
46
|
}: StripeCheckoutFormProps) {
|
|
@@ -229,17 +231,30 @@ function StripeCheckoutForm({
|
|
|
229
231
|
</Center>
|
|
230
232
|
)}
|
|
231
233
|
{stripe && elements && state.loaded && (
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
234
|
+
<>
|
|
235
|
+
<LoadingButton
|
|
236
|
+
fullWidth
|
|
237
|
+
sx={{ mt: 2, mb: 1, borderRadius: 0, fontSize: '0.875rem' }}
|
|
238
|
+
type="submit"
|
|
239
|
+
disabled={state.confirming || !state.loaded}
|
|
240
|
+
loading={state.confirming}
|
|
241
|
+
variant="contained"
|
|
242
|
+
color="primary"
|
|
243
|
+
size="large">
|
|
244
|
+
{submitButtonText || t('payment.checkout.continue', { action: t(`payment.checkout.${mode}`) })}
|
|
245
|
+
</LoadingButton>
|
|
246
|
+
{onSkip && (
|
|
247
|
+
<LoadingButton
|
|
248
|
+
fullWidth
|
|
249
|
+
sx={{ mb: 1, borderRadius: 0, fontSize: '0.875rem', borderColor: 'divider' }}
|
|
250
|
+
disabled={state.confirming}
|
|
251
|
+
variant="outlined"
|
|
252
|
+
color="primary"
|
|
253
|
+
onClick={() => onSkip()}>
|
|
254
|
+
{t('payment.checkout.skipPaymentMethod', { defaultValue: 'Skip, bind later' })}
|
|
255
|
+
</LoadingButton>
|
|
256
|
+
)}
|
|
257
|
+
</>
|
|
243
258
|
)}
|
|
244
259
|
{state.message && <Typography sx={{ mt: 1, color: 'error.main' }}>{state.message}</Typography>}
|
|
245
260
|
</Content>
|
|
@@ -264,6 +279,7 @@ export type StripeCheckoutProps = {
|
|
|
264
279
|
customer: TCustomer;
|
|
265
280
|
onConfirm: Function;
|
|
266
281
|
onCancel: Function;
|
|
282
|
+
onSkip?: Function | null;
|
|
267
283
|
returnUrl?: string;
|
|
268
284
|
title?: string;
|
|
269
285
|
submitButtonText?: string;
|
|
@@ -276,6 +292,7 @@ export default function StripeCheckout({
|
|
|
276
292
|
customer,
|
|
277
293
|
onConfirm,
|
|
278
294
|
onCancel,
|
|
295
|
+
onSkip = null,
|
|
279
296
|
returnUrl = '',
|
|
280
297
|
title = '',
|
|
281
298
|
submitButtonText = '',
|
|
@@ -349,6 +366,7 @@ export default function StripeCheckout({
|
|
|
349
366
|
mode={mode}
|
|
350
367
|
customer={customer}
|
|
351
368
|
onConfirm={onConfirm}
|
|
369
|
+
onSkip={onSkip}
|
|
352
370
|
returnUrl={returnUrl}
|
|
353
371
|
submitButtonText={submitButtonText}
|
|
354
372
|
/>
|