@blocklet/payment-react 1.13.121 → 1.13.123
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/payment/form/index.js +62 -42
- package/es/payment/index.js +46 -0
- package/lib/payment/form/index.js +55 -68
- package/lib/payment/index.js +46 -0
- package/package.json +3 -3
- package/src/payment/form/index.tsx +59 -43
- package/src/payment/index.tsx +46 -0
package/es/payment/form/index.js
CHANGED
|
@@ -4,18 +4,19 @@ import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
|
|
|
4
4
|
import { useTheme } from "@arcblock/ux/lib/Theme";
|
|
5
5
|
import Toast from "@arcblock/ux/lib/Toast";
|
|
6
6
|
import { LoadingButton } from "@mui/lab";
|
|
7
|
-
import { Avatar, Fade, InputAdornment,
|
|
7
|
+
import { Avatar, Card, Fade, InputAdornment, Stack, Typography } from "@mui/material";
|
|
8
8
|
import { useCreation, useSetState, useSize } from "ahooks";
|
|
9
9
|
import { PhoneNumberUtil } from "google-libphonenumber";
|
|
10
10
|
import pWaitFor from "p-wait-for";
|
|
11
|
-
import { useEffect } from "react";
|
|
11
|
+
import { useEffect, useState } from "react";
|
|
12
12
|
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
|
13
|
+
import { joinURL } from "ufo";
|
|
13
14
|
import { dispatch } from "use-bus";
|
|
14
15
|
import isEmail from "validator/es/lib/isEmail";
|
|
15
16
|
import api from "../../api.js";
|
|
16
17
|
import FormInput from "../../components/input.js";
|
|
17
18
|
import { usePaymentContext } from "../../contexts/payment.js";
|
|
18
|
-
import { formatError, getStatementDescriptor } from "../../util.js";
|
|
19
|
+
import { formatError, getPrefix, getStatementDescriptor } from "../../util.js";
|
|
19
20
|
import UserButtons from "./addon.js";
|
|
20
21
|
import AddressForm from "./address.js";
|
|
21
22
|
import PhoneInput from "./phone.js";
|
|
@@ -36,6 +37,19 @@ const waitForCheckoutComplete = async (sessionId) => {
|
|
|
36
37
|
);
|
|
37
38
|
return result;
|
|
38
39
|
};
|
|
40
|
+
const flatPaymentMethods = (methods = []) => {
|
|
41
|
+
const out = [];
|
|
42
|
+
methods.forEach((method) => {
|
|
43
|
+
const currencies = method.paymentCurrencies || method.payment_currencies || [];
|
|
44
|
+
currencies.forEach((currency) => {
|
|
45
|
+
out.push({
|
|
46
|
+
...currency,
|
|
47
|
+
method
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
return out;
|
|
52
|
+
};
|
|
39
53
|
PaymentForm.defaultProps = {};
|
|
40
54
|
export default function PaymentForm({
|
|
41
55
|
checkoutSession,
|
|
@@ -59,6 +73,8 @@ export default function PaymentForm({
|
|
|
59
73
|
customer,
|
|
60
74
|
stripePaying: false
|
|
61
75
|
});
|
|
76
|
+
const currencies = flatPaymentMethods(paymentMethods);
|
|
77
|
+
const [paymentCurrencyIndex, setPaymentCurrencyIndex] = useState(0);
|
|
62
78
|
useEffect(() => {
|
|
63
79
|
if (session?.user) {
|
|
64
80
|
const values = getValues();
|
|
@@ -73,9 +89,11 @@ export default function PaymentForm({
|
|
|
73
89
|
}
|
|
74
90
|
}
|
|
75
91
|
}, [session?.user, getValues, setValue]);
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
setValue("payment_method", currencies[paymentCurrencyIndex].method.id);
|
|
94
|
+
setValue("payment_currency", currencies[paymentCurrencyIndex].id);
|
|
95
|
+
}, [paymentCurrencyIndex, currencies, setValue]);
|
|
76
96
|
const paymentMethod = useWatch({ control, name: "payment_method" });
|
|
77
|
-
const paymentCurrency = useWatch({ control, name: "payment_currency" });
|
|
78
|
-
const paymentCurrencies = paymentMethods.find((x) => x.id === paymentMethod)?.payment_currencies || [];
|
|
79
97
|
const domSize = useSize(document.body);
|
|
80
98
|
const isColumnLayout = useCreation(() => {
|
|
81
99
|
if (domSize) {
|
|
@@ -88,12 +106,8 @@ export default function PaymentForm({
|
|
|
88
106
|
const payee = getStatementDescriptor(checkoutSession.line_items);
|
|
89
107
|
const buttonText = session?.user ? t(`payment.checkout.${checkoutSession.mode}`) : t("payment.checkout.connect", { action: t(`payment.checkout.${checkoutSession.mode}`) });
|
|
90
108
|
const method = paymentMethods.find((x) => x.id === paymentMethod);
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
const currencies = paymentMethods.find((x) => x.id === e.target.value)?.payment_currencies || [];
|
|
94
|
-
if (currencies.some((x) => x.id === paymentCurrency) === false) {
|
|
95
|
-
setValue("payment_currency", currencies[0]?.id);
|
|
96
|
-
}
|
|
109
|
+
const handleCurrencyChange = (index) => {
|
|
110
|
+
setPaymentCurrencyIndex(index);
|
|
97
111
|
};
|
|
98
112
|
const handleConnected = async () => {
|
|
99
113
|
try {
|
|
@@ -156,6 +170,7 @@ export default function PaymentForm({
|
|
|
156
170
|
} else {
|
|
157
171
|
connect.open({
|
|
158
172
|
action: checkoutSession.mode,
|
|
173
|
+
prefix: joinURL(getPrefix(), "/api/did"),
|
|
159
174
|
timeout: 5 * 60 * 1e3,
|
|
160
175
|
extraParams: { checkoutSessionId: checkoutSession.id },
|
|
161
176
|
onSuccess: async () => {
|
|
@@ -267,36 +282,42 @@ export default function PaymentForm({
|
|
|
267
282
|
/* @__PURE__ */ jsx(AddressForm, { mode: checkoutSession.billing_address_collection, stripe: method?.type === "stripe" }),
|
|
268
283
|
/* @__PURE__ */ jsx(Fade, { in: true, children: /* @__PURE__ */ jsxs(Stack, { direction: "column", alignItems: "flex-start", className: "cko-payment-methods", children: [
|
|
269
284
|
/* @__PURE__ */ jsx(Typography, { sx: { mb: 2, color: "text.primary", fontWeight: 600 }, children: t("payment.checkout.method") }),
|
|
270
|
-
/* @__PURE__ */
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
285
|
+
/* @__PURE__ */ jsx(Stack, { direction: "row", sx: { width: "100%" }, children: /* @__PURE__ */ jsx(
|
|
286
|
+
Controller,
|
|
287
|
+
{
|
|
288
|
+
name: "payment_currency",
|
|
289
|
+
control,
|
|
290
|
+
render: () => /* @__PURE__ */ jsx(
|
|
291
|
+
"section",
|
|
292
|
+
{
|
|
293
|
+
style: {
|
|
294
|
+
display: currencies.length > 1 ? "grid" : "block",
|
|
295
|
+
gridTemplateColumns: "50% 50%",
|
|
296
|
+
width: "100%"
|
|
297
|
+
},
|
|
298
|
+
children: currencies.map((x, i) => {
|
|
299
|
+
const selected = i === paymentCurrencyIndex;
|
|
300
|
+
return /* @__PURE__ */ jsx(
|
|
301
|
+
Card,
|
|
302
|
+
{
|
|
303
|
+
variant: "outlined",
|
|
304
|
+
onClick: () => handleCurrencyChange(i),
|
|
305
|
+
className: selected ? "cko-payment-card" : "cko-payment-card-unselect",
|
|
306
|
+
children: /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", children: [
|
|
307
|
+
/* @__PURE__ */ jsx(Avatar, { src: x.logo, alt: x.name, sx: { width: 30, height: 30, marginRight: "10px" } }),
|
|
308
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
309
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", component: "div", children: x.symbol }),
|
|
310
|
+
/* @__PURE__ */ jsx(Typography, { sx: { fontSize: 14 }, color: "text.secondary", gutterBottom: true, children: x.method.name })
|
|
311
|
+
] })
|
|
312
|
+
] })
|
|
313
|
+
},
|
|
314
|
+
x.id
|
|
315
|
+
);
|
|
316
|
+
})
|
|
317
|
+
}
|
|
318
|
+
)
|
|
319
|
+
}
|
|
320
|
+
) }),
|
|
300
321
|
state.stripePaying && state.stripeContext && /* @__PURE__ */ jsx(
|
|
301
322
|
StripeCheckout,
|
|
302
323
|
{
|
|
@@ -319,7 +340,6 @@ export default function PaymentForm({
|
|
|
319
340
|
size: "large",
|
|
320
341
|
onClick: onAction,
|
|
321
342
|
fullWidth: true,
|
|
322
|
-
loadingPosition: "end",
|
|
323
343
|
disabled: state.submitting || state.paying || state.stripePaying,
|
|
324
344
|
loading: state.submitting || state.paying,
|
|
325
345
|
children: state.submitting || state.paying ? t("payment.checkout.processing") : buttonText
|
package/es/payment/index.js
CHANGED
|
@@ -286,6 +286,52 @@ export const Root = styled(Box)`
|
|
|
286
286
|
.cko-payment-methods {
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
+
.cko-payment-card {
|
|
290
|
+
position: relative;
|
|
291
|
+
border: 2px solid #3773f2;
|
|
292
|
+
padding: 5px 10px;
|
|
293
|
+
margin: 5px 0;
|
|
294
|
+
cursor: pointer;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.cko-payment-card::before {
|
|
298
|
+
content: '';
|
|
299
|
+
position: absolute;
|
|
300
|
+
right: 0;
|
|
301
|
+
top: 0;
|
|
302
|
+
border: 12px solid #3773f2;
|
|
303
|
+
border-bottom-color: transparent;
|
|
304
|
+
border-left-color: transparent;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.cko-payment-card-unselect {
|
|
308
|
+
border: 2px solid #bbb;
|
|
309
|
+
padding: 5px 10px;
|
|
310
|
+
margin: 5px 0;
|
|
311
|
+
cursor: pointer;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.cko-payment-card:nth-child(odd) {
|
|
315
|
+
margin-right: 5px;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.cko-payment-card-unselect:nth-child(odd) {
|
|
319
|
+
margin-right: 5px;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.cko-payment-card::after {
|
|
323
|
+
content: '';
|
|
324
|
+
width: 6px;
|
|
325
|
+
height: 10px;
|
|
326
|
+
position: absolute;
|
|
327
|
+
right: 3px;
|
|
328
|
+
top: 0px;
|
|
329
|
+
border: 2px solid #fff;
|
|
330
|
+
border-top-color: transparent;
|
|
331
|
+
border-left-color: transparent;
|
|
332
|
+
transform: rotate(35deg);
|
|
333
|
+
}
|
|
334
|
+
|
|
289
335
|
.cko-payment-submit {
|
|
290
336
|
.MuiButtonBase-root {
|
|
291
337
|
border-radius: 0;
|
|
@@ -16,6 +16,7 @@ var _googleLibphonenumber = require("google-libphonenumber");
|
|
|
16
16
|
var _pWaitFor = _interopRequireDefault(require("p-wait-for"));
|
|
17
17
|
var _react = require("react");
|
|
18
18
|
var _reactHookForm = require("react-hook-form");
|
|
19
|
+
var _ufo = require("ufo");
|
|
19
20
|
var _useBus = require("use-bus");
|
|
20
21
|
var _isEmail = _interopRequireDefault(require("validator/es/lib/isEmail"));
|
|
21
22
|
var _api = _interopRequireDefault(require("../../api"));
|
|
@@ -45,6 +46,19 @@ const waitForCheckoutComplete = async sessionId => {
|
|
|
45
46
|
});
|
|
46
47
|
return result;
|
|
47
48
|
};
|
|
49
|
+
const flatPaymentMethods = (methods = []) => {
|
|
50
|
+
const out = [];
|
|
51
|
+
methods.forEach(method => {
|
|
52
|
+
const currencies = method.paymentCurrencies || method.payment_currencies || [];
|
|
53
|
+
currencies.forEach(currency => {
|
|
54
|
+
out.push({
|
|
55
|
+
...currency,
|
|
56
|
+
method
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
return out;
|
|
61
|
+
};
|
|
48
62
|
PaymentForm.defaultProps = {};
|
|
49
63
|
function PaymentForm({
|
|
50
64
|
checkoutSession,
|
|
@@ -78,6 +92,8 @@ function PaymentForm({
|
|
|
78
92
|
customer,
|
|
79
93
|
stripePaying: false
|
|
80
94
|
});
|
|
95
|
+
const currencies = flatPaymentMethods(paymentMethods);
|
|
96
|
+
const [paymentCurrencyIndex, setPaymentCurrencyIndex] = (0, _react.useState)(0);
|
|
81
97
|
(0, _react.useEffect)(() => {
|
|
82
98
|
if (session?.user) {
|
|
83
99
|
const values = getValues();
|
|
@@ -92,15 +108,14 @@ function PaymentForm({
|
|
|
92
108
|
}
|
|
93
109
|
}
|
|
94
110
|
}, [session?.user, getValues, setValue]);
|
|
111
|
+
(0, _react.useEffect)(() => {
|
|
112
|
+
setValue("payment_method", currencies[paymentCurrencyIndex].method.id);
|
|
113
|
+
setValue("payment_currency", currencies[paymentCurrencyIndex].id);
|
|
114
|
+
}, [paymentCurrencyIndex, currencies, setValue]);
|
|
95
115
|
const paymentMethod = (0, _reactHookForm.useWatch)({
|
|
96
116
|
control,
|
|
97
117
|
name: "payment_method"
|
|
98
118
|
});
|
|
99
|
-
const paymentCurrency = (0, _reactHookForm.useWatch)({
|
|
100
|
-
control,
|
|
101
|
-
name: "payment_currency"
|
|
102
|
-
});
|
|
103
|
-
const paymentCurrencies = paymentMethods.find(x => x.id === paymentMethod)?.payment_currencies || [];
|
|
104
119
|
const domSize = (0, _ahooks.useSize)(document.body);
|
|
105
120
|
const isColumnLayout = (0, _ahooks.useCreation)(() => {
|
|
106
121
|
if (domSize) {
|
|
@@ -115,12 +130,8 @@ function PaymentForm({
|
|
|
115
130
|
action: t(`payment.checkout.${checkoutSession.mode}`)
|
|
116
131
|
});
|
|
117
132
|
const method = paymentMethods.find(x => x.id === paymentMethod);
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
const currencies = paymentMethods.find(x => x.id === e.target.value)?.payment_currencies || [];
|
|
121
|
-
if (currencies.some(x => x.id === paymentCurrency) === false) {
|
|
122
|
-
setValue("payment_currency", currencies[0]?.id);
|
|
123
|
-
}
|
|
133
|
+
const handleCurrencyChange = index => {
|
|
134
|
+
setPaymentCurrencyIndex(index);
|
|
124
135
|
};
|
|
125
136
|
const handleConnected = async () => {
|
|
126
137
|
try {
|
|
@@ -194,6 +205,7 @@ function PaymentForm({
|
|
|
194
205
|
} else {
|
|
195
206
|
connect.open({
|
|
196
207
|
action: checkoutSession.mode,
|
|
208
|
+
prefix: (0, _ufo.joinURL)((0, _util.getPrefix)(), "/api/did"),
|
|
197
209
|
timeout: 5 * 60 * 1e3,
|
|
198
210
|
extraParams: {
|
|
199
211
|
checkoutSessionId: checkoutSession.id
|
|
@@ -348,80 +360,56 @@ function PaymentForm({
|
|
|
348
360
|
fontWeight: 600
|
|
349
361
|
},
|
|
350
362
|
children: t("payment.checkout.method")
|
|
351
|
-
}), /* @__PURE__ */(0, _jsxRuntime.
|
|
363
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Stack, {
|
|
352
364
|
direction: "row",
|
|
353
365
|
sx: {
|
|
354
|
-
width:
|
|
366
|
+
width: "100%"
|
|
355
367
|
},
|
|
356
|
-
|
|
357
|
-
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_reactHookForm.Controller, {
|
|
358
|
-
name: "payment_method",
|
|
359
|
-
control,
|
|
360
|
-
render: ({
|
|
361
|
-
field
|
|
362
|
-
}) => /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Select, {
|
|
363
|
-
...field,
|
|
364
|
-
onChange: handleMethodChange,
|
|
365
|
-
sx: {
|
|
366
|
-
flex: 1
|
|
367
|
-
},
|
|
368
|
-
size: "small",
|
|
369
|
-
children: paymentMethods.map(x => {
|
|
370
|
-
const selected = x.id === paymentMethod;
|
|
371
|
-
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.MenuItem, {
|
|
372
|
-
value: x.id,
|
|
373
|
-
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
374
|
-
direction: "row",
|
|
375
|
-
spacing: 1,
|
|
376
|
-
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Avatar, {
|
|
377
|
-
src: x.logo,
|
|
378
|
-
alt: x.name,
|
|
379
|
-
sx: {
|
|
380
|
-
width: 20,
|
|
381
|
-
height: 20
|
|
382
|
-
}
|
|
383
|
-
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
384
|
-
color: selected ? "text.primary" : "text.secondary",
|
|
385
|
-
children: x.name
|
|
386
|
-
})]
|
|
387
|
-
})
|
|
388
|
-
}, x.id);
|
|
389
|
-
})
|
|
390
|
-
})
|
|
391
|
-
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_reactHookForm.Controller, {
|
|
368
|
+
children: /* @__PURE__ */(0, _jsxRuntime.jsx)(_reactHookForm.Controller, {
|
|
392
369
|
name: "payment_currency",
|
|
393
370
|
control,
|
|
394
|
-
render: ({
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
flex: 1
|
|
371
|
+
render: () => /* @__PURE__ */(0, _jsxRuntime.jsx)("section", {
|
|
372
|
+
style: {
|
|
373
|
+
display: currencies.length > 1 ? "grid" : "block",
|
|
374
|
+
gridTemplateColumns: "50% 50%",
|
|
375
|
+
width: "100%"
|
|
400
376
|
},
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
377
|
+
children: currencies.map((x, i) => {
|
|
378
|
+
const selected = i === paymentCurrencyIndex;
|
|
379
|
+
return /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Card, {
|
|
380
|
+
variant: "outlined",
|
|
381
|
+
onClick: () => handleCurrencyChange(i),
|
|
382
|
+
className: selected ? "cko-payment-card" : "cko-payment-card-unselect",
|
|
406
383
|
children: /* @__PURE__ */(0, _jsxRuntime.jsxs)(_material.Stack, {
|
|
407
384
|
direction: "row",
|
|
408
|
-
|
|
385
|
+
alignItems: "center",
|
|
409
386
|
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Avatar, {
|
|
410
387
|
src: x.logo,
|
|
411
388
|
alt: x.name,
|
|
412
389
|
sx: {
|
|
413
|
-
width:
|
|
414
|
-
height:
|
|
390
|
+
width: 30,
|
|
391
|
+
height: 30,
|
|
392
|
+
marginRight: "10px"
|
|
415
393
|
}
|
|
416
|
-
}), /* @__PURE__ */(0, _jsxRuntime.
|
|
417
|
-
|
|
418
|
-
|
|
394
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsxs)("div", {
|
|
395
|
+
children: [/* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
396
|
+
variant: "h5",
|
|
397
|
+
component: "div",
|
|
398
|
+
children: x.symbol
|
|
399
|
+
}), /* @__PURE__ */(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
400
|
+
sx: {
|
|
401
|
+
fontSize: 14
|
|
402
|
+
},
|
|
403
|
+
color: "text.secondary",
|
|
404
|
+
gutterBottom: true,
|
|
405
|
+
children: x.method.name
|
|
406
|
+
})]
|
|
419
407
|
})]
|
|
420
408
|
})
|
|
421
409
|
}, x.id);
|
|
422
410
|
})
|
|
423
411
|
})
|
|
424
|
-
})
|
|
412
|
+
})
|
|
425
413
|
}), state.stripePaying && state.stripeContext && /* @__PURE__ */(0, _jsxRuntime.jsx)(_stripe.default, {
|
|
426
414
|
clientSecret: state.stripeContext.client_secret,
|
|
427
415
|
intentType: state.stripeContext.intent_type,
|
|
@@ -442,7 +430,6 @@ function PaymentForm({
|
|
|
442
430
|
size: "large",
|
|
443
431
|
onClick: onAction,
|
|
444
432
|
fullWidth: true,
|
|
445
|
-
loadingPosition: "end",
|
|
446
433
|
disabled: state.submitting || state.paying || state.stripePaying,
|
|
447
434
|
loading: state.submitting || state.paying,
|
|
448
435
|
children: state.submitting || state.paying ? t("payment.checkout.processing") : buttonText
|
package/lib/payment/index.js
CHANGED
|
@@ -344,6 +344,52 @@ const Root = exports.Root = (0, _system.styled)(_material.Box)`
|
|
|
344
344
|
.cko-payment-methods {
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
+
.cko-payment-card {
|
|
348
|
+
position: relative;
|
|
349
|
+
border: 2px solid #3773f2;
|
|
350
|
+
padding: 5px 10px;
|
|
351
|
+
margin: 5px 0;
|
|
352
|
+
cursor: pointer;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.cko-payment-card::before {
|
|
356
|
+
content: '';
|
|
357
|
+
position: absolute;
|
|
358
|
+
right: 0;
|
|
359
|
+
top: 0;
|
|
360
|
+
border: 12px solid #3773f2;
|
|
361
|
+
border-bottom-color: transparent;
|
|
362
|
+
border-left-color: transparent;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.cko-payment-card-unselect {
|
|
366
|
+
border: 2px solid #bbb;
|
|
367
|
+
padding: 5px 10px;
|
|
368
|
+
margin: 5px 0;
|
|
369
|
+
cursor: pointer;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.cko-payment-card:nth-child(odd) {
|
|
373
|
+
margin-right: 5px;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.cko-payment-card-unselect:nth-child(odd) {
|
|
377
|
+
margin-right: 5px;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.cko-payment-card::after {
|
|
381
|
+
content: '';
|
|
382
|
+
width: 6px;
|
|
383
|
+
height: 10px;
|
|
384
|
+
position: absolute;
|
|
385
|
+
right: 3px;
|
|
386
|
+
top: 0px;
|
|
387
|
+
border: 2px solid #fff;
|
|
388
|
+
border-top-color: transparent;
|
|
389
|
+
border-left-color: transparent;
|
|
390
|
+
transform: rotate(35deg);
|
|
391
|
+
}
|
|
392
|
+
|
|
347
393
|
.cko-payment-submit {
|
|
348
394
|
.MuiButtonBase-root {
|
|
349
395
|
border-radius: 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/payment-react",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.123",
|
|
4
4
|
"description": "Reusable react components for payment kit v2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"@babel/core": "^7.19.3",
|
|
90
90
|
"@babel/preset-env": "^7.19.3",
|
|
91
91
|
"@babel/preset-react": "^7.18.6",
|
|
92
|
-
"@blocklet/payment-types": "1.13.
|
|
92
|
+
"@blocklet/payment-types": "1.13.123",
|
|
93
93
|
"@storybook/addon-essentials": "^7.6.10",
|
|
94
94
|
"@storybook/addon-interactions": "^7.6.10",
|
|
95
95
|
"@storybook/addon-links": "^7.6.10",
|
|
@@ -118,5 +118,5 @@
|
|
|
118
118
|
"vite-plugin-babel": "^1.2.0",
|
|
119
119
|
"vite-plugin-node-polyfills": "^0.19.0"
|
|
120
120
|
},
|
|
121
|
-
"gitHead": "
|
|
121
|
+
"gitHead": "ea37183dafcf5a89c0593886aa895b33eccf8529"
|
|
122
122
|
}
|
|
@@ -3,14 +3,15 @@ import 'react-international-phone/style.css';
|
|
|
3
3
|
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
|
|
4
4
|
import { useTheme } from '@arcblock/ux/lib/Theme';
|
|
5
5
|
import Toast from '@arcblock/ux/lib/Toast';
|
|
6
|
-
import type { TCustomer, TPaymentIntent, TPaymentMethodExpanded } from '@blocklet/payment-types';
|
|
6
|
+
import type { PaymentCurrency, TCustomer, TPaymentIntent, TPaymentMethodExpanded } from '@blocklet/payment-types';
|
|
7
7
|
import { LoadingButton } from '@mui/lab';
|
|
8
|
-
import { Avatar, Fade, InputAdornment,
|
|
8
|
+
import { Avatar, Card, Fade, InputAdornment, Stack, Typography } from '@mui/material';
|
|
9
9
|
import { useCreation, useSetState, useSize } from 'ahooks';
|
|
10
10
|
import { PhoneNumberUtil } from 'google-libphonenumber';
|
|
11
11
|
import pWaitFor from 'p-wait-for';
|
|
12
|
-
import { useEffect } from 'react';
|
|
12
|
+
import { useEffect, useState } from 'react';
|
|
13
13
|
import { Controller, useFormContext, useWatch } from 'react-hook-form';
|
|
14
|
+
import { joinURL } from 'ufo';
|
|
14
15
|
import { dispatch } from 'use-bus';
|
|
15
16
|
import isEmail from 'validator/es/lib/isEmail';
|
|
16
17
|
|
|
@@ -18,7 +19,7 @@ import api from '../../api';
|
|
|
18
19
|
import FormInput from '../../components/input';
|
|
19
20
|
import { usePaymentContext } from '../../contexts/payment';
|
|
20
21
|
import { CheckoutCallbacks, CheckoutContext } from '../../types';
|
|
21
|
-
import { formatError, getStatementDescriptor } from '../../util';
|
|
22
|
+
import { formatError, getPrefix, getStatementDescriptor } from '../../util';
|
|
22
23
|
import UserButtons from './addon';
|
|
23
24
|
import AddressForm from './address';
|
|
24
25
|
import PhoneInput from './phone';
|
|
@@ -56,6 +57,22 @@ const waitForCheckoutComplete = async (sessionId: string) => {
|
|
|
56
57
|
|
|
57
58
|
type PageData = CheckoutContext & CheckoutCallbacks;
|
|
58
59
|
|
|
60
|
+
const flatPaymentMethods = (methods: TPaymentMethodExpanded[] = []) => {
|
|
61
|
+
const out: PaymentCurrency[] = [];
|
|
62
|
+
|
|
63
|
+
methods.forEach((method: any) => {
|
|
64
|
+
const currencies = method.paymentCurrencies || method.payment_currencies || [];
|
|
65
|
+
currencies.forEach((currency: any) => {
|
|
66
|
+
out.push({
|
|
67
|
+
...currency,
|
|
68
|
+
method,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return out;
|
|
74
|
+
};
|
|
75
|
+
|
|
59
76
|
PaymentForm.defaultProps = {};
|
|
60
77
|
|
|
61
78
|
// FIXME: https://stripe.com/docs/elements/address-element
|
|
@@ -98,6 +115,9 @@ export default function PaymentForm({
|
|
|
98
115
|
stripePaying: false,
|
|
99
116
|
});
|
|
100
117
|
|
|
118
|
+
const currencies = flatPaymentMethods(paymentMethods);
|
|
119
|
+
const [paymentCurrencyIndex, setPaymentCurrencyIndex] = useState(0);
|
|
120
|
+
|
|
101
121
|
useEffect(() => {
|
|
102
122
|
if (session?.user) {
|
|
103
123
|
const values = getValues();
|
|
@@ -113,9 +133,12 @@ export default function PaymentForm({
|
|
|
113
133
|
}
|
|
114
134
|
}, [session?.user, getValues, setValue]);
|
|
115
135
|
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
setValue('payment_method', (currencies[paymentCurrencyIndex] as any).method.id);
|
|
138
|
+
setValue('payment_currency', currencies[paymentCurrencyIndex].id);
|
|
139
|
+
}, [paymentCurrencyIndex, currencies, setValue]);
|
|
140
|
+
|
|
116
141
|
const paymentMethod = useWatch({ control, name: 'payment_method' });
|
|
117
|
-
const paymentCurrency = useWatch({ control, name: 'payment_currency' });
|
|
118
|
-
const paymentCurrencies = paymentMethods.find((x) => x.id === paymentMethod)?.payment_currencies || [];
|
|
119
142
|
|
|
120
143
|
const domSize = useSize(document.body);
|
|
121
144
|
|
|
@@ -135,12 +158,8 @@ export default function PaymentForm({
|
|
|
135
158
|
|
|
136
159
|
const method = paymentMethods.find((x) => x.id === paymentMethod) as TPaymentMethodExpanded;
|
|
137
160
|
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
const currencies = paymentMethods.find((x) => x.id === e.target.value)?.payment_currencies || [];
|
|
141
|
-
if (currencies.some((x) => x.id === paymentCurrency) === false) {
|
|
142
|
-
setValue('payment_currency', currencies[0]?.id);
|
|
143
|
-
}
|
|
161
|
+
const handleCurrencyChange = (index: number) => {
|
|
162
|
+
setPaymentCurrencyIndex(index);
|
|
144
163
|
};
|
|
145
164
|
|
|
146
165
|
const handleConnected = async () => {
|
|
@@ -208,6 +227,7 @@ export default function PaymentForm({
|
|
|
208
227
|
} else {
|
|
209
228
|
connect.open({
|
|
210
229
|
action: checkoutSession.mode,
|
|
230
|
+
prefix: joinURL(getPrefix(), '/api/did'),
|
|
211
231
|
timeout: 5 * 60 * 1000,
|
|
212
232
|
extraParams: { checkoutSessionId: checkoutSession.id },
|
|
213
233
|
onSuccess: async () => {
|
|
@@ -322,43 +342,40 @@ export default function PaymentForm({
|
|
|
322
342
|
<Fade in>
|
|
323
343
|
<Stack direction="column" alignItems="flex-start" className="cko-payment-methods">
|
|
324
344
|
<Typography sx={{ mb: 2, color: 'text.primary', fontWeight: 600 }}>{t('payment.checkout.method')}</Typography>
|
|
325
|
-
<Stack direction="row" sx={{ width:
|
|
326
|
-
<Controller
|
|
327
|
-
name="payment_method"
|
|
328
|
-
control={control}
|
|
329
|
-
render={({ field }) => (
|
|
330
|
-
<Select {...field} onChange={handleMethodChange} sx={{ flex: 1 }} size="small">
|
|
331
|
-
{paymentMethods.map((x) => {
|
|
332
|
-
const selected = x.id === paymentMethod;
|
|
333
|
-
return (
|
|
334
|
-
<MenuItem key={x.id} value={x.id}>
|
|
335
|
-
<Stack direction="row" spacing={1}>
|
|
336
|
-
<Avatar src={x.logo} alt={x.name} sx={{ width: 20, height: 20 }} />
|
|
337
|
-
<Typography color={selected ? 'text.primary' : 'text.secondary'}>{x.name}</Typography>
|
|
338
|
-
</Stack>
|
|
339
|
-
</MenuItem>
|
|
340
|
-
);
|
|
341
|
-
})}
|
|
342
|
-
</Select>
|
|
343
|
-
)}
|
|
344
|
-
/>
|
|
345
|
+
<Stack direction="row" sx={{ width: '100%' }}>
|
|
345
346
|
<Controller
|
|
346
347
|
name="payment_currency"
|
|
347
348
|
control={control}
|
|
348
|
-
render={(
|
|
349
|
-
<
|
|
350
|
-
{
|
|
351
|
-
|
|
349
|
+
render={() => (
|
|
350
|
+
<section
|
|
351
|
+
style={{
|
|
352
|
+
display: currencies.length > 1 ? 'grid' : 'block',
|
|
353
|
+
gridTemplateColumns: '50% 50%',
|
|
354
|
+
width: '100%',
|
|
355
|
+
}}>
|
|
356
|
+
{currencies.map((x, i) => {
|
|
357
|
+
const selected = i === paymentCurrencyIndex;
|
|
352
358
|
return (
|
|
353
|
-
<
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
359
|
+
<Card
|
|
360
|
+
key={x.id}
|
|
361
|
+
variant="outlined"
|
|
362
|
+
onClick={() => handleCurrencyChange(i)}
|
|
363
|
+
className={selected ? 'cko-payment-card' : 'cko-payment-card-unselect'}>
|
|
364
|
+
<Stack direction="row" alignItems="center">
|
|
365
|
+
<Avatar src={x.logo} alt={x.name} sx={{ width: 30, height: 30, marginRight: '10px' }} />
|
|
366
|
+
<div>
|
|
367
|
+
<Typography variant="h5" component="div">
|
|
368
|
+
{x.symbol}
|
|
369
|
+
</Typography>
|
|
370
|
+
<Typography sx={{ fontSize: 14 }} color="text.secondary" gutterBottom>
|
|
371
|
+
{(x as any).method.name}
|
|
372
|
+
</Typography>
|
|
373
|
+
</div>
|
|
357
374
|
</Stack>
|
|
358
|
-
</
|
|
375
|
+
</Card>
|
|
359
376
|
);
|
|
360
377
|
})}
|
|
361
|
-
</
|
|
378
|
+
</section>
|
|
362
379
|
)}
|
|
363
380
|
/>
|
|
364
381
|
</Stack>
|
|
@@ -383,7 +400,6 @@ export default function PaymentForm({
|
|
|
383
400
|
size="large"
|
|
384
401
|
onClick={onAction}
|
|
385
402
|
fullWidth
|
|
386
|
-
loadingPosition="end"
|
|
387
403
|
disabled={state.submitting || state.paying || state.stripePaying}
|
|
388
404
|
loading={state.submitting || state.paying}>
|
|
389
405
|
{state.submitting || state.paying ? t('payment.checkout.processing') : buttonText}
|
package/src/payment/index.tsx
CHANGED
|
@@ -331,6 +331,52 @@ export const Root = styled(Box)<{ mode: LiteralUnion<'standalone' | 'inline' | '
|
|
|
331
331
|
.cko-payment-methods {
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
+
.cko-payment-card {
|
|
335
|
+
position: relative;
|
|
336
|
+
border: 2px solid #3773f2;
|
|
337
|
+
padding: 5px 10px;
|
|
338
|
+
margin: 5px 0;
|
|
339
|
+
cursor: pointer;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.cko-payment-card::before {
|
|
343
|
+
content: '';
|
|
344
|
+
position: absolute;
|
|
345
|
+
right: 0;
|
|
346
|
+
top: 0;
|
|
347
|
+
border: 12px solid #3773f2;
|
|
348
|
+
border-bottom-color: transparent;
|
|
349
|
+
border-left-color: transparent;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.cko-payment-card-unselect {
|
|
353
|
+
border: 2px solid #bbb;
|
|
354
|
+
padding: 5px 10px;
|
|
355
|
+
margin: 5px 0;
|
|
356
|
+
cursor: pointer;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.cko-payment-card:nth-child(odd) {
|
|
360
|
+
margin-right: 5px;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.cko-payment-card-unselect:nth-child(odd) {
|
|
364
|
+
margin-right: 5px;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.cko-payment-card::after {
|
|
368
|
+
content: '';
|
|
369
|
+
width: 6px;
|
|
370
|
+
height: 10px;
|
|
371
|
+
position: absolute;
|
|
372
|
+
right: 3px;
|
|
373
|
+
top: 0px;
|
|
374
|
+
border: 2px solid #fff;
|
|
375
|
+
border-top-color: transparent;
|
|
376
|
+
border-left-color: transparent;
|
|
377
|
+
transform: rotate(35deg);
|
|
378
|
+
}
|
|
379
|
+
|
|
334
380
|
.cko-payment-submit {
|
|
335
381
|
.MuiButtonBase-root {
|
|
336
382
|
border-radius: 0;
|