strapi-plugin-payone-provider 1.1.3 → 1.2.4
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/README.md +1041 -377
- package/admin/src/index.js +4 -1
- package/admin/src/pages/App/components/AppHeader.js +37 -0
- package/admin/src/pages/App/components/AppTabs.js +126 -0
- package/admin/src/pages/App/components/ConfigurationPanel.js +34 -35
- package/admin/src/pages/App/components/GooglePaybutton.js +300 -0
- package/admin/src/pages/App/components/HistoryPanel.js +25 -38
- package/admin/src/pages/App/components/PaymentActionsPanel.js +95 -280
- package/admin/src/pages/App/components/TransactionHistoryItem.js +4 -1
- package/admin/src/pages/App/components/paymentActions/AuthorizationForm.js +93 -0
- package/admin/src/pages/App/components/paymentActions/CaptureForm.js +64 -0
- package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.js +52 -0
- package/admin/src/pages/App/components/paymentActions/PaymentResult.js +85 -0
- package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.js +93 -0
- package/admin/src/pages/App/components/paymentActions/RefundForm.js +89 -0
- package/admin/src/pages/App/index.js +41 -465
- package/admin/src/pages/App/styles.css +294 -0
- package/admin/src/pages/constants/paymentConstants.js +37 -0
- package/admin/src/pages/hooks/usePaymentActions.js +271 -0
- package/admin/src/pages/hooks/useSettings.js +111 -0
- package/admin/src/pages/hooks/useTransactionHistory.js +87 -0
- package/admin/src/pages/utils/api.js +10 -0
- package/admin/src/pages/utils/injectGooglePayScript.js +31 -0
- package/admin/src/pages/utils/paymentUtils.js +113 -13
- package/package.json +1 -1
- package/server/controllers/payone.js +71 -64
- package/server/routes/index.js +17 -0
- package/server/services/paymentService.js +214 -0
- package/server/services/payone.js +25 -648
- package/server/services/settingsService.js +59 -0
- package/server/services/testConnectionService.js +190 -0
- package/server/services/transactionService.js +114 -0
- package/server/utils/normalize.js +51 -0
- package/server/utils/paymentMethodParams.js +126 -0
- package/server/utils/requestBuilder.js +110 -0
- package/server/utils/responseParser.js +80 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Flex, Typography, TextInput, Button } from "@strapi/design-system";
|
|
3
|
+
import { Play } from "@strapi/icons";
|
|
4
|
+
import GooglePayButton from "../GooglePaybutton";
|
|
5
|
+
|
|
6
|
+
const AuthorizationForm = ({
|
|
7
|
+
paymentAmount,
|
|
8
|
+
setPaymentAmount,
|
|
9
|
+
authReference,
|
|
10
|
+
setAuthReference,
|
|
11
|
+
isProcessingPayment,
|
|
12
|
+
onAuthorization,
|
|
13
|
+
paymentMethod,
|
|
14
|
+
settings,
|
|
15
|
+
googlePayToken,
|
|
16
|
+
setGooglePayToken
|
|
17
|
+
}) => {
|
|
18
|
+
const handleGooglePayToken = (token, paymentData) => {
|
|
19
|
+
if (!token) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
setGooglePayToken(token);
|
|
23
|
+
onAuthorization(token);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const handleGooglePayError = (error) => {
|
|
27
|
+
if (onError) {
|
|
28
|
+
onError(error);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return (
|
|
32
|
+
<Flex direction="column" alignItems="stretch" gap={4}>
|
|
33
|
+
<Flex direction="row" gap={2}>
|
|
34
|
+
<Typography variant="omega" fontWeight="semiBold" textColor="neutral800" className="payment-form-title">
|
|
35
|
+
Authorization
|
|
36
|
+
</Typography>
|
|
37
|
+
<Typography variant="pi" textColor="neutral600" className="payment-form-description">
|
|
38
|
+
Authorize and capture an amount immediately.
|
|
39
|
+
</Typography>
|
|
40
|
+
</Flex>
|
|
41
|
+
|
|
42
|
+
<Flex gap={4} wrap="wrap">
|
|
43
|
+
<TextInput
|
|
44
|
+
label="Amount (in cents) *"
|
|
45
|
+
name="authAmount"
|
|
46
|
+
value={paymentAmount}
|
|
47
|
+
onChange={(e) => setPaymentAmount(e.target.value)}
|
|
48
|
+
placeholder="Enter amount (e.g., 1000 for €10.00)"
|
|
49
|
+
hint="Amount in cents (e.g., 1000 = €10.00)"
|
|
50
|
+
required
|
|
51
|
+
className="payment-input"
|
|
52
|
+
style={{ flex: 1, minWidth: "250px" }}
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<TextInput
|
|
56
|
+
label="Reference *"
|
|
57
|
+
name="authReference"
|
|
58
|
+
value={authReference}
|
|
59
|
+
onChange={(e) => setAuthReference(e.target.value)}
|
|
60
|
+
placeholder="Enter reference"
|
|
61
|
+
hint="Reference for this transaction"
|
|
62
|
+
required
|
|
63
|
+
className="payment-input"
|
|
64
|
+
style={{ flex: 1, minWidth: "250px" }}
|
|
65
|
+
/>
|
|
66
|
+
</Flex>
|
|
67
|
+
|
|
68
|
+
{paymentMethod === "gpp" ? (
|
|
69
|
+
<GooglePayButton
|
|
70
|
+
amount={paymentAmount}
|
|
71
|
+
currency="EUR"
|
|
72
|
+
onTokenReceived={handleGooglePayToken}
|
|
73
|
+
onError={handleGooglePayError}
|
|
74
|
+
settings={settings}
|
|
75
|
+
/>
|
|
76
|
+
) : (
|
|
77
|
+
<Button
|
|
78
|
+
variant="default"
|
|
79
|
+
onClick={onAuthorization}
|
|
80
|
+
loading={isProcessingPayment}
|
|
81
|
+
startIcon={<Play />}
|
|
82
|
+
className="payment-button payment-button-primary"
|
|
83
|
+
disabled={!paymentAmount.trim() || !authReference.trim()}
|
|
84
|
+
>
|
|
85
|
+
Process Authorization
|
|
86
|
+
</Button>
|
|
87
|
+
)}
|
|
88
|
+
</Flex>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default AuthorizationForm;
|
|
93
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Flex, Typography, TextInput, Button } from "@strapi/design-system";
|
|
3
|
+
import { Play } from "@strapi/icons";
|
|
4
|
+
|
|
5
|
+
const CaptureForm = ({
|
|
6
|
+
paymentAmount,
|
|
7
|
+
setPaymentAmount,
|
|
8
|
+
captureTxid,
|
|
9
|
+
setCaptureTxid,
|
|
10
|
+
isProcessingPayment,
|
|
11
|
+
onCapture
|
|
12
|
+
}) => {
|
|
13
|
+
return (
|
|
14
|
+
<Flex direction="column" alignItems="stretch" gap={4}>
|
|
15
|
+
<Flex direction="row" gap={2}>
|
|
16
|
+
<Typography variant="omega" fontWeight="semiBold" textColor="neutral800" className="payment-form-title">
|
|
17
|
+
Capture
|
|
18
|
+
</Typography>
|
|
19
|
+
<Typography variant="pi" textColor="neutral600" className="payment-form-description">
|
|
20
|
+
Capture a previously authorized amount. Note: Reference parameter is
|
|
21
|
+
not supported by Payone capture.
|
|
22
|
+
</Typography>
|
|
23
|
+
</Flex>
|
|
24
|
+
|
|
25
|
+
<Flex gap={4} wrap="wrap">
|
|
26
|
+
<TextInput
|
|
27
|
+
label="Transaction ID"
|
|
28
|
+
name="captureTxid"
|
|
29
|
+
value={captureTxid}
|
|
30
|
+
onChange={(e) => setCaptureTxid(e.target.value)}
|
|
31
|
+
placeholder="Enter TxId from preauthorization"
|
|
32
|
+
hint="Transaction ID from a previous preauthorization"
|
|
33
|
+
className="payment-input"
|
|
34
|
+
style={{ flex: 1, minWidth: "250px" }}
|
|
35
|
+
/>
|
|
36
|
+
|
|
37
|
+
<TextInput
|
|
38
|
+
label="Amount (in cents)"
|
|
39
|
+
name="captureAmount"
|
|
40
|
+
value={paymentAmount}
|
|
41
|
+
onChange={(e) => setPaymentAmount(e.target.value)}
|
|
42
|
+
placeholder="1000"
|
|
43
|
+
hint="Amount in cents to capture"
|
|
44
|
+
className="payment-input"
|
|
45
|
+
style={{ flex: 1, minWidth: "250px" }}
|
|
46
|
+
/>
|
|
47
|
+
</Flex>
|
|
48
|
+
|
|
49
|
+
<Button
|
|
50
|
+
variant="default"
|
|
51
|
+
onClick={onCapture}
|
|
52
|
+
loading={isProcessingPayment}
|
|
53
|
+
startIcon={<Play />}
|
|
54
|
+
className="payment-button payment-button-primary"
|
|
55
|
+
disabled={!captureTxid.trim() || !paymentAmount.trim()}
|
|
56
|
+
>
|
|
57
|
+
Process Capture
|
|
58
|
+
</Button>
|
|
59
|
+
</Flex>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export default CaptureForm;
|
|
64
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Flex, Select, Option } from "@strapi/design-system";
|
|
3
|
+
import {
|
|
4
|
+
getPaymentMethodOptions,
|
|
5
|
+
supportsCaptureMode,
|
|
6
|
+
getCaptureModeOptions,
|
|
7
|
+
getPaymentMethodDisplayName
|
|
8
|
+
} from "../../../utils/paymentUtils";
|
|
9
|
+
|
|
10
|
+
const PaymentMethodSelector = ({
|
|
11
|
+
paymentMethod,
|
|
12
|
+
setPaymentMethod,
|
|
13
|
+
captureMode,
|
|
14
|
+
setCaptureMode
|
|
15
|
+
}) => {
|
|
16
|
+
return (
|
|
17
|
+
<Box>
|
|
18
|
+
<Flex direction="column" alignItems="stretch" gap={4}>
|
|
19
|
+
<Select
|
|
20
|
+
label="Select Payment Method"
|
|
21
|
+
name="paymentMethod"
|
|
22
|
+
value={paymentMethod}
|
|
23
|
+
onChange={(value) => setPaymentMethod(value)}
|
|
24
|
+
hint={`Current: ${getPaymentMethodDisplayName(paymentMethod)}`}
|
|
25
|
+
>
|
|
26
|
+
{getPaymentMethodOptions().map((option) => (
|
|
27
|
+
<Option key={option.value} value={option.value}>
|
|
28
|
+
{option.label}
|
|
29
|
+
</Option>
|
|
30
|
+
))}
|
|
31
|
+
</Select>
|
|
32
|
+
{supportsCaptureMode(paymentMethod) && (
|
|
33
|
+
<Select
|
|
34
|
+
label="Capture Mode"
|
|
35
|
+
name="captureMode"
|
|
36
|
+
value={captureMode}
|
|
37
|
+
onChange={(value) => setCaptureMode(value)}
|
|
38
|
+
hint="Select capture mode for wallet payments"
|
|
39
|
+
>
|
|
40
|
+
{getCaptureModeOptions().map((option) => (
|
|
41
|
+
<Option key={option.value} value={option.value}>
|
|
42
|
+
{option.label}
|
|
43
|
+
</Option>
|
|
44
|
+
))}
|
|
45
|
+
</Select>
|
|
46
|
+
)}
|
|
47
|
+
</Flex>
|
|
48
|
+
</Box>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default PaymentMethodSelector;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Box,
|
|
4
|
+
Card,
|
|
5
|
+
CardBody,
|
|
6
|
+
Divider,
|
|
7
|
+
Flex,
|
|
8
|
+
Stack,
|
|
9
|
+
Typography,
|
|
10
|
+
Alert
|
|
11
|
+
} from "@strapi/design-system";
|
|
12
|
+
import StatusBadge from "../StatusBadge";
|
|
13
|
+
import { formatTransactionData } from "../../../utils/formatTransactionData";
|
|
14
|
+
|
|
15
|
+
const PaymentResult = ({ paymentError, paymentResult }) => {
|
|
16
|
+
if (!paymentError && !paymentResult) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
{paymentError && (
|
|
23
|
+
<Alert
|
|
24
|
+
variant="danger"
|
|
25
|
+
title="Error"
|
|
26
|
+
className="payment-alert"
|
|
27
|
+
>
|
|
28
|
+
{paymentError}
|
|
29
|
+
</Alert>
|
|
30
|
+
)}
|
|
31
|
+
|
|
32
|
+
{paymentResult && (
|
|
33
|
+
<Card className="payment-result-card">
|
|
34
|
+
<CardBody>
|
|
35
|
+
<Stack spacing={4}>
|
|
36
|
+
<Flex justifyContent="space-between" alignItems="center">
|
|
37
|
+
<Typography variant="delta" as="h3" className="payment-section-title">
|
|
38
|
+
Payment Result
|
|
39
|
+
</Typography>
|
|
40
|
+
{paymentResult.Status && (
|
|
41
|
+
<StatusBadge status={paymentResult.Status} />
|
|
42
|
+
)}
|
|
43
|
+
</Flex>
|
|
44
|
+
|
|
45
|
+
<hr className="payment-divider" style={{ margin: '16px 0' }} />
|
|
46
|
+
|
|
47
|
+
<Box>
|
|
48
|
+
<Stack spacing={3}>
|
|
49
|
+
{formatTransactionData(paymentResult).map((item, index) => (
|
|
50
|
+
<Flex
|
|
51
|
+
key={index}
|
|
52
|
+
justifyContent="space-between"
|
|
53
|
+
alignItems="start"
|
|
54
|
+
style={{
|
|
55
|
+
padding: '8px 0',
|
|
56
|
+
borderBottom: index < formatTransactionData(paymentResult).length - 1 ? '1px solid #e8e8ea' : 'none'
|
|
57
|
+
}}
|
|
58
|
+
>
|
|
59
|
+
<Typography
|
|
60
|
+
variant="pi"
|
|
61
|
+
textColor="neutral600"
|
|
62
|
+
style={{ minWidth: "200px", fontWeight: '500' }}
|
|
63
|
+
>
|
|
64
|
+
{item.key}:
|
|
65
|
+
</Typography>
|
|
66
|
+
<Typography
|
|
67
|
+
variant="pi"
|
|
68
|
+
style={{ flex: 1, textAlign: "right", fontWeight: '400' }}
|
|
69
|
+
>
|
|
70
|
+
{item.value}
|
|
71
|
+
</Typography>
|
|
72
|
+
</Flex>
|
|
73
|
+
))}
|
|
74
|
+
</Stack>
|
|
75
|
+
</Box>
|
|
76
|
+
</Stack>
|
|
77
|
+
</CardBody>
|
|
78
|
+
</Card>
|
|
79
|
+
)}
|
|
80
|
+
</>
|
|
81
|
+
);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export default PaymentResult;
|
|
85
|
+
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Flex, Typography, TextInput, Button } from "@strapi/design-system";
|
|
3
|
+
import { Play } from "@strapi/icons";
|
|
4
|
+
import GooglePayButton from "../GooglePaybutton";
|
|
5
|
+
|
|
6
|
+
const PreauthorizationForm = ({
|
|
7
|
+
paymentAmount,
|
|
8
|
+
setPaymentAmount,
|
|
9
|
+
preauthReference,
|
|
10
|
+
setPreauthReference,
|
|
11
|
+
isProcessingPayment,
|
|
12
|
+
onPreauthorization,
|
|
13
|
+
paymentMethod,
|
|
14
|
+
settings,
|
|
15
|
+
googlePayToken,
|
|
16
|
+
setGooglePayToken
|
|
17
|
+
}) => {
|
|
18
|
+
const handleGooglePayToken = (token, paymentData) => {
|
|
19
|
+
if (!token) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
setGooglePayToken(token);
|
|
23
|
+
onPreauthorization(token);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const handleGooglePayError = (error) => {
|
|
27
|
+
if (onError) {
|
|
28
|
+
onError(error);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return (
|
|
32
|
+
<Flex direction="column" alignItems="stretch" gap={4}>
|
|
33
|
+
<Flex direction="row" gap={2}>
|
|
34
|
+
<Typography variant="omega" fontWeight="semiBold" textColor="neutral800" className="payment-form-title">
|
|
35
|
+
Preauthorization
|
|
36
|
+
</Typography>
|
|
37
|
+
<Typography variant="pi" textColor="neutral600" className="payment-form-description">
|
|
38
|
+
Reserve an amount on a credit card without capturing it immediately.
|
|
39
|
+
</Typography>
|
|
40
|
+
</Flex>
|
|
41
|
+
|
|
42
|
+
<Flex gap={4} wrap="wrap">
|
|
43
|
+
<TextInput
|
|
44
|
+
label="Amount (in cents) *"
|
|
45
|
+
name="paymentAmount"
|
|
46
|
+
value={paymentAmount}
|
|
47
|
+
onChange={(e) => setPaymentAmount(e.target.value)}
|
|
48
|
+
placeholder="Enter amount (e.g., 1000 for €10.00)"
|
|
49
|
+
hint="Amount in cents (e.g., 1000 = €10.00)"
|
|
50
|
+
required
|
|
51
|
+
className="payment-input"
|
|
52
|
+
style={{ flex: 1, minWidth: "250px" }}
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<TextInput
|
|
56
|
+
label="Reference *"
|
|
57
|
+
name="preauthReference"
|
|
58
|
+
value={preauthReference}
|
|
59
|
+
onChange={(e) => setPreauthReference(e.target.value)}
|
|
60
|
+
placeholder="Enter reference"
|
|
61
|
+
hint="Reference for this transaction"
|
|
62
|
+
required
|
|
63
|
+
className="payment-input"
|
|
64
|
+
style={{ flex: 1, minWidth: "250px" }}
|
|
65
|
+
/>
|
|
66
|
+
</Flex>
|
|
67
|
+
|
|
68
|
+
{paymentMethod === "gpp" ? (
|
|
69
|
+
<GooglePayButton
|
|
70
|
+
amount={paymentAmount}
|
|
71
|
+
currency="EUR"
|
|
72
|
+
onTokenReceived={handleGooglePayToken}
|
|
73
|
+
onError={handleGooglePayError}
|
|
74
|
+
settings={settings}
|
|
75
|
+
/>
|
|
76
|
+
) : (
|
|
77
|
+
<Button
|
|
78
|
+
variant="default"
|
|
79
|
+
onClick={onPreauthorization}
|
|
80
|
+
loading={isProcessingPayment}
|
|
81
|
+
startIcon={<Play />}
|
|
82
|
+
className="payment-button payment-button-primary"
|
|
83
|
+
disabled={!paymentAmount.trim() || !preauthReference.trim()}
|
|
84
|
+
>
|
|
85
|
+
Process Preauthorization
|
|
86
|
+
</Button>
|
|
87
|
+
)}
|
|
88
|
+
</Flex>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default PreauthorizationForm;
|
|
93
|
+
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Box, Flex, Typography, TextInput, Button } from "@strapi/design-system";
|
|
3
|
+
import { Play } from "@strapi/icons";
|
|
4
|
+
|
|
5
|
+
const RefundForm = ({
|
|
6
|
+
paymentAmount,
|
|
7
|
+
setPaymentAmount,
|
|
8
|
+
refundTxid,
|
|
9
|
+
setRefundTxid,
|
|
10
|
+
refundSequenceNumber,
|
|
11
|
+
setRefundSequenceNumber,
|
|
12
|
+
refundReference,
|
|
13
|
+
setRefundReference,
|
|
14
|
+
isProcessingPayment,
|
|
15
|
+
onRefund
|
|
16
|
+
}) => {
|
|
17
|
+
return (
|
|
18
|
+
<Flex direction="column" alignItems="stretch" gap={4}>
|
|
19
|
+
<Flex direction="row" gap={2}>
|
|
20
|
+
<Typography variant="omega" fontWeight="semiBold" textColor="neutral800" className="payment-form-title">
|
|
21
|
+
Refund
|
|
22
|
+
</Typography>
|
|
23
|
+
<Typography variant="pi" textColor="neutral600" className="payment-form-description">
|
|
24
|
+
Refund a previously captured amount.
|
|
25
|
+
</Typography>
|
|
26
|
+
</Flex>
|
|
27
|
+
|
|
28
|
+
<Flex gap={4} wrap="wrap">
|
|
29
|
+
<TextInput
|
|
30
|
+
label="Transaction ID"
|
|
31
|
+
name="refundTxid"
|
|
32
|
+
value={refundTxid}
|
|
33
|
+
onChange={(e) => setRefundTxid(e.target.value)}
|
|
34
|
+
placeholder="Enter TxId from capture"
|
|
35
|
+
hint="Transaction ID from a previous capture"
|
|
36
|
+
className="payment-input"
|
|
37
|
+
style={{ flex: 1, minWidth: "200px" }}
|
|
38
|
+
/>
|
|
39
|
+
|
|
40
|
+
<TextInput
|
|
41
|
+
label="Sequence Number"
|
|
42
|
+
name="refundSequenceNumber"
|
|
43
|
+
value={refundSequenceNumber}
|
|
44
|
+
onChange={(e) => setRefundSequenceNumber(e.target.value)}
|
|
45
|
+
placeholder="2"
|
|
46
|
+
hint="Sequence number for this refund (1-127) and by default for first 2"
|
|
47
|
+
className="payment-input"
|
|
48
|
+
style={{ flex: 1, minWidth: "200px" }}
|
|
49
|
+
/>
|
|
50
|
+
|
|
51
|
+
<TextInput
|
|
52
|
+
label="Amount (in cents)"
|
|
53
|
+
name="refundAmount"
|
|
54
|
+
value={paymentAmount}
|
|
55
|
+
onChange={(e) => setPaymentAmount(e.target.value)}
|
|
56
|
+
placeholder="1000"
|
|
57
|
+
hint="Amount in cents to refund (will be negative)"
|
|
58
|
+
className="payment-input"
|
|
59
|
+
style={{ flex: 1, minWidth: "200px" }}
|
|
60
|
+
/>
|
|
61
|
+
|
|
62
|
+
<TextInput
|
|
63
|
+
label="Reference"
|
|
64
|
+
name="refundReference"
|
|
65
|
+
value={refundReference}
|
|
66
|
+
onChange={(e) => setRefundReference(e.target.value)}
|
|
67
|
+
placeholder="Optional reference"
|
|
68
|
+
hint="Optional reference for this refund"
|
|
69
|
+
className="payment-input"
|
|
70
|
+
style={{ flex: 1, minWidth: "200px" }}
|
|
71
|
+
/>
|
|
72
|
+
</Flex>
|
|
73
|
+
|
|
74
|
+
<Button
|
|
75
|
+
variant="default"
|
|
76
|
+
onClick={onRefund}
|
|
77
|
+
loading={isProcessingPayment}
|
|
78
|
+
startIcon={<Play />}
|
|
79
|
+
className="payment-button payment-button-primary"
|
|
80
|
+
disabled={!refundTxid.trim() || !paymentAmount.trim()}
|
|
81
|
+
>
|
|
82
|
+
Process Refund
|
|
83
|
+
</Button>
|
|
84
|
+
</Flex>
|
|
85
|
+
);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export default RefundForm;
|
|
89
|
+
|