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.
- package/README.md +1191 -1191
- package/admin/src/components/Initializer/index.jsx +16 -16
- package/admin/src/components/PluginIcon/index.jsx +17 -17
- package/admin/src/index.js +57 -57
- package/admin/src/pages/App/components/AppHeader.jsx +45 -45
- package/admin/src/pages/App/components/AppTabs.jsx +105 -105
- package/admin/src/pages/App/components/ApplePayBtn.jsx +355 -355
- package/admin/src/pages/App/components/ApplePayConfig.jsx +357 -357
- package/admin/src/pages/App/components/DocsPanel.jsx +53 -53
- package/admin/src/pages/App/components/RenderInput.jsx +78 -78
- package/admin/src/pages/App/components/StatusBadge.jsx +87 -87
- package/admin/src/pages/App/components/icons/BankIcon.jsx +10 -10
- package/admin/src/pages/App/components/icons/ChevronDownIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/ChevronUpIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/CreditCardIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/ErrorIcon.jsx +10 -10
- package/admin/src/pages/App/components/icons/InfoIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/MarkCircle.jsx +19 -19
- package/admin/src/pages/App/components/icons/PaymentIcon.jsx +10 -10
- package/admin/src/pages/App/components/icons/PendingIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/PersonIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/SuccessIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/WalletIcon.jsx +9 -9
- package/admin/src/pages/App/components/icons/index.jsx +12 -12
- package/admin/src/pages/App/components/payment-actions/AuthorizationForm.jsx +334 -334
- package/admin/src/pages/App/components/payment-actions/CaptureForm.jsx +120 -120
- package/admin/src/pages/App/components/payment-actions/PaymentActionsPanel.jsx +183 -183
- package/admin/src/pages/App/components/payment-actions/PaymentMethodSelector.jsx +315 -315
- package/admin/src/pages/App/components/payment-actions/PaymentResult.jsx +129 -129
- package/admin/src/pages/App/components/payment-actions/PreauthorizationForm.jsx +273 -273
- package/admin/src/pages/App/components/payment-actions/RefundForm.jsx +114 -114
- package/admin/src/pages/App/components/transaction-history/ImportExportBar.jsx +153 -153
- package/admin/src/pages/App/components/transaction-history/details/TransactionHistoryItem.jsx +526 -526
- package/admin/src/pages/App/index.jsx +96 -96
- package/admin/src/pages/App/styles.css +176 -176
- package/admin/src/pages/constants/paymentConstants.js +71 -71
- package/admin/src/pages/hooks/use-system-theme.js +27 -27
- package/admin/src/pages/hooks/usePaymentActions.js +498 -498
- package/admin/src/pages/hooks/usePluginTranslations.js +12 -12
- package/admin/src/pages/hooks/useSettings.js +183 -183
- package/admin/src/pages/hooks/useTransactionHistory.js +148 -148
- package/admin/src/pages/utils/api.js +97 -97
- package/admin/src/pages/utils/applePayConstants.js +196 -196
- package/admin/src/pages/utils/formatTransactionData.js +15 -15
- package/admin/src/pages/utils/getInputComponent.jsx +200 -200
- package/admin/src/pages/utils/paymentUtils.js +661 -661
- package/admin/src/pages/utils/tooltipHelpers.js +18 -18
- package/admin/src/pages/utils/transactionTableUtils.js +71 -71
- package/admin/src/pluginId.js +9 -9
- package/admin/src/translations/de.json +235 -235
- package/admin/src/translations/en.json +235 -235
- package/admin/src/translations/fr.json +235 -235
- package/admin/src/translations/ru.json +235 -235
- package/admin/src/utils/prefixPluginTranslations.js +13 -13
- package/package.json +45 -45
- package/server/bootstrap.js +107 -107
- package/server/config/index.js +83 -83
- package/server/content-types/index.js +4 -4
- package/server/content-types/transactions/index.js +4 -4
- package/server/content-types/transactions/schema.json +86 -86
- package/server/controllers/index.js +7 -7
- package/server/controllers/payone.js +503 -506
- package/server/destroy.js +5 -5
- package/server/index.js +23 -23
- package/server/policies/index.js +7 -7
- package/server/policies/is-auth.js +29 -29
- package/server/policies/isSuperAdmin.js +20 -20
- package/server/register.js +5 -5
- package/server/routes/index.js +218 -218
- package/server/services/applePayService.js +295 -295
- package/server/services/index.js +9 -9
- package/server/services/paymentService.js +264 -223
- package/server/services/payone.js +78 -78
- package/server/services/settingsService.js +59 -59
- package/server/services/testConnectionService.js +115 -115
- package/server/services/transactionService.js +262 -262
- package/server/utils/csvTransactions.js +82 -82
- package/server/utils/normalize.js +39 -39
- package/server/utils/paymentMethodParams.js +288 -288
- package/server/utils/requestBuilder.js +115 -100
- package/server/utils/responseParser.js +141 -141
- package/strapi-admin.js +4 -4
- 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
|
+
};
|
package/server/services/index.js
CHANGED
|
@@ -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
|
+
};
|