strapi-plugin-payone-provider 4.6.10 → 4.6.11
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 +64 -0
- package/admin/src/pages/App/components/AppHeader.jsx +3 -2
- package/admin/src/pages/App/components/AppTabs.jsx +34 -88
- package/admin/src/pages/App/components/DocsPanel.jsx +1726 -1726
- package/admin/src/pages/App/components/GooglePaybutton.jsx +300 -300
- package/admin/src/pages/App/components/StatusBadge.jsx +1 -1
- package/admin/src/pages/App/components/common/InfoTooltip.jsx +16 -0
- package/admin/src/pages/App/components/{ApplePayConfig.jsx → configuration/ApplePayConfig.jsx} +191 -62
- package/admin/src/pages/App/components/{ApplePayConfigPanel.jsx → configuration/ApplePayConfigPanel.jsx} +71 -70
- package/admin/src/pages/App/components/configuration/ConfigurationFields.jsx +408 -0
- package/admin/src/pages/App/components/configuration/ConfigurationPanel.jsx +67 -0
- package/admin/src/pages/App/components/{GooglePayConfig.jsx → configuration/GooglePayConfig.jsx} +254 -254
- package/admin/src/pages/App/components/{GooglePayConfigPanel.jsx → configuration/GooglePayConfigPanel.jsx} +82 -82
- package/admin/src/pages/App/components/configuration/TestConnection.jsx +129 -0
- package/admin/src/pages/App/components/paymentActions/ApplePayPanel.jsx +137 -95
- package/admin/src/pages/App/components/paymentActions/CaptureForm.jsx +119 -14
- package/admin/src/pages/App/components/paymentActions/CardDetailsInput.jsx +85 -24
- package/admin/src/pages/App/components/paymentActions/PaymentActionsPanel.jsx +361 -0
- package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.jsx +22 -4
- package/admin/src/pages/App/components/paymentActions/RefundForm.jsx +91 -20
- package/admin/src/pages/App/components/paymentActions/authorization/AuthorizationForm.jsx +157 -0
- package/admin/src/pages/App/components/paymentActions/authorization/AuthorizationFormFields.jsx +308 -0
- package/admin/src/pages/App/components/paymentActions/authorization/AuthorizationFormHeader.jsx +27 -0
- package/admin/src/pages/App/components/paymentActions/authorization/AuthorizationPaymentButtons.jsx +93 -0
- package/admin/src/pages/App/components/paymentActions/preauthorization/PreauthorizationForm.jsx +134 -0
- package/admin/src/pages/App/components/paymentActions/preauthorization/PreauthorizationFormFields.jsx +295 -0
- package/admin/src/pages/App/components/paymentActions/preauthorization/PreauthorizationFormHeader.jsx +27 -0
- package/admin/src/pages/App/components/paymentActions/preauthorization/PreauthorizationPaymentButtons.jsx +53 -0
- package/admin/src/pages/App/components/transaction-history/FiltersPanel.jsx +182 -0
- package/admin/src/pages/App/components/transaction-history/HistoryPanel.jsx +49 -0
- package/admin/src/pages/App/components/transaction-history/TransactionTable.jsx +169 -0
- package/admin/src/pages/App/components/transaction-history/TransactionTablePagination.jsx +28 -0
- package/admin/src/pages/App/components/transaction-history/details/TransactionDetails.jsx +155 -0
- package/admin/src/pages/App/index.jsx +5 -29
- package/admin/src/pages/hooks/usePaymentActions.js +87 -11
- package/admin/src/pages/hooks/useSettings.js +64 -22
- package/admin/src/pages/hooks/useTransactionHistory.js +100 -88
- package/admin/src/pages/utils/api.js +31 -3
- package/admin/src/pages/utils/countryLanguageUtils.js +236 -0
- package/admin/src/pages/utils/transactionTableUtils.js +60 -0
- package/package.json +1 -1
- package/server/bootstrap.js +6 -6
- package/server/controllers/payone.js +27 -3
- package/server/policies/index.js +2 -1
- package/server/policies/is-payone-notification.js +31 -0
- package/server/routes/index.js +10 -0
- package/server/services/payone.js +11 -4
- package/server/services/settingsService.js +8 -2
- package/server/services/testConnectionService.js +11 -72
- package/server/services/transactionService.js +58 -78
- package/server/services/transactionStatusService.js +87 -0
- package/admin/src/pages/App/components/ConfigurationPanel.jsx +0 -517
- package/admin/src/pages/App/components/CustomerInfoPopover.jsx +0 -147
- package/admin/src/pages/App/components/HistoryPanel.jsx +0 -94
- package/admin/src/pages/App/components/PaymentActionsPanel.jsx +0 -280
- package/admin/src/pages/App/components/RawDataPopover.jsx +0 -113
- package/admin/src/pages/App/components/TransactionHistoryItem.jsx +0 -522
- package/admin/src/pages/App/components/TransactionHistoryTable/TransactionHistoryTableFilters.jsx +0 -113
- package/admin/src/pages/App/components/TransactionHistoryTable/TransactionHistoryTablePagination.jsx +0 -180
- package/admin/src/pages/App/components/TransactionHistoryTable/index.jsx +0 -225
- package/admin/src/pages/App/components/paymentActions/AuthorizationForm.jsx +0 -197
- package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.jsx +0 -142
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const getStatusColor = (status) => {
|
|
2
|
+
switch (status) {
|
|
3
|
+
case "APPROVED":
|
|
4
|
+
return "success200";
|
|
5
|
+
case "ERROR":
|
|
6
|
+
return "danger200";
|
|
7
|
+
case "PENDING":
|
|
8
|
+
return "warning200";
|
|
9
|
+
case "REDIRECT":
|
|
10
|
+
return "success100";
|
|
11
|
+
default:
|
|
12
|
+
return "success100";
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const formatAmount = (amount, currency) => {
|
|
17
|
+
if (amount === null || amount === undefined) return "N/A";
|
|
18
|
+
return `${(amount / 100).toFixed(2)} ${currency || "EUR"}`;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const formatDate = (dateString) => {
|
|
22
|
+
if (!dateString) return "N/A";
|
|
23
|
+
return new Date(dateString).toLocaleString("de-DE", {
|
|
24
|
+
year: "numeric",
|
|
25
|
+
month: "2-digit",
|
|
26
|
+
day: "2-digit",
|
|
27
|
+
hour: "2-digit",
|
|
28
|
+
minute: "2-digit",
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const getPaymentMethodName = (clearingtype, wallettype, cardtype) => {
|
|
33
|
+
switch (clearingtype) {
|
|
34
|
+
case "cc":
|
|
35
|
+
return cardtype ? `CC / ${cardtype}` : "Credit Card";
|
|
36
|
+
case "sb":
|
|
37
|
+
return "Online Banking";
|
|
38
|
+
case "wlt":
|
|
39
|
+
return wallettype === "PPE" ? "PayPal" : "Wallet";
|
|
40
|
+
case "elv":
|
|
41
|
+
return "Direct Debit (SEPA)";
|
|
42
|
+
default:
|
|
43
|
+
return clearingtype || "Unknown";
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const getCardTypeName = (cardtype) => {
|
|
48
|
+
switch (cardtype) {
|
|
49
|
+
case "V":
|
|
50
|
+
return "Visa";
|
|
51
|
+
case "M":
|
|
52
|
+
return "Mastercard";
|
|
53
|
+
case "A":
|
|
54
|
+
return "American Express";
|
|
55
|
+
default:
|
|
56
|
+
return cardtype || "Unknown";
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
|
package/package.json
CHANGED
package/server/bootstrap.js
CHANGED
|
@@ -22,12 +22,12 @@ module.exports = async ({ strapi }) => {
|
|
|
22
22
|
displayName: "",
|
|
23
23
|
domainName: "",
|
|
24
24
|
merchantIdentifier: "",
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
enableSepaDirectDebit:
|
|
25
|
+
enable3DSecure: false,
|
|
26
|
+
enableCreditCard: false,
|
|
27
|
+
enablePayPal: false,
|
|
28
|
+
enableGooglePay: false,
|
|
29
|
+
enableApplePay: false,
|
|
30
|
+
enableSepaDirectDebit: false
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
}
|
|
@@ -118,9 +118,15 @@ module.exports = ({ strapi }) => ({
|
|
|
118
118
|
|
|
119
119
|
async getTransactionHistory(ctx) {
|
|
120
120
|
try {
|
|
121
|
-
const filters = ctx.query || {};
|
|
122
|
-
const
|
|
123
|
-
|
|
121
|
+
const { filters = {}, pagination = {} } = ctx.query || {};
|
|
122
|
+
const page = parseInt(pagination.page || "1", 10);
|
|
123
|
+
const pageSize = parseInt(pagination.pageSize || "10", 10);
|
|
124
|
+
|
|
125
|
+
const result = await getPayoneService(strapi).getTransactionHistory({
|
|
126
|
+
filters: filters || {},
|
|
127
|
+
pagination: { page, pageSize }
|
|
128
|
+
});
|
|
129
|
+
ctx.body = result
|
|
124
130
|
} catch (error) {
|
|
125
131
|
handleError(ctx, error);
|
|
126
132
|
}
|
|
@@ -246,5 +252,23 @@ module.exports = ({ strapi }) => ({
|
|
|
246
252
|
}
|
|
247
253
|
};
|
|
248
254
|
}
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
async handleTransactionStatus(ctx) {
|
|
258
|
+
try {
|
|
259
|
+
const notificationData = ctx.request.body || {};
|
|
260
|
+
await getPayoneService(strapi).processTransactionStatus(notificationData);
|
|
261
|
+
|
|
262
|
+
ctx.status = 200;
|
|
263
|
+
ctx.body = "TSOK";
|
|
264
|
+
ctx.type = "text/plain";
|
|
265
|
+
console.log(`[Payone TransactionStatus] Responded TSOK`);
|
|
266
|
+
} catch (error) {
|
|
267
|
+
console.log("[Payone TransactionStatus] Error handling notification:", error);
|
|
268
|
+
ctx.status = 200;
|
|
269
|
+
ctx.body = "TSOK";
|
|
270
|
+
ctx.type = "text/plain";
|
|
271
|
+
}
|
|
249
272
|
}
|
|
273
|
+
|
|
250
274
|
});
|
package/server/policies/index.js
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
module.exports = async (ctx, config, { strapi }) => {
|
|
4
|
+
const { request } = ctx;
|
|
5
|
+
const userAgent = request.header["user-agent"] || request.header["User-Agent"] || "";
|
|
6
|
+
const clientIp = request.ip || request.connection?.remoteAddress || "";
|
|
7
|
+
|
|
8
|
+
if (userAgent !== "PAYONE FinanceGate") {
|
|
9
|
+
console.log(`[Payone TransactionStatus] Invalid User-Agent: ${userAgent}, IP: ${clientIp}`);
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
const isValidIp = (ip) => {
|
|
15
|
+
if (ip.startsWith("185.60.20.")) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (ip === "54.246.203.105") {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
if (!isValidIp(clientIp)) {
|
|
26
|
+
console.log(`[Payone TransactionStatus] Invalid IP address: ${clientIp}, User-Agent: ${userAgent}`);
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return true;
|
|
31
|
+
};
|
package/server/routes/index.js
CHANGED
|
@@ -162,6 +162,16 @@ module.exports = {
|
|
|
162
162
|
auth: false
|
|
163
163
|
}
|
|
164
164
|
},
|
|
165
|
+
|
|
166
|
+
{
|
|
167
|
+
method: "POST",
|
|
168
|
+
path: "/transaction-status",
|
|
169
|
+
handler: "payone.handleTransactionStatus",
|
|
170
|
+
config: {
|
|
171
|
+
policies: ["plugin::strapi-plugin-payone-provider.is-payone-notification"],
|
|
172
|
+
auth: false
|
|
173
|
+
}
|
|
174
|
+
},
|
|
165
175
|
]
|
|
166
176
|
}
|
|
167
177
|
};
|
|
@@ -5,7 +5,7 @@ const transactionService = require("./transactionService");
|
|
|
5
5
|
const paymentService = require("./paymentService");
|
|
6
6
|
const testConnectionService = require("./testConnectionService");
|
|
7
7
|
const applePayService = require("./applePayService");
|
|
8
|
-
|
|
8
|
+
const transactionStatusService = require("./transactionStatusService");
|
|
9
9
|
module.exports = ({ strapi }) => ({
|
|
10
10
|
// Settings
|
|
11
11
|
async getSettings() {
|
|
@@ -38,8 +38,9 @@ module.exports = ({ strapi }) => ({
|
|
|
38
38
|
return await transactionService.logTransaction(strapi, transactionData);
|
|
39
39
|
},
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
|
|
42
|
+
async getTransactionHistory({ filters = {}, pagination = {} }) {
|
|
43
|
+
return await transactionService.getTransactionHistory(strapi, { filters, pagination });
|
|
43
44
|
},
|
|
44
45
|
|
|
45
46
|
// Test connection
|
|
@@ -59,5 +60,11 @@ module.exports = ({ strapi }) => ({
|
|
|
59
60
|
|
|
60
61
|
async initializeApplePaySession(params) {
|
|
61
62
|
return await applePayService.initializeApplePaySession(strapi, params);
|
|
62
|
-
}
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
// TransactionStatus Notification
|
|
66
|
+
async processTransactionStatus(notificationData) {
|
|
67
|
+
return await transactionStatusService.processTransactionStatus(strapi, notificationData);
|
|
68
|
+
},
|
|
69
|
+
|
|
63
70
|
});
|
|
@@ -17,11 +17,17 @@ const getSettings = async (strapi) => {
|
|
|
17
17
|
|
|
18
18
|
const updateSettings = async (strapi, settings) => {
|
|
19
19
|
const pluginStore = getPluginStore(strapi);
|
|
20
|
+
const currentSettings = await getSettings(strapi) || {};
|
|
21
|
+
const mergedSettings = {
|
|
22
|
+
...currentSettings,
|
|
23
|
+
...settings
|
|
24
|
+
};
|
|
25
|
+
|
|
20
26
|
await pluginStore.set({
|
|
21
27
|
key: "settings",
|
|
22
|
-
value:
|
|
28
|
+
value: mergedSettings
|
|
23
29
|
});
|
|
24
|
-
return
|
|
30
|
+
return mergedSettings;
|
|
25
31
|
};
|
|
26
32
|
|
|
27
33
|
const validateSettings = (settings) => {
|
|
@@ -55,81 +55,18 @@ const testConnection = async (strapi) => {
|
|
|
55
55
|
|
|
56
56
|
const result = parseResponse(response.data, strapi.log);
|
|
57
57
|
const status = result.status || result.Status || result.STATUS;
|
|
58
|
-
const errorMessage =
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
result.ERRORMESSAGE ||
|
|
62
|
-
result.error ||
|
|
63
|
-
result.Error?.ErrorMessage ||
|
|
64
|
-
"";
|
|
65
|
-
const errorCode =
|
|
66
|
-
result.errorcode ||
|
|
67
|
-
result.Errorcode ||
|
|
68
|
-
result.ERRORCODE ||
|
|
69
|
-
result.Error?.ErrorCode ||
|
|
70
|
-
"";
|
|
71
|
-
const customErrorMessage =
|
|
72
|
-
result.customerrormessage ||
|
|
73
|
-
result.Customerrormessage ||
|
|
74
|
-
result.CUSTOMERRORMESSAGE ||
|
|
75
|
-
result.Error?.CustomerMessage ||
|
|
76
|
-
"";
|
|
58
|
+
const errorMessage = result?.Error?.ErrorMessage;
|
|
59
|
+
const errorCode = result?.Error?.ErrorCode;
|
|
60
|
+
const customErrorMessage = result?.Error?.CustomerMessage;
|
|
77
61
|
|
|
78
62
|
if (status === "ERROR" || status === "error") {
|
|
79
|
-
if (["2006", "920", "921", "922", "401", "403"].includes(errorCode)) {
|
|
80
|
-
return {
|
|
81
|
-
success: false,
|
|
82
|
-
message: `Authentication failed: ${customErrorMessage || errorMessage || "Invalid credentials"}`,
|
|
83
|
-
errorcode: errorCode
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const errorMessageStr = typeof errorMessage === "string" ? errorMessage : JSON.stringify(errorMessage);
|
|
88
|
-
const errorMessageLower = (errorMessageStr || "").toLowerCase();
|
|
89
|
-
const authErrorKeywords = [
|
|
90
|
-
"key incorrect",
|
|
91
|
-
"invalid key",
|
|
92
|
-
"portal key",
|
|
93
|
-
"unauthorized",
|
|
94
|
-
"not authorized",
|
|
95
|
-
"unknown aid",
|
|
96
|
-
"unknown account",
|
|
97
|
-
"unknown portal",
|
|
98
|
-
"unknown merchant",
|
|
99
|
-
"invalid aid",
|
|
100
|
-
"invalid mid",
|
|
101
|
-
"invalid portalid"
|
|
102
|
-
];
|
|
103
|
-
|
|
104
|
-
if (authErrorKeywords.some((keyword) => errorMessageLower.includes(keyword))) {
|
|
105
|
-
return {
|
|
106
|
-
success: false,
|
|
107
|
-
message: `Authentication failed: ${errorMessageStr}`,
|
|
108
|
-
errorcode: errorCode || "AUTH"
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (errorCode === "911") {
|
|
113
|
-
return {
|
|
114
|
-
success: true,
|
|
115
|
-
message: "Connection successful! Your Payone credentials are valid.",
|
|
116
|
-
details: {
|
|
117
|
-
mode: settings.mode,
|
|
118
|
-
aid: settings.aid,
|
|
119
|
-
portalid: settings.portalid,
|
|
120
|
-
mid: settings.mid
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
|
|
125
63
|
return {
|
|
126
64
|
success: false,
|
|
127
|
-
message: `
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
rawResponse: JSON.stringify(result).substring(0, 200)
|
|
65
|
+
message: `Test connection failed: ${errorCode}`,
|
|
66
|
+
error: {
|
|
67
|
+
ErrorCode: errorCode,
|
|
68
|
+
ErrorMessage: errorMessage,
|
|
69
|
+
CustomerMessage: customErrorMessage
|
|
133
70
|
}
|
|
134
71
|
};
|
|
135
72
|
}
|
|
@@ -147,6 +84,7 @@ const testConnection = async (strapi) => {
|
|
|
147
84
|
};
|
|
148
85
|
}
|
|
149
86
|
|
|
87
|
+
|
|
150
88
|
return {
|
|
151
89
|
success: false,
|
|
152
90
|
message: "Unexpected response format from Payone API",
|
|
@@ -157,11 +95,12 @@ const testConnection = async (strapi) => {
|
|
|
157
95
|
rawResponse: JSON.stringify(result).substring(0, 200)
|
|
158
96
|
}
|
|
159
97
|
};
|
|
98
|
+
|
|
160
99
|
} catch (error) {
|
|
161
100
|
strapi.log.error("Payone test connection error:", error);
|
|
162
101
|
return {
|
|
163
102
|
success: false,
|
|
164
|
-
message: `
|
|
103
|
+
message: `Test connection error: ${error.message || "Unknown error"}`,
|
|
165
104
|
error: error.toString(),
|
|
166
105
|
details: {
|
|
167
106
|
errorType: error.constructor.name,
|
|
@@ -65,36 +65,32 @@ const logTransaction = async (strapi, transactionData) => {
|
|
|
65
65
|
strapi.log.info("Transaction logged:", logEntry);
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const txid = (transaction.txid || "").toLowerCase();
|
|
78
|
-
const reference = (transaction.reference || "").toLowerCase();
|
|
79
|
-
|
|
80
|
-
return (
|
|
81
|
-
status.includes(searchLower) ||
|
|
82
|
-
txid.includes(searchLower) ||
|
|
83
|
-
reference.includes(searchLower)
|
|
84
|
-
);
|
|
68
|
+
const applyFilters = (transactions, filters = {}) => {
|
|
69
|
+
let result = [...transactions];
|
|
70
|
+
|
|
71
|
+
if (filters.search && typeof filters.search === 'string' && filters.search.trim() !== '') {
|
|
72
|
+
const search = filters.search.toLowerCase().trim();
|
|
73
|
+
result = result.filter((t) => {
|
|
74
|
+
const txid = (t.txid || "").toString().toLowerCase();
|
|
75
|
+
const reference = (t.reference || "").toString().toLowerCase();
|
|
76
|
+
return txid.includes(search) || reference.includes(search);
|
|
85
77
|
});
|
|
86
78
|
}
|
|
87
79
|
|
|
88
|
-
if (filters.
|
|
89
|
-
|
|
90
|
-
(
|
|
80
|
+
if (filters.status) {
|
|
81
|
+
result = result.filter(
|
|
82
|
+
(t) => (t.status || "").toUpperCase() === filters.status.toUpperCase()
|
|
91
83
|
);
|
|
92
84
|
}
|
|
93
85
|
|
|
86
|
+
if (filters.request_type) {
|
|
87
|
+
result = result.filter((t) => t.request_type === filters.request_type);
|
|
88
|
+
}
|
|
89
|
+
|
|
94
90
|
if (filters.payment_method) {
|
|
95
|
-
|
|
96
|
-
const clearingtype =
|
|
97
|
-
const wallettype =
|
|
91
|
+
result = result.filter((t) => {
|
|
92
|
+
const clearingtype = t.raw_request?.clearingtype;
|
|
93
|
+
const wallettype = t.raw_request?.wallettype;
|
|
98
94
|
|
|
99
95
|
switch (filters.payment_method) {
|
|
100
96
|
case "credit_card":
|
|
@@ -102,82 +98,66 @@ const getTransactionHistory = async (strapi, filters = {}) => {
|
|
|
102
98
|
case "paypal":
|
|
103
99
|
return clearingtype === "wlt" && wallettype === "PPE";
|
|
104
100
|
case "google_pay":
|
|
105
|
-
return clearingtype === "wlt" &&
|
|
101
|
+
return clearingtype === "wlt" && ["GPY", "GOOGLEPAY"].includes(wallettype);
|
|
106
102
|
case "apple_pay":
|
|
107
|
-
return clearingtype === "wlt" &&
|
|
103
|
+
return clearingtype === "wlt" && ["APL", "APPLEPAY"].includes(wallettype);
|
|
108
104
|
case "sofort":
|
|
109
105
|
return clearingtype === "sb";
|
|
110
106
|
case "sepa":
|
|
111
107
|
return clearingtype === "elv";
|
|
112
108
|
default:
|
|
113
|
-
return
|
|
109
|
+
return true;
|
|
114
110
|
}
|
|
115
111
|
});
|
|
116
112
|
}
|
|
117
113
|
|
|
118
114
|
if (filters.date_from) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
115
|
+
const dateFrom = new Date(filters.date_from);
|
|
116
|
+
dateFrom.setHours(0, 0, 0, 0);
|
|
117
|
+
result = result.filter(
|
|
118
|
+
(t) => new Date(t.timestamp || t.created_at) >= dateFrom
|
|
122
119
|
);
|
|
123
120
|
}
|
|
124
121
|
|
|
125
122
|
if (filters.date_to) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
const dateTo = new Date(filters.date_to);
|
|
124
|
+
dateTo.setHours(23, 59, 59, 999);
|
|
125
|
+
result = result.filter(
|
|
126
|
+
(t) => new Date(t.timestamp || t.created_at) <= dateTo
|
|
129
127
|
);
|
|
130
128
|
}
|
|
131
129
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
(transaction) => transaction.status === filters.status
|
|
135
|
-
);
|
|
136
|
-
}
|
|
130
|
+
return result;
|
|
131
|
+
};
|
|
137
132
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const sortOrder = filters.sort_order === "desc" ? -1 : 1;
|
|
141
|
-
|
|
142
|
-
transactionHistory.sort((a, b) => {
|
|
143
|
-
let aValue, bValue;
|
|
144
|
-
|
|
145
|
-
switch (filters.sort_by) {
|
|
146
|
-
case "amount":
|
|
147
|
-
aValue = a.amount || 0;
|
|
148
|
-
bValue = b.amount || 0;
|
|
149
|
-
break;
|
|
150
|
-
case "created_at":
|
|
151
|
-
aValue = new Date(a.created_at || a.timestamp || 0).getTime();
|
|
152
|
-
bValue = new Date(b.created_at || b.timestamp || 0).getTime();
|
|
153
|
-
break;
|
|
154
|
-
case "status":
|
|
155
|
-
aValue = (a.status || "").toLowerCase();
|
|
156
|
-
bValue = (b.status || "").toLowerCase();
|
|
157
|
-
break;
|
|
158
|
-
case "reference":
|
|
159
|
-
aValue = (a.reference || "").toLowerCase();
|
|
160
|
-
bValue = (b.reference || "").toLowerCase();
|
|
161
|
-
break;
|
|
162
|
-
case "method":
|
|
163
|
-
const aClearingType = a.raw_request?.clearingtype || "";
|
|
164
|
-
const bClearingType = b.raw_request?.clearingtype || "";
|
|
165
|
-
const aWalletType = a.raw_request?.wallettype || "";
|
|
166
|
-
const bWalletType = b.raw_request?.wallettype || "";
|
|
167
|
-
aValue = `${aClearingType}_${aWalletType}`.toLowerCase();
|
|
168
|
-
bValue = `${bClearingType}_${bWalletType}`.toLowerCase();
|
|
169
|
-
break;
|
|
170
|
-
default:
|
|
171
|
-
return 0;
|
|
172
|
-
}
|
|
133
|
+
const getTransactionHistory = async (strapi, { filters = {}, pagination = {} }) => {
|
|
134
|
+
const pluginStore = getPluginStore(strapi);
|
|
173
135
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
136
|
+
let transactions =
|
|
137
|
+
(await pluginStore.get({ key: "transactionHistory" })) || [];
|
|
138
|
+
|
|
139
|
+
transactions = applyFilters(transactions, filters);
|
|
140
|
+
const page = Number(pagination.page) || 1;
|
|
141
|
+
const pageSize = Number(pagination.pageSize) || 10;
|
|
142
|
+
|
|
143
|
+
const total = transactions.length;
|
|
144
|
+
const pageCount = Math.max(1, Math.ceil(total / pageSize));
|
|
179
145
|
|
|
180
|
-
|
|
146
|
+
const validPage = Math.min(Math.max(1, page), pageCount);
|
|
147
|
+
|
|
148
|
+
const start = (validPage - 1) * pageSize;
|
|
149
|
+
const end = Math.min(start + pageSize, total);
|
|
150
|
+
|
|
151
|
+
const paginatedData = start < total ? transactions.slice(start, end) : [];
|
|
152
|
+
return {
|
|
153
|
+
data: paginatedData,
|
|
154
|
+
pagination: {
|
|
155
|
+
page: validPage,
|
|
156
|
+
pageSize,
|
|
157
|
+
pageCount,
|
|
158
|
+
total,
|
|
159
|
+
},
|
|
160
|
+
};
|
|
181
161
|
};
|
|
182
162
|
|
|
183
163
|
module.exports = {
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const crypto = require("crypto");
|
|
4
|
+
const { getPluginStore, getSettings } = require("./settingsService");
|
|
5
|
+
|
|
6
|
+
const verifyHash = (notificationData, portalKey) => {
|
|
7
|
+
const {
|
|
8
|
+
portalid = "",
|
|
9
|
+
aid = "",
|
|
10
|
+
txid = "",
|
|
11
|
+
sequencenumber = "",
|
|
12
|
+
price = "",
|
|
13
|
+
currency = "",
|
|
14
|
+
mode = "",
|
|
15
|
+
} = notificationData;
|
|
16
|
+
|
|
17
|
+
const hashString = `${portalid}${aid}${txid}${sequencenumber}${price}${currency}${mode}${portalKey}`;
|
|
18
|
+
const expectedHash = crypto.createHash("md5").update(hashString).digest("hex");
|
|
19
|
+
|
|
20
|
+
return expectedHash.toLowerCase() === (notificationData.key || "").toLowerCase();
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const processTransactionStatus = async (strapi, notificationData) => {
|
|
24
|
+
try {
|
|
25
|
+
const settings = await getSettings(strapi);
|
|
26
|
+
const txid = notificationData.txid;
|
|
27
|
+
|
|
28
|
+
if (!settings || !settings.key) {
|
|
29
|
+
console.log("[Payone TransactionStatus] Settings not found or key missing");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const isValid = verifyHash(notificationData, settings.key);
|
|
34
|
+
if (!isValid) {
|
|
35
|
+
console.log(`[Payone TransactionStatus] Hash verification failed txid: ${txid}`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (notificationData.portalid !== settings.portalid || notificationData.aid !== settings.aid) {
|
|
40
|
+
console.log(`[Payone TransactionStatus] Portal ID or AID mismatch txid: ${txid}`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const pluginStore = getPluginStore(strapi);
|
|
45
|
+
let transactionHistory = (await pluginStore.get({ key: "transactionHistory" })) || [];
|
|
46
|
+
|
|
47
|
+
const transaction = transactionHistory.find((t) => t.txid === txid || t.id === txid);
|
|
48
|
+
|
|
49
|
+
if (transaction) {
|
|
50
|
+
Object.assign(transaction, {
|
|
51
|
+
...notificationData,
|
|
52
|
+
status: notificationData?.transaction_status,
|
|
53
|
+
txaction: notificationData?.txaction,
|
|
54
|
+
txtime: notificationData?.txtime,
|
|
55
|
+
sequencenumber: notificationData?.sequencenumber,
|
|
56
|
+
balance: notificationData?.balance,
|
|
57
|
+
receivable: notificationData?.receivable,
|
|
58
|
+
price: notificationData?.price,
|
|
59
|
+
amount: notificationData?.price ? parseFloat(notificationData?.price) * 100 : transaction?.amount,
|
|
60
|
+
userid: notificationData?.userid,
|
|
61
|
+
updated_at: new Date().toISOString(),
|
|
62
|
+
body: {
|
|
63
|
+
...transaction?.body,
|
|
64
|
+
...notificationData,
|
|
65
|
+
status: notificationData?.transaction_status
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await pluginStore.set({
|
|
70
|
+
key: "transactionHistory",
|
|
71
|
+
value: transactionHistory,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
console.log(`[Payone TransactionStatus] Successfully updated transaction txid: ${txid}`);
|
|
75
|
+
} else {
|
|
76
|
+
console.log(`[Payone TransactionStatus] Transaction ${txid} not found in history. Notification ignored.`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.log(`[Payone TransactionStatus] Error processing notification: ${error}`);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
module.exports = {
|
|
85
|
+
verifyHash,
|
|
86
|
+
processTransactionStatus,
|
|
87
|
+
};
|