nets-service-sdk 1.1.15 → 1.1.17

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 (2) hide show
  1. package/dist/index.js +179 -49
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12,16 +12,15 @@ var require_utils_helper = __commonJS({
12
12
  return String(num).padStart(totalLength, "0");
13
13
  };
14
14
  module2.exports.xorCalculation = (value) => {
15
- const splitted_arr = value.match(/[\w]{2}/g);
16
- let response = "";
17
- _.map(splitted_arr, (value2, i) => {
18
- if (i == 0) {
19
- response = value2;
20
- } else {
21
- response = xor(response, value2);
22
- }
23
- });
24
- return response.toUpperCase();
15
+ if (!value) return "00";
16
+ const splitted_arr = value.match(/[0-9A-Fa-f]{2}/g);
17
+ if (!splitted_arr) return "00";
18
+ let res = Buffer.from(splitted_arr[0], "hex");
19
+ for (let i = 1; i < splitted_arr.length; i++) {
20
+ const nextByte = Buffer.from(splitted_arr[i], "hex");
21
+ res[0] ^= nextByte[0];
22
+ }
23
+ return res.toString("hex").toUpperCase();
25
24
  };
26
25
  String.prototype.toHexString = function() {
27
26
  var res = [];
@@ -32,12 +31,6 @@ var require_utils_helper = __commonJS({
32
31
  }
33
32
  return res.join("").toUpperCase();
34
33
  };
35
- function xor(hex1, hex2) {
36
- const buf1 = Buffer.from(hex1, "hex");
37
- const buf2 = Buffer.from(hex2, "hex");
38
- const bufResult = buf1.map((b, i) => b ^ buf2[i]);
39
- return bufResult.toString("hex");
40
- }
41
34
  String.prototype.toAsciiString = function() {
42
35
  return this.match(/.{1,2}/g).map(function(v) {
43
36
  return String.fromCharCode(parseInt(v, 16));
@@ -190,7 +183,22 @@ var require_queue = __commonJS({
190
183
  var require_sendMessage = __commonJS({
191
184
  "src/sendMessage.js"(exports2, module2) {
192
185
  var logger = require_winston()(module2);
186
+ var path = require("path");
187
+ var fs = require("fs");
188
+ var sdkVersion = "unknown";
189
+ try {
190
+ const pkgPath = path.resolve(__dirname, "../package.json");
191
+ if (fs.existsSync(pkgPath)) {
192
+ const pkg2 = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
193
+ sdkVersion = pkg2.version;
194
+ }
195
+ } catch (err) {
196
+ logger.error({ level: "error", message: `Error reading SDK package.json: ${err.message}` });
197
+ }
193
198
  module2.exports.sendMessage = (room = "clientRoom", tag, msg) => {
199
+ if (typeof msg === "object" && msg !== null) {
200
+ msg.sdkVersion = sdkVersion;
201
+ }
194
202
  logger.log({
195
203
  level: "info",
196
204
  message: JSON.stringify(msg)
@@ -353,6 +361,40 @@ var require_httpRequest = __commonJS({
353
361
  var require_parser = __commonJS({
354
362
  "src/payment/parser.js"(exports2, module2) {
355
363
  var logger = require_winston()(module2);
364
+ var RESPONSE_CODES = {
365
+ "00": { status: "APPROVED", detail: "SUCCESS", category: "SUCCESS" },
366
+ "04": { status: "DECLINED", detail: "PICKUP_CARD", category: "HARD_FAIL" },
367
+ "05": { status: "DECLINED", detail: "DO_NOT_HONOUR", category: "HARD_FAIL" },
368
+ "07": { status: "DECLINED", detail: "PICKUP_CARD_SPECIAL", category: "HARD_FAIL" },
369
+ "12": { status: "DECLINED", detail: "INVALID_TRANSACTION", category: "HARD_FAIL" },
370
+ "13": { status: "DECLINED", detail: "INVALID_AMOUNT", category: "HARD_FAIL" },
371
+ "14": { status: "DECLINED", detail: "INVALID_CARD", category: "HARD_FAIL" },
372
+ "30": { status: "DECLINED", detail: "FORMAT_ERROR", category: "HARD_FAIL" },
373
+ "41": { status: "DECLINED", detail: "LOST_CARD", category: "HARD_FAIL" },
374
+ "43": { status: "DECLINED", detail: "STOLEN_CARD", category: "HARD_FAIL" },
375
+ "51": { status: "DECLINED", detail: "INSUFFICIENT_FUNDS", category: "HARD_FAIL" },
376
+ "54": { status: "DECLINED", detail: "EXPIRED_CARD", category: "HARD_FAIL" },
377
+ "55": { status: "DECLINED", detail: "WRONG_PIN", category: "HARD_FAIL" },
378
+ "57": { status: "DECLINED", detail: "NOT_PERMITTED", category: "HARD_FAIL" },
379
+ "58": { status: "DECLINED", detail: "TERMINAL_NOT_ALLOWED", category: "HARD_FAIL" },
380
+ "61": { status: "DECLINED", detail: "LIMIT_EXCEEDED", category: "HARD_FAIL" },
381
+ "62": { status: "DECLINED", detail: "RESTRICTED_CARD", category: "HARD_FAIL" },
382
+ "63": { status: "DECLINED", detail: "SECURITY_ISSUE", category: "HARD_FAIL" },
383
+ "65": { status: "DECLINED", detail: "FREQUENCY_LIMIT", category: "HARD_FAIL" },
384
+ "68": { status: "RETRY", detail: "RESPONSE_RECEIVED_TOO_LATE", category: "RETRY" },
385
+ "75": { status: "DECLINED", detail: "PIN_LOCKED", category: "HARD_FAIL" },
386
+ "91": { status: "RETRY", detail: "ISSUER_UNAVAILABLE", category: "RETRY" },
387
+ "96": { status: "DECLINED", detail: "SYSTEM_ERROR", category: "HARD_FAIL" },
388
+ "TO": { status: "TIME_OUT", detail: "TIMEOUT", category: "RETRY" },
389
+ "CE": { status: "RETRY", detail: "COMMUNICATION_ERROR", category: "RETRY" },
390
+ "PE": { status: "DECLINED", detail: "PROTOCOL_ERROR", category: "HARD_FAIL" },
391
+ "NA": { status: "RETRY", detail: "NO_ACKNOWLEDGEMENT", category: "RETRY" },
392
+ "US": { status: "USER_CANCELLED", detail: "USER_CANCELLED", category: "HARD_FAIL" },
393
+ "GX": { status: "OUT_OF_PAPER", detail: "OUT_OF_PAPER", category: "HARD_FAIL" }
394
+ };
395
+ function getResponseFromCode(code) {
396
+ return RESPONSE_CODES[code] || null;
397
+ }
356
398
  module2.exports.statusParser = (hexCode, ecn) => {
357
399
  const splitted = hexCode.split("1C");
358
400
  for (let i = 0; i < splitted.length; i++) {
@@ -377,11 +419,11 @@ var require_parser = __commonJS({
377
419
  } else {
378
420
  const subStringArray = ascii.splitAtIndex(2);
379
421
  if (subStringArray.length > 0) {
380
- if (subStringArray.length > 2 && subStringArray[0] == "02" && subStringArray[0]?.indexOf("APPROVED") > -1) {
422
+ if (subStringArray.length > 1 && subStringArray[0].cleanUp() == "02" && subStringArray[1].cleanUp()?.indexOf("APPROVED") > -1) {
381
423
  status = true;
382
424
  }
383
425
  const identifier = subStringArray[0].cleanUp();
384
- const value = subStringArray[1].cleanUp();
426
+ const value = subStringArray[1]?.cleanUp();
385
427
  if (identifier && value) {
386
428
  json[identifier] = value;
387
429
  }
@@ -465,6 +507,7 @@ var require_parser = __commonJS({
465
507
  if (statusResponse) {
466
508
  translatedJson.status = statusResponse.status;
467
509
  translatedJson.description = statusResponse.detail;
510
+ translatedJson.category = statusResponse.category;
468
511
  if (statusResponse.balance) {
469
512
  translatedJson["balance"] = statusResponse.balance;
470
513
  }
@@ -473,6 +516,7 @@ var require_parser = __commonJS({
473
516
  if (ecnnError) {
474
517
  translatedJson.status = ecnnError.status;
475
518
  translatedJson.description = ecnnError.detail;
519
+ translatedJson.category = ecnnError.category;
476
520
  }
477
521
  translatedJson["responsetext"] = obj[key];
478
522
  }
@@ -553,6 +597,12 @@ var require_parser = __commonJS({
553
597
  }
554
598
  if (key == "HC") {
555
599
  translatedJson["hostResponseCode"] = obj[key];
600
+ const mapped = getResponseFromCode(obj[key]);
601
+ if (mapped) {
602
+ translatedJson.status = mapped.status;
603
+ translatedJson.description = mapped.detail;
604
+ translatedJson.category = mapped.category;
605
+ }
556
606
  }
557
607
  if (key == "HD") {
558
608
  translatedJson["enhancedECRReferenceNumber"] = obj[key];
@@ -598,8 +648,19 @@ var require_parser = __commonJS({
598
648
  return { translated: translatedJson, raw: obj };
599
649
  };
600
650
  function statusCheck(data) {
651
+ if (!data) return null;
652
+ const code = data.substring(0, 2);
653
+ const mapped = getResponseFromCode(code);
654
+ if (mapped) {
655
+ const result = { ...mapped };
656
+ if (code === "00" && data.indexOf("BAL:") > -1) {
657
+ const balance = data.split("BAL:");
658
+ result.balance = balance[1].trim();
659
+ }
660
+ return result;
661
+ }
601
662
  if (data?.indexOf("APPROVED") > -1) {
602
- const response = { status: "APPROVED", detail: "Payment Succeed" };
663
+ const response = { status: "APPROVED", detail: "Payment Succeed", category: "SUCCESS" };
603
664
  if (data?.indexOf("BAL:") > -1) {
604
665
  const balance = data.split("BAL:");
605
666
  response.balance = balance[1].trim();
@@ -607,28 +668,25 @@ var require_parser = __commonJS({
607
668
  return response;
608
669
  }
609
670
  if (data?.indexOf("INVALID CARD") > -1) {
610
- return { status: "INVALID_CARD", detail: "Invalid Card" };
671
+ return { status: "INVALID_CARD", detail: "Invalid Card", category: "HARD_FAIL" };
611
672
  }
612
673
  if (data?.indexOf("F3905-Parameter") > -1) {
613
- return { status: "INVALID_CARD", detail: "Invalid Card" };
674
+ return { status: "INVALID_CARD", detail: "Invalid Card", category: "HARD_FAIL" };
614
675
  }
615
676
  if (data?.indexOf("DECLINED") > -1) {
616
- return { status: "DECLINED", detail: "Transaction Declined" };
677
+ return { status: "DECLINED", detail: "Transaction Declined", category: "HARD_FAIL" };
617
678
  }
618
679
  if (data?.indexOf("CARD NOT SUPPORTED") > -1) {
619
- return { status: "CARD_NOT_SUPPORTED", detail: "Card not supported" };
680
+ return { status: "CARD_NOT_SUPPORTED", detail: "Card not supported", category: "HARD_FAIL" };
620
681
  }
621
682
  return null;
622
683
  }
623
684
  function CheckECNERROR(data) {
624
- if (data?.indexOf("US") > -1) {
625
- return { status: "USER_CANCELLED", detail: "User Cancelled" };
626
- }
627
- if (data?.indexOf("GX") > -1) {
628
- return { status: "OUT_OF_PAPER", detail: "Out of Paper" };
629
- }
630
- if (data?.indexOf("TO") > -1) {
631
- return { status: "TIME_OUT", detail: "Time Out" };
685
+ if (!data) return null;
686
+ for (const code of ["US", "GX", "TO"]) {
687
+ if (data.indexOf(code) > -1) {
688
+ return getResponseFromCode(code);
689
+ }
632
690
  }
633
691
  return null;
634
692
  }
@@ -770,7 +828,7 @@ var require_responseHandler = __commonJS({
770
828
  activePaymentEcn = null;
771
829
  }
772
830
  if (response.translated) {
773
- if (response.translated.status == "APPROVED") {
831
+ if (response.translated.category == "SUCCESS" || response.translated.status == "APPROVED") {
774
832
  sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
775
833
  success: true,
776
834
  status: "SUCCESS",
@@ -778,15 +836,13 @@ var require_responseHandler = __commonJS({
778
836
  action: "COMPLETED"
779
837
  });
780
838
  sendPaymentResponseToCloud(response.translated);
781
- }
782
- if (response.translated.status == "TIME_OUT") {
839
+ } else if (response.translated.category == "RETRY" || response.translated.status == "TIME_OUT") {
783
840
  sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
784
841
  status: "RETRY",
785
842
  response,
786
843
  action: "RETRY"
787
844
  });
788
- }
789
- if (response.translated.status == "USER_CANCELLED" || response.translated.status == "OUT_OF_PAPER" || response.translated.status == "INVALID_CARD" || response.translated.status == "DECLINED" || response.translated.status == "CARD_NOT_SUPPORTED") {
845
+ } else {
790
846
  sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
791
847
  status: "CANCELLED",
792
848
  response,
@@ -803,7 +859,7 @@ var require_responseHandler = __commonJS({
803
859
  activePaymentEcn = null;
804
860
  }
805
861
  if (response.translated) {
806
- if (response.translated.status == "APPROVED") {
862
+ if (response.translated.category == "SUCCESS" || response.translated.status == "APPROVED") {
807
863
  sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
808
864
  success: true,
809
865
  status: "SUCCESS",
@@ -811,15 +867,13 @@ var require_responseHandler = __commonJS({
811
867
  action: "COMPLETED"
812
868
  });
813
869
  sendPaymentResponseToCloud(response.translated);
814
- }
815
- if (response.translated.status == "TIME_OUT") {
870
+ } else if (response.translated.category == "RETRY" || response.translated.status == "TIME_OUT") {
816
871
  sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
817
872
  status: "RETRY",
818
873
  response,
819
874
  action: "RETRY"
820
875
  });
821
- }
822
- if (response.translated.status == "USER_CANCELLED" || response.translated.status == "OUT_OF_PAPER" || response.translated.status == "INVALID_CARD" || response.translated.status == "DECLINED" || response.translated.status == "CARD_NOT_SUPPORTED") {
876
+ } else {
823
877
  sendMessage2("clientRoom", "PAYMENT_MESSAGE", {
824
878
  status: "CANCELLED",
825
879
  response,
@@ -852,9 +906,17 @@ var require_responseHandler = __commonJS({
852
906
  if (!hexValue || hexValue.length < 4) return false;
853
907
  const value = hexValue.substring(2, hexValue.length - 2);
854
908
  const xor = xorCalculation(value).toUpperCase();
855
- const lrcCheck = hexValue.substring(hexValue.length - 2, hexValue.length).toUpperCase();
856
- logger.info({ level: "info", message: `LRC Check: Calculated ${xor} vs Received ${lrcCheck}` });
857
- return xor === lrcCheck;
909
+ const lrcReceived = hexValue.substring(hexValue.length - 2, hexValue.length).toUpperCase();
910
+ const isMatch = xor === lrcReceived;
911
+ if (!isMatch) {
912
+ logger.error({
913
+ level: "error",
914
+ message: `LRC Mismatch! Calculated: ${xor}, Received: ${lrcReceived}. Checked range (hex): ${value.substring(0, 20)}...${value.substring(value.length - 10)}`
915
+ });
916
+ } else {
917
+ logger.info({ level: "info", message: `LRC Correct: ${xor}` });
918
+ }
919
+ return isMatch;
858
920
  };
859
921
  }
860
922
  });
@@ -1022,7 +1084,7 @@ var require_communication = __commonJS({
1022
1084
  };
1023
1085
  module2.exports.processIncomingData = () => {
1024
1086
  while (dataBuffer.length > 0) {
1025
- if (dataBuffer[0] === 6 || dataBuffer[0] === 21) {
1087
+ if ((dataBuffer[0] === 6 || dataBuffer[0] === 21) && (dataBuffer.length === 1 || dataBuffer[1] !== 2)) {
1026
1088
  const byte = dataBuffer[0];
1027
1089
  ackOrNack = Buffer.from([byte]);
1028
1090
  dataBuffer = dataBuffer.slice(1);
@@ -1057,10 +1119,26 @@ var require_communication = __commonJS({
1057
1119
  }
1058
1120
  }
1059
1121
  if (dataBuffer.length < 3) break;
1060
- const lenBytes = dataBuffer.slice(1, 3).toString("hex");
1061
- const bodyLen = parseInt(lenBytes, 10);
1062
- const expectedFrameSize = 1 + 2 + bodyLen + 2;
1063
- if (dataBuffer.length < expectedFrameSize) break;
1122
+ const bcdLenStr = dataBuffer.slice(1, 3).toString("hex");
1123
+ const bcdLen = parseInt(bcdLenStr, 10);
1124
+ const binLen = dataBuffer.readUInt16BE(1);
1125
+ let bodyLen = bcdLen;
1126
+ let expectedFrameSize = 1 + 2 + bodyLen + 2;
1127
+ if (dataBuffer.length >= expectedFrameSize && dataBuffer[3 + bodyLen] === 3) {
1128
+ } else if (dataBuffer.length >= 1 + 2 + binLen + 2 && dataBuffer[3 + binLen] === 3) {
1129
+ bodyLen = binLen;
1130
+ expectedFrameSize = 1 + 2 + bodyLen + 2;
1131
+ }
1132
+ if (dataBuffer.length < expectedFrameSize) {
1133
+ const etxIndex = dataBuffer.indexOf(3, 3);
1134
+ if (etxIndex !== -1 && dataBuffer.length > etxIndex + 1) {
1135
+ const frame = dataBuffer.slice(0, etxIndex + 2);
1136
+ dataBuffer = dataBuffer.slice(etxIndex + 2);
1137
+ exports2.handleFullMessage(frame);
1138
+ continue;
1139
+ }
1140
+ break;
1141
+ }
1064
1142
  if (dataBuffer[3 + bodyLen] === 3) {
1065
1143
  const frame = dataBuffer.slice(0, expectedFrameSize);
1066
1144
  dataBuffer = dataBuffer.slice(expectedFrameSize);
@@ -1205,6 +1283,56 @@ var require_communication = __commonJS({
1205
1283
  }
1206
1284
  });
1207
1285
 
1286
+ // package.json
1287
+ var require_package = __commonJS({
1288
+ "package.json"(exports2, module2) {
1289
+ module2.exports = {
1290
+ name: "nets-service-sdk",
1291
+ version: "1.1.17",
1292
+ description: "Utility functions for Nets Service",
1293
+ source: "src/index.js",
1294
+ main: "dist/index.js",
1295
+ module: "dist/index.module.js",
1296
+ unpkg: "dist/index.umd.js",
1297
+ scripts: {
1298
+ build: "esbuild src/index.js --bundle --platform=node --packages=external --outfile=dist/index.js",
1299
+ watch: "microbundle watch",
1300
+ test: 'echo "Error: no test specified" && exit 1'
1301
+ },
1302
+ keywords: [
1303
+ "nets",
1304
+ "payment",
1305
+ "terminal",
1306
+ "pos",
1307
+ "sqlite",
1308
+ "transaction",
1309
+ "serial",
1310
+ "payment-gateway"
1311
+ ],
1312
+ author: "dineshhv",
1313
+ license: "ISC",
1314
+ files: [
1315
+ "dist"
1316
+ ],
1317
+ dependencies: {
1318
+ "better-sqlite3": "^12.5.0",
1319
+ "dollars-to-cents": "^1.0.3",
1320
+ lodash: "^4.17.21",
1321
+ moment: "^2.29.4",
1322
+ "node-cron": "^4.2.1",
1323
+ request: "^2.88.2",
1324
+ serialport: "^10.5.0",
1325
+ "socket.io-client": "^4.7.2",
1326
+ winston: "^3.8.2"
1327
+ },
1328
+ devDependencies: {
1329
+ esbuild: "^0.27.0",
1330
+ microbundle: "^0.15.1"
1331
+ }
1332
+ };
1333
+ }
1334
+ });
1335
+
1208
1336
  // src/index.js
1209
1337
  var utilsHelper = require_utils_helper();
1210
1338
  var winston = require_winston();
@@ -1216,7 +1344,9 @@ var hexRequest = require_hexRequest();
1216
1344
  var httpRequest = require_httpRequest();
1217
1345
  var parser = require_parser();
1218
1346
  var responseHandler = require_responseHandler();
1347
+ var pkg = require_package();
1219
1348
  module.exports = {
1349
+ version: pkg.version,
1220
1350
  ...utilsHelper,
1221
1351
  logger: winston,
1222
1352
  manageConfig,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nets-service-sdk",
3
- "version": "1.1.15",
3
+ "version": "1.1.17",
4
4
  "description": "Utility functions for Nets Service",
5
5
  "source": "src/index.js",
6
6
  "main": "dist/index.js",