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.
Files changed (83) hide show
  1. package/README.md +1191 -1191
  2. package/admin/src/components/Initializer/index.jsx +16 -16
  3. package/admin/src/components/PluginIcon/index.jsx +17 -17
  4. package/admin/src/index.js +57 -57
  5. package/admin/src/pages/App/components/AppHeader.jsx +45 -45
  6. package/admin/src/pages/App/components/AppTabs.jsx +105 -105
  7. package/admin/src/pages/App/components/ApplePayBtn.jsx +355 -355
  8. package/admin/src/pages/App/components/ApplePayConfig.jsx +357 -357
  9. package/admin/src/pages/App/components/DocsPanel.jsx +53 -53
  10. package/admin/src/pages/App/components/RenderInput.jsx +78 -78
  11. package/admin/src/pages/App/components/StatusBadge.jsx +87 -87
  12. package/admin/src/pages/App/components/icons/BankIcon.jsx +10 -10
  13. package/admin/src/pages/App/components/icons/ChevronDownIcon.jsx +9 -9
  14. package/admin/src/pages/App/components/icons/ChevronUpIcon.jsx +9 -9
  15. package/admin/src/pages/App/components/icons/CreditCardIcon.jsx +9 -9
  16. package/admin/src/pages/App/components/icons/ErrorIcon.jsx +10 -10
  17. package/admin/src/pages/App/components/icons/InfoIcon.jsx +9 -9
  18. package/admin/src/pages/App/components/icons/MarkCircle.jsx +19 -19
  19. package/admin/src/pages/App/components/icons/PaymentIcon.jsx +10 -10
  20. package/admin/src/pages/App/components/icons/PendingIcon.jsx +9 -9
  21. package/admin/src/pages/App/components/icons/PersonIcon.jsx +9 -9
  22. package/admin/src/pages/App/components/icons/SuccessIcon.jsx +9 -9
  23. package/admin/src/pages/App/components/icons/WalletIcon.jsx +9 -9
  24. package/admin/src/pages/App/components/icons/index.jsx +12 -12
  25. package/admin/src/pages/App/components/payment-actions/AuthorizationForm.jsx +334 -334
  26. package/admin/src/pages/App/components/payment-actions/CaptureForm.jsx +120 -120
  27. package/admin/src/pages/App/components/payment-actions/PaymentActionsPanel.jsx +183 -183
  28. package/admin/src/pages/App/components/payment-actions/PaymentMethodSelector.jsx +315 -315
  29. package/admin/src/pages/App/components/payment-actions/PaymentResult.jsx +129 -129
  30. package/admin/src/pages/App/components/payment-actions/PreauthorizationForm.jsx +273 -273
  31. package/admin/src/pages/App/components/payment-actions/RefundForm.jsx +114 -114
  32. package/admin/src/pages/App/components/transaction-history/ImportExportBar.jsx +153 -153
  33. package/admin/src/pages/App/components/transaction-history/details/TransactionHistoryItem.jsx +526 -526
  34. package/admin/src/pages/App/index.jsx +96 -96
  35. package/admin/src/pages/App/styles.css +176 -176
  36. package/admin/src/pages/constants/paymentConstants.js +71 -71
  37. package/admin/src/pages/hooks/use-system-theme.js +27 -27
  38. package/admin/src/pages/hooks/usePaymentActions.js +498 -498
  39. package/admin/src/pages/hooks/usePluginTranslations.js +12 -12
  40. package/admin/src/pages/hooks/useSettings.js +183 -183
  41. package/admin/src/pages/hooks/useTransactionHistory.js +148 -148
  42. package/admin/src/pages/utils/api.js +97 -97
  43. package/admin/src/pages/utils/applePayConstants.js +196 -196
  44. package/admin/src/pages/utils/formatTransactionData.js +15 -15
  45. package/admin/src/pages/utils/getInputComponent.jsx +200 -200
  46. package/admin/src/pages/utils/paymentUtils.js +661 -661
  47. package/admin/src/pages/utils/tooltipHelpers.js +18 -18
  48. package/admin/src/pages/utils/transactionTableUtils.js +71 -71
  49. package/admin/src/pluginId.js +9 -9
  50. package/admin/src/translations/de.json +235 -235
  51. package/admin/src/translations/en.json +235 -235
  52. package/admin/src/translations/fr.json +235 -235
  53. package/admin/src/translations/ru.json +235 -235
  54. package/admin/src/utils/prefixPluginTranslations.js +13 -13
  55. package/package.json +45 -45
  56. package/server/bootstrap.js +107 -107
  57. package/server/config/index.js +83 -83
  58. package/server/content-types/index.js +4 -4
  59. package/server/content-types/transactions/index.js +4 -4
  60. package/server/content-types/transactions/schema.json +86 -86
  61. package/server/controllers/index.js +7 -7
  62. package/server/controllers/payone.js +503 -506
  63. package/server/destroy.js +5 -5
  64. package/server/index.js +23 -23
  65. package/server/policies/index.js +7 -7
  66. package/server/policies/is-auth.js +29 -29
  67. package/server/policies/isSuperAdmin.js +20 -20
  68. package/server/register.js +5 -5
  69. package/server/routes/index.js +218 -218
  70. package/server/services/applePayService.js +295 -295
  71. package/server/services/index.js +9 -9
  72. package/server/services/paymentService.js +264 -223
  73. package/server/services/payone.js +78 -78
  74. package/server/services/settingsService.js +59 -59
  75. package/server/services/testConnectionService.js +115 -115
  76. package/server/services/transactionService.js +262 -262
  77. package/server/utils/csvTransactions.js +82 -82
  78. package/server/utils/normalize.js +39 -39
  79. package/server/utils/paymentMethodParams.js +288 -288
  80. package/server/utils/requestBuilder.js +115 -100
  81. package/server/utils/responseParser.js +141 -141
  82. package/strapi-admin.js +4 -4
  83. package/strapi-server.js +3 -3
