nets-service-sdk 1.1.18 → 1.1.20
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/dist/index.js +144 -19
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -280,6 +280,17 @@ var require_hexRequest = __commonJS({
|
|
|
280
280
|
console.log("buffer", buffer);
|
|
281
281
|
return { buffer, ecn: body.ecn, hexString };
|
|
282
282
|
};
|
|
283
|
+
module2.exports.generateFunction56Request = () => {
|
|
284
|
+
const date = moment().format("DDMMYYHHmmss");
|
|
285
|
+
const paddedValue = padWithLeadingZeros(date, "12");
|
|
286
|
+
const hexValue = paddedValue.toHexString();
|
|
287
|
+
const calculated = `0018${hexValue}35363031301C03`;
|
|
288
|
+
const calculatedXor = xorCalculation(calculated);
|
|
289
|
+
const hexString = `02${calculated}` + calculatedXor;
|
|
290
|
+
console.log("Recovery Function 56 Request:", hexString);
|
|
291
|
+
const buffer = Buffer.from(hexString, "hex");
|
|
292
|
+
return { buffer, ecn: date };
|
|
293
|
+
};
|
|
283
294
|
}
|
|
284
295
|
});
|
|
285
296
|
|
|
@@ -502,13 +513,19 @@ var require_parser = __commonJS({
|
|
|
502
513
|
const data = { ...obj };
|
|
503
514
|
const keys = Object.keys(data);
|
|
504
515
|
const translatedJson = {};
|
|
516
|
+
const ecnError = CheckECNERROR(obj["ECN"]);
|
|
517
|
+
if (ecnError) {
|
|
518
|
+
translatedJson.status = ecnError.status;
|
|
519
|
+
translatedJson.description = ecnError.detail;
|
|
520
|
+
translatedJson.category = ecnError.category;
|
|
521
|
+
}
|
|
505
522
|
keys.forEach((key) => {
|
|
506
523
|
if (key == "01") {
|
|
507
524
|
translatedJson["approvalCode"] = obj[key];
|
|
508
525
|
}
|
|
509
526
|
if (key == "02") {
|
|
510
527
|
const statusResponse = statusCheck(obj[key]);
|
|
511
|
-
if (statusResponse) {
|
|
528
|
+
if (statusResponse && !translatedJson.status) {
|
|
512
529
|
translatedJson.status = statusResponse.status;
|
|
513
530
|
translatedJson.description = statusResponse.detail;
|
|
514
531
|
translatedJson.category = statusResponse.category;
|
|
@@ -516,12 +533,6 @@ var require_parser = __commonJS({
|
|
|
516
533
|
translatedJson["balance"] = statusResponse.balance;
|
|
517
534
|
}
|
|
518
535
|
}
|
|
519
|
-
const ecnnError = CheckECNERROR(obj["ECN"]);
|
|
520
|
-
if (ecnnError) {
|
|
521
|
-
translatedJson.status = ecnnError.status;
|
|
522
|
-
translatedJson.description = ecnnError.detail;
|
|
523
|
-
translatedJson.category = ecnnError.category;
|
|
524
|
-
}
|
|
525
536
|
translatedJson["responsetext"] = obj[key];
|
|
526
537
|
}
|
|
527
538
|
if (key == "03") {
|
|
@@ -602,7 +613,7 @@ var require_parser = __commonJS({
|
|
|
602
613
|
if (key == "HC") {
|
|
603
614
|
translatedJson["hostResponseCode"] = obj[key];
|
|
604
615
|
const mapped = getResponseFromCode(obj[key]);
|
|
605
|
-
if (mapped) {
|
|
616
|
+
if (mapped && !translatedJson.status) {
|
|
606
617
|
translatedJson.status = mapped.status;
|
|
607
618
|
translatedJson.description = mapped.detail;
|
|
608
619
|
translatedJson.category = mapped.category;
|
|
@@ -648,6 +659,11 @@ var require_parser = __commonJS({
|
|
|
648
659
|
translatedJson["receiptTextFormat"] = obj[key];
|
|
649
660
|
}
|
|
650
661
|
});
|
|
662
|
+
if (!translatedJson.status) {
|
|
663
|
+
translatedJson.status = "UNKNOWN";
|
|
664
|
+
translatedJson.description = "NO_RESPONSE_CODE";
|
|
665
|
+
translatedJson.category = "RETRY";
|
|
666
|
+
}
|
|
651
667
|
logger.log({ level: "info", message: "jsonProcessor translated terminal response into JSON format." });
|
|
652
668
|
return { translated: translatedJson, raw: obj };
|
|
653
669
|
};
|
|
@@ -680,6 +696,9 @@ var require_parser = __commonJS({
|
|
|
680
696
|
if (data?.indexOf("DECLINED") > -1) {
|
|
681
697
|
return { status: "DECLINED", detail: "Transaction Declined", category: "HARD_FAIL" };
|
|
682
698
|
}
|
|
699
|
+
if (data?.indexOf("CANCELLED") > -1) {
|
|
700
|
+
return { status: "USER_CANCELLED", detail: "USER_CANCELLED", category: "HARD_FAIL" };
|
|
701
|
+
}
|
|
683
702
|
if (data?.indexOf("CARD NOT SUPPORTED") > -1) {
|
|
684
703
|
return { status: "CARD_NOT_SUPPORTED", detail: "Card not supported", category: "HARD_FAIL" };
|
|
685
704
|
}
|
|
@@ -922,6 +941,32 @@ var require_responseHandler = __commonJS({
|
|
|
922
941
|
}
|
|
923
942
|
return isMatch;
|
|
924
943
|
};
|
|
944
|
+
module2.exports.terminalRecovery = (hexFrame) => {
|
|
945
|
+
const ecn = activePaymentEcn;
|
|
946
|
+
const parsedValue = netsPaymentParser(hexFrame, ecn);
|
|
947
|
+
const response = jsonProcessor(parsedValue);
|
|
948
|
+
if (response.translated) {
|
|
949
|
+
activePaymentEcn = null;
|
|
950
|
+
}
|
|
951
|
+
if (response.translated && (response.translated.category == "SUCCESS" || response.translated.status == "APPROVED")) {
|
|
952
|
+
logger.log({ level: "info", message: "\u2705 Recovery SUCCESS: Last transaction was APPROVED." });
|
|
953
|
+
sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
|
|
954
|
+
success: true,
|
|
955
|
+
status: "SUCCESS",
|
|
956
|
+
response,
|
|
957
|
+
action: "COMPLETED"
|
|
958
|
+
});
|
|
959
|
+
sendPaymentResponseToCloud(response.translated);
|
|
960
|
+
} else {
|
|
961
|
+
logger.log({ level: "warn", message: "\u26A0\uFE0F Recovery FAILED: Transaction status could not be confirmed as APPROVED." });
|
|
962
|
+
sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
|
|
963
|
+
status: "FAILED",
|
|
964
|
+
action: "CANCELLED",
|
|
965
|
+
message: "Payment needs verification / Failed",
|
|
966
|
+
reason: "RECOVERY_NOT_CONFIRMED"
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
};
|
|
925
970
|
}
|
|
926
971
|
});
|
|
927
972
|
|
|
@@ -951,13 +996,14 @@ var require_communication = __commonJS({
|
|
|
951
996
|
var { initialiseRequest } = require_httpRequest();
|
|
952
997
|
var requestType;
|
|
953
998
|
var calculated;
|
|
954
|
-
var MAX_COUNT =
|
|
999
|
+
var MAX_COUNT = 2;
|
|
955
1000
|
var WRONG_LRC_MAX_COUNT = 3;
|
|
956
1001
|
var count = MAX_COUNT;
|
|
957
1002
|
var lrcCount = WRONG_LRC_MAX_COUNT;
|
|
958
1003
|
var ackOrNack = null;
|
|
959
1004
|
var requestPayload = null;
|
|
960
1005
|
var ackTimeout = null;
|
|
1006
|
+
var dataTimeout = null;
|
|
961
1007
|
var ACK = Buffer.alloc(1, 6, "hex");
|
|
962
1008
|
var NACK = Buffer.alloc(1, 21, "hex");
|
|
963
1009
|
var dataBuffer = Buffer.alloc(0);
|
|
@@ -973,6 +1019,10 @@ var require_communication = __commonJS({
|
|
|
973
1019
|
clearTimeout(ackTimeout);
|
|
974
1020
|
ackTimeout = null;
|
|
975
1021
|
}
|
|
1022
|
+
if (dataTimeout) {
|
|
1023
|
+
clearTimeout(dataTimeout);
|
|
1024
|
+
dataTimeout = null;
|
|
1025
|
+
}
|
|
976
1026
|
};
|
|
977
1027
|
module2.exports.checkACKorNACK = () => {
|
|
978
1028
|
if (ackTimeout) clearTimeout(ackTimeout);
|
|
@@ -992,12 +1042,12 @@ var require_communication = __commonJS({
|
|
|
992
1042
|
message: `On ACK/NACK Listener: Terminal did not respond with ACK/NACK after max ${count} retries. Sending TERMINAL_ERROR to client.`
|
|
993
1043
|
});
|
|
994
1044
|
sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
|
|
995
|
-
|
|
1045
|
+
status: "FAILED",
|
|
996
1046
|
action: "TERMINAL_ERROR"
|
|
997
1047
|
});
|
|
998
1048
|
}
|
|
999
1049
|
}
|
|
1000
|
-
},
|
|
1050
|
+
}, 2e3);
|
|
1001
1051
|
};
|
|
1002
1052
|
var resendData = () => {
|
|
1003
1053
|
if (requestType == "STATUS_CHECK") {
|
|
@@ -1097,6 +1147,7 @@ var require_communication = __commonJS({
|
|
|
1097
1147
|
clearTimeout(ackTimeout);
|
|
1098
1148
|
ackTimeout = null;
|
|
1099
1149
|
}
|
|
1150
|
+
exports2.startDataTimeout();
|
|
1100
1151
|
if (byte === 21) {
|
|
1101
1152
|
count--;
|
|
1102
1153
|
if (count >= 0) {
|
|
@@ -1107,7 +1158,7 @@ var require_communication = __commonJS({
|
|
|
1107
1158
|
level: "error",
|
|
1108
1159
|
message: `Terminal responded with NACK multiple times. Max retries reached. Sending TERMINAL_ERROR.`
|
|
1109
1160
|
});
|
|
1110
|
-
sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
|
|
1161
|
+
sendMessage2("clientRoom", "PAYMENT_MESSAGE", { status: "FAILED", action: "TERMINAL_ERROR" });
|
|
1111
1162
|
}
|
|
1112
1163
|
}
|
|
1113
1164
|
continue;
|
|
@@ -1163,18 +1214,37 @@ var require_communication = __commonJS({
|
|
|
1163
1214
|
}
|
|
1164
1215
|
}
|
|
1165
1216
|
};
|
|
1217
|
+
module2.exports.triggerRecovery = () => {
|
|
1218
|
+
const { generateFunction56Request } = require_hexRequest();
|
|
1219
|
+
exports2.reset();
|
|
1220
|
+
lrcCount = WRONG_LRC_MAX_COUNT;
|
|
1221
|
+
count = MAX_COUNT;
|
|
1222
|
+
const req = generateFunction56Request();
|
|
1223
|
+
requestType = "RECOVERY";
|
|
1224
|
+
calculated = req;
|
|
1225
|
+
logger.log({ level: "info", message: "\u{1F680} Triggering Recovery (Function 56) due to LRC failures..." });
|
|
1226
|
+
global.port.write(req.buffer);
|
|
1227
|
+
exports2.checkACKorNACK();
|
|
1228
|
+
};
|
|
1166
1229
|
module2.exports.handleFullMessage = (fullFrame) => {
|
|
1167
|
-
const { checkLrc: checkLrc2, terminalStatus: terminalStatus2, terminalLogon: terminalLogon2, terminalPayment: terminalPayment2, terminalCreditPayment: terminalCreditPayment2 } = require_responseHandler();
|
|
1230
|
+
const { checkLrc: checkLrc2, terminalStatus: terminalStatus2, terminalLogon: terminalLogon2, terminalPayment: terminalPayment2, terminalCreditPayment: terminalCreditPayment2, terminalRecovery } = require_responseHandler();
|
|
1168
1231
|
if (ackTimeout) {
|
|
1169
1232
|
clearTimeout(ackTimeout);
|
|
1170
1233
|
ackTimeout = null;
|
|
1171
1234
|
}
|
|
1235
|
+
if (dataTimeout) {
|
|
1236
|
+
clearTimeout(dataTimeout);
|
|
1237
|
+
dataTimeout = null;
|
|
1238
|
+
}
|
|
1172
1239
|
ackOrNack = Buffer.from([6]);
|
|
1173
1240
|
const hexFrame = fullFrame.toString("hex").toUpperCase();
|
|
1174
1241
|
logger.log({ level: "info", message: `Full frame processed: ${hexFrame}` });
|
|
1175
|
-
|
|
1242
|
+
const isLrcCorrect = checkLrc2(hexFrame);
|
|
1243
|
+
if (isLrcCorrect) {
|
|
1176
1244
|
logger.log({ level: "info", message: `LRC Correct. Sending ACK (0x06).` });
|
|
1177
1245
|
global.port.write(ACK);
|
|
1246
|
+
lrcCount = WRONG_LRC_MAX_COUNT;
|
|
1247
|
+
count = MAX_COUNT;
|
|
1178
1248
|
logger.log({ level: "info", message: `requestType: ${requestType}` });
|
|
1179
1249
|
if (requestType === "STATUS_CHECK") {
|
|
1180
1250
|
terminalStatus2(calculated?.ecn, hexFrame);
|
|
@@ -1184,12 +1254,65 @@ var require_communication = __commonJS({
|
|
|
1184
1254
|
terminalPayment2(hexFrame, calculated?.ecn);
|
|
1185
1255
|
} else if (requestType === "CREDIT_PAYMENT") {
|
|
1186
1256
|
terminalCreditPayment2(hexFrame, calculated?.ecn);
|
|
1257
|
+
} else if (requestType === "RECOVERY") {
|
|
1258
|
+
terminalRecovery(hexFrame);
|
|
1187
1259
|
}
|
|
1188
1260
|
} else {
|
|
1189
|
-
|
|
1190
|
-
|
|
1261
|
+
lrcCount--;
|
|
1262
|
+
if (lrcCount > 0) {
|
|
1263
|
+
logger.log({ level: "error", message: `LRC Incorrect. Sending NACK (0x15). Retries left: ${lrcCount}` });
|
|
1264
|
+
global.port.write(NACK);
|
|
1265
|
+
} else {
|
|
1266
|
+
if (hexFrame.indexOf("415050524F564544") > -1) {
|
|
1267
|
+
logger.log({ level: "info", message: "\u2705 LRC Incorrect 3 times, but APPROVED found in hex payload. Accepting with ACK." });
|
|
1268
|
+
global.port.write(ACK);
|
|
1269
|
+
lrcCount = WRONG_LRC_MAX_COUNT;
|
|
1270
|
+
count = MAX_COUNT;
|
|
1271
|
+
if (requestType === "PAYMENT") terminalPayment2(hexFrame, calculated?.ecn);
|
|
1272
|
+
else if (requestType === "CREDIT_PAYMENT") terminalCreditPayment2(hexFrame, calculated?.ecn);
|
|
1273
|
+
else if (requestType === "RECOVERY") terminalRecovery(hexFrame);
|
|
1274
|
+
else if (requestType === "LOGON") terminalLogon2(calculated?.ecn, hexFrame);
|
|
1275
|
+
else if (requestType === "STATUS_CHECK") terminalStatus2(calculated?.ecn, hexFrame);
|
|
1276
|
+
} else {
|
|
1277
|
+
logger.log({ level: "warn", message: `LRC Incorrect 3 times and NO approval found. Stopping.` });
|
|
1278
|
+
global.port.write(NACK);
|
|
1279
|
+
if (ackTimeout) {
|
|
1280
|
+
clearTimeout(ackTimeout);
|
|
1281
|
+
ackTimeout = null;
|
|
1282
|
+
}
|
|
1283
|
+
if (requestType !== "RECOVERY") {
|
|
1284
|
+
sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
|
|
1285
|
+
status: "UNKNOWN",
|
|
1286
|
+
action: "VERIFYING_STATUS",
|
|
1287
|
+
message: "Payment status uncertain. Please wait while we verify...",
|
|
1288
|
+
reason: "LRC_FAILURE"
|
|
1289
|
+
});
|
|
1290
|
+
setTimeout(() => exports2.triggerRecovery(), 2e3);
|
|
1291
|
+
} else {
|
|
1292
|
+
sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
|
|
1293
|
+
status: "FAILED",
|
|
1294
|
+
action: "CANCELLED",
|
|
1295
|
+
message: "Payment needs manual verification / Recovery failed.",
|
|
1296
|
+
reason: "RECOVERY_LRC_FAILURE"
|
|
1297
|
+
});
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1191
1301
|
}
|
|
1192
1302
|
};
|
|
1303
|
+
module2.exports.startDataTimeout = () => {
|
|
1304
|
+
if (dataTimeout) clearTimeout(dataTimeout);
|
|
1305
|
+
dataTimeout = setTimeout(() => {
|
|
1306
|
+
dataTimeout = null;
|
|
1307
|
+
logger.error({ level: "error", message: `Terminal response time out (60 seconds) after ACK.` });
|
|
1308
|
+
sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
|
|
1309
|
+
status: "FAILED",
|
|
1310
|
+
action: "TERMINAL_ERROR",
|
|
1311
|
+
message: "Terminal response time out (60 seconds)"
|
|
1312
|
+
});
|
|
1313
|
+
exports2.reset();
|
|
1314
|
+
}, 6e4);
|
|
1315
|
+
};
|
|
1193
1316
|
module2.exports.checkPortConnection = async () => {
|
|
1194
1317
|
const portPath = config.simulation ? config.simulationPort : config.com;
|
|
1195
1318
|
try {
|
|
@@ -1292,7 +1415,7 @@ var require_package = __commonJS({
|
|
|
1292
1415
|
"package.json"(exports2, module2) {
|
|
1293
1416
|
module2.exports = {
|
|
1294
1417
|
name: "nets-service-sdk",
|
|
1295
|
-
version: "1.1.
|
|
1418
|
+
version: "1.1.20",
|
|
1296
1419
|
description: "Utility functions for Nets Service",
|
|
1297
1420
|
source: "src/index.js",
|
|
1298
1421
|
main: "dist/index.js",
|
|
@@ -1301,7 +1424,7 @@ var require_package = __commonJS({
|
|
|
1301
1424
|
scripts: {
|
|
1302
1425
|
build: "esbuild src/index.js --bundle --platform=node --packages=external --outfile=dist/index.js",
|
|
1303
1426
|
watch: "microbundle watch",
|
|
1304
|
-
test:
|
|
1427
|
+
test: "jest"
|
|
1305
1428
|
},
|
|
1306
1429
|
keywords: [
|
|
1307
1430
|
"nets",
|
|
@@ -1327,10 +1450,12 @@ var require_package = __commonJS({
|
|
|
1327
1450
|
request: "^2.88.2",
|
|
1328
1451
|
serialport: "^10.5.0",
|
|
1329
1452
|
"socket.io-client": "^4.7.2",
|
|
1330
|
-
winston: "^3.8.2"
|
|
1453
|
+
winston: "^3.8.2",
|
|
1454
|
+
"winston-daily-rotate-file": "^5.0.0"
|
|
1331
1455
|
},
|
|
1332
1456
|
devDependencies: {
|
|
1333
1457
|
esbuild: "^0.27.0",
|
|
1458
|
+
jest: "^30.3.0",
|
|
1334
1459
|
microbundle: "^0.15.1"
|
|
1335
1460
|
}
|
|
1336
1461
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nets-service-sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.20",
|
|
4
4
|
"description": "Utility functions for Nets Service",
|
|
5
5
|
"source": "src/index.js",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "esbuild src/index.js --bundle --platform=node --packages=external --outfile=dist/index.js",
|
|
11
11
|
"watch": "microbundle watch",
|
|
12
|
-
"test": "
|
|
12
|
+
"test": "jest"
|
|
13
13
|
},
|
|
14
14
|
"keywords": [
|
|
15
15
|
"nets",
|
|
@@ -35,10 +35,12 @@
|
|
|
35
35
|
"request": "^2.88.2",
|
|
36
36
|
"serialport": "^10.5.0",
|
|
37
37
|
"socket.io-client": "^4.7.2",
|
|
38
|
-
"winston": "^3.8.2"
|
|
38
|
+
"winston": "^3.8.2",
|
|
39
|
+
"winston-daily-rotate-file": "^5.0.0"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
42
|
"esbuild": "^0.27.0",
|
|
43
|
+
"jest": "^30.3.0",
|
|
42
44
|
"microbundle": "^0.15.1"
|
|
43
45
|
}
|
|
44
46
|
}
|