strapi-plugin-payone-provider 1.1.2 → 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 +1045 -330
- 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
|
@@ -1,679 +1,56 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// Keep only alphanumeric characters
|
|
12
|
-
let normalized = raw.replace(/[^A-Za-z0-9]/g, "");
|
|
13
|
-
if (!normalized) {
|
|
14
|
-
normalized = `${fallbackPrefix}${Date.now()}`;
|
|
15
|
-
}
|
|
16
|
-
// Limit length to 20 chars (safe for PAYONE)
|
|
17
|
-
if (normalized.length > 20) normalized = normalized.slice(0, 20);
|
|
18
|
-
return normalized;
|
|
19
|
-
} catch (_) {
|
|
20
|
-
const fallback = `${fallbackPrefix}${Date.now()}`;
|
|
21
|
-
return fallback.slice(0, 20);
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const buildClientRequestParams = (settings, params) => {
|
|
26
|
-
const requestParams = {
|
|
27
|
-
request: params.request,
|
|
28
|
-
aid: settings.aid,
|
|
29
|
-
mid: settings.mid,
|
|
30
|
-
portalid: settings.portalid,
|
|
31
|
-
mode: settings.mode || "test",
|
|
32
|
-
encoding: "UTF-8",
|
|
33
|
-
...params
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
requestParams.key = crypto
|
|
37
|
-
.createHash("md5")
|
|
38
|
-
.update(settings.portalKey || settings.key)
|
|
39
|
-
.digest("hex");
|
|
40
|
-
|
|
41
|
-
if (!requestParams.salutation) requestParams.salutation = "Herr";
|
|
42
|
-
if (!requestParams.gender) requestParams.gender = "m";
|
|
43
|
-
if (!requestParams.telephonenumber)
|
|
44
|
-
requestParams.telephonenumber = "01752345678";
|
|
45
|
-
if (!requestParams.ip) requestParams.ip = "127.0.0.1";
|
|
46
|
-
if (!requestParams.language) requestParams.language = "de";
|
|
47
|
-
if (!requestParams.customer_is_present)
|
|
48
|
-
requestParams.customer_is_present = "yes";
|
|
49
|
-
|
|
50
|
-
return requestParams;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const toFormData = (requestParams) => {
|
|
55
|
-
const formData = new URLSearchParams();
|
|
56
|
-
for (const [key, value] of Object.entries(requestParams)) {
|
|
57
|
-
if (value !== undefined && value !== null) {
|
|
58
|
-
formData.append(key, value);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return formData;
|
|
62
|
-
};
|
|
63
|
-
|
|
3
|
+
const settingsService = require("./settingsService");
|
|
4
|
+
const transactionService = require("./transactionService");
|
|
5
|
+
const paymentService = require("./paymentService");
|
|
6
|
+
const testConnectionService = require("./testConnectionService");
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Main Payone service - aggregates all sub-services
|
|
10
|
+
*/
|
|
64
11
|
module.exports = ({ strapi }) => ({
|
|
12
|
+
// Settings
|
|
65
13
|
async getSettings() {
|
|
66
|
-
|
|
67
|
-
environment: "",
|
|
68
|
-
type: "plugin",
|
|
69
|
-
name: "strapi-plugin-payone-provider"
|
|
70
|
-
});
|
|
71
|
-
return await pluginStore.get({ key: "settings" });
|
|
14
|
+
return await settingsService.getSettings(strapi);
|
|
72
15
|
},
|
|
73
16
|
|
|
74
17
|
async updateSettings(settings) {
|
|
75
|
-
|
|
76
|
-
environment: "",
|
|
77
|
-
type: "plugin",
|
|
78
|
-
name: "strapi-plugin-payone-provider"
|
|
79
|
-
});
|
|
80
|
-
await pluginStore.set({
|
|
81
|
-
key: "settings",
|
|
82
|
-
value: settings
|
|
83
|
-
});
|
|
84
|
-
return settings;
|
|
85
|
-
},
|
|
86
|
-
|
|
87
|
-
async sendRequest(params) {
|
|
88
|
-
try {
|
|
89
|
-
strapi.log.info("Payone sendRequest called with params:", params);
|
|
90
|
-
|
|
91
|
-
const settings = await this.getSettings();
|
|
92
|
-
|
|
93
|
-
if (!settings || !settings.aid || !settings.portalid || !settings.key) {
|
|
94
|
-
throw new Error("Payone settings not configured");
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const reqType = params.request;
|
|
98
|
-
if (reqType === "authorization" || reqType === "preauthorization" || reqType === "refund") {
|
|
99
|
-
const prefix = reqType === "refund" ? "REF" : reqType === "preauthorization" ? "PRE" : "AUTH";
|
|
100
|
-
params.reference = normalizeReference(params.reference, prefix);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const requestParams = buildClientRequestParams(settings, params);
|
|
104
|
-
const debugParams = { ...requestParams };
|
|
105
|
-
if (debugParams.key) debugParams.key = "***HIDDEN***";
|
|
106
|
-
strapi.log.info("Payone Client API request params:", debugParams);
|
|
107
|
-
const formData = toFormData(requestParams);
|
|
108
|
-
|
|
109
|
-
strapi.log.info("Payone form data being sent:", formData.toString());
|
|
110
|
-
strapi.log.info("Payone form data reference:", formData.get("reference"));
|
|
111
|
-
|
|
112
|
-
const response = await axios.post(POST_GATEWAY_URL, formData, {
|
|
113
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
114
|
-
timeout: 30000
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
let dataSample = "null";
|
|
118
|
-
if (response.data) {
|
|
119
|
-
if (typeof response.data === "string") {
|
|
120
|
-
dataSample = response.data.substring(0, 200);
|
|
121
|
-
} else {
|
|
122
|
-
dataSample = JSON.stringify(response.data).substring(0, 200);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
strapi.log.info("Payone raw response:", {
|
|
126
|
-
status: response.status,
|
|
127
|
-
statusText: response.statusText,
|
|
128
|
-
dataType: typeof response.data,
|
|
129
|
-
dataSample,
|
|
130
|
-
fullData:
|
|
131
|
-
typeof response.data === "string"
|
|
132
|
-
? response.data
|
|
133
|
-
: JSON.stringify(response.data)
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
const responseData = this.parseResponse(response.data);
|
|
137
|
-
const extractTxId = (data) => {
|
|
138
|
-
return (
|
|
139
|
-
data.txid ||
|
|
140
|
-
data.TxId ||
|
|
141
|
-
data.tx_id ||
|
|
142
|
-
data.transactionid ||
|
|
143
|
-
data.transaction_id ||
|
|
144
|
-
data.id ||
|
|
145
|
-
null
|
|
146
|
-
);
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
await this.logTransaction({
|
|
150
|
-
txid: extractTxId(responseData) || params.txid || null,
|
|
151
|
-
reference: params.reference || null,
|
|
152
|
-
status: responseData.status || responseData.Status || "unknown",
|
|
153
|
-
request_type: params.request,
|
|
154
|
-
amount: params.amount || null,
|
|
155
|
-
currency: params.currency || "EUR",
|
|
156
|
-
raw_request: requestParams,
|
|
157
|
-
raw_response: responseData,
|
|
158
|
-
error_code: responseData.Error?.ErrorCode || null,
|
|
159
|
-
error_message: responseData.Error?.ErrorMessage || null,
|
|
160
|
-
customer_message: responseData.Error?.CustomerMessage || null
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
return responseData;
|
|
164
|
-
} catch (error) {
|
|
165
|
-
strapi.log.error("Payone sendRequest error:", error);
|
|
166
|
-
throw error;
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
|
|
170
|
-
parseResponse(responseText) {
|
|
171
|
-
try {
|
|
172
|
-
if (typeof responseText === "object") {
|
|
173
|
-
return responseText;
|
|
174
|
-
}
|
|
175
|
-
if (responseText.trim().startsWith("{")) {
|
|
176
|
-
return JSON.parse(responseText);
|
|
177
|
-
}
|
|
178
|
-
} catch (e) {
|
|
179
|
-
strapi.log.error("Payone parseResponse error:", e);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const params = new URLSearchParams(responseText);
|
|
183
|
-
const response = {};
|
|
184
|
-
for (const [key, value] of params) {
|
|
185
|
-
response[key.toLowerCase()] = value;
|
|
186
|
-
response[key] = value;
|
|
187
|
-
}
|
|
188
|
-
return response;
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
addPaymentMethodParams(params) {
|
|
192
|
-
const updated = { ...params };
|
|
193
|
-
const clearingtype = updated.clearingtype || "cc";
|
|
194
|
-
|
|
195
|
-
switch (clearingtype) {
|
|
196
|
-
case "cc":
|
|
197
|
-
if (!updated.cardpan) updated.cardpan = "4111111111111111";
|
|
198
|
-
if (!updated.cardexpiredate) updated.cardexpiredate = "2512";
|
|
199
|
-
if (!updated.cardcvc2) updated.cardcvc2 = "123";
|
|
200
|
-
if (!updated.cardtype) updated.cardtype = "V";
|
|
201
|
-
break;
|
|
202
|
-
|
|
203
|
-
case "wlt":
|
|
204
|
-
if (!updated.wallettype) updated.wallettype = "PPE";
|
|
205
|
-
break;
|
|
206
|
-
|
|
207
|
-
case "elv":
|
|
208
|
-
if (!updated.bankcountry) updated.bankcountry = "DE";
|
|
209
|
-
if (!updated.iban) updated.iban = "DE89370400440532013000";
|
|
210
|
-
if (!updated.bic) updated.bic = "COBADEFFXXX";
|
|
211
|
-
if (!updated.bankaccountholder)
|
|
212
|
-
updated.bankaccountholder = `${updated.firstname || "Test"} ${updated.lastname || "User"}`;
|
|
213
|
-
break;
|
|
214
|
-
|
|
215
|
-
case "sb":
|
|
216
|
-
if (!updated.bankcountry) updated.bankcountry = "DE";
|
|
217
|
-
if (!updated.onlinebanktransfertype) updated.onlinebanktransfertype = "PNT";
|
|
218
|
-
break;
|
|
219
|
-
|
|
220
|
-
case "gp":
|
|
221
|
-
if (!updated.bankcountry) updated.bankcountry = "DE";
|
|
222
|
-
if (!updated.onlinebanktransfertype) updated.onlinebanktransfertype = "GPY";
|
|
223
|
-
break;
|
|
224
|
-
|
|
225
|
-
case "idl":
|
|
226
|
-
if (!updated.bankcountry) updated.bankcountry = "NL";
|
|
227
|
-
if (!updated.onlinebanktransfertype) updated.onlinebanktransfertype = "IDL";
|
|
228
|
-
break;
|
|
229
|
-
|
|
230
|
-
case "bct":
|
|
231
|
-
if (!updated.bankcountry) updated.bankcountry = "BE";
|
|
232
|
-
if (!updated.onlinebanktransfertype) updated.onlinebanktransfertype = "BCT";
|
|
233
|
-
break;
|
|
234
|
-
|
|
235
|
-
case "rec":
|
|
236
|
-
if (!updated.recurrence) updated.recurrence = "recurring";
|
|
237
|
-
break;
|
|
238
|
-
|
|
239
|
-
case "fnc":
|
|
240
|
-
if (!updated.financingtype) updated.financingtype = "fnc";
|
|
241
|
-
break;
|
|
242
|
-
|
|
243
|
-
case "iv":
|
|
244
|
-
if (!updated.invoicetype) updated.invoicetype = "invoice";
|
|
245
|
-
break;
|
|
246
|
-
|
|
247
|
-
default:
|
|
248
|
-
strapi.log.warn(`Unknown clearingtype: ${clearingtype}, using credit card defaults`);
|
|
249
|
-
if (!updated.cardpan) updated.cardpan = "4111111111111111";
|
|
250
|
-
if (!updated.cardexpiredate) updated.cardexpiredate = "2512";
|
|
251
|
-
if (!updated.cardcvc2) updated.cardcvc2 = "123";
|
|
252
|
-
if (!updated.cardtype) updated.cardtype = "V";
|
|
253
|
-
break;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (!updated.salutation) updated.salutation = "Herr";
|
|
257
|
-
if (!updated.gender) updated.gender = "m";
|
|
258
|
-
if (!updated.telephonenumber) updated.telephonenumber = "01752345678";
|
|
259
|
-
if (!updated.ip) updated.ip = "127.0.0.1";
|
|
260
|
-
if (!updated.language) updated.language = "de";
|
|
261
|
-
if (!updated.customer_is_present) updated.customer_is_present = "yes";
|
|
262
|
-
|
|
263
|
-
return updated;
|
|
18
|
+
return await settingsService.updateSettings(strapi, settings);
|
|
264
19
|
},
|
|
265
20
|
|
|
21
|
+
// Payment operations
|
|
266
22
|
async preauthorization(params) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const requiredParams = {
|
|
270
|
-
request: "preauthorization",
|
|
271
|
-
clearingtype: params.clearingtype || "cc",
|
|
272
|
-
...params
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
if (!requiredParams.amount) requiredParams.amount = 1000;
|
|
276
|
-
if (!requiredParams.currency) requiredParams.currency = "EUR";
|
|
277
|
-
if (!requiredParams.reference)
|
|
278
|
-
requiredParams.reference = `PREAUTH-${Date.now()}`;
|
|
279
|
-
if (!requiredParams.firstname) requiredParams.firstname = "Test";
|
|
280
|
-
if (!requiredParams.lastname) requiredParams.lastname = "User";
|
|
281
|
-
if (!requiredParams.street) requiredParams.street = "Test Street 1";
|
|
282
|
-
if (!requiredParams.zip) requiredParams.zip = "12345";
|
|
283
|
-
if (!requiredParams.city) requiredParams.city = "Test City";
|
|
284
|
-
if (!requiredParams.country) requiredParams.country = "DE";
|
|
285
|
-
if (!requiredParams.email) requiredParams.email = "test@example.com";
|
|
286
|
-
|
|
287
|
-
const updatedParams = this.addPaymentMethodParams(requiredParams);
|
|
288
|
-
|
|
289
|
-
return await this.sendRequest(updatedParams);
|
|
23
|
+
return await paymentService.preauthorization(strapi, params);
|
|
290
24
|
},
|
|
291
25
|
|
|
292
26
|
async authorization(params) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const requiredParams = {
|
|
296
|
-
request: "authorization",
|
|
297
|
-
clearingtype: params.clearingtype || "cc",
|
|
298
|
-
...params
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
const updatedParams = this.addPaymentMethodParams(requiredParams);
|
|
302
|
-
|
|
303
|
-
return await this.sendRequest(updatedParams);
|
|
27
|
+
return await paymentService.authorization(strapi, params);
|
|
304
28
|
},
|
|
305
29
|
|
|
306
30
|
async capture(params) {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (!params.txid) {
|
|
310
|
-
throw new Error("Transaction ID (txid) is required for capture");
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const requiredParams = {
|
|
314
|
-
request: "capture",
|
|
315
|
-
txid: params.txid,
|
|
316
|
-
amount: params.amount || 1000,
|
|
317
|
-
currency: params.currency || "EUR",
|
|
318
|
-
...params
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
delete requiredParams.reference;
|
|
322
|
-
|
|
323
|
-
strapi.log.info("Payone capture required params:", requiredParams);
|
|
324
|
-
|
|
325
|
-
return await this.sendRequest(requiredParams);
|
|
31
|
+
return await paymentService.capture(strapi, params);
|
|
326
32
|
},
|
|
327
33
|
|
|
328
34
|
async refund(params) {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
if (!params.txid) {
|
|
332
|
-
throw new Error("Transaction ID (txid) is required for refund");
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
const requiredParams = {
|
|
336
|
-
request: "refund",
|
|
337
|
-
txid: params.txid,
|
|
338
|
-
...params
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
if (!requiredParams.amount) requiredParams.amount = 1000; // 10.00 EUR in cents
|
|
342
|
-
if (!requiredParams.currency) requiredParams.currency = "EUR";
|
|
343
|
-
if (!requiredParams.reference)
|
|
344
|
-
requiredParams.reference = `REFUND-${Date.now()}`;
|
|
345
|
-
|
|
346
|
-
return await this.sendRequest(requiredParams);
|
|
35
|
+
return await paymentService.refund(strapi, params);
|
|
347
36
|
},
|
|
348
37
|
|
|
38
|
+
// Transaction history
|
|
349
39
|
async logTransaction(transactionData) {
|
|
350
|
-
|
|
351
|
-
environment: "",
|
|
352
|
-
type: "plugin",
|
|
353
|
-
name: "strapi-plugin-payone-provider"
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
let transactionHistory =
|
|
357
|
-
(await pluginStore.get({ key: "transactionHistory" })) || [];
|
|
358
|
-
|
|
359
|
-
const logEntry = {
|
|
360
|
-
id: Date.now().toString(),
|
|
361
|
-
timestamp: new Date().toISOString(),
|
|
362
|
-
txid: transactionData.txid || null,
|
|
363
|
-
reference: transactionData.reference || null,
|
|
364
|
-
request_type:
|
|
365
|
-
transactionData.request_type || transactionData.request || "unknown",
|
|
366
|
-
amount: transactionData.amount || null,
|
|
367
|
-
currency: transactionData.currency || "EUR",
|
|
368
|
-
status: transactionData.status || transactionData.Status || "unknown",
|
|
369
|
-
error_code:
|
|
370
|
-
transactionData.error_code || transactionData.Error?.ErrorCode || null,
|
|
371
|
-
error_message:
|
|
372
|
-
transactionData.error_message ||
|
|
373
|
-
transactionData.Error?.ErrorMessage ||
|
|
374
|
-
null,
|
|
375
|
-
customer_message:
|
|
376
|
-
transactionData.customer_message ||
|
|
377
|
-
transactionData.Error?.CustomerMessage ||
|
|
378
|
-
null,
|
|
379
|
-
raw_request: transactionData.raw_request || null,
|
|
380
|
-
raw_response: transactionData.raw_response || transactionData,
|
|
381
|
-
created_at: new Date().toISOString(),
|
|
382
|
-
updated_at: new Date().toISOString()
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
transactionHistory.unshift(logEntry);
|
|
386
|
-
|
|
387
|
-
if (transactionHistory.length > 1000) {
|
|
388
|
-
transactionHistory = transactionHistory.slice(0, 1000);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
await pluginStore.set({
|
|
392
|
-
key: "transactionHistory",
|
|
393
|
-
value: transactionHistory
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
strapi.log.info("Transaction logged:", logEntry);
|
|
40
|
+
return await transactionService.logTransaction(strapi, transactionData);
|
|
397
41
|
},
|
|
398
42
|
|
|
399
43
|
async getTransactionHistory(filters = {}) {
|
|
400
|
-
|
|
401
|
-
environment: "",
|
|
402
|
-
type: "plugin",
|
|
403
|
-
name: "strapi-plugin-payone-provider"
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
let transactionHistory =
|
|
407
|
-
(await pluginStore.get({ key: "transactionHistory" })) || [];
|
|
408
|
-
|
|
409
|
-
if (filters.status) {
|
|
410
|
-
transactionHistory = transactionHistory.filter(
|
|
411
|
-
(transaction) => transaction.status === filters.status
|
|
412
|
-
);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
if (filters.request_type) {
|
|
416
|
-
transactionHistory = transactionHistory.filter(
|
|
417
|
-
(transaction) => transaction.request_type === filters.request_type
|
|
418
|
-
);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
if (filters.txid) {
|
|
422
|
-
transactionHistory = transactionHistory.filter(
|
|
423
|
-
(transaction) => transaction.txid === filters.txid
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
if (filters.reference) {
|
|
428
|
-
transactionHistory = transactionHistory.filter(
|
|
429
|
-
(transaction) => transaction.reference === filters.reference
|
|
430
|
-
);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
if (filters.date_from) {
|
|
434
|
-
transactionHistory = transactionHistory.filter(
|
|
435
|
-
(transaction) =>
|
|
436
|
-
new Date(transaction.timestamp) >= new Date(filters.date_from)
|
|
437
|
-
);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
if (filters.date_to) {
|
|
441
|
-
transactionHistory = transactionHistory.filter(
|
|
442
|
-
(transaction) =>
|
|
443
|
-
new Date(transaction.timestamp) <= new Date(filters.date_to)
|
|
444
|
-
);
|
|
445
|
-
}
|
|
446
|
-
return transactionHistory;
|
|
44
|
+
return await transactionService.getTransactionHistory(strapi, filters);
|
|
447
45
|
},
|
|
448
46
|
|
|
47
|
+
// Test connection
|
|
449
48
|
async testConnection() {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
if (!settings || !settings.aid || !settings.portalid || !settings.key) {
|
|
454
|
-
return {
|
|
455
|
-
success: false,
|
|
456
|
-
message:
|
|
457
|
-
"Payone settings not configured. Please fill in all required fields."
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
const timestamp = Date.now();
|
|
462
|
-
const testParams = {
|
|
463
|
-
request: "authorization",
|
|
464
|
-
amount: 100,
|
|
465
|
-
currency: "EUR",
|
|
466
|
-
reference: `TEST-${timestamp}`, // Unique reference for each test
|
|
467
|
-
clearingtype: "cc",
|
|
468
|
-
cardtype: "V",
|
|
469
|
-
cardpan: "4111111111111111",
|
|
470
|
-
cardexpiredate: "2512",
|
|
471
|
-
cardcvc2: "123",
|
|
472
|
-
firstname: "Test",
|
|
473
|
-
lastname: "User",
|
|
474
|
-
street: "Test Street 1",
|
|
475
|
-
zip: "12345",
|
|
476
|
-
city: "Test City",
|
|
477
|
-
country: "DE",
|
|
478
|
-
email: "test@example.com",
|
|
479
|
-
salutation: "Herr",
|
|
480
|
-
gender: "m",
|
|
481
|
-
telephonenumber: "01752345678",
|
|
482
|
-
ip: "127.0.0.1",
|
|
483
|
-
customer_is_present: "yes",
|
|
484
|
-
language: "de"
|
|
485
|
-
};
|
|
486
|
-
|
|
487
|
-
const originalSendRequest = this.sendRequest.bind(this);
|
|
488
|
-
this.sendRequest = async (params) => {
|
|
489
|
-
try {
|
|
490
|
-
const settings = await this.getSettings();
|
|
491
|
-
|
|
492
|
-
if (
|
|
493
|
-
!settings ||
|
|
494
|
-
!settings.aid ||
|
|
495
|
-
!settings.portalid ||
|
|
496
|
-
!settings.key
|
|
497
|
-
) {
|
|
498
|
-
throw new Error("Payone settings not configured");
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
const requestParams = buildClientRequestParams(settings, params);
|
|
502
|
-
const formData = toFormData(requestParams);
|
|
503
|
-
|
|
504
|
-
// Send request to Payone
|
|
505
|
-
const response = await axios.post(POST_GATEWAY_URL, formData, {
|
|
506
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
507
|
-
timeout: 30000
|
|
508
|
-
});
|
|
509
|
-
const responseData = this.parseResponse(response.data);
|
|
510
|
-
|
|
511
|
-
return responseData;
|
|
512
|
-
} catch (error) {
|
|
513
|
-
strapi.log.error("Payone API request failed:", error.message);
|
|
514
|
-
|
|
515
|
-
if (error.response) {
|
|
516
|
-
strapi.log.error("Response error:", {
|
|
517
|
-
status: error.response.status,
|
|
518
|
-
data: error.response.data
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
throw error;
|
|
523
|
-
}
|
|
524
|
-
};
|
|
525
|
-
|
|
526
|
-
const result = await this.sendRequest(testParams);
|
|
527
|
-
|
|
528
|
-
this.sendRequest = originalSendRequest;
|
|
529
|
-
|
|
530
|
-
const status = result.status || result.Status || result.STATUS;
|
|
531
|
-
const errorMessage =
|
|
532
|
-
result.errormessage ||
|
|
533
|
-
result.Errormessage ||
|
|
534
|
-
result.ERRORMESSAGE ||
|
|
535
|
-
result.error ||
|
|
536
|
-
result.Error ||
|
|
537
|
-
result.ERROR ||
|
|
538
|
-
"";
|
|
539
|
-
const errorCode =
|
|
540
|
-
result.errorcode ||
|
|
541
|
-
result.Errorcode ||
|
|
542
|
-
result.ERRORCODE ||
|
|
543
|
-
(result.Error && result.Error.ErrorCode) ||
|
|
544
|
-
"";
|
|
545
|
-
const customErrorMessage =
|
|
546
|
-
result.customerrormessage ||
|
|
547
|
-
result.Customerrormessage ||
|
|
548
|
-
result.CUSTOMERRORMESSAGE ||
|
|
549
|
-
(result.Error && result.Error.CustomerMessage) ||
|
|
550
|
-
"";
|
|
551
|
-
|
|
552
|
-
strapi.log.info("Payone test connection response:", {
|
|
553
|
-
status,
|
|
554
|
-
errorCode,
|
|
555
|
-
keys: Object.keys(result)
|
|
556
|
-
});
|
|
557
|
-
|
|
558
|
-
if (status === "ERROR" || status === "error") {
|
|
559
|
-
// First check for authentication errors (including "Key incorrect")
|
|
560
|
-
if (
|
|
561
|
-
errorCode === "2006" ||
|
|
562
|
-
errorCode === "920" ||
|
|
563
|
-
errorCode === "921" ||
|
|
564
|
-
errorCode === "922" ||
|
|
565
|
-
errorCode === "401" || // common unauthorized style codes
|
|
566
|
-
errorCode === "403"
|
|
567
|
-
) {
|
|
568
|
-
const errorMsg =
|
|
569
|
-
customErrorMessage ||
|
|
570
|
-
(typeof errorMessage === "string"
|
|
571
|
-
? errorMessage
|
|
572
|
-
: JSON.stringify(errorMessage)) ||
|
|
573
|
-
"Invalid credentials";
|
|
574
|
-
return {
|
|
575
|
-
success: false,
|
|
576
|
-
message: `Authentication failed: ${errorMsg}`,
|
|
577
|
-
errorcode: errorCode
|
|
578
|
-
};
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// Additional heuristic for invalid credentials based on message content
|
|
582
|
-
const errorMessageStr =
|
|
583
|
-
typeof errorMessage === "string"
|
|
584
|
-
? errorMessage
|
|
585
|
-
: JSON.stringify(errorMessage);
|
|
586
|
-
const errorMessageLower = (errorMessageStr || "").toLowerCase();
|
|
587
|
-
if (
|
|
588
|
-
errorMessageLower.includes("key incorrect") ||
|
|
589
|
-
errorMessageLower.includes("invalid key") ||
|
|
590
|
-
errorMessageLower.includes("portal key") ||
|
|
591
|
-
errorMessageLower.includes("unauthorized") ||
|
|
592
|
-
errorMessageLower.includes("not authorized") ||
|
|
593
|
-
errorMessageLower.includes("unknown aid") ||
|
|
594
|
-
errorMessageLower.includes("unknown account") ||
|
|
595
|
-
errorMessageLower.includes("unknown portal") ||
|
|
596
|
-
errorMessageLower.includes("unknown merchant") ||
|
|
597
|
-
errorMessageLower.includes("invalid aid") ||
|
|
598
|
-
errorMessageLower.includes("invalid mid") ||
|
|
599
|
-
errorMessageLower.includes("invalid portalid")
|
|
600
|
-
) {
|
|
601
|
-
return {
|
|
602
|
-
success: false,
|
|
603
|
-
message: `Authentication failed: ${errorMessageStr}`,
|
|
604
|
-
errorcode: errorCode || "AUTH"
|
|
605
|
-
};
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
// Check for reference already exists (911) - this means credentials are working
|
|
609
|
-
if (errorCode === "911") {
|
|
610
|
-
return {
|
|
611
|
-
success: true,
|
|
612
|
-
message:
|
|
613
|
-
"Connection successful! Your Payone credentials are valid.",
|
|
614
|
-
details: {
|
|
615
|
-
mode: settings.mode,
|
|
616
|
-
aid: settings.aid,
|
|
617
|
-
portalid: settings.portalid,
|
|
618
|
-
mid: settings.mid
|
|
619
|
-
}
|
|
620
|
-
};
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
// Otherwise, for any ERROR status treat as failure
|
|
624
|
-
const errorMsg =
|
|
625
|
-
customErrorMessage ||
|
|
626
|
-
(typeof errorMessage === "string"
|
|
627
|
-
? errorMessage
|
|
628
|
-
: JSON.stringify(errorMessage)) ||
|
|
629
|
-
"Unknown error";
|
|
630
|
-
return {
|
|
631
|
-
success: false,
|
|
632
|
-
message: `Connection failed: ${errorMsg}`,
|
|
633
|
-
errorcode: errorCode,
|
|
634
|
-
details: {
|
|
635
|
-
status,
|
|
636
|
-
errorCode,
|
|
637
|
-
rawResponse: JSON.stringify(result).substring(0, 200) // Include partial raw response for debugging
|
|
638
|
-
}
|
|
639
|
-
};
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
// APPROVED status shouldn't happen with dummy txid, but if it does, connection is OK
|
|
643
|
-
if (status === "APPROVED" || status === "approved") {
|
|
644
|
-
return {
|
|
645
|
-
success: true,
|
|
646
|
-
message: "Connection successful! Your Payone credentials are valid.",
|
|
647
|
-
details: {
|
|
648
|
-
mode: settings.mode,
|
|
649
|
-
aid: settings.aid,
|
|
650
|
-
portalid: settings.portalid,
|
|
651
|
-
mid: settings.mid
|
|
652
|
-
}
|
|
653
|
-
};
|
|
654
|
-
}
|
|
49
|
+
return await testConnectionService.testConnection(strapi);
|
|
50
|
+
},
|
|
655
51
|
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
response: result,
|
|
660
|
-
details: {
|
|
661
|
-
status,
|
|
662
|
-
keys: Object.keys(result),
|
|
663
|
-
rawResponse: JSON.stringify(result).substring(0, 200)
|
|
664
|
-
}
|
|
665
|
-
};
|
|
666
|
-
} catch (error) {
|
|
667
|
-
strapi.log.error("Payone test connection error:", error);
|
|
668
|
-
return {
|
|
669
|
-
success: false,
|
|
670
|
-
message: `Connection error: ${error.message || "Unknown error"}`,
|
|
671
|
-
error: error.toString(),
|
|
672
|
-
details: {
|
|
673
|
-
errorType: error.constructor.name,
|
|
674
|
-
stack: error.stack ? error.stack.substring(0, 200) : "No stack trace"
|
|
675
|
-
}
|
|
676
|
-
};
|
|
677
|
-
}
|
|
52
|
+
// 3D Secure callback handler
|
|
53
|
+
async handle3DSCallback(callbackData) {
|
|
54
|
+
return await paymentService.handle3DSCallback(strapi, callbackData);
|
|
678
55
|
}
|
|
679
56
|
});
|