@@ -1,295 +1,295 @@
1
- "use strict";
2
-
3
- const axios = require("axios");
4
- const { buildClientRequestParams, toFormData } = require("../utils/requestBuilder");
5
- const { getSettings, validateSettings } = require("./settingsService");
6
-
7
- const POST_GATEWAY_URL = "https://api.pay1.de/post-gateway/";
8
-
9
- const parseResponse = (responseData) => {
10
- if (typeof responseData === 'string') {
11
- if (responseData.trim().startsWith('{')) {
12
- try {
13
- return JSON.parse(responseData);
14
- } catch (e) {
15
- // Fall through to URL-encoded parsing
16
- }
17
- }
18
-
19
- const params = new URLSearchParams(responseData);
20
- const parsed = {};
21
- for (const [key, value] of params.entries()) {
22
- parsed[key] = value;
23
- const normalizedKey = key.toLowerCase().replace(/\[/g, '_').replace(/\]/g, '');
24
- if (normalizedKey !== key.toLowerCase()) {
25
- parsed[normalizedKey] = value;
26
- }
27
- }
28
- return parsed;
29
- }
30
-
31
- if (typeof responseData === 'object' && responseData !== null) {
32
- const result = { ...responseData };
33
- if (result['add_paydata[applepay_payment_session]']) {
34
- result.add_paydata = result.add_paydata || {};
35
- result.add_paydata.applepay_payment_session = result['add_paydata[applepay_payment_session]'];
36
- }
37
- return result;
38
- }
39
-
40
- return responseData;
41
- };
42
-
43
- const initializeApplePaySession = async (strapi, params) => {
44
- let settings = null;
45
- try {
46
- settings = await getSettings(strapi);
47
-
48
- const validationErrors = [];
49
-
50
- if (!settings.aid || settings.aid.trim() === "") {
51
- validationErrors.push("aid (Subaccount ID) is missing or empty");
52
- }
53
- if (!settings.portalid || settings.portalid.trim() === "") {
54
- validationErrors.push("portalid (Portal ID) is missing or empty");
55
- }
56
- if (!settings.mid || settings.mid.trim() === "") {
57
- validationErrors.push("mid (Merchant ID) is missing or empty");
58
- }
59
- if (!settings.key || settings.key.trim() === "") {
60
- validationErrors.push("key (Portal Key) is missing or empty");
61
- }
62
-
63
- const mode = (settings.mode || "test").toLowerCase();
64
- if (mode !== "live") {
65
- validationErrors.push(`Mode is set to "${mode}" but Apple Pay only works in "live" mode according to Payone documentation`);
66
- }
67
-
68
- const applePayConfig = settings?.applePayConfig || {};
69
- const currency = params.currency || applePayConfig.currencyCode || "EUR";
70
- const merchantName = params.displayName || settings?.merchantName || "Store";
71
- const domain = params.domain || params.domainName || "localhost";
72
-
73
- const baseParams = {
74
- request: "genericpayment",
75
- clearingtype: "wlt",
76
- wallettype: "APL",
77
- currency: currency,
78
- "add_paydata[action]": "init_applepay_session",
79
- "add_paydata[display_name]": merchantName,
80
- "add_paydata[domain_name]": domain
81
- };
82
-
83
- const requestParams = buildClientRequestParams(settings, baseParams, strapi.log);
84
- const formData = toFormData(requestParams);
85
-
86
- const response = await axios.post(`${POST_GATEWAY_URL}Genericpayment`, formData, {
87
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
88
- timeout: 30000,
89
- validateStatus: function (status) {
90
- return status >= 200 && status < 600;
91
- }
92
- });
93
-
94
-
95
- if (response.status === 403) {
96
- const responseData = parseResponse(response.data);
97
- const errorCode = responseData.errorcode || responseData.ErrorCode;
98
- const errorMessage = responseData.errormessage || responseData.ErrorMessage || responseData.customermessage || responseData.CustomerMessage;
99
-
100
- strapi.log.error("[Apple Pay] 403 Forbidden from Payone:", {
101
- errorcode: errorCode,
102
- errormessage: errorMessage
103
- });
104
-
105
- const detailedError = new Error("403 Forbidden: Authentication failed with Payone API. " +
106
- (errorCode ? `Error Code: ${errorCode}. ` : "") +
107
- (errorMessage ? `Error: ${errorMessage}. ` : ""));
108
- Object.assign(detailedError, { status: 403, response: response });
109
- throw detailedError;
110
- }
111
-
112
- if (response.status >= 400 && response.status < 500) {
113
- const responseData = parseResponse(response.data);
114
- const errorCode = responseData.errorcode || responseData.ErrorCode;
115
- const errorMessage = responseData.errormessage || responseData.ErrorMessage || responseData.customermessage || responseData.CustomerMessage;
116
-
117
- strapi.log.error("[Apple Pay] Client error from Payone:", {
118
- status: response.status,
119
- errorcode: errorCode,
120
- errormessage: errorMessage
121
- });
122
-
123
- const detailedError = new Error(`Payone API error (${response.status}): ${errorMessage || 'Unknown error'}`);
124
- Object.assign(detailedError, { status: response.status, response: response });
125
- throw detailedError;
126
- }
127
-
128
- if (response.status >= 500) {
129
- strapi.log.error("[Apple Pay] Server error from Payone:", {
130
- status: response.status,
131
- statusText: response.statusText,
132
- data: response.data
133
- });
134
-
135
- const detailedError = new Error(`Payone server error (${response.status}): ${response.statusText || 'Internal server error'}`);
136
- Object.assign(detailedError, { status: response.status, response: response });
137
- throw detailedError;
138
- }
139
-
140
- const responseData = parseResponse(response.data);
141
-
142
- if (responseData.errorcode || responseData.ErrorCode) {
143
- strapi.log.error("[Apple Pay] Payone error:", {
144
- errorcode: responseData.errorcode || responseData.ErrorCode,
145
- errormessage: responseData.errormessage || responseData.ErrorMessage,
146
- customermessage: responseData.customermessage || responseData.CustomerMessage
147
- });
148
- }
149
-
150
- return responseData;
151
- } catch (error) {
152
- strapi.log.error("[Apple Pay] Error:", error instanceof Error ? error.message : error);
153
- throw error;
154
- }
155
- };
156
-
157
- const validateApplePayMerchant = async (strapi, params) => {
158
- try {
159
- const settings = await getSettings(strapi);
160
-
161
- if (!validateSettings(settings)) {
162
- throw new Error("Payone settings are not properly configured. Please check your plugin settings (aid, portalid, mid, key).");
163
- }
164
-
165
- const applePayConfig = settings?.applePayConfig || {};
166
-
167
- if (!params.currency && applePayConfig.currencyCode) {
168
- params.currency = applePayConfig.currencyCode;
169
- }
170
-
171
- if (!params.countryCode && applePayConfig.countryCode) {
172
- params.countryCode = applePayConfig.countryCode;
173
- }
174
-
175
- const sessionResponse = await initializeApplePaySession(strapi, params);
176
-
177
- // Extract add_paydata[applepay_payment_session] from response
178
- // Payone returns this in URL-encoded format: add_paydata[applepay_payment_session]=BASE64_STRING
179
- const applePaySessionBase64 =
180
- sessionResponse["add_paydata[applepay_payment_session]"] ||
181
- sessionResponse["add_paydata_applepay_payment_session"] ||
182
- sessionResponse.add_paydata?.applepay_payment_session ||
183
- (sessionResponse.add_paydata && typeof sessionResponse.add_paydata === 'object'
184
- ? sessionResponse.add_paydata["applepay_payment_session"]
185
- : null);
186
-
187
- strapi.log.info("[Apple Pay] Genericpayment response:", {
188
- status: sessionResponse.status,
189
- workorderid: sessionResponse.workorderid,
190
- hasApplePaySession: !!applePaySessionBase64,
191
- applePaySessionLength: applePaySessionBase64 ? applePaySessionBase64.length : 0,
192
- responseKeys: Object.keys(sessionResponse),
193
- hasAddPaydataKey: !!sessionResponse["add_paydata[applepay_payment_session]"],
194
- hasAddPaydataObject: !!sessionResponse.add_paydata,
195
- addPaydataKeys: sessionResponse.add_paydata ? Object.keys(sessionResponse.add_paydata) : null
196
- });
197
-
198
- if (!applePaySessionBase64) {
199
- strapi.log.error("[Apple Pay] Missing applepay_payment_session in response:", {
200
- status: sessionResponse.status,
201
- responseKeys: Object.keys(sessionResponse),
202
- responseSample: JSON.stringify(sessionResponse).substring(0, 1000),
203
- addPaydataKeys: sessionResponse.add_paydata ? Object.keys(sessionResponse.add_paydata) : null
204
- });
205
- throw new Error("Missing applepay_payment_session in Payone response. Please check your Payone Apple Pay configuration in PMI.");
206
- }
207
-
208
- if (sessionResponse.status === "OK" && applePaySessionBase64 && applePaySessionBase64.length > 0) {
209
- try {
210
- strapi.log.info("[Apple Pay] Extracting merchant session from Base64:", {
211
- base64Length: applePaySessionBase64.length,
212
- base64Preview: applePaySessionBase64.substring(0, 100) + "...",
213
- base64End: applePaySessionBase64.substring(Math.max(0, applePaySessionBase64.length - 50))
214
- });
215
-
216
- // Decode Base64 to get merchant session JSON
217
- let merchantSessionJson;
218
- try {
219
- merchantSessionJson = Buffer.from(applePaySessionBase64, 'base64').toString('utf-8');
220
- strapi.log.info("[Apple Pay] Base64 decoded successfully, JSON length:", merchantSessionJson.length);
221
- } catch (decodeError) {
222
- strapi.log.error("[Apple Pay] Failed to decode Base64:", {
223
- error: decodeError.message,
224
- base64Length: applePaySessionBase64.length
225
- });
226
- throw new Error(`Failed to decode Base64 merchant session: ${decodeError.message}`);
227
- }
228
-
229
- // Parse JSON merchant session
230
- let merchantSession;
231
- try {
232
- merchantSession = JSON.parse(merchantSessionJson);
233
- strapi.log.info("[Apple Pay] Merchant session JSON parsed successfully");
234
- } catch (parseError) {
235
- strapi.log.error("[Apple Pay] Failed to parse merchant session JSON:", {
236
- error: parseError.message,
237
- jsonPreview: merchantSessionJson.substring(0, 500)
238
- });
239
- throw new Error(`Failed to parse merchant session JSON: ${parseError.message}`);
240
- }
241
-
242
- strapi.log.info("[Apple Pay] Merchant session extracted successfully:", {
243
- hasMerchantIdentifier: !!merchantSession.merchantIdentifier,
244
- hasEpochTimestamp: !!merchantSession.epochTimestamp,
245
- hasExpiresAt: !!merchantSession.expiresAt,
246
- merchantSessionKeys: Object.keys(merchantSession)
247
- });
248
-
249
- if (merchantSession.epochTimestamp && merchantSession.epochTimestamp > 1000000000000) {
250
- merchantSession.epochTimestamp = Math.floor(merchantSession.epochTimestamp / 1000);
251
- }
252
-
253
- if (merchantSession.expiresAt && merchantSession.expiresAt > 1000000000000) {
254
- merchantSession.expiresAt = Math.floor(merchantSession.expiresAt / 1000);
255
- }
256
-
257
- if (!merchantSession.merchantIdentifier ||
258
- merchantSession.merchantIdentifier === 'undefined' ||
259
- merchantSession.merchantIdentifier === 'null') {
260
- merchantSession.merchantIdentifier = settings.mid || settings.merchantIdentifier || settings.portalid;
261
- }
262
-
263
- if (!merchantSession.merchantIdentifier) {
264
- throw new Error("Merchant identifier is missing. Please configure Merchant ID (mid) in plugin settings.");
265
- }
266
-
267
- return merchantSession;
268
- } catch (parseError) {
269
- throw new Error(`Failed to parse merchant session from Payone: ${parseError.message}`);
270
- }
271
- }
272
-
273
- const errorCode = sessionResponse.errorcode || sessionResponse.ErrorCode;
274
- const errorMessage = sessionResponse.errormessage || sessionResponse.ErrorMessage ||
275
- sessionResponse.errortxt || sessionResponse.ErrorTxt;
276
-
277
- strapi.log.error("[Apple Pay] Payone Apple Pay initialization failed:", {
278
- errorcode: errorCode,
279
- errormessage: errorMessage
280
- });
281
-
282
- throw new Error(
283
- `Payone Apple Pay initialization failed: ${errorCode ? `Error ${errorCode}` : 'Unknown error'} - ${errorMessage || 'Please check your Payone Apple Pay configuration in PMI'}`
284
- );
285
-
286
- } catch (error) {
287
- strapi.log.error("[Apple Pay] Error:", error instanceof Error ? error.message : error);
288
- throw error;
289
- }
290
- };
291
-
292
- module.exports = {
293
- initializeApplePaySession,
294
- validateApplePayMerchant
295
- };
1
+ "use strict";
2
+
3
+ const axios = require("axios");
4
+ const { buildClientRequestParams, toFormData } = require("../utils/requestBuilder");
5
+ const { getSettings, validateSettings } = require("./settingsService");
6
+
7
+ const POST_GATEWAY_URL = "https://api.pay1.de/post-gateway/";
8
+
9
+ const parseResponse = (responseData) => {
10
+ if (typeof responseData === 'string') {
11
+ if (responseData.trim().startsWith('{')) {
12
+ try {
13
+ return JSON.parse(responseData);
14
+ } catch (e) {
15
+ // Fall through to URL-encoded parsing
16
+ }
17
+ }
18
+
19
+ const params = new URLSearchParams(responseData);
20
+ const parsed = {};
21
+ for (const [key, value] of params.entries()) {
22
+ parsed[key] = value;
23
+ const normalizedKey = key.toLowerCase().replace(/\[/g, '_').replace(/\]/g, '');
24
+ if (normalizedKey !== key.toLowerCase()) {
25
+ parsed[normalizedKey] = value;
26
+ }
27
+ }
28
+ return parsed;
29
+ }
30
+
31
+ if (typeof responseData === 'object' && responseData !== null) {
32
+ const result = { ...responseData };
33
+ if (result['add_paydata[applepay_payment_session]']) {
34
+ result.add_paydata = result.add_paydata || {};
35
+ result.add_paydata.applepay_payment_session = result['add_paydata[applepay_payment_session]'];
36
+ }
37
+ return result;
38
+ }
39
+
40
+ return responseData;
41
+ };
42
+
43
+ const initializeApplePaySession = async (strapi, params) => {
44
+ let settings = null;
45
+ try {
46
+ settings = await getSettings(strapi);
47
+
48
+ const validationErrors = [];
49
+
50
+ if (!settings.aid || settings.aid.trim() === "") {
51
+ validationErrors.push("aid (Subaccount ID) is missing or empty");
52
+ }
53
+ if (!settings.portalid || settings.portalid.trim() === "") {
54
+ validationErrors.push("portalid (Portal ID) is missing or empty");
55
+ }
56
+ if (!settings.mid || settings.mid.trim() === "") {
57
+ validationErrors.push("mid (Merchant ID) is missing or empty");
58
+ }
59
+ if (!settings.key || settings.key.trim() === "") {
60
+ validationErrors.push("key (Portal Key) is missing or empty");
61
+ }
62
+
63
+ const mode = (settings.mode || "test").toLowerCase();
64
+ if (mode !== "live") {
65
+ validationErrors.push(`Mode is set to "${mode}" but Apple Pay only works in "live" mode according to Payone documentation`);
66
+ }
67
+
68
+ const applePayConfig = settings?.applePayConfig || {};
69
+ const currency = params.currency || applePayConfig.currencyCode || "EUR";
70
+ const merchantName = params.displayName || settings?.merchantName || "Store";
71
+ const domain = params.domain || params.domainName || "localhost";
72
+
73
+ const baseParams = {
74
+ request: "genericpayment",
75
+ clearingtype: "wlt",
76
+ wallettype: "APL",
77
+ currency: currency,
78
+ "add_paydata[action]": "init_applepay_session",
79
+ "add_paydata[display_name]": merchantName,
80
+ "add_paydata[domain_name]": domain
81
+ };
82
+
83
+ const requestParams = buildClientRequestParams(settings, baseParams, strapi.log);
84
+ const formData = toFormData(requestParams);
85
+
86
+ const response = await axios.post(`${POST_GATEWAY_URL}Genericpayment`, formData, {
87
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
88
+ timeout: 30000,
89
+ validateStatus: function (status) {
90
+ return status >= 200 && status < 600;
91
+ }
92
+ });
93
+
94
+
95
+ if (response.status === 403) {
96
+ const responseData = parseResponse(response.data);
97
+ const errorCode = responseData.errorcode || responseData.ErrorCode;
98
+ const errorMessage = responseData.errormessage || responseData.ErrorMessage || responseData.customermessage || responseData.CustomerMessage;
99
+
100
+ strapi.log.error("[Apple Pay] 403 Forbidden from Payone:", {
101
+ errorcode: errorCode,
102
+ errormessage: errorMessage
103
+ });
104
+
105
+ const detailedError = new Error("403 Forbidden: Authentication failed with Payone API. " +
106
+ (errorCode ? `Error Code: ${errorCode}. ` : "") +
107
+ (errorMessage ? `Error: ${errorMessage}. ` : ""));
108
+ Object.assign(detailedError, { status: 403, response: response });
109
+ throw detailedError;
110
+ }
111
+
112
+ if (response.status >= 400 && response.status < 500) {
113
+ const responseData = parseResponse(response.data);
114
+ const errorCode = responseData.errorcode || responseData.ErrorCode;
115
+ const errorMessage = responseData.errormessage || responseData.ErrorMessage || responseData.customermessage || responseData.CustomerMessage;
116
+
117
+ strapi.log.error("[Apple Pay] Client error from Payone:", {
118
+ status: response.status,
119
+ errorcode: errorCode,
120
+ errormessage: errorMessage
121
+ });
122
+
123
+ const detailedError = new Error(`Payone API error (${response.status}): ${errorMessage || 'Unknown error'}`);
124
+ Object.assign(detailedError, { status: response.status, response: response });
125
+ throw detailedError;
126
+ }
127
+
128
+ if (response.status >= 500) {
129
+ strapi.log.error("[Apple Pay] Server error from Payone:", {
130
+ status: response.status,
131
+ statusText: response.statusText,
132
+ data: response.data
133
+ });
134
+
135
+ const detailedError = new Error(`Payone server error (${response.status}): ${response.statusText || 'Internal server error'}`);
136
+ Object.assign(detailedError, { status: response.status, response: response });
137
+ throw detailedError;
138
+ }
139
+
140
+ const responseData = parseResponse(response.data);
141
+
142
+ if (responseData.errorcode || responseData.ErrorCode) {
143
+ strapi.log.error("[Apple Pay] Payone error:", {
144
+ errorcode: responseData.errorcode || responseData.ErrorCode,
145
+ errormessage: responseData.errormessage || responseData.ErrorMessage,
146
+ customermessage: responseData.customermessage || responseData.CustomerMessage
147
+ });
148
+ }
149
+
150
+ return responseData;
151
+ } catch (error) {
152
+ strapi.log.error("[Apple Pay] Error:", error instanceof Error ? error.message : error);
153
+ throw error;
154
+ }
155
+ };
156
+
157
+ const validateApplePayMerchant = async (strapi, params) => {
158
+ try {
159
+ const settings = await getSettings(strapi);
160
+
161
+ if (!validateSettings(settings)) {
162
+ throw new Error("Payone settings are not properly configured. Please check your plugin settings (aid, portalid, mid, key).");
163
+ }
164
+
165
+ const applePayConfig = settings?.applePayConfig || {};
166
+
167
+ if (!params.currency && applePayConfig.currencyCode) {
168
+ params.currency = applePayConfig.currencyCode;
169
+ }
170
+
171
+ if (!params.countryCode && applePayConfig.countryCode) {
172
+ params.countryCode = applePayConfig.countryCode;
173
+ }
174
+
175
+ const sessionResponse = await initializeApplePaySession(strapi, params);
176
+
177
+ // Extract add_paydata[applepay_payment_session] from response
178
+ // Payone returns this in URL-encoded format: add_paydata[applepay_payment_session]=BASE64_STRING
179
+ const applePaySessionBase64 =
180
+ sessionResponse["add_paydata[applepay_payment_session]"] ||
181
+ sessionResponse["add_paydata_applepay_payment_session"] ||
182
+ sessionResponse.add_paydata?.applepay_payment_session ||
183
+ (sessionResponse.add_paydata && typeof sessionResponse.add_paydata === 'object'
184
+ ? sessionResponse.add_paydata["applepay_payment_session"]
185
+ : null);
186
+
187
+ strapi.log.info("[Apple Pay] Genericpayment response:", {
188
+ status: sessionResponse.status,
189
+ workorderid: sessionResponse.workorderid,
190
+ hasApplePaySession: !!applePaySessionBase64,
191
+ applePaySessionLength: applePaySessionBase64 ? applePaySessionBase64.length : 0,
192
+ responseKeys: Object.keys(sessionResponse),
193
+ hasAddPaydataKey: !!sessionResponse["add_paydata[applepay_payment_session]"],
194
+ hasAddPaydataObject: !!sessionResponse.add_paydata,
195
+ addPaydataKeys: sessionResponse.add_paydata ? Object.keys(sessionResponse.add_paydata) : null
196
+ });
197
+
198
+ if (!applePaySessionBase64) {
199
+ strapi.log.error("[Apple Pay] Missing applepay_payment_session in response:", {
200
+ status: sessionResponse.status,
201
+ responseKeys: Object.keys(sessionResponse),
202
+ responseSample: JSON.stringify(sessionResponse).substring(0, 1000),
203
+ addPaydataKeys: sessionResponse.add_paydata ? Object.keys(sessionResponse.add_paydata) : null
204
+ });
205
+ throw new Error("Missing applepay_payment_session in Payone response. Please check your Payone Apple Pay configuration in PMI.");
206
+ }
207
+
208
+ if (sessionResponse.status === "OK" && applePaySessionBase64 && applePaySessionBase64.length > 0) {
209
+ try {
210
+ strapi.log.info("[Apple Pay] Extracting merchant session from Base64:", {
211
+ base64Length: applePaySessionBase64.length,
212
+ base64Preview: applePaySessionBase64.substring(0, 100) + "...",
213
+ base64End: applePaySessionBase64.substring(Math.max(0, applePaySessionBase64.length - 50))
214
+ });
215
+
216
+ // Decode Base64 to get merchant session JSON
217
+ let merchantSessionJson;
218
+ try {
219
+ merchantSessionJson = Buffer.from(applePaySessionBase64, 'base64').toString('utf-8');
220
+ strapi.log.info("[Apple Pay] Base64 decoded successfully, JSON length:", merchantSessionJson.length);
221
+ } catch (decodeError) {
222
+ strapi.log.error("[Apple Pay] Failed to decode Base64:", {
223
+ error: decodeError.message,
224
+ base64Length: applePaySessionBase64.length
225
+ });
226
+ throw new Error(`Failed to decode Base64 merchant session: ${decodeError.message}`);
227
+ }
228
+
229
+ // Parse JSON merchant session
230
+ let merchantSession;
231
+ try {
232
+ merchantSession = JSON.parse(merchantSessionJson);
233
+ strapi.log.info("[Apple Pay] Merchant session JSON parsed successfully");
234
+ } catch (parseError) {
235
+ strapi.log.error("[Apple Pay] Failed to parse merchant session JSON:", {
236
+ error: parseError.message,
237
+ jsonPreview: merchantSessionJson.substring(0, 500)
238
+ });
239
+ throw new Error(`Failed to parse merchant session JSON: ${parseError.message}`);
240
+ }
241
+
242
+ strapi.log.info("[Apple Pay] Merchant session extracted successfully:", {
243
+ hasMerchantIdentifier: !!merchantSession.merchantIdentifier,
244
+ hasEpochTimestamp: !!merchantSession.epochTimestamp,
245
+ hasExpiresAt: !!merchantSession.expiresAt,
246
+ merchantSessionKeys: Object.keys(merchantSession)
247
+ });
248
+
249
+ if (merchantSession.epochTimestamp && merchantSession.epochTimestamp > 1000000000000) {
250
+ merchantSession.epochTimestamp = Math.floor(merchantSession.epochTimestamp / 1000);
251
+ }
252
+
253
+ if (merchantSession.expiresAt && merchantSession.expiresAt > 1000000000000) {
254
+ merchantSession.expiresAt = Math.floor(merchantSession.expiresAt / 1000);
255
+ }
256
+
257
+ if (!merchantSession.merchantIdentifier ||
258
+ merchantSession.merchantIdentifier === 'undefined' ||
259
+ merchantSession.merchantIdentifier === 'null') {
260
+ merchantSession.merchantIdentifier = settings.mid || settings.merchantIdentifier || settings.portalid;
261
+ }
262
+
263
+ if (!merchantSession.merchantIdentifier) {
264
+ throw new Error("Merchant identifier is missing. Please configure Merchant ID (mid) in plugin settings.");
265
+ }
266
+
267
+ return merchantSession;
268
+ } catch (parseError) {
269
+ throw new Error(`Failed to parse merchant session from Payone: ${parseError.message}`);
270
+ }
271
+ }
272
+
273
+ const errorCode = sessionResponse.errorcode || sessionResponse.ErrorCode;
274
+ const errorMessage = sessionResponse.errormessage || sessionResponse.ErrorMessage ||
275
+ sessionResponse.errortxt || sessionResponse.ErrorTxt;
276
+
277
+ strapi.log.error("[Apple Pay] Payone Apple Pay initialization failed:", {
278
+ errorcode: errorCode,
279
+ errormessage: errorMessage
280
+ });
281
+
282
+ throw new Error(
283
+ `Payone Apple Pay initialization failed: ${errorCode ? `Error ${errorCode}` : 'Unknown error'} - ${errorMessage || 'Please check your Payone Apple Pay configuration in PMI'}`
284
+ );
285
+
286
+ } catch (error) {
287
+ strapi.log.error("[Apple Pay] Error:", error instanceof Error ? error.message : error);
288
+ throw error;
289
+ }
290
+ };
291
+
292
+ module.exports = {
293
+ initializeApplePaySession,
294
+ validateApplePayMerchant
295
+ };
@@ -1,9 +1,9 @@
1
- "use strict";
2
-
3
- const payone = require("./payone");
4
- const newHostedTokenizationService = require("./newHostedTokenizationService");
5
-
6
- module.exports = {
7
- payone,
8
- newHostedTokenizationService,
9
- };
1
+ "use strict";
2
+
3
+ const payone = require("./payone");
4
+ const newHostedTokenizationService = require("./newHostedTokenizationService");
5
+
6
+ module.exports = {
7
+ payone,
8
+ newHostedTokenizationService,
9
+ };