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.
Files changed (36) hide show
  1. package/README.md +1041 -377
  2. package/admin/src/index.js +4 -1
  3. package/admin/src/pages/App/components/AppHeader.js +37 -0
  4. package/admin/src/pages/App/components/AppTabs.js +126 -0
  5. package/admin/src/pages/App/components/ConfigurationPanel.js +34 -35
  6. package/admin/src/pages/App/components/GooglePaybutton.js +300 -0
  7. package/admin/src/pages/App/components/HistoryPanel.js +25 -38
  8. package/admin/src/pages/App/components/PaymentActionsPanel.js +95 -280
  9. package/admin/src/pages/App/components/TransactionHistoryItem.js +4 -1
  10. package/admin/src/pages/App/components/paymentActions/AuthorizationForm.js +93 -0
  11. package/admin/src/pages/App/components/paymentActions/CaptureForm.js +64 -0
  12. package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.js +52 -0
  13. package/admin/src/pages/App/components/paymentActions/PaymentResult.js +85 -0
  14. package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.js +93 -0
  15. package/admin/src/pages/App/components/paymentActions/RefundForm.js +89 -0
  16. package/admin/src/pages/App/index.js +41 -465
  17. package/admin/src/pages/App/styles.css +294 -0
  18. package/admin/src/pages/constants/paymentConstants.js +37 -0
  19. package/admin/src/pages/hooks/usePaymentActions.js +271 -0
  20. package/admin/src/pages/hooks/useSettings.js +111 -0
  21. package/admin/src/pages/hooks/useTransactionHistory.js +87 -0
  22. package/admin/src/pages/utils/api.js +10 -0
  23. package/admin/src/pages/utils/injectGooglePayScript.js +31 -0
  24. package/admin/src/pages/utils/paymentUtils.js +113 -13
  25. package/package.json +1 -1
  26. package/server/controllers/payone.js +71 -64
  27. package/server/routes/index.js +17 -0
  28. package/server/services/paymentService.js +214 -0
  29. package/server/services/payone.js +25 -648
  30. package/server/services/settingsService.js +59 -0
  31. package/server/services/testConnectionService.js +190 -0
  32. package/server/services/transactionService.js +114 -0
  33. package/server/utils/normalize.js +51 -0
  34. package/server/utils/paymentMethodParams.js +126 -0
  35. package/server/utils/requestBuilder.js +110 -0
  36. package/server/utils/responseParser.js +80 -0
