strapi-plugin-payone-provider 5.7.25 → 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/package.json
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
const crypto = require("crypto");
|
|
4
4
|
const PLUGIN_NAME = "strapi-plugin-payone-provider";
|
|
5
|
-
const {
|
|
5
|
+
const {
|
|
6
|
+
rowsToCsv,
|
|
7
|
+
csvToRows,
|
|
8
|
+
TRANSACTION_ATTRS
|
|
9
|
+
} = require("../utils/csvTransactions");
|
|
6
10
|
|
|
7
11
|
const getPayoneService = (strapi) => {
|
|
8
12
|
return strapi.plugin(PLUGIN_NAME).service("payone");
|
|
@@ -84,8 +88,8 @@ module.exports = ({ strapi }) => ({
|
|
|
84
88
|
googlePay: settings?.enableGooglePay,
|
|
85
89
|
applePay: settings?.enableApplePay,
|
|
86
90
|
sofort: settings?.enableSofort,
|
|
87
|
-
sepa: settings?.enableSepaDirectDebit
|
|
88
|
-
}
|
|
91
|
+
sepa: settings?.enableSepaDirectDebit
|
|
92
|
+
}
|
|
89
93
|
}
|
|
90
94
|
};
|
|
91
95
|
} catch (error) {
|
|
@@ -97,7 +101,7 @@ module.exports = ({ strapi }) => ({
|
|
|
97
101
|
try {
|
|
98
102
|
const bodyData = ctx.request.body?.data || ctx.request.body;
|
|
99
103
|
|
|
100
|
-
if (!bodyData || typeof bodyData !==
|
|
104
|
+
if (!bodyData || typeof bodyData !== "object") {
|
|
101
105
|
ctx.throw(400, "Invalid request body");
|
|
102
106
|
}
|
|
103
107
|
|
|
@@ -106,7 +110,10 @@ module.exports = ({ strapi }) => ({
|
|
|
106
110
|
if (bodyData.key === "***HIDDEN***" || !bodyData.key) {
|
|
107
111
|
bodyData.key = currentSettings?.key;
|
|
108
112
|
}
|
|
109
|
-
if (
|
|
113
|
+
if (
|
|
114
|
+
bodyData.serverApiSecret === "***HIDDEN***" ||
|
|
115
|
+
!bodyData.serverApiSecret
|
|
116
|
+
) {
|
|
110
117
|
bodyData.serverApiSecret = currentSettings?.serverApiSecret;
|
|
111
118
|
}
|
|
112
119
|
|
|
@@ -120,7 +127,7 @@ module.exports = ({ strapi }) => ({
|
|
|
120
127
|
async preauthorization(ctx) {
|
|
121
128
|
try {
|
|
122
129
|
const params = ctx.request.body?.data || ctx.request.body;
|
|
123
|
-
if (!params || typeof params !==
|
|
130
|
+
if (!params || typeof params !== "object") {
|
|
124
131
|
ctx.throw(400, "Invalid request body");
|
|
125
132
|
}
|
|
126
133
|
|
|
@@ -134,10 +141,7 @@ module.exports = ({ strapi }) => ({
|
|
|
134
141
|
async authorization(ctx) {
|
|
135
142
|
try {
|
|
136
143
|
const params = ctx.request.body?.data || ctx.request.body;
|
|
137
|
-
|
|
138
|
-
if (!params || typeof params !== 'object') {
|
|
139
|
-
ctx.throw(400, "Invalid request body");
|
|
140
|
-
}
|
|
144
|
+
if (!params || typeof params !== "object") ctx.throw(400, "Invalid request body");
|
|
141
145
|
|
|
142
146
|
const result = await getPayoneService(strapi).authorization(params);
|
|
143
147
|
ctx.body = result;
|
|
@@ -150,7 +154,7 @@ module.exports = ({ strapi }) => ({
|
|
|
150
154
|
try {
|
|
151
155
|
const params = ctx.request.body?.data || ctx.request.body;
|
|
152
156
|
|
|
153
|
-
if (!params || typeof params !==
|
|
157
|
+
if (!params || typeof params !== "object") {
|
|
154
158
|
ctx.throw(400, "Invalid request body");
|
|
155
159
|
}
|
|
156
160
|
|
|
@@ -165,7 +169,7 @@ module.exports = ({ strapi }) => ({
|
|
|
165
169
|
try {
|
|
166
170
|
const params = ctx.request.body?.data || ctx.request.body;
|
|
167
171
|
|
|
168
|
-
if (!params || typeof params !==
|
|
172
|
+
if (!params || typeof params !== "object") {
|
|
169
173
|
ctx.throw(400, "Invalid request body");
|
|
170
174
|
}
|
|
171
175
|
|
|
@@ -201,7 +205,7 @@ module.exports = ({ strapi }) => ({
|
|
|
201
205
|
data: result.data || [],
|
|
202
206
|
meta: {
|
|
203
207
|
pagination: result.pagination
|
|
204
|
-
}
|
|
208
|
+
}
|
|
205
209
|
};
|
|
206
210
|
} catch (error) {
|
|
207
211
|
handleError(ctx, error);
|
|
@@ -210,25 +214,36 @@ module.exports = ({ strapi }) => ({
|
|
|
210
214
|
|
|
211
215
|
async exportTransactions(ctx) {
|
|
212
216
|
try {
|
|
213
|
-
const {
|
|
217
|
+
const {
|
|
218
|
+
filters: rawFilters = {},
|
|
219
|
+
format = "json",
|
|
220
|
+
sort_by,
|
|
221
|
+
sort_order
|
|
222
|
+
} = ctx.query || {};
|
|
214
223
|
const filters = buildFiltersFromQuery(rawFilters);
|
|
215
224
|
const data = await getPayoneService(strapi).getTransactionsForExport({
|
|
216
225
|
filters,
|
|
217
226
|
sort_by: sort_by || "createdAt",
|
|
218
|
-
sort_order: sort_order || "desc"
|
|
227
|
+
sort_order: sort_order || "desc"
|
|
219
228
|
});
|
|
220
229
|
const rows = Array.isArray(data) ? data : [];
|
|
221
230
|
const fmt = (format || "json").toLowerCase();
|
|
222
231
|
|
|
223
232
|
if (fmt === "csv") {
|
|
224
233
|
ctx.set("Content-Type", "text/csv; charset=utf-8");
|
|
225
|
-
ctx.set(
|
|
234
|
+
ctx.set(
|
|
235
|
+
"Content-Disposition",
|
|
236
|
+
'attachment; filename="transactions.csv"'
|
|
237
|
+
);
|
|
226
238
|
ctx.body = rowsToCsv(rows, TRANSACTION_ATTRS);
|
|
227
239
|
return;
|
|
228
240
|
}
|
|
229
241
|
|
|
230
242
|
ctx.set("Content-Type", "application/json");
|
|
231
|
-
ctx.set(
|
|
243
|
+
ctx.set(
|
|
244
|
+
"Content-Disposition",
|
|
245
|
+
'attachment; filename="transactions.json"'
|
|
246
|
+
);
|
|
232
247
|
ctx.body = rows;
|
|
233
248
|
} catch (error) {
|
|
234
249
|
handleError(ctx, error);
|
|
@@ -238,7 +253,8 @@ module.exports = ({ strapi }) => ({
|
|
|
238
253
|
async importTransactions(ctx) {
|
|
239
254
|
try {
|
|
240
255
|
const body = ctx.request.body;
|
|
241
|
-
if (!body || typeof body !== "object")
|
|
256
|
+
if (!body || typeof body !== "object")
|
|
257
|
+
ctx.throw(400, "Request body must be JSON");
|
|
242
258
|
|
|
243
259
|
let rows = [];
|
|
244
260
|
if (Array.isArray(body)) {
|
|
@@ -248,18 +264,26 @@ module.exports = ({ strapi }) => ({
|
|
|
248
264
|
} else if (body.format === "csv" && typeof body.data === "string") {
|
|
249
265
|
rows = csvToRows(body.data);
|
|
250
266
|
} else {
|
|
251
|
-
ctx.throw(
|
|
267
|
+
ctx.throw(
|
|
268
|
+
400,
|
|
269
|
+
"Body must be an array, { data: array }, or { format: 'csv', data: csvString }"
|
|
270
|
+
);
|
|
252
271
|
}
|
|
253
272
|
|
|
254
273
|
if (rows.length === 0) {
|
|
255
|
-
ctx.body = {
|
|
274
|
+
ctx.body = {
|
|
275
|
+
imported: 0,
|
|
276
|
+
failed: 0,
|
|
277
|
+
errors: [],
|
|
278
|
+
message: "No rows to import"
|
|
279
|
+
};
|
|
256
280
|
return;
|
|
257
281
|
}
|
|
258
282
|
|
|
259
283
|
const result = await getPayoneService(strapi).importTransactions(rows);
|
|
260
284
|
ctx.body = {
|
|
261
285
|
...result,
|
|
262
|
-
message: `Imported ${result.imported}, failed ${result.failed}
|
|
286
|
+
message: `Imported ${result.imported}, failed ${result.failed}`
|
|
263
287
|
};
|
|
264
288
|
} catch (error) {
|
|
265
289
|
handleError(ctx, error);
|
|
@@ -291,19 +315,22 @@ module.exports = ({ strapi }) => ({
|
|
|
291
315
|
|
|
292
316
|
const callbackData = isGetRequest
|
|
293
317
|
? ctx.query
|
|
294
|
-
:
|
|
318
|
+
: ctx.request.body || ctx.request.body?.data || ctx.request?.data;
|
|
295
319
|
|
|
296
|
-
const result = await getPayoneService(strapi).handle3DSCallback(
|
|
320
|
+
const result = await getPayoneService(strapi).handle3DSCallback(
|
|
321
|
+
callbackData,
|
|
322
|
+
resultType
|
|
323
|
+
);
|
|
297
324
|
|
|
298
325
|
if (isGetRequest) {
|
|
299
|
-
const isContentUI = currentPath.includes(
|
|
300
|
-
const basePath = isContentUI ?
|
|
301
|
-
const pluginPath =
|
|
326
|
+
const isContentUI = currentPath.includes("/content-ui");
|
|
327
|
+
const basePath = isContentUI ? "/content-ui" : "/admin";
|
|
328
|
+
const pluginPath = "/plugins/strapi-plugin-payone-provider";
|
|
302
329
|
|
|
303
330
|
const queryParams = new URLSearchParams();
|
|
304
|
-
queryParams.set(
|
|
305
|
-
if (result.txid) queryParams.set(
|
|
306
|
-
if (result.status) queryParams.set(
|
|
331
|
+
queryParams.set("3ds", resultType);
|
|
332
|
+
if (result.txid) queryParams.set("txid", result.txid);
|
|
333
|
+
if (result.status) queryParams.set("status", result.status);
|
|
307
334
|
|
|
308
335
|
const redirectUrl = `${basePath}${pluginPath}?${queryParams.toString()}`;
|
|
309
336
|
return ctx.redirect(redirectUrl);
|
|
@@ -320,14 +347,15 @@ module.exports = ({ strapi }) => ({
|
|
|
320
347
|
const settings = await getPayoneService(strapi).getSettings();
|
|
321
348
|
const applePayConfig = settings?.applePayConfig || {};
|
|
322
349
|
|
|
323
|
-
const params =
|
|
350
|
+
const params =
|
|
351
|
+
ctx.request.body || ctx.request.body?.data || ctx.request?.data;
|
|
324
352
|
|
|
325
353
|
if (!params) {
|
|
326
354
|
throw new Error("Request body is missing");
|
|
327
355
|
}
|
|
328
356
|
|
|
329
357
|
if (!params.domain && !params.domainName) {
|
|
330
|
-
params.domain = ctx.request.hostname || ctx.request.host ||
|
|
358
|
+
params.domain = ctx.request.hostname || ctx.request.host || "localhost";
|
|
331
359
|
params.domainName = params.domain;
|
|
332
360
|
} else if (params.domain && !params.domainName) {
|
|
333
361
|
params.domainName = params.domain;
|
|
@@ -346,28 +374,40 @@ module.exports = ({ strapi }) => ({
|
|
|
346
374
|
params.countryCode = applePayConfig.countryCode || "DE";
|
|
347
375
|
}
|
|
348
376
|
|
|
349
|
-
let result =
|
|
377
|
+
let result =
|
|
378
|
+
await getPayoneService(strapi).validateApplePayMerchant(params);
|
|
350
379
|
|
|
351
380
|
if (!result) {
|
|
352
|
-
throw new Error(
|
|
381
|
+
throw new Error(
|
|
382
|
+
"Merchant validation returned null. Please check your Payone Apple Pay configuration."
|
|
383
|
+
);
|
|
353
384
|
}
|
|
354
385
|
|
|
355
386
|
ctx.body = result;
|
|
356
387
|
} catch (error) {
|
|
357
|
-
const errorStatus =
|
|
358
|
-
|
|
359
|
-
|
|
388
|
+
const errorStatus =
|
|
389
|
+
error.status || (error.message?.includes("403") ? 403 : 500);
|
|
390
|
+
|
|
391
|
+
if (
|
|
392
|
+
error.response ||
|
|
393
|
+
errorStatus === 403 ||
|
|
394
|
+
errorStatus === 401 ||
|
|
395
|
+
errorStatus >= 500
|
|
396
|
+
) {
|
|
360
397
|
strapi.log.error("[Apple Pay] Controller error:", {
|
|
361
398
|
status: errorStatus,
|
|
362
399
|
message: error.message
|
|
363
400
|
});
|
|
364
401
|
}
|
|
365
402
|
|
|
366
|
-
let errorMessage =
|
|
367
|
-
|
|
403
|
+
let errorMessage =
|
|
404
|
+
error.message || "Apple Pay merchant validation failed";
|
|
405
|
+
let errorDetails =
|
|
406
|
+
"Please check your Payone Apple Pay configuration in PMI (CONFIGURATION → PAYMENT PORTALS → [Your Portal] → Apple Pay). Ensure that Merchant ID (mid) is correctly configured and Apple Pay is enabled for your portal.";
|
|
368
407
|
|
|
369
|
-
if (errorStatus === 403 || error.message?.includes(
|
|
370
|
-
errorDetails =
|
|
408
|
+
if (errorStatus === 403 || error.message?.includes("403")) {
|
|
409
|
+
errorDetails =
|
|
410
|
+
"403 Forbidden: Authentication failed with Payone. " +
|
|
371
411
|
"Please check: 1) Your Payone credentials (aid, portalid, mid, key) in plugin settings, " +
|
|
372
412
|
"2) Mode is set to 'live' (Apple Pay only works in live mode), " +
|
|
373
413
|
"3) Your domain is registered with Payone Merchant Services, " +
|
|
@@ -392,7 +432,7 @@ module.exports = ({ strapi }) => ({
|
|
|
392
432
|
const notificationData = ctx.request.body || {};
|
|
393
433
|
await getPayoneService(strapi).processTransactionStatus(notificationData);
|
|
394
434
|
console.warn("[Payone] Notification Status", {
|
|
395
|
-
ip: ctx.request.ip
|
|
435
|
+
ip: ctx.request.ip
|
|
396
436
|
});
|
|
397
437
|
} catch (error) {
|
|
398
438
|
strapi.log.error("[Payone TransactionStatus] Error:", error);
|
|
@@ -405,12 +445,15 @@ module.exports = ({ strapi }) => ({
|
|
|
405
445
|
|
|
406
446
|
async hostedTokenizationJwt(ctx) {
|
|
407
447
|
try {
|
|
408
|
-
const result =
|
|
448
|
+
const result =
|
|
449
|
+
await getNewHostedTokenizationService(
|
|
450
|
+
strapi
|
|
451
|
+
).createHostedTokenizationJwt();
|
|
409
452
|
ctx.body = {
|
|
410
453
|
data: {
|
|
411
454
|
token: result?.token || null,
|
|
412
|
-
expirationDate: result?.expirationDate || null
|
|
413
|
-
}
|
|
455
|
+
expirationDate: result?.expirationDate || null
|
|
456
|
+
}
|
|
414
457
|
};
|
|
415
458
|
} catch (error) {
|
|
416
459
|
handleError(ctx, error);
|
|
@@ -428,8 +471,16 @@ module.exports = ({ strapi }) => ({
|
|
|
428
471
|
}
|
|
429
472
|
|
|
430
473
|
// Validate required settings
|
|
431
|
-
if (
|
|
432
|
-
|
|
474
|
+
if (
|
|
475
|
+
!settings?.aid ||
|
|
476
|
+
!settings?.mid ||
|
|
477
|
+
!settings?.portalid ||
|
|
478
|
+
!settings?.mode
|
|
479
|
+
) {
|
|
480
|
+
ctx.throw(
|
|
481
|
+
400,
|
|
482
|
+
"Required settings (aid, mid, portalid, mode) are not configured"
|
|
483
|
+
);
|
|
433
484
|
}
|
|
434
485
|
|
|
435
486
|
// Construct the string from settings values
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const axios = require("axios");
|
|
4
|
-
const { buildClientRequestParams, toFormData } = require("../utils/requestBuilder");
|
|
4
|
+
const { buildClientRequestParams, toFormData, is3dsViable } = require("../utils/requestBuilder");
|
|
5
5
|
const { addPaymentMethodParams } = require("../utils/paymentMethodParams");
|
|
6
6
|
const { parseResponse, extractTxId, requires3DSRedirect, get3DSRedirectUrl } = require("../utils/responseParser");
|
|
7
7
|
const { getSettings, validateSettings } = require("./settingsService");
|
|
@@ -37,14 +37,11 @@ const getInvoiceIdObject = (invoiceid) => {
|
|
|
37
37
|
const sendRequest = async (strapi, params) => {
|
|
38
38
|
try {
|
|
39
39
|
const settings = await getSettings(strapi);
|
|
40
|
-
|
|
41
|
-
if (!validateSettings(settings)) {
|
|
42
|
-
throw new Error("Payone settings not configured");
|
|
43
|
-
}
|
|
40
|
+
if (!validateSettings(settings)) throw new Error("Payone settings not configured");
|
|
44
41
|
|
|
45
42
|
const requestParams = buildClientRequestParams(settings, params, strapi.log);
|
|
46
|
-
const formData = toFormData(requestParams);
|
|
47
43
|
|
|
44
|
+
const formData = toFormData(requestParams);
|
|
48
45
|
const response = await axios.post(POST_GATEWAY_URL, formData, {
|
|
49
46
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
50
47
|
timeout: 30000
|
|
@@ -60,7 +57,6 @@ const sendRequest = async (strapi, params) => {
|
|
|
60
57
|
responseData.requires3DSRedirect = true;
|
|
61
58
|
responseData.redirectUrl = redirectUrl;
|
|
62
59
|
responseData.is3DSRequired = is3DSRequiredError;
|
|
63
|
-
|
|
64
60
|
}
|
|
65
61
|
|
|
66
62
|
const errorMessage = responseData?.Error?.ErrorMessage || null;
|
|
@@ -96,8 +92,7 @@ const sendRequest = async (strapi, params) => {
|
|
|
96
92
|
};
|
|
97
93
|
|
|
98
94
|
const preauthorization = async (strapi, params) => {
|
|
99
|
-
|
|
100
|
-
const requiredParams = {
|
|
95
|
+
const requestParams = {
|
|
101
96
|
request: "preauthorization",
|
|
102
97
|
clearingtype: params.clearingtype,
|
|
103
98
|
amount: params.amount,
|
|
@@ -115,14 +110,20 @@ const preauthorization = async (strapi, params) => {
|
|
|
115
110
|
...params
|
|
116
111
|
};
|
|
117
112
|
|
|
113
|
+
const settings = await getSettings(strapi);
|
|
118
114
|
|
|
119
|
-
|
|
120
|
-
|
|
115
|
+
// Happnes only when CC-payment and 3DS is enabled and is Pre/Authorization request
|
|
116
|
+
if (is3dsViable(params, settings)) {
|
|
117
|
+
requestParams = await perform3DSCheck(strapi, requestParams);
|
|
118
|
+
if (!requestParams) throw new Error('3DS check failed');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
requestParams = addPaymentMethodParams(requestParams, strapi.log);
|
|
122
|
+
return await sendRequest(strapi, requestParams);
|
|
121
123
|
};
|
|
122
124
|
|
|
123
125
|
const authorization = async (strapi, params) => {
|
|
124
|
-
|
|
125
|
-
const requiredParams = {
|
|
126
|
+
let requestParams = {
|
|
126
127
|
request: "authorization",
|
|
127
128
|
clearingtype: params.clearingtype,
|
|
128
129
|
reference: params.reference,
|
|
@@ -138,8 +139,16 @@ const authorization = async (strapi, params) => {
|
|
|
138
139
|
...params
|
|
139
140
|
};
|
|
140
141
|
|
|
141
|
-
const
|
|
142
|
-
|
|
142
|
+
const settings = await getSettings(strapi);
|
|
143
|
+
|
|
144
|
+
// Happnes only when CC-payment and 3DS is enabled and is Pre/Authorization request
|
|
145
|
+
if (is3dsViable(params, settings)) {
|
|
146
|
+
requestParams = await perform3DSCheck(strapi, requestParams);
|
|
147
|
+
if (!requestParams) throw new Error('3DS check failed');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
requestParams = addPaymentMethodParams(requestParams, strapi.log);
|
|
151
|
+
return await sendRequest(strapi, requestParams);
|
|
143
152
|
};
|
|
144
153
|
|
|
145
154
|
const capture = async (strapi, params) => {
|
|
@@ -147,7 +156,6 @@ const capture = async (strapi, params) => {
|
|
|
147
156
|
throw new Error("Transaction ID (txid) is required for capture");
|
|
148
157
|
}
|
|
149
158
|
|
|
150
|
-
|
|
151
159
|
const requiredParams = {
|
|
152
160
|
request: "capture",
|
|
153
161
|
txid: params.txid,
|
|
@@ -165,7 +173,6 @@ const refund = async (strapi, params) => {
|
|
|
165
173
|
throw new Error("Transaction ID (txid) is required for refund");
|
|
166
174
|
}
|
|
167
175
|
|
|
168
|
-
|
|
169
176
|
const requiredParams = {
|
|
170
177
|
request: "refund",
|
|
171
178
|
txid: params.txid,
|
|
@@ -179,6 +186,39 @@ const refund = async (strapi, params) => {
|
|
|
179
186
|
return await sendRequest(strapi, requiredParams);
|
|
180
187
|
};
|
|
181
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Performs a 3DS check and returns the modified params
|
|
191
|
+
* The modified params include the pseudocardpan if the 3DS check is valid
|
|
192
|
+
*
|
|
193
|
+
* @param strapi - Strapi instance
|
|
194
|
+
* @param params - Request params
|
|
195
|
+
* @returns The modified params
|
|
196
|
+
*/
|
|
197
|
+
const perform3DSCheck = async (strapi, params) => {
|
|
198
|
+
try {
|
|
199
|
+
const result = await sendRequest(strapi, {
|
|
200
|
+
...params,
|
|
201
|
+
request: "3dscheck",
|
|
202
|
+
exiturl: params.successurl ?? '',
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
if (result?.errorCode || result?.errorMessage || result?.Status === 'Failed' || result?.Status === 'Invalid')
|
|
206
|
+
throw new Error('3DS check failed');
|
|
207
|
+
|
|
208
|
+
const modifiedParams = {
|
|
209
|
+
...params,
|
|
210
|
+
pseudocardpan: result?.CreditCard?.PseudoCardPan,
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
if (result?.Status === 'Valid') modifiedParams.xid = result?.CreditCard?.ThreeDS?.Xid;
|
|
214
|
+
|
|
215
|
+
return modifiedParams;
|
|
216
|
+
} catch (error) {
|
|
217
|
+
strapi.log.error("3DS check error:", error);
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
182
222
|
const handle3DSCallback = async (strapi, callbackData, resultType = 'callback') => {
|
|
183
223
|
try {
|
|
184
224
|
const parsedData = callbackData && Object.keys(callbackData).length > 0
|
|
@@ -218,6 +258,7 @@ module.exports = {
|
|
|
218
258
|
authorization,
|
|
219
259
|
capture,
|
|
220
260
|
refund,
|
|
221
|
-
handle3DSCallback
|
|
261
|
+
handle3DSCallback,
|
|
262
|
+
perform3DSCheck
|
|
222
263
|
};
|
|
223
264
|
|
|
@@ -28,7 +28,7 @@ const buildClientRequestParams = (settings, params, logger = null) => {
|
|
|
28
28
|
const isCreditCard = requestParams.clearingtype === "cc";
|
|
29
29
|
const enable3DSecure = settings.enable3DSecure !== false;
|
|
30
30
|
|
|
31
|
-
if (
|
|
31
|
+
if (is3dsViable(requestParams, settings)) {
|
|
32
32
|
requestParams["3dsecure"] = "yes";
|
|
33
33
|
requestParams.ecommercemode = params.ecommercemode || "internet";
|
|
34
34
|
|
|
@@ -93,8 +93,23 @@ const toFormData = (requestParams) => {
|
|
|
93
93
|
return formData;
|
|
94
94
|
};
|
|
95
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Checks if the request is viable for 3DS according to the settings
|
|
98
|
+
*
|
|
99
|
+
* @param params - Request params
|
|
100
|
+
* @param settings - Set up in admin
|
|
101
|
+
* @returns
|
|
102
|
+
*/
|
|
103
|
+
const is3dsViable = (params, settings) => {
|
|
104
|
+
const isCreditCard = params.clearingtype === "cc";
|
|
105
|
+
const enable3DSecure = settings.enable3DSecure !== false;
|
|
106
|
+
|
|
107
|
+
return isCreditCard && enable3DSecure && (params.request === "preauthorization" || params.request === "authorization")
|
|
108
|
+
};
|
|
109
|
+
|
|
96
110
|
module.exports = {
|
|
97
111
|
buildClientRequestParams,
|
|
98
|
-
toFormData
|
|
112
|
+
toFormData,
|
|
113
|
+
is3dsViable
|
|
99
114
|
};
|
|
100
115
|
|