strapi-plugin-payone-provider 1.1.3 → 1.3.0
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 +1156 -380
- 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 +134 -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 +119 -280
- package/admin/src/pages/App/components/StatusBadge.js +3 -1
- package/admin/src/pages/App/components/TransactionHistoryItem.js +4 -1
- package/admin/src/pages/App/components/paymentActions/AuthorizationForm.js +122 -0
- package/admin/src/pages/App/components/paymentActions/CaptureForm.js +64 -0
- package/admin/src/pages/App/components/paymentActions/CardDetailsInput.js +189 -0
- package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.js +52 -0
- package/admin/src/pages/App/components/paymentActions/PaymentResult.js +148 -0
- package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.js +122 -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 +456 -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 +119 -15
- package/package.json +1 -1
- package/server/controllers/payone.js +71 -64
- package/server/routes/index.js +17 -0
- package/server/services/paymentService.js +271 -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 +121 -0
- package/server/utils/responseParser.js +134 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const axios = require("axios");
|
|
4
|
+
const { normalizeReference } = require("../utils/normalize");
|
|
5
|
+
const { buildClientRequestParams, toFormData } = require("../utils/requestBuilder");
|
|
6
|
+
const { addPaymentMethodParams } = require("../utils/paymentMethodParams");
|
|
7
|
+
const { parseResponse, extractTxId, requires3DSRedirect, get3DSRedirectUrl } = require("../utils/responseParser");
|
|
8
|
+
const { getSettings, validateSettings } = require("./settingsService");
|
|
9
|
+
const { logTransaction } = require("./transactionService");
|
|
10
|
+
|
|
11
|
+
const POST_GATEWAY_URL = "https://api.pay1.de/post-gateway/";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Send request to Payone API
|
|
15
|
+
* @param {Object} strapi - Strapi instance
|
|
16
|
+
* @param {Object} params - Request parameters
|
|
17
|
+
* @returns {Promise<Object>} Response data
|
|
18
|
+
*/
|
|
19
|
+
const sendRequest = async (strapi, params) => {
|
|
20
|
+
try {
|
|
21
|
+
const settings = await getSettings(strapi);
|
|
22
|
+
|
|
23
|
+
if (!validateSettings(settings)) {
|
|
24
|
+
throw new Error("Payone settings not configured");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const reqType = params.request;
|
|
28
|
+
if (["authorization", "preauthorization", "refund"].includes(reqType)) {
|
|
29
|
+
const prefix =
|
|
30
|
+
reqType === "refund" ? "REF" : reqType === "preauthorization" ? "PRE" : "AUTH";
|
|
31
|
+
params.reference = normalizeReference(params.reference, prefix);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const requestParams = buildClientRequestParams(settings, params, strapi.log);
|
|
35
|
+
const formData = toFormData(requestParams);
|
|
36
|
+
|
|
37
|
+
const response = await axios.post(POST_GATEWAY_URL, formData, {
|
|
38
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
39
|
+
timeout: 30000
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const responseData = parseResponse(response.data, strapi.log);
|
|
43
|
+
|
|
44
|
+
// Log full response for debugging
|
|
45
|
+
strapi.log.info("Payone API Response:", JSON.stringify(responseData, null, 2));
|
|
46
|
+
strapi.log.info("Response Status:", responseData.status || responseData.Status);
|
|
47
|
+
strapi.log.info("Response Error Code:", responseData.errorcode || responseData.ErrorCode || responseData.Error?.ErrorCode);
|
|
48
|
+
strapi.log.info("Response Error Message:", responseData.errormessage || responseData.ErrorMessage || responseData.Error?.ErrorMessage);
|
|
49
|
+
|
|
50
|
+
// Log all possible redirect URL fields
|
|
51
|
+
strapi.log.info("Redirect URL fields:", {
|
|
52
|
+
redirecturl: responseData.redirecturl,
|
|
53
|
+
RedirectUrl: responseData.RedirectUrl,
|
|
54
|
+
redirect_url: responseData.redirect_url,
|
|
55
|
+
redirectUrl: responseData.redirectUrl,
|
|
56
|
+
url: responseData.url,
|
|
57
|
+
Url: responseData.Url
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Extract error information from various possible fields
|
|
61
|
+
const errorCode =
|
|
62
|
+
responseData.errorcode ||
|
|
63
|
+
responseData.ErrorCode ||
|
|
64
|
+
responseData.Error?.ErrorCode ||
|
|
65
|
+
responseData.error_code ||
|
|
66
|
+
null;
|
|
67
|
+
|
|
68
|
+
// Check for 3DS redirect
|
|
69
|
+
const requires3DSErrorCodes = ["4219", 4219];
|
|
70
|
+
const is3DSRequiredError = requires3DSErrorCodes.includes(errorCode);
|
|
71
|
+
|
|
72
|
+
if (requires3DSRedirect(responseData) || is3DSRequiredError) {
|
|
73
|
+
const redirectUrl = get3DSRedirectUrl(responseData);
|
|
74
|
+
responseData.requires3DSRedirect = true;
|
|
75
|
+
responseData.redirectUrl = redirectUrl;
|
|
76
|
+
responseData.is3DSRequired = is3DSRequiredError;
|
|
77
|
+
|
|
78
|
+
// If 3DS required but no redirect URL, log for debugging
|
|
79
|
+
if (is3DSRequiredError && !redirectUrl) {
|
|
80
|
+
strapi.log.warn("3DS authentication required (Error 4219) but no redirect URL found. May need 3dscheck request.");
|
|
81
|
+
strapi.log.info("Full response data:", JSON.stringify(responseData, null, 2));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const errorMessage =
|
|
86
|
+
responseData.errormessage ||
|
|
87
|
+
responseData.ErrorMessage ||
|
|
88
|
+
responseData.Error?.ErrorMessage ||
|
|
89
|
+
responseData.error_message ||
|
|
90
|
+
null;
|
|
91
|
+
|
|
92
|
+
const customerMessage =
|
|
93
|
+
responseData.customermessage ||
|
|
94
|
+
responseData.CustomerMessage ||
|
|
95
|
+
responseData.Error?.CustomerMessage ||
|
|
96
|
+
responseData.customer_message ||
|
|
97
|
+
null;
|
|
98
|
+
|
|
99
|
+
const status = (responseData.status || responseData.Status || "unknown").toUpperCase();
|
|
100
|
+
|
|
101
|
+
// Log transaction
|
|
102
|
+
await logTransaction(strapi, {
|
|
103
|
+
txid: extractTxId(responseData) || params.txid || null,
|
|
104
|
+
reference: params.reference || null,
|
|
105
|
+
status: status,
|
|
106
|
+
request_type: params.request,
|
|
107
|
+
amount: params.amount || null,
|
|
108
|
+
currency: params.currency || "EUR",
|
|
109
|
+
raw_request: requestParams,
|
|
110
|
+
raw_response: responseData,
|
|
111
|
+
error_code: errorCode,
|
|
112
|
+
error_message: errorMessage,
|
|
113
|
+
customer_message: customerMessage
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Add normalized error fields to response
|
|
117
|
+
responseData.errorCode = errorCode;
|
|
118
|
+
responseData.errorMessage = errorMessage;
|
|
119
|
+
responseData.customerMessage = customerMessage;
|
|
120
|
+
responseData.status = status;
|
|
121
|
+
|
|
122
|
+
return responseData;
|
|
123
|
+
} catch (error) {
|
|
124
|
+
strapi.log.error("Payone sendRequest error:", error);
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Preauthorization
|
|
131
|
+
* @param {Object} strapi - Strapi instance
|
|
132
|
+
* @param {Object} params - Request parameters
|
|
133
|
+
* @returns {Promise<Object>} Response data
|
|
134
|
+
*/
|
|
135
|
+
const preauthorization = async (strapi, params) => {
|
|
136
|
+
const requiredParams = {
|
|
137
|
+
request: "preauthorization",
|
|
138
|
+
clearingtype: params.clearingtype || "cc",
|
|
139
|
+
amount: params.amount || 1000,
|
|
140
|
+
currency: params.currency || "EUR",
|
|
141
|
+
reference: params.reference || `PREAUTH-${Date.now()}`,
|
|
142
|
+
firstname: params.firstname || "Test",
|
|
143
|
+
lastname: params.lastname || "User",
|
|
144
|
+
street: params.street || "Test Street 1",
|
|
145
|
+
zip: params.zip || "12345",
|
|
146
|
+
city: params.city || "Test City",
|
|
147
|
+
country: params.country || "DE",
|
|
148
|
+
email: params.email || "test@example.com",
|
|
149
|
+
...params
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const updatedParams = addPaymentMethodParams(requiredParams, strapi.log);
|
|
153
|
+
return await sendRequest(strapi, updatedParams);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Authorization
|
|
158
|
+
* @param {Object} strapi - Strapi instance
|
|
159
|
+
* @param {Object} params - Request parameters
|
|
160
|
+
* @returns {Promise<Object>} Response data
|
|
161
|
+
*/
|
|
162
|
+
const authorization = async (strapi, params) => {
|
|
163
|
+
const requiredParams = {
|
|
164
|
+
request: "authorization",
|
|
165
|
+
clearingtype: params.clearingtype || "cc",
|
|
166
|
+
...params
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const updatedParams = addPaymentMethodParams(requiredParams, strapi.log);
|
|
170
|
+
return await sendRequest(strapi, updatedParams);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Capture
|
|
175
|
+
* @param {Object} strapi - Strapi instance
|
|
176
|
+
* @param {Object} params - Request parameters
|
|
177
|
+
* @returns {Promise<Object>} Response data
|
|
178
|
+
*/
|
|
179
|
+
const capture = async (strapi, params) => {
|
|
180
|
+
if (!params.txid) {
|
|
181
|
+
throw new Error("Transaction ID (txid) is required for capture");
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const requiredParams = {
|
|
185
|
+
request: "capture",
|
|
186
|
+
txid: params.txid,
|
|
187
|
+
amount: params.amount || 1000,
|
|
188
|
+
currency: params.currency || "EUR",
|
|
189
|
+
...params
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
delete requiredParams.reference;
|
|
193
|
+
return await sendRequest(strapi, requiredParams);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Refund
|
|
198
|
+
* @param {Object} strapi - Strapi instance
|
|
199
|
+
* @param {Object} params - Request parameters
|
|
200
|
+
* @returns {Promise<Object>} Response data
|
|
201
|
+
*/
|
|
202
|
+
const refund = async (strapi, params) => {
|
|
203
|
+
if (!params.txid) {
|
|
204
|
+
throw new Error("Transaction ID (txid) is required for refund");
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const requiredParams = {
|
|
208
|
+
request: "refund",
|
|
209
|
+
txid: params.txid,
|
|
210
|
+
amount: params.amount || 1000,
|
|
211
|
+
currency: params.currency || "EUR",
|
|
212
|
+
reference: params.reference || `REFUND-${Date.now()}`,
|
|
213
|
+
...params
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
return await sendRequest(strapi, requiredParams);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Handle 3D Secure callback from Payone
|
|
221
|
+
* This processes the callback after customer completes 3DS authentication
|
|
222
|
+
* @param {Object} strapi - Strapi instance
|
|
223
|
+
* @param {Object} callbackData - Callback data from Payone
|
|
224
|
+
* @returns {Promise<Object>} Processed callback result
|
|
225
|
+
*/
|
|
226
|
+
const handle3DSCallback = async (strapi, callbackData) => {
|
|
227
|
+
try {
|
|
228
|
+
const parsedData = parseResponse(callbackData, strapi.log);
|
|
229
|
+
|
|
230
|
+
// Extract transaction information
|
|
231
|
+
const txid = extractTxId(parsedData);
|
|
232
|
+
const status = parsedData.status || parsedData.Status || "unknown";
|
|
233
|
+
const reference = parsedData.reference || parsedData.Reference || null;
|
|
234
|
+
|
|
235
|
+
// Log the callback transaction
|
|
236
|
+
await logTransaction(strapi, {
|
|
237
|
+
txid: txid || null,
|
|
238
|
+
reference: reference || null,
|
|
239
|
+
status: status,
|
|
240
|
+
request_type: "3ds_callback",
|
|
241
|
+
amount: parsedData.amount || null,
|
|
242
|
+
currency: parsedData.currency || "EUR",
|
|
243
|
+
raw_request: callbackData,
|
|
244
|
+
raw_response: parsedData,
|
|
245
|
+
error_code: parsedData.Error?.ErrorCode || null,
|
|
246
|
+
error_message: parsedData.Error?.ErrorMessage || null,
|
|
247
|
+
customer_message: parsedData.Error?.CustomerMessage || null
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
success: status.toUpperCase() === "APPROVED" || status.toUpperCase() === "REDIRECT",
|
|
252
|
+
status: status,
|
|
253
|
+
txid: txid,
|
|
254
|
+
reference: reference,
|
|
255
|
+
data: parsedData
|
|
256
|
+
};
|
|
257
|
+
} catch (error) {
|
|
258
|
+
strapi.log.error("3DS callback processing error:", error);
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
module.exports = {
|
|
264
|
+
sendRequest,
|
|
265
|
+
preauthorization,
|
|
266
|
+
authorization,
|
|
267
|
+
capture,
|
|
268
|
+
refund,
|
|
269
|
+
handle3DSCallback
|
|
270
|
+
};
|
|
271
|
+
|