@@ -29,22 +29,21 @@ const HistoryPanel = ({
29
29
 
30
30
  return (
31
31
  <Box
32
- hasRadius
33
- shadow="filterShadow"
32
+ className="payment-container"
34
33
  paddingTop={8}
35
34
  paddingBottom={8}
36
35
  paddingLeft={8}
37
36
  paddingRight={8}
38
- style={{
39
- borderRadius: "12px",
40
- boxShadow: "0 4px 20px rgba(0, 0, 0, 0.08)",
41
- border: "1px solid #f6f6f9"
42
- }}
43
37
  >
44
38
  <Flex direction="column" alignItems="stretch" gap={8}>
45
- <Typography variant="beta" as="h2" marginBottom={2}>
46
- Transaction Management
47
- </Typography>
39
+ <Box>
40
+ <Typography variant="beta" as="h2" className="payment-title" style={{ fontSize: '20px', marginBottom: '4px' }}>
41
+ Transaction Management
42
+ </Typography>
43
+ <Typography variant="pi" textColor="neutral600" className="payment-subtitle" style={{ fontSize: '14px', marginTop: '4px' }}>
44
+ View and filter all payment transactions processed through Payone
45
+ </Typography>
46
+ </Box>
48
47
  {/* Filters */}
49
48
  <Box>
50
49
  <Box marginBottom={4}>
@@ -55,7 +54,7 @@ const HistoryPanel = ({
55
54
  Filter transactions by status, type, date range, and more
56
55
  </Typography>
57
56
  </Box>
58
- <Card style={{ borderRadius: "8px", border: "1px solid #e4e2e7" }}>
57
+ <Card className="payment-card">
59
58
  <CardBody padding={6}>
60
59
  <Stack spacing={4}>
61
60
  <Flex gap={4} wrap="wrap" alignItems="center">
@@ -65,6 +64,7 @@ const HistoryPanel = ({
65
64
  value={filters.status}
66
65
  onChange={(e) => onFilterChange("status", e.target.value)}
67
66
  placeholder="APPROVED, ERROR, etc."
67
+ className="payment-input"
68
68
  style={{ flex: 1, minWidth: "200px" }}
69
69
  />
70
70
  <TextInput
@@ -75,6 +75,7 @@ const HistoryPanel = ({
75
75
  onFilterChange("request_type", e.target.value)
76
76
  }
77
77
  placeholder="preauthorization, authorization, etc."
78
+ className="payment-input"
78
79
  style={{ flex: 1, minWidth: "200px" }}
79
80
  />
80
81
  <TextInput
@@ -83,6 +84,7 @@ const HistoryPanel = ({
83
84
  value={filters.txid}
84
85
  onChange={(e) => onFilterChange("txid", e.target.value)}
85
86
  placeholder="Enter TxId"
87
+ className="payment-input"
86
88
  style={{ flex: 1, minWidth: "200px" }}
87
89
  />
88
90
  <TextInput
@@ -93,6 +95,7 @@ const HistoryPanel = ({
93
95
  onFilterChange("reference", e.target.value)
94
96
  }
95
97
  placeholder="Enter reference"
98
+ className="payment-input"
96
99
  style={{ flex: 1, minWidth: "200px" }}
97
100
  />
98
101
  <TextInput
@@ -104,6 +107,7 @@ const HistoryPanel = ({
104
107
  }
105
108
  placeholder="YYYY-MM-DD"
106
109
  type="date"
110
+ className="payment-input"
107
111
  style={{ flex: 1, minWidth: "200px" }}
108
112
  />
109
113
  <TextInput
@@ -113,6 +117,7 @@ const HistoryPanel = ({
113
117
  onChange={(e) => onFilterChange("date_to", e.target.value)}
114
118
  placeholder="YYYY-MM-DD"
115
119
  type="date"
120
+ className="payment-input"
116
121
  style={{ flex: 1, minWidth: "200px" }}
117
122
  />
118
123
  <Button
@@ -120,6 +125,7 @@ const HistoryPanel = ({
120
125
  onClick={onFilterApply}
121
126
  loading={isLoadingHistory}
122
127
  startIcon={<Search />}
128
+ className="payment-button payment-button-primary"
123
129
  >
124
130
  Apply Filters
125
131
  </Button>
@@ -155,13 +161,7 @@ const HistoryPanel = ({
155
161
  loading={isLoadingHistory}
156
162
  startIcon={<Search />}
157
163
  size="S"
158
- style={{
159
- background: "#28a745",
160
- border: "none",
161
- color: "white",
162
- fontWeight: "600",
163
- borderRadius: "8px"
164
- }}
164
+ className="payment-button payment-button-success"
165
165
  >
166
166
  Refresh
167
167
  </Button>
@@ -189,9 +189,7 @@ const HistoryPanel = ({
189
189
 
190
190
  {/* Pagination */}
191
191
  <Box paddingTop={6} paddingBottom={4}>
192
- <Card
193
- style={{ borderRadius: "8px", border: "1px solid #e4e2e7" }}
194
- >
192
+ <Card className="payment-card">
195
193
  <CardBody padding={4}>
196
194
  <Flex justifyContent="space-between" alignItems="center">
197
195
  {transactionHistory.length > pageSize &&
@@ -204,13 +202,10 @@ const HistoryPanel = ({
204
202
  onPageChange(Math.max(1, currentPage - 1))
205
203
  }
206
204
  disabled={currentPage === 1}
205
+ className={`payment-button ${currentPage === 1 ? '' : 'payment-button-success'}`}
207
206
  style={{
208
- background:
209
- currentPage === 1 ? "#f6f6f9" : "#28a745",
210
- border: "none",
211
- color: currentPage === 1 ? "#666687" : "white",
212
- fontWeight: "600",
213
- borderRadius: "6px"
207
+ background: currentPage === 1 ? "#f6f6f9" : undefined,
208
+ color: currentPage === 1 ? "#666687" : undefined
214
209
  }}
215
210
  >
216
211
  ← Previous
@@ -239,18 +234,10 @@ const HistoryPanel = ({
239
234
  )
240
235
  }
241
236
  disabled={currentPage === totalPages}
237
+ className={`payment-button ${currentPage === totalPages ? '' : 'payment-button-success'}`}
242
238
  style={{
243
- background:
244
- currentPage === totalPages
245
- ? "#f6f6f9"
246
- : "#28a745",
247
- border: "none",
248
- color:
249
- currentPage === totalPages
250
- ? "#666687"
251
- : "white",
252
- fontWeight: "600",
253
- borderRadius: "6px"
239
+ background: currentPage === totalPages ? "#f6f6f9" : undefined,
240
+ color: currentPage === totalPages ? "#666687" : undefined
254
241
  }}
255
242
  >
256
243
  Next →
@@ -1,19 +1,11 @@
1
1
  import React from "react";
2
- import {
3
- Box,
4
- Button,
5
- Card,
6
- CardBody,
7
- Divider,
8
- Flex,
9
- Stack,
10
- Typography,
11
- TextInput,
12
- Alert
13
- } from "@strapi/design-system";
14
- import { Play } from "@strapi/icons";
15
- import StatusBadge from "./StatusBadge";
16
- import { formatTransactionData } from "../../utils/formatTransactionData";
2
+ import { Box, Flex, Typography } from "@strapi/design-system";
3
+ import PaymentMethodSelector from "./paymentActions/PaymentMethodSelector";
4
+ import PreauthorizationForm from "./paymentActions/PreauthorizationForm";
5
+ import AuthorizationForm from "./paymentActions/AuthorizationForm";
6
+ import CaptureForm from "./paymentActions/CaptureForm";
7
+ import RefundForm from "./paymentActions/RefundForm";
8
+ import PaymentResult from "./paymentActions/PaymentResult";
17
9
 
18
10
  const PaymentActionsPanel = ({
19
11
  paymentAmount,
@@ -30,293 +22,116 @@ const PaymentActionsPanel = ({
30
22
  setRefundSequenceNumber,
31
23
  refundReference,
32
24
  setRefundReference,
25
+ paymentMethod,
26
+ setPaymentMethod,
27
+ captureMode,
28
+ setCaptureMode,
33
29
  isProcessingPayment,
34
30
  paymentError,
35
31
  paymentResult,
36
32
  onPreauthorization,
37
33
  onAuthorization,
38
34
  onCapture,
39
- onRefund
35
+ onRefund,
36
+ settings,
37
+ googlePayToken,
38
+ setGooglePayToken
40
39
  }) => {
41
40
  return (
42
41
  <Box
43
- background="neutral0"
44
- hasRadius
45
- shadow="filterShadow"
46
- paddingTop={6}
47
- paddingBottom={6}
48
- paddingLeft={7}
49
- paddingRight={7}
42
+ className="payment-container"
43
+ paddingTop={8}
44
+ paddingBottom={8}
45
+ paddingLeft={8}
46
+ paddingRight={8}
50
47
  >
51
48
  <Flex direction="column" alignItems="stretch" gap={6}>
52
- <Typography variant="beta" as="h2">
53
- Payment Actions
54
- </Typography>
55
-
56
- {/* Preauthorization */}
57
49
  <Box>
58
- <Flex direction="column" alignItems="stretch" gap={4}>
59
- <Typography variant="delta" as="h3">
60
- Preauthorization
61
- </Typography>
62
- <Typography variant="pi" textColor="neutral600">
63
- Reserve an amount on a credit card without capturing it
64
- immediately.
65
- </Typography>
66
-
67
- <Flex gap={4}>
68
- <TextInput
69
- label="Amount (in cents) *"
70
- name="paymentAmount"
71
- value={paymentAmount}
72
- onChange={(e) => setPaymentAmount(e.target.value)}
73
- placeholder="Enter amount (e.g., 1000 for €10.00)"
74
- hint="Amount in cents (e.g., 1000 = €10.00)"
75
- required
76
- style={{ flex: 1 }}
77
- />
78
-
79
- <TextInput
80
- label="Reference *"
81
- name="preauthReference"
82
- value={preauthReference}
83
- onChange={(e) => setPreauthReference(e.target.value)}
84
- placeholder="Enter reference"
85
- hint="Reference for this transaction"
86
- required
87
- style={{ flex: 1 }}
88
- />
89
- </Flex>
90
-
91
- <Button
92
- variant="default"
93
- onClick={onPreauthorization}
94
- loading={isProcessingPayment}
95
- startIcon={<Play />}
96
- fullWidth={false}
97
- disabled={!paymentAmount.trim() || !preauthReference.trim()}
98
- >
99
- Process Preauthorization
100
- </Button>
101
- </Flex>
50
+ <Typography variant="beta" as="h2" className="payment-title" style={{ fontSize: '20px', marginBottom: '4px' }}>
51
+ Payment Actions
52
+ </Typography>
53
+ <Typography variant="pi" textColor="neutral600" className="payment-subtitle" style={{ fontSize: '14px' }}>
54
+ Process payments, captures, and refunds with multiple payment methods
55
+ </Typography>
102
56
  </Box>
103
57
 
104
- <Divider />
105
-
106
- {/* Authorization */}
107
- <Box>
108
- <Flex direction="column" alignItems="stretch" gap={4}>
109
- <Typography variant="delta" as="h3">
110
- Authorization
111
- </Typography>
112
- <Typography variant="pi" textColor="neutral600">
113
- Authorize and capture an amount immediately.
114
- </Typography>
115
-
116
- <Flex gap={4}>
117
- <TextInput
118
- label="Amount (in cents) *"
119
- name="authAmount"
120
- value={paymentAmount}
121
- onChange={(e) => setPaymentAmount(e.target.value)}
122
- placeholder="Enter amount (e.g., 1000 for €10.00)"
123
- hint="Amount in cents (e.g., 1000 = €10.00)"
124
- required
125
- style={{ flex: 1 }}
126
- />
127
-
128
- <TextInput
129
- label="Reference *"
130
- name="authReference"
131
- value={authReference}
132
- onChange={(e) => setAuthReference(e.target.value)}
133
- placeholder="Enter reference"
134
- hint="Reference for this transaction"
135
- required
136
- style={{ flex: 1 }}
137
- />
138
- </Flex>
139
-
140
- <Button
141
- variant="default"
142
- onClick={onAuthorization}
143
- loading={isProcessingPayment}
144
- startIcon={<Play />}
145
- fullWidth={false}
146
- disabled={!paymentAmount.trim() || !authReference.trim()}
147
- >
148
- Process Authorization
149
- </Button>
150
- </Flex>
58
+ <PaymentMethodSelector
59
+ paymentMethod={paymentMethod}
60
+ setPaymentMethod={setPaymentMethod}
61
+ captureMode={captureMode}
62
+ setCaptureMode={setCaptureMode}
63
+ />
64
+
65
+ <hr className="payment-divider" />
66
+
67
+ <Box className="payment-form-section">
68
+ <PreauthorizationForm
69
+ paymentAmount={paymentAmount}
70
+ setPaymentAmount={setPaymentAmount}
71
+ preauthReference={preauthReference}
72
+ setPreauthReference={setPreauthReference}
73
+ isProcessingPayment={isProcessingPayment}
74
+ onPreauthorization={onPreauthorization}
75
+ paymentMethod={paymentMethod}
76
+ settings={settings}
77
+ googlePayToken={googlePayToken}
78
+ setGooglePayToken={setGooglePayToken}
79
+ />
151
80
  </Box>
152
81
 
153
- <Divider />
154
-
155
- {/* Capture */}
156
- <Box>
157
- <Flex direction="column" alignItems="stretch" gap={4}>
158
- <Typography variant="delta" as="h3">
159
- Capture
160
- </Typography>
161
- <Typography variant="pi" textColor="neutral600">
162
- Capture a previously authorized amount. Note: Reference parameter
163
- is not supported by Payone capture.
164
- </Typography>
165
-
166
- <Flex gap={4}>
167
- <TextInput
168
- label="Transaction ID"
169
- name="captureTxid"
170
- value={captureTxid}
171
- onChange={(e) => setCaptureTxid(e.target.value)}
172
- placeholder="Enter TxId from preauthorization"
173
- hint="Transaction ID from a previous preauthorization"
174
- style={{ flex: 1 }}
175
- />
176
-
177
- <TextInput
178
- label="Amount (in cents)"
179
- name="captureAmount"
180
- value={paymentAmount}
181
- onChange={(e) => setPaymentAmount(e.target.value)}
182
- placeholder="1000"
183
- hint="Amount in cents to capture"
184
- style={{ flex: 1 }}
185
- />
186
- </Flex>
187
-
188
- <Button
189
- variant="default"
190
- onClick={onCapture}
191
- loading={isProcessingPayment}
192
- startIcon={<Play />}
193
- fullWidth={false}
194
- disabled={!captureTxid.trim() || !paymentAmount.trim()}
195
- >
196
- Process Capture
197
- </Button>
198
- </Flex>
82
+ <hr className="payment-divider" />
83
+
84
+ <Box className="payment-form-section">
85
+ <AuthorizationForm
86
+ paymentAmount={paymentAmount}
87
+ setPaymentAmount={setPaymentAmount}
88
+ authReference={authReference}
89
+ setAuthReference={setAuthReference}
90
+ isProcessingPayment={isProcessingPayment}
91
+ onAuthorization={onAuthorization}
92
+ paymentMethod={paymentMethod}
93
+ settings={settings}
94
+ googlePayToken={googlePayToken}
95
+ setGooglePayToken={setGooglePayToken}
96
+ />
199
97
  </Box>
200
98
 
201
- <Divider />
202
-
203
- {/* Refund */}
204
- <Box>
205
- <Flex direction="column" alignItems="stretch" gap={4}>
206
- <Typography variant="delta" as="h3">
207
- Refund
208
- </Typography>
209
- <Typography variant="pi" textColor="neutral600">
210
- Refund a previously captured amount.
211
- </Typography>
212
-
213
- <Flex gap={4}>
214
- <TextInput
215
- label="Transaction ID"
216
- name="refundTxid"
217
- value={refundTxid}
218
- onChange={(e) => setRefundTxid(e.target.value)}
219
- placeholder="Enter TxId from capture"
220
- hint="Transaction ID from a previous capture"
221
- style={{ flex: 1 }}
222
- />
223
-
224
- <TextInput
225
- label="Sequence Number"
226
- name="refundSequenceNumber"
227
- value={refundSequenceNumber}
228
- onChange={(e) => setRefundSequenceNumber(e.target.value)}
229
- placeholder="2"
230
- hint="Sequence number for this refund (1-127) and by default for first 2"
231
- style={{ flex: 1 }}
232
- />
233
-
234
- <TextInput
235
- label="Amount (in cents)"
236
- name="refundAmount"
237
- value={paymentAmount}
238
- onChange={(e) => setPaymentAmount(e.target.value)}
239
- placeholder="1000"
240
- hint="Amount in cents to refund (will be negative)"
241
- style={{ flex: 1 }}
242
- />
243
-
244
- <TextInput
245
- label="Reference"
246
- name="refundReference"
247
- value={refundReference}
248
- onChange={(e) => setRefundReference(e.target.value)}
249
- placeholder="Optional reference"
250
- hint="Optional reference for this refund"
251
- style={{ flex: 1 }}
252
- />
253
- </Flex>
254
-
255
- <Button
256
- variant="default"
257
- onClick={onRefund}
258
- loading={isProcessingPayment}
259
- startIcon={<Play />}
260
- fullWidth={false}
261
- disabled={!refundTxid.trim() || !paymentAmount.trim()}
262
- >
263
- Process Refund
264
- </Button>
265
- </Flex>
99
+ <hr className="payment-divider" />
100
+
101
+ <Box className="payment-form-section">
102
+ <CaptureForm
103
+ paymentAmount={paymentAmount}
104
+ setPaymentAmount={setPaymentAmount}
105
+ captureTxid={captureTxid}
106
+ setCaptureTxid={setCaptureTxid}
107
+ isProcessingPayment={isProcessingPayment}
108
+ onCapture={onCapture}
109
+ />
266
110
  </Box>
267
111
 
268
- <Divider />
269
-
270
- {paymentError && (
271
- <Alert variant="danger" title="Error">
272
- {paymentError}
273
- </Alert>
274
- )}
275
-
276
- {paymentResult && (
277
- <Card>
278
- <CardBody>
279
- <Stack spacing={4}>
280
- <Flex justifyContent="space-between" alignItems="center">
281
- <Typography variant="delta" as="h3">
282
- Payment Result
283
- </Typography>
284
- {paymentResult.Status && (
285
- <StatusBadge status={paymentResult.Status} />
286
- )}
287
- </Flex>
112
+ <hr className="payment-divider" />
113
+
114
+ <Box className="payment-form-section">
115
+ <RefundForm
116
+ paymentAmount={paymentAmount}
117
+ setPaymentAmount={setPaymentAmount}
118
+ refundTxid={refundTxid}
119
+ setRefundTxid={setRefundTxid}
120
+ refundSequenceNumber={refundSequenceNumber}
121
+ setRefundSequenceNumber={setRefundSequenceNumber}
122
+ refundReference={refundReference}
123
+ setRefundReference={setRefundReference}
124
+ isProcessingPayment={isProcessingPayment}
125
+ onRefund={onRefund}
126
+ />
127
+ </Box>
288
128
 
289
- <Divider />
129
+ <hr className="payment-divider" />
290
130
 
291
- <Box>
292
- <Stack spacing={3}>
293
- {formatTransactionData(paymentResult).map((item, index) => (
294
- <Flex
295
- key={index}
296
- justifyContent="space-between"
297
- alignItems="start"
298
- >
299
- <Typography
300
- variant="pi"
301
- textColor="neutral600"
302
- style={{ minWidth: "200px" }}
303
- >
304
- {item.key}:
305
- </Typography>
306
- <Typography
307
- variant="pi"
308
- style={{ flex: 1, textAlign: "right" }}
309
- >
310
- {item.value}
311
- </Typography>
312
- </Flex>
313
- ))}
314
- </Stack>
315
- </Box>
316
- </Stack>
317
- </CardBody>
318
- </Card>
319
- )}
131
+ <PaymentResult
132
+ paymentError={paymentError}
133
+ paymentResult={paymentResult}
134
+ />
320
135
 
321
136
  <Box paddingTop={4}>
322
137
  <Typography variant="sigma" textColor="neutral600">
@@ -75,6 +75,7 @@ const TransactionHistoryItem = ({ transaction }) => {
75
75
 
76
76
  return (
77
77
  <Card
78
+ className="payment-transaction-item"
78
79
  background="neutral0"
79
80
  hasRadius
80
81
  shadow="filterShadow"
@@ -147,6 +148,7 @@ const TransactionHistoryItem = ({ transaction }) => {
147
148
  size="S"
148
149
  onClick={() => setIsExpanded(!isExpanded)}
149
150
  startIcon={isExpanded ? <ChevronUpIcon size={16} /> : <ChevronDownIcon size={16} />}
151
+ className="payment-button payment-button-primary"
150
152
  >
151
153
  {isExpanded ? 'Hide Details' : 'Show Details'}
152
154
  </Button>
@@ -154,7 +156,7 @@ const TransactionHistoryItem = ({ transaction }) => {
154
156
 
155
157
  {/* Expanded Details */}
156
158
  {isExpanded && (
157
- <Box marginTop={4}>
159
+ <Box marginTop={4} style={{ animation: 'fadeIn 0.3s ease-out' }}>
158
160
  <Stack spacing={4}>
159
161
  {/* Error Message */}
160
162
  {transaction.status === 'ERROR' && (
@@ -163,6 +165,7 @@ const TransactionHistoryItem = ({ transaction }) => {
163
165
  padding={3}
164
166
  background="danger100"
165
167
  hasRadius
168
+ className="payment-alert"
166
169
  style={{
167
170
  border: '1px solid',
168
171
  borderColor: 'var(--strapi-colors-danger200)',