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.
Files changed (38) hide show
  1. package/README.md +1156 -380
  2. package/admin/src/index.js +4 -1
  3. package/admin/src/pages/App/components/AppHeader.js +37 -0
  4. package/admin/src/pages/App/components/AppTabs.js +134 -0
  5. package/admin/src/pages/App/components/ConfigurationPanel.js +34 -35
  6. package/admin/src/pages/App/components/GooglePaybutton.js +300 -0
  7. package/admin/src/pages/App/components/HistoryPanel.js +25 -38
  8. package/admin/src/pages/App/components/PaymentActionsPanel.js +119 -280
  9. package/admin/src/pages/App/components/StatusBadge.js +3 -1
  10. package/admin/src/pages/App/components/TransactionHistoryItem.js +4 -1
  11. package/admin/src/pages/App/components/paymentActions/AuthorizationForm.js +122 -0
  12. package/admin/src/pages/App/components/paymentActions/CaptureForm.js +64 -0
  13. package/admin/src/pages/App/components/paymentActions/CardDetailsInput.js +189 -0
  14. package/admin/src/pages/App/components/paymentActions/PaymentMethodSelector.js +52 -0
  15. package/admin/src/pages/App/components/paymentActions/PaymentResult.js +148 -0
  16. package/admin/src/pages/App/components/paymentActions/PreauthorizationForm.js +122 -0
  17. package/admin/src/pages/App/components/paymentActions/RefundForm.js +89 -0
  18. package/admin/src/pages/App/index.js +41 -465
  19. package/admin/src/pages/App/styles.css +294 -0
  20. package/admin/src/pages/constants/paymentConstants.js +37 -0
  21. package/admin/src/pages/hooks/usePaymentActions.js +456 -0
  22. package/admin/src/pages/hooks/useSettings.js +111 -0
  23. package/admin/src/pages/hooks/useTransactionHistory.js +87 -0
  24. package/admin/src/pages/utils/api.js +10 -0
  25. package/admin/src/pages/utils/injectGooglePayScript.js +31 -0
  26. package/admin/src/pages/utils/paymentUtils.js +119 -15
  27. package/package.json +1 -1
  28. package/server/controllers/payone.js +71 -64
  29. package/server/routes/index.js +17 -0
  30. package/server/services/paymentService.js +271 -0
  31. package/server/services/payone.js +25 -648
  32. package/server/services/settingsService.js +59 -0
  33. package/server/services/testConnectionService.js +190 -0
  34. package/server/services/transactionService.js +114 -0
  35. package/server/utils/normalize.js +51 -0
  36. package/server/utils/paymentMethodParams.js +126 -0
  37. package/server/utils/requestBuilder.js +121 -0
  38. 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
+