strapi-plugin-payone-provider 5.7.26 → 5.8.26
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 +1191 -1191
- package/admin/src/components/Initializer/index.jsx +16 -16
- package/admin/src/components/PluginIcon/index.jsx +17 -17
- package/admin/src/index.js +57 -57
- package/admin/src/pages/App/components/AppHeader.jsx +45 -45
- package/admin/src/pages/App/components/AppTabs.jsx +105 -105
- package/admin/src/pages/App/components/ApplePayBtn.jsx +355 -355
- package/admin/src/pages/App/components/ApplePayConfig.jsx +357 -357
- package/admin/src/pages/App/components/DocsPanel.jsx +53 -53
- package/admin/src/pages/App/components/RenderInput.jsx +78 -78
- package/admin/src/pages/App/components/StatusBadge.jsx +87 -87
- package/admin/src/pages/App/components/icons/BankIcon.jsx +10 -10
- package/admin/src/pages/App/components/icons/ChevronDownIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/ChevronUpIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/CreditCardIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/ErrorIcon.jsx +10 -10
- package/admin/src/pages/App/components/icons/InfoIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/MarkCircle.jsx +19 -19
- package/admin/src/pages/App/components/icons/PaymentIcon.jsx +10 -10
- package/admin/src/pages/App/components/icons/PendingIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/PersonIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/SuccessIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/WalletIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/index.jsx +12 -12
- package/admin/src/pages/App/components/payment-actions/AuthorizationForm.jsx +334 -334
- package/admin/src/pages/App/components/payment-actions/CaptureForm.jsx +120 -120
- package/admin/src/pages/App/components/payment-actions/PaymentActionsPanel.jsx +183 -183
- package/admin/src/pages/App/components/payment-actions/PaymentMethodSelector.jsx +315 -315
- package/admin/src/pages/App/components/payment-actions/PaymentResult.jsx +129 -129
- package/admin/src/pages/App/components/payment-actions/PreauthorizationForm.jsx +273 -273
- package/admin/src/pages/App/components/payment-actions/RefundForm.jsx +114 -114
- package/admin/src/pages/App/components/transaction-history/ImportExportBar.jsx +153 -153
- package/admin/src/pages/App/components/transaction-history/details/TransactionHistoryItem.jsx +526 -526
- package/admin/src/pages/App/index.jsx +96 -96
- package/admin/src/pages/App/styles.css +176 -176
- package/admin/src/pages/constants/paymentConstants.js +71 -71
- package/admin/src/pages/hooks/use-system-theme.js +27 -27
- package/admin/src/pages/hooks/usePaymentActions.js +498 -498
- package/admin/src/pages/hooks/usePluginTranslations.js +12 -12
- package/admin/src/pages/hooks/useSettings.js +183 -183
- package/admin/src/pages/hooks/useTransactionHistory.js +148 -148
- package/admin/src/pages/utils/api.js +97 -97
- package/admin/src/pages/utils/applePayConstants.js +196 -196
- package/admin/src/pages/utils/formatTransactionData.js +15 -15
- package/admin/src/pages/utils/getInputComponent.jsx +200 -200
- package/admin/src/pages/utils/paymentUtils.js +661 -661
- package/admin/src/pages/utils/tooltipHelpers.js +18 -18
- package/admin/src/pages/utils/transactionTableUtils.js +71 -71
- package/admin/src/pluginId.js +9 -9
- package/admin/src/translations/de.json +235 -235
- package/admin/src/translations/en.json +235 -235
- package/admin/src/translations/fr.json +235 -235
- package/admin/src/translations/ru.json +235 -235
- package/admin/src/utils/prefixPluginTranslations.js +13 -13
- package/package.json +45 -45
- package/server/bootstrap.js +107 -107
- package/server/config/index.js +83 -83
- package/server/content-types/index.js +4 -4
- package/server/content-types/transactions/index.js +4 -4
- package/server/content-types/transactions/schema.json +86 -86
- package/server/controllers/index.js +7 -7
- package/server/controllers/payone.js +503 -506
- package/server/destroy.js +5 -5
- package/server/index.js +23 -23
- package/server/policies/index.js +7 -7
- package/server/policies/is-auth.js +29 -29
- package/server/policies/isSuperAdmin.js +20 -20
- package/server/register.js +5 -5
- package/server/routes/index.js +218 -218
- package/server/services/applePayService.js +295 -295
- package/server/services/index.js +9 -9
- package/server/services/paymentService.js +264 -223
- package/server/services/payone.js +78 -78
- package/server/services/settingsService.js +59 -59
- package/server/services/testConnectionService.js +115 -115
- package/server/services/transactionService.js +262 -262
- package/server/utils/csvTransactions.js +82 -82
- package/server/utils/normalize.js +39 -39
- package/server/utils/paymentMethodParams.js +288 -288
- package/server/utils/requestBuilder.js +115 -100
- package/server/utils/responseParser.js +141 -141
- package/strapi-admin.js +4 -4
- package/strapi-server.js +3 -3
|
@@ -1,506 +1,503 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const crypto = require("crypto");
|
|
4
|
-
const PLUGIN_NAME = "strapi-plugin-payone-provider";
|
|
5
|
-
const {
|
|
6
|
-
rowsToCsv,
|
|
7
|
-
csvToRows,
|
|
8
|
-
TRANSACTION_ATTRS
|
|
9
|
-
} = require("../utils/csvTransactions");
|
|
10
|
-
|
|
11
|
-
const getPayoneService = (strapi) => {
|
|
12
|
-
return strapi.plugin(PLUGIN_NAME).service("payone");
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const getNewHostedTokenizationService = (strapi) => {
|
|
16
|
-
return strapi.plugin(PLUGIN_NAME).service("newHostedTokenizationService");
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const buildFiltersFromQuery = (rawFilters = {}) => {
|
|
20
|
-
const filters = {};
|
|
21
|
-
if (rawFilters && typeof rawFilters === "object") {
|
|
22
|
-
for (const [key, value] of Object.entries(rawFilters)) {
|
|
23
|
-
const v = value == null ? "" : String(value).trim();
|
|
24
|
-
if (v !== "" && v.toLowerCase() !== "all") filters[key] = value;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return filters;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const handleError = (ctx, error) => {
|
|
31
|
-
const status = error.status || error.response?.status || 500;
|
|
32
|
-
const message = error.message || "Internal server error";
|
|
33
|
-
|
|
34
|
-
if (status >= 400) {
|
|
35
|
-
console.log("[Payone] Controller error:", {
|
|
36
|
-
status,
|
|
37
|
-
message,
|
|
38
|
-
error: error.stack || error
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
ctx.status = status;
|
|
43
|
-
ctx.body = {
|
|
44
|
-
error: {
|
|
45
|
-
status,
|
|
46
|
-
message,
|
|
47
|
-
name: error.name || "Error"
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const hideKey = (settings) => {
|
|
53
|
-
if (settings && settings.key) {
|
|
54
|
-
settings.key = "***HIDDEN***";
|
|
55
|
-
}
|
|
56
|
-
if (settings && settings.serverApiSecret) {
|
|
57
|
-
settings.serverApiSecret = "***HIDDEN***";
|
|
58
|
-
}
|
|
59
|
-
return settings;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
module.exports = ({ strapi }) => ({
|
|
63
|
-
async getSettings(ctx) {
|
|
64
|
-
try {
|
|
65
|
-
const settings = await getPayoneService(strapi).getSettings();
|
|
66
|
-
ctx.body = {
|
|
67
|
-
...hideKey(settings || {})
|
|
68
|
-
};
|
|
69
|
-
} catch (error) {
|
|
70
|
-
handleError(ctx, error);
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
async getPublicSettings(ctx) {
|
|
75
|
-
try {
|
|
76
|
-
const settings = await getPayoneService(strapi).getSettings();
|
|
77
|
-
ctx.body = {
|
|
78
|
-
data: {
|
|
79
|
-
mid: settings?.mid || null,
|
|
80
|
-
mode: settings?.mode || null,
|
|
81
|
-
domainName: settings?.domainName || null,
|
|
82
|
-
displayName: settings?.displayName || null,
|
|
83
|
-
portalid: settings?.portalid || null,
|
|
84
|
-
accountId: settings?.aid || null,
|
|
85
|
-
paymentMethods: {
|
|
86
|
-
creditCard: settings?.enableCreditCard,
|
|
87
|
-
paypal: settings?.enablePayPal,
|
|
88
|
-
googlePay: settings?.enableGooglePay,
|
|
89
|
-
applePay: settings?.enableApplePay,
|
|
90
|
-
sofort: settings?.enableSofort,
|
|
91
|
-
sepa: settings?.enableSepaDirectDebit
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
} catch (error) {
|
|
96
|
-
handleError(ctx, error);
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
async updateSettings(ctx) {
|
|
101
|
-
try {
|
|
102
|
-
const bodyData = ctx.request.body?.data || ctx.request.body;
|
|
103
|
-
|
|
104
|
-
if (!bodyData || typeof bodyData !== "object") {
|
|
105
|
-
ctx.throw(400, "Invalid request body");
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const currentSettings = await getPayoneService(strapi).getSettings();
|
|
109
|
-
|
|
110
|
-
if (bodyData.key === "***HIDDEN***" || !bodyData.key) {
|
|
111
|
-
bodyData.key = currentSettings?.key;
|
|
112
|
-
}
|
|
113
|
-
if (
|
|
114
|
-
bodyData.serverApiSecret === "***HIDDEN***" ||
|
|
115
|
-
!bodyData.serverApiSecret
|
|
116
|
-
) {
|
|
117
|
-
bodyData.serverApiSecret = currentSettings?.serverApiSecret;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const settings = await getPayoneService(strapi).updateSettings(bodyData);
|
|
121
|
-
ctx.body = { ...hideKey(settings) };
|
|
122
|
-
} catch (error) {
|
|
123
|
-
handleError(ctx, error);
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
|
-
|
|
127
|
-
async preauthorization(ctx) {
|
|
128
|
-
try {
|
|
129
|
-
const params = ctx.request.body?.data || ctx.request.body;
|
|
130
|
-
if (!params || typeof params !== "object") {
|
|
131
|
-
ctx.throw(400, "Invalid request body");
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const result = await getPayoneService(strapi).preauthorization(params);
|
|
135
|
-
ctx.body = result;
|
|
136
|
-
} catch (error) {
|
|
137
|
-
handleError(ctx, error);
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
|
|
141
|
-
async authorization(ctx) {
|
|
142
|
-
try {
|
|
143
|
-
const params = ctx.request.body?.data || ctx.request.body;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
);
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
if (
|
|
361
|
-
params.
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
if (!params.
|
|
374
|
-
params.
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
error.
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
"
|
|
414
|
-
"
|
|
415
|
-
"
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
!settings?.
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
//
|
|
491
|
-
const
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
});
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const crypto = require("crypto");
|
|
4
|
+
const PLUGIN_NAME = "strapi-plugin-payone-provider";
|
|
5
|
+
const {
|
|
6
|
+
rowsToCsv,
|
|
7
|
+
csvToRows,
|
|
8
|
+
TRANSACTION_ATTRS
|
|
9
|
+
} = require("../utils/csvTransactions");
|
|
10
|
+
|
|
11
|
+
const getPayoneService = (strapi) => {
|
|
12
|
+
return strapi.plugin(PLUGIN_NAME).service("payone");
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const getNewHostedTokenizationService = (strapi) => {
|
|
16
|
+
return strapi.plugin(PLUGIN_NAME).service("newHostedTokenizationService");
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const buildFiltersFromQuery = (rawFilters = {}) => {
|
|
20
|
+
const filters = {};
|
|
21
|
+
if (rawFilters && typeof rawFilters === "object") {
|
|
22
|
+
for (const [key, value] of Object.entries(rawFilters)) {
|
|
23
|
+
const v = value == null ? "" : String(value).trim();
|
|
24
|
+
if (v !== "" && v.toLowerCase() !== "all") filters[key] = value;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return filters;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const handleError = (ctx, error) => {
|
|
31
|
+
const status = error.status || error.response?.status || 500;
|
|
32
|
+
const message = error.message || "Internal server error";
|
|
33
|
+
|
|
34
|
+
if (status >= 400) {
|
|
35
|
+
console.log("[Payone] Controller error:", {
|
|
36
|
+
status,
|
|
37
|
+
message,
|
|
38
|
+
error: error.stack || error
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
ctx.status = status;
|
|
43
|
+
ctx.body = {
|
|
44
|
+
error: {
|
|
45
|
+
status,
|
|
46
|
+
message,
|
|
47
|
+
name: error.name || "Error"
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const hideKey = (settings) => {
|
|
53
|
+
if (settings && settings.key) {
|
|
54
|
+
settings.key = "***HIDDEN***";
|
|
55
|
+
}
|
|
56
|
+
if (settings && settings.serverApiSecret) {
|
|
57
|
+
settings.serverApiSecret = "***HIDDEN***";
|
|
58
|
+
}
|
|
59
|
+
return settings;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
module.exports = ({ strapi }) => ({
|
|
63
|
+
async getSettings(ctx) {
|
|
64
|
+
try {
|
|
65
|
+
const settings = await getPayoneService(strapi).getSettings();
|
|
66
|
+
ctx.body = {
|
|
67
|
+
...hideKey(settings || {})
|
|
68
|
+
};
|
|
69
|
+
} catch (error) {
|
|
70
|
+
handleError(ctx, error);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
async getPublicSettings(ctx) {
|
|
75
|
+
try {
|
|
76
|
+
const settings = await getPayoneService(strapi).getSettings();
|
|
77
|
+
ctx.body = {
|
|
78
|
+
data: {
|
|
79
|
+
mid: settings?.mid || null,
|
|
80
|
+
mode: settings?.mode || null,
|
|
81
|
+
domainName: settings?.domainName || null,
|
|
82
|
+
displayName: settings?.displayName || null,
|
|
83
|
+
portalid: settings?.portalid || null,
|
|
84
|
+
accountId: settings?.aid || null,
|
|
85
|
+
paymentMethods: {
|
|
86
|
+
creditCard: settings?.enableCreditCard,
|
|
87
|
+
paypal: settings?.enablePayPal,
|
|
88
|
+
googlePay: settings?.enableGooglePay,
|
|
89
|
+
applePay: settings?.enableApplePay,
|
|
90
|
+
sofort: settings?.enableSofort,
|
|
91
|
+
sepa: settings?.enableSepaDirectDebit
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
} catch (error) {
|
|
96
|
+
handleError(ctx, error);
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
async updateSettings(ctx) {
|
|
101
|
+
try {
|
|
102
|
+
const bodyData = ctx.request.body?.data || ctx.request.body;
|
|
103
|
+
|
|
104
|
+
if (!bodyData || typeof bodyData !== "object") {
|
|
105
|
+
ctx.throw(400, "Invalid request body");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const currentSettings = await getPayoneService(strapi).getSettings();
|
|
109
|
+
|
|
110
|
+
if (bodyData.key === "***HIDDEN***" || !bodyData.key) {
|
|
111
|
+
bodyData.key = currentSettings?.key;
|
|
112
|
+
}
|
|
113
|
+
if (
|
|
114
|
+
bodyData.serverApiSecret === "***HIDDEN***" ||
|
|
115
|
+
!bodyData.serverApiSecret
|
|
116
|
+
) {
|
|
117
|
+
bodyData.serverApiSecret = currentSettings?.serverApiSecret;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const settings = await getPayoneService(strapi).updateSettings(bodyData);
|
|
121
|
+
ctx.body = { ...hideKey(settings) };
|
|
122
|
+
} catch (error) {
|
|
123
|
+
handleError(ctx, error);
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
async preauthorization(ctx) {
|
|
128
|
+
try {
|
|
129
|
+
const params = ctx.request.body?.data || ctx.request.body;
|
|
130
|
+
if (!params || typeof params !== "object") {
|
|
131
|
+
ctx.throw(400, "Invalid request body");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const result = await getPayoneService(strapi).preauthorization(params);
|
|
135
|
+
ctx.body = result;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
handleError(ctx, error);
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
async authorization(ctx) {
|
|
142
|
+
try {
|
|
143
|
+
const params = ctx.request.body?.data || ctx.request.body;
|
|
144
|
+
if (!params || typeof params !== "object") ctx.throw(400, "Invalid request body");
|
|
145
|
+
|
|
146
|
+
const result = await getPayoneService(strapi).authorization(params);
|
|
147
|
+
ctx.body = result;
|
|
148
|
+
} catch (error) {
|
|
149
|
+
handleError(ctx, error);
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
async capture(ctx) {
|
|
154
|
+
try {
|
|
155
|
+
const params = ctx.request.body?.data || ctx.request.body;
|
|
156
|
+
|
|
157
|
+
if (!params || typeof params !== "object") {
|
|
158
|
+
ctx.throw(400, "Invalid request body");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const result = await getPayoneService(strapi).capture(params);
|
|
162
|
+
ctx.body = result;
|
|
163
|
+
} catch (error) {
|
|
164
|
+
handleError(ctx, error);
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
async refund(ctx) {
|
|
169
|
+
try {
|
|
170
|
+
const params = ctx.request.body?.data || ctx.request.body;
|
|
171
|
+
|
|
172
|
+
if (!params || typeof params !== "object") {
|
|
173
|
+
ctx.throw(400, "Invalid request body");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const result = await getPayoneService(strapi).refund(params);
|
|
177
|
+
ctx.body = result;
|
|
178
|
+
} catch (error) {
|
|
179
|
+
handleError(ctx, error);
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
async getTransactionHistory(ctx) {
|
|
184
|
+
try {
|
|
185
|
+
const { filters: rawFilters = {}, pagination = {} } = ctx.query || {};
|
|
186
|
+
const page = parseInt(pagination.page || "1", 10);
|
|
187
|
+
const pageSize = parseInt(pagination.pageSize || "10", 10);
|
|
188
|
+
|
|
189
|
+
const filters = {};
|
|
190
|
+
if (rawFilters && typeof rawFilters === "object") {
|
|
191
|
+
for (const [key, value] of Object.entries(rawFilters)) {
|
|
192
|
+
const v = value == null ? "" : String(value).trim();
|
|
193
|
+
if (v !== "" && v.toLowerCase() !== "all") {
|
|
194
|
+
filters[key] = value;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const result = await getPayoneService(strapi).getTransactionHistory({
|
|
200
|
+
filters,
|
|
201
|
+
pagination: { page, pageSize }
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
ctx.body = {
|
|
205
|
+
data: result.data || [],
|
|
206
|
+
meta: {
|
|
207
|
+
pagination: result.pagination
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
} catch (error) {
|
|
211
|
+
handleError(ctx, error);
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
async exportTransactions(ctx) {
|
|
216
|
+
try {
|
|
217
|
+
const {
|
|
218
|
+
filters: rawFilters = {},
|
|
219
|
+
format = "json",
|
|
220
|
+
sort_by,
|
|
221
|
+
sort_order
|
|
222
|
+
} = ctx.query || {};
|
|
223
|
+
const filters = buildFiltersFromQuery(rawFilters);
|
|
224
|
+
const data = await getPayoneService(strapi).getTransactionsForExport({
|
|
225
|
+
filters,
|
|
226
|
+
sort_by: sort_by || "createdAt",
|
|
227
|
+
sort_order: sort_order || "desc"
|
|
228
|
+
});
|
|
229
|
+
const rows = Array.isArray(data) ? data : [];
|
|
230
|
+
const fmt = (format || "json").toLowerCase();
|
|
231
|
+
|
|
232
|
+
if (fmt === "csv") {
|
|
233
|
+
ctx.set("Content-Type", "text/csv; charset=utf-8");
|
|
234
|
+
ctx.set(
|
|
235
|
+
"Content-Disposition",
|
|
236
|
+
'attachment; filename="transactions.csv"'
|
|
237
|
+
);
|
|
238
|
+
ctx.body = rowsToCsv(rows, TRANSACTION_ATTRS);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
ctx.set("Content-Type", "application/json");
|
|
243
|
+
ctx.set(
|
|
244
|
+
"Content-Disposition",
|
|
245
|
+
'attachment; filename="transactions.json"'
|
|
246
|
+
);
|
|
247
|
+
ctx.body = rows;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
handleError(ctx, error);
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
async importTransactions(ctx) {
|
|
254
|
+
try {
|
|
255
|
+
const body = ctx.request.body;
|
|
256
|
+
if (!body || typeof body !== "object")
|
|
257
|
+
ctx.throw(400, "Request body must be JSON");
|
|
258
|
+
|
|
259
|
+
let rows = [];
|
|
260
|
+
if (Array.isArray(body)) {
|
|
261
|
+
rows = body;
|
|
262
|
+
} else if (Array.isArray(body.data)) {
|
|
263
|
+
rows = body.data;
|
|
264
|
+
} else if (body.format === "csv" && typeof body.data === "string") {
|
|
265
|
+
rows = csvToRows(body.data);
|
|
266
|
+
} else {
|
|
267
|
+
ctx.throw(
|
|
268
|
+
400,
|
|
269
|
+
"Body must be an array, { data: array }, or { format: 'csv', data: csvString }"
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (rows.length === 0) {
|
|
274
|
+
ctx.body = {
|
|
275
|
+
imported: 0,
|
|
276
|
+
failed: 0,
|
|
277
|
+
errors: [],
|
|
278
|
+
message: "No rows to import"
|
|
279
|
+
};
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const result = await getPayoneService(strapi).importTransactions(rows);
|
|
284
|
+
ctx.body = {
|
|
285
|
+
...result,
|
|
286
|
+
message: `Imported ${result.imported}, failed ${result.failed}`
|
|
287
|
+
};
|
|
288
|
+
} catch (error) {
|
|
289
|
+
handleError(ctx, error);
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
|
|
293
|
+
async testConnection(ctx) {
|
|
294
|
+
try {
|
|
295
|
+
const result = await getPayoneService(strapi).testConnection();
|
|
296
|
+
ctx.body = result || {};
|
|
297
|
+
} catch (error) {
|
|
298
|
+
handleError(ctx, error);
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
|
|
302
|
+
async handle3DSCallback(ctx) {
|
|
303
|
+
try {
|
|
304
|
+
const isGetRequest = ctx.request.method === "GET";
|
|
305
|
+
const currentPath = ctx.request.url;
|
|
306
|
+
|
|
307
|
+
let resultType = "callback";
|
|
308
|
+
if (currentPath.includes("/success")) {
|
|
309
|
+
resultType = "success";
|
|
310
|
+
} else if (currentPath.includes("/error")) {
|
|
311
|
+
resultType = "error";
|
|
312
|
+
} else if (currentPath.includes("/back")) {
|
|
313
|
+
resultType = "cancelled";
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const callbackData = isGetRequest
|
|
317
|
+
? ctx.query
|
|
318
|
+
: ctx.request.body || ctx.request.body?.data || ctx.request?.data;
|
|
319
|
+
|
|
320
|
+
const result = await getPayoneService(strapi).handle3DSCallback(
|
|
321
|
+
callbackData,
|
|
322
|
+
resultType
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
if (isGetRequest) {
|
|
326
|
+
const isContentUI = currentPath.includes("/content-ui");
|
|
327
|
+
const basePath = isContentUI ? "/content-ui" : "/admin";
|
|
328
|
+
const pluginPath = "/plugins/strapi-plugin-payone-provider";
|
|
329
|
+
|
|
330
|
+
const queryParams = new URLSearchParams();
|
|
331
|
+
queryParams.set("3ds", resultType);
|
|
332
|
+
if (result.txid) queryParams.set("txid", result.txid);
|
|
333
|
+
if (result.status) queryParams.set("status", result.status);
|
|
334
|
+
|
|
335
|
+
const redirectUrl = `${basePath}${pluginPath}?${queryParams.toString()}`;
|
|
336
|
+
return ctx.redirect(redirectUrl);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
ctx.body = result;
|
|
340
|
+
} catch (error) {
|
|
341
|
+
handleError(ctx, error);
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
|
|
345
|
+
async validateApplePayMerchant(ctx) {
|
|
346
|
+
try {
|
|
347
|
+
const settings = await getPayoneService(strapi).getSettings();
|
|
348
|
+
const applePayConfig = settings?.applePayConfig || {};
|
|
349
|
+
|
|
350
|
+
const params =
|
|
351
|
+
ctx.request.body || ctx.request.body?.data || ctx.request?.data;
|
|
352
|
+
|
|
353
|
+
if (!params) {
|
|
354
|
+
throw new Error("Request body is missing");
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (!params.domain && !params.domainName) {
|
|
358
|
+
params.domain = ctx.request.hostname || ctx.request.host || "localhost";
|
|
359
|
+
params.domainName = params.domain;
|
|
360
|
+
} else if (params.domain && !params.domainName) {
|
|
361
|
+
params.domainName = params.domain;
|
|
362
|
+
} else if (params.domainName && !params.domain) {
|
|
363
|
+
params.domain = params.domainName;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (!params.displayName) {
|
|
367
|
+
params.displayName = settings?.merchantName || "Store";
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (!params.currency) {
|
|
371
|
+
params.currency = applePayConfig.currencyCode || "EUR";
|
|
372
|
+
}
|
|
373
|
+
if (!params.countryCode) {
|
|
374
|
+
params.countryCode = applePayConfig.countryCode || "DE";
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
let result =
|
|
378
|
+
await getPayoneService(strapi).validateApplePayMerchant(params);
|
|
379
|
+
|
|
380
|
+
if (!result) {
|
|
381
|
+
throw new Error(
|
|
382
|
+
"Merchant validation returned null. Please check your Payone Apple Pay configuration."
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
ctx.body = result;
|
|
387
|
+
} catch (error) {
|
|
388
|
+
const errorStatus =
|
|
389
|
+
error.status || (error.message?.includes("403") ? 403 : 500);
|
|
390
|
+
|
|
391
|
+
if (
|
|
392
|
+
error.response ||
|
|
393
|
+
errorStatus === 403 ||
|
|
394
|
+
errorStatus === 401 ||
|
|
395
|
+
errorStatus >= 500
|
|
396
|
+
) {
|
|
397
|
+
strapi.log.error("[Apple Pay] Controller error:", {
|
|
398
|
+
status: errorStatus,
|
|
399
|
+
message: error.message
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
let errorMessage =
|
|
404
|
+
error.message || "Apple Pay merchant validation failed";
|
|
405
|
+
let errorDetails =
|
|
406
|
+
"Please check your Payone Apple Pay configuration in PMI (CONFIGURATION → PAYMENT PORTALS → [Your Portal] → Apple Pay). Ensure that Merchant ID (mid) is correctly configured and Apple Pay is enabled for your portal.";
|
|
407
|
+
|
|
408
|
+
if (errorStatus === 403 || error.message?.includes("403")) {
|
|
409
|
+
errorDetails =
|
|
410
|
+
"403 Forbidden: Authentication failed with Payone. " +
|
|
411
|
+
"Please check: 1) Your Payone credentials (aid, portalid, mid, key) in plugin settings, " +
|
|
412
|
+
"2) Mode is set to 'live' (Apple Pay only works in live mode), " +
|
|
413
|
+
"3) Your domain is registered with Payone Merchant Services, " +
|
|
414
|
+
"4) Merchant ID (mid) matches your merchantIdentifier in PMI, " +
|
|
415
|
+
"5) Apple Pay is enabled for your portal in PMI.";
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
ctx.status = errorStatus;
|
|
419
|
+
ctx.body = {
|
|
420
|
+
error: {
|
|
421
|
+
status: errorStatus,
|
|
422
|
+
name: error.name || "Error",
|
|
423
|
+
message: errorMessage,
|
|
424
|
+
details: errorDetails
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
|
|
430
|
+
async handleTransactionStatus(ctx) {
|
|
431
|
+
try {
|
|
432
|
+
const notificationData = ctx.request.body || {};
|
|
433
|
+
await getPayoneService(strapi).processTransactionStatus(notificationData);
|
|
434
|
+
console.warn("[Payone] Notification Status", {
|
|
435
|
+
ip: ctx.request.ip
|
|
436
|
+
});
|
|
437
|
+
} catch (error) {
|
|
438
|
+
strapi.log.error("[Payone TransactionStatus] Error:", error);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
ctx.status = 200;
|
|
442
|
+
ctx.body = "TSOK";
|
|
443
|
+
ctx.type = "text/plain";
|
|
444
|
+
},
|
|
445
|
+
|
|
446
|
+
async hostedTokenizationJwt(ctx) {
|
|
447
|
+
try {
|
|
448
|
+
const result =
|
|
449
|
+
await getNewHostedTokenizationService(
|
|
450
|
+
strapi
|
|
451
|
+
).createHostedTokenizationJwt();
|
|
452
|
+
ctx.body = {
|
|
453
|
+
data: {
|
|
454
|
+
token: result?.token || null,
|
|
455
|
+
expirationDate: result?.expirationDate || null
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
} catch (error) {
|
|
459
|
+
handleError(ctx, error);
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
|
|
463
|
+
async hash384(ctx) {
|
|
464
|
+
try {
|
|
465
|
+
// Get settings
|
|
466
|
+
const settings = await getPayoneService(strapi).getSettings();
|
|
467
|
+
const hmacKey = settings?.key || "";
|
|
468
|
+
|
|
469
|
+
if (!hmacKey) {
|
|
470
|
+
ctx.throw(400, "Payone key is not configured in plugin settings");
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Validate required settings
|
|
474
|
+
if (
|
|
475
|
+
!settings?.aid ||
|
|
476
|
+
!settings?.mid ||
|
|
477
|
+
!settings?.portalid ||
|
|
478
|
+
!settings?.mode
|
|
479
|
+
) {
|
|
480
|
+
ctx.throw(
|
|
481
|
+
400,
|
|
482
|
+
"Required settings (aid, mid, portalid, mode) are not configured"
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// Construct the string from settings values
|
|
487
|
+
// Format: ${aid}UTF-8${mid}${mode}${portalid}creditcardcheckJSONyes
|
|
488
|
+
const textToHash = `${settings.aid}UTF-8${settings.mid}${settings.mode}${settings.portalid}creditcardcheckJSONyes`;
|
|
489
|
+
|
|
490
|
+
// Create HMAC SHA-384 hash
|
|
491
|
+
const hmac = crypto.createHmac("sha384", hmacKey);
|
|
492
|
+
hmac.update(textToHash);
|
|
493
|
+
const hash = hmac.digest("hex");
|
|
494
|
+
|
|
495
|
+
ctx.body = {
|
|
496
|
+
hash,
|
|
497
|
+
text: textToHash
|
|
498
|
+
};
|
|
499
|
+
} catch (error) {
|
|
500
|
+
handleError(ctx, error);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
});
|