ibantools 3.2.4 → 4.0.0

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/ChangeLog CHANGED
@@ -1,6 +1,45 @@
1
+ 2021-11-17 Saša Jovanić <sasa@simplify.ba>
2
+ * Version 4.0.0
3
+ * Fixed Senegal (SN) regular expression
4
+ * Updated Burundi (BI) specification
5
+ * Added Spain (ES) extra BBAN validation
6
+ * Added Poland (PL) extra BBAN validation
7
+ * Added test to check for extra BBAN validation function
8
+
9
+ 2021-09-30 Simen Mailund Svendsen <simen.m.s@hotmail.com>
10
+ * Fix invalid norwegian BBANS (failing MOD11 check) being incorrectly returned as valid
11
+
12
+ 2021-07-24 Saša Jovanić <sasa@simplify.ba>
13
+ * Version 3.3.1
14
+ * Fixed issue not showing AD and BG as SEPA countries
15
+ * Fixed issue when incorrectly showing GL and FO as SEPA countryes
16
+ * Fixed incorrect documentation for `composeIBAN`
17
+ * Updates list of supported Node.js versions
18
+ * Update dev dependencies
19
+
20
+ 2021-05-05 Daniel Friesen <d@danf.ca>
21
+ * Fixed `validateIBAN`'s handling of unsupported countries like US
22
+ * Added checksum validation for unsupported/unknown countries to `validateIBAN`
23
+
24
+ 2021-04-03 Saša Jovanić <sasa@simplify.ba>
25
+ * Coverage improved to 100%
26
+
27
+ 2021-04-03 Saša Jovanić <sasa@simplify.ba>
28
+ * Version 3.3.0
29
+ * Error codes for IBAN and BIC validation. Added `validateIBAN` and `validateBIC` methods that will return error codes.
30
+
31
+ 2021-04-03 Saša Jovanić <sasa@simplify.ba>
32
+ * Version 3.2.5
33
+ * (Dependabot) Bump y18n from 3.2.1 to 3.2.2
34
+
35
+ 2021-03-29 Xavier Alvarez
36
+ * Fix validation for Burkina Faso, Benin, Algeria and Mali
37
+
1
38
  2021-03-10 Saša Jovanić <sasa@simplify.ba>
2
39
  * Version 3.2.4
3
40
  * Exported `countrySpecs` to restore a bit of compatibility broken in 3.2.3
41
+ * Updated development dependencies
42
+ * Documentation is now part of master branch
4
43
 
5
44
  2021-02-07 Saša Jovanić <sasa@simplify.ba>
6
45
  * Version 3.2.3
package/README.md CHANGED
@@ -43,6 +43,12 @@ See [full documentation](http://simplify.github.io/ibantools) with examples on G
43
43
  const ibantools = require('ibantools');
44
44
  const iban = electronicFormatIBAN('NL91 ABNA 0517 1643 00'); // 'NL91ABNA0517164300'
45
45
  ibantools.isValidIBAN(iban);
46
+
47
+ // If you want to know reason why IBAN is invalid
48
+ ibantools.validateIBAN('NL91ABNA0517164300');
49
+ // Returns { valid: false, errorCodes: [iban.ValidationErrorsIBAN.WrongIBANChecksum] }
50
+
51
+ // Validate BIC
46
52
  ibantools.isValidBIC('ABNANL2A');
47
53
  ```
48
54
 
@@ -13,8 +13,34 @@
13
13
  * // returns false
14
14
  * ibantools.isValidIBAN("NL92ABNA0517164300");
15
15
  * ```
16
- */
16
+ v */
17
17
  export declare function isValidIBAN(iban: string): boolean;
18
+ /**
19
+ * IBAM validation errors
20
+ */
21
+ export declare enum ValidationErrorsIBAN {
22
+ NoIBANProvided = 0,
23
+ NoIBANCountry = 1,
24
+ WrongBBANLength = 2,
25
+ WrongBBANFormat = 3,
26
+ ChecksumNotNumber = 4,
27
+ WrongIBANChecksum = 5
28
+ }
29
+ /**
30
+ * Interface for ValidateIBAN result
31
+ */
32
+ export interface ValidateIBANResult {
33
+ errorCodes: ValidationErrorsIBAN[];
34
+ valid: boolean;
35
+ }
36
+ /**
37
+ * validateIBAN
38
+ * ```
39
+ * // returns {errorCodes: [], valid: true}
40
+ * ibantools.validateIBAN("NL91 ABNA 0417 1643 00");
41
+ * ```
42
+ */
43
+ export declare function validateIBAN(iban?: string): ValidateIBANResult;
18
44
  /**
19
45
  * Validate BBAN
20
46
  *
@@ -52,7 +78,7 @@ export interface ComposeIBANParams {
52
78
  *
53
79
  * ```
54
80
  * // returns NL91ABNA0417164300
55
- * ibantools.composeIBAN("NL", "ABNA0417164300");
81
+ * ibantools.composeIBAN({ countryCode: "NL", bban: "ABNA0417164300" });
56
82
  * ```
57
83
  */
58
84
  export declare function composeIBAN(params: ComposeIBANParams): string | null;
@@ -114,7 +140,7 @@ export declare function friendlyFormatIBAN(iban?: string, separator?: string): s
114
140
  * let country = ibantools.getCountrySpecifications()[$(this).val()];
115
141
  * // Add country code letters to IBAN form field
116
142
  * $("input#iban").value($(this).val());
117
- * // Add new value to "pattern" attribute to #iban input text field
143
+ * // Add New value to "pattern" attribute to #iban input text field
118
144
  * $("input#iban").attr("pattern", $(this).val() + "[0-9]{2}" + country.bban_regexp.slice(1).replace("$",""));
119
145
  * });
120
146
  * ```
@@ -138,6 +164,29 @@ export declare function getCountrySpecifications(): CountryMap;
138
164
  * ```
139
165
  */
140
166
  export declare function isValidBIC(bic: string): boolean;
167
+ /**
168
+ * BIC validation errors
169
+ */
170
+ export declare enum ValidationErrorsBIC {
171
+ NoBICProvided = 0,
172
+ NoBICCountry = 1,
173
+ WrongBICFormat = 2
174
+ }
175
+ /**
176
+ * Interface for ValidateBIC result
177
+ */
178
+ export interface ValidateBICResult {
179
+ errorCodes: ValidationErrorsBIC[];
180
+ valid: boolean;
181
+ }
182
+ /**
183
+ * validateBIC
184
+ * ```
185
+ * // returns {errorCodes: [], valid: true}
186
+ * ibantools.validateBIC("NEDSZAJJXXX");
187
+ * ```
188
+ */
189
+ export declare function validateBIC(bic?: string): ValidateBICResult;
141
190
  /**
142
191
  * Interface for ExtractBIC result
143
192
  */
@@ -178,6 +227,7 @@ export interface CountryMap {
178
227
  interface CountrySpecInternal {
179
228
  chars?: number;
180
229
  bban_regexp?: string;
230
+ bban_validation_func?: (bban: string) => boolean;
181
231
  IBANRegistry?: boolean;
182
232
  SEPA?: boolean;
183
233
  }
@@ -5,16 +5,16 @@
5
5
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
6
  /**
7
7
  * Validation, extraction and creation of IBAN, BBAN, BIC/SWIFT numbers plus some other helpful stuff
8
- * @packageDocumentation
8
+ * @package Documentation
9
9
  * @author Saša Jovanić
10
10
  * @module ibantools
11
- * @version 3.2.4
11
+ * @version 4.0.0
12
12
  * @license MPL-2.0
13
13
  * @preferred
14
14
  */
15
15
  'use strict';
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.countrySpecs = exports.extractBIC = exports.isValidBIC = exports.getCountrySpecifications = exports.friendlyFormatIBAN = exports.electronicFormatIBAN = exports.extractIBAN = exports.composeIBAN = exports.isSEPACountry = exports.isValidBBAN = exports.isValidIBAN = void 0;
17
+ exports.countrySpecs = exports.extractBIC = exports.validateBIC = exports.ValidationErrorsBIC = exports.isValidBIC = exports.getCountrySpecifications = exports.friendlyFormatIBAN = exports.electronicFormatIBAN = exports.extractIBAN = exports.composeIBAN = exports.isSEPACountry = exports.isValidBBAN = exports.validateIBAN = exports.ValidationErrorsIBAN = exports.isValidIBAN = void 0;
18
18
  /**
19
19
  * Validate IBAN
20
20
  * ```
@@ -25,7 +25,7 @@ exports.countrySpecs = exports.extractBIC = exports.isValidBIC = exports.getCoun
25
25
  * // returns false
26
26
  * ibantools.isValidIBAN("NL92ABNA0517164300");
27
27
  * ```
28
- */
28
+ v */
29
29
  function isValidIBAN(iban) {
30
30
  if (iban !== undefined && iban !== null) {
31
31
  var reg = new RegExp('^[0-9]{2}$', '');
@@ -36,7 +36,7 @@ function isValidIBAN(iban) {
36
36
  spec.chars &&
37
37
  spec.chars === iban.length &&
38
38
  reg.test(iban.slice(2, 4)) &&
39
- checkFormatBBAN(iban.slice(4), spec.bban_regexp) &&
39
+ isValidBBAN(iban.slice(4), iban.slice(0, 2)) &&
40
40
  isValidIBANChecksum(iban)) {
41
41
  return true;
42
42
  }
@@ -44,6 +44,58 @@ function isValidIBAN(iban) {
44
44
  return false;
45
45
  }
46
46
  exports.isValidIBAN = isValidIBAN;
47
+ /**
48
+ * IBAM validation errors
49
+ */
50
+ var ValidationErrorsIBAN;
51
+ (function (ValidationErrorsIBAN) {
52
+ ValidationErrorsIBAN[ValidationErrorsIBAN["NoIBANProvided"] = 0] = "NoIBANProvided";
53
+ ValidationErrorsIBAN[ValidationErrorsIBAN["NoIBANCountry"] = 1] = "NoIBANCountry";
54
+ ValidationErrorsIBAN[ValidationErrorsIBAN["WrongBBANLength"] = 2] = "WrongBBANLength";
55
+ ValidationErrorsIBAN[ValidationErrorsIBAN["WrongBBANFormat"] = 3] = "WrongBBANFormat";
56
+ ValidationErrorsIBAN[ValidationErrorsIBAN["ChecksumNotNumber"] = 4] = "ChecksumNotNumber";
57
+ ValidationErrorsIBAN[ValidationErrorsIBAN["WrongIBANChecksum"] = 5] = "WrongIBANChecksum";
58
+ })(ValidationErrorsIBAN = exports.ValidationErrorsIBAN || (exports.ValidationErrorsIBAN = {}));
59
+ /**
60
+ * validateIBAN
61
+ * ```
62
+ * // returns {errorCodes: [], valid: true}
63
+ * ibantools.validateIBAN("NL91 ABNA 0417 1643 00");
64
+ * ```
65
+ */
66
+ function validateIBAN(iban) {
67
+ var result = { errorCodes: [], valid: true };
68
+ if (iban !== undefined && iban !== null && iban !== '') {
69
+ var spec = exports.countrySpecs[iban.slice(0, 2)];
70
+ if (!spec || !(spec.bban_regexp || spec.chars)) {
71
+ result.valid = false;
72
+ result.errorCodes.push(ValidationErrorsIBAN.NoIBANCountry);
73
+ }
74
+ if (spec && spec.chars && spec.chars !== iban.length) {
75
+ result.valid = false;
76
+ result.errorCodes.push(ValidationErrorsIBAN.WrongBBANLength);
77
+ }
78
+ if (spec && spec.bban_regexp && !isValidBBAN(iban.slice(4), iban.slice(0, 2))) {
79
+ result.valid = false;
80
+ result.errorCodes.push(ValidationErrorsIBAN.WrongBBANFormat);
81
+ }
82
+ var reg = new RegExp('^[0-9]{2}$', '');
83
+ if (!reg.test(iban.slice(2, 4))) {
84
+ result.valid = false;
85
+ result.errorCodes.push(ValidationErrorsIBAN.ChecksumNotNumber);
86
+ }
87
+ if (!isValidIBANChecksum(iban)) {
88
+ result.valid = false;
89
+ result.errorCodes.push(ValidationErrorsIBAN.WrongIBANChecksum);
90
+ }
91
+ }
92
+ else {
93
+ result.valid = false;
94
+ result.errorCodes.push(ValidationErrorsIBAN.NoIBANProvided);
95
+ }
96
+ return result;
97
+ }
98
+ exports.validateIBAN = validateIBAN;
47
99
  /**
48
100
  * Validate BBAN
49
101
  *
@@ -67,6 +119,9 @@ function isValidBBAN(bban, countryCode) {
67
119
  spec.chars !== null &&
68
120
  spec.chars - 4 === bban.length &&
69
121
  checkFormatBBAN(bban, spec.bban_regexp)) {
122
+ if (spec.bban_validation_func) {
123
+ return spec.bban_validation_func(bban.replace(/[\s.]+/g, ''));
124
+ }
70
125
  return true;
71
126
  }
72
127
  }
@@ -99,7 +154,7 @@ exports.isSEPACountry = isSEPACountry;
99
154
  *
100
155
  * ```
101
156
  * // returns NL91ABNA0417164300
102
- * ibantools.composeIBAN("NL", "ABNA0417164300");
157
+ * ibantools.composeIBAN({ countryCode: "NL", bban: "ABNA0417164300" });
103
158
  * ```
104
159
  */
105
160
  function composeIBAN(params) {
@@ -189,6 +244,7 @@ function friendlyFormatIBAN(iban, separator) {
189
244
  separator = ' ';
190
245
  }
191
246
  var electronic_iban = electronicFormatIBAN(iban);
247
+ /* istanbul ignore if */
192
248
  if (electronic_iban === null) {
193
249
  return null;
194
250
  }
@@ -260,7 +316,7 @@ function mod9710(iban) {
260
316
  * let country = ibantools.getCountrySpecifications()[$(this).val()];
261
317
  * // Add country code letters to IBAN form field
262
318
  * $("input#iban").value($(this).val());
263
- * // Add new value to "pattern" attribute to #iban input text field
319
+ * // Add New value to "pattern" attribute to #iban input text field
264
320
  * $("input#iban").attr("pattern", $(this).val() + "[0-9]{2}" + country.bban_regexp.slice(1).replace("$",""));
265
321
  * });
266
322
  * ```
@@ -305,6 +361,45 @@ function isValidBIC(bic) {
305
361
  return reg.test(bic) && spec !== undefined;
306
362
  }
307
363
  exports.isValidBIC = isValidBIC;
364
+ /**
365
+ * BIC validation errors
366
+ */
367
+ var ValidationErrorsBIC;
368
+ (function (ValidationErrorsBIC) {
369
+ ValidationErrorsBIC[ValidationErrorsBIC["NoBICProvided"] = 0] = "NoBICProvided";
370
+ ValidationErrorsBIC[ValidationErrorsBIC["NoBICCountry"] = 1] = "NoBICCountry";
371
+ ValidationErrorsBIC[ValidationErrorsBIC["WrongBICFormat"] = 2] = "WrongBICFormat";
372
+ })(ValidationErrorsBIC = exports.ValidationErrorsBIC || (exports.ValidationErrorsBIC = {}));
373
+ /**
374
+ * validateBIC
375
+ * ```
376
+ * // returns {errorCodes: [], valid: true}
377
+ * ibantools.validateBIC("NEDSZAJJXXX");
378
+ * ```
379
+ */
380
+ function validateBIC(bic) {
381
+ var result = { errorCodes: [], valid: true };
382
+ if (bic !== undefined && bic !== null && bic !== '') {
383
+ var spec = exports.countrySpecs[bic.toUpperCase().slice(4, 6)];
384
+ if (spec === undefined) {
385
+ result.valid = false;
386
+ result.errorCodes.push(ValidationErrorsBIC.NoBICCountry);
387
+ }
388
+ else {
389
+ var reg = new RegExp('^[a-zA-Z]{6}[a-zA-Z0-9]{2}([a-zA-Z0-9]{3})?$', '');
390
+ if (!reg.test(bic)) {
391
+ result.valid = false;
392
+ result.errorCodes.push(ValidationErrorsBIC.WrongBICFormat);
393
+ }
394
+ }
395
+ }
396
+ else {
397
+ result.valid = false;
398
+ result.errorCodes.push(ValidationErrorsBIC.NoBICProvided);
399
+ }
400
+ return result;
401
+ }
402
+ exports.validateBIC = validateBIC;
308
403
  /**
309
404
  * extractBIC
310
405
  * ```
@@ -329,6 +424,71 @@ function extractBIC(inputBic) {
329
424
  return result;
330
425
  }
331
426
  exports.extractBIC = extractBIC;
427
+ /**
428
+ * Used for Norway BBAN check
429
+ *
430
+ * @ignore
431
+ */
432
+ var checkNorwayBBAN = function (bban) {
433
+ var weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
434
+ var bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, '');
435
+ if (bbanWithoutSpacesAndPeriods.length !== 11) {
436
+ return false;
437
+ }
438
+ else {
439
+ var controlDigit = parseInt(bbanWithoutSpacesAndPeriods.charAt(10), 10);
440
+ var bbanWithoutControlDigit = bbanWithoutSpacesAndPeriods.substring(0, 10);
441
+ var sum = 0;
442
+ for (var index = 0; index < 10; index++) {
443
+ sum += parseInt(bbanWithoutControlDigit.charAt(index), 10) * weights[index];
444
+ }
445
+ var remainder = sum % 11;
446
+ return controlDigit === (remainder === 0 ? 0 : 11 - remainder);
447
+ }
448
+ };
449
+ /**
450
+ * Used for Poland BBAN check
451
+ *
452
+ * @ignore
453
+ */
454
+ var checkPolandBBAN = function (bban) {
455
+ var weights = [3, 9, 7, 1, 3, 9, 7];
456
+ var controlDigit = parseInt(bban.charAt(7), 10);
457
+ var toCheck = bban.substring(0, 7);
458
+ var sum = 0;
459
+ for (var index = 0; index < 7; index++) {
460
+ sum += parseInt(toCheck.charAt(index), 10) * weights[index];
461
+ }
462
+ var remainder = sum % 10;
463
+ return controlDigit === (remainder === 0 ? 0 : 10 - remainder);
464
+ };
465
+ /**
466
+ * Spain (ES) BBAN check
467
+ *
468
+ * @ignore
469
+ */
470
+ var checkSpainBBAN = function (bban) {
471
+ var weightsBankBranch = [4, 8, 5, 10, 9, 7, 3, 6];
472
+ var weightsAccount = [1, 2, 4, 8, 5, 10, 9, 7, 3, 6];
473
+ var controlBankBranch = parseInt(bban.charAt(8), 10);
474
+ var controlAccount = parseInt(bban.charAt(9), 10);
475
+ var bankBranch = bban.substring(0, 8);
476
+ var account = bban.substring(10, 20);
477
+ var sum = 0;
478
+ for (var index = 0; index < 8; index++) {
479
+ sum += parseInt(bankBranch.charAt(index), 10) * weightsBankBranch[index];
480
+ }
481
+ var remainder = sum % 11;
482
+ if (controlBankBranch !== (remainder === 0 ? 0 : 11 - remainder)) {
483
+ return false;
484
+ }
485
+ sum = 0;
486
+ for (var index = 0; index < 10; index++) {
487
+ sum += parseInt(account.charAt(index), 10) * weightsAccount[index];
488
+ }
489
+ remainder = sum % 11;
490
+ return controlAccount === (remainder === 0 ? 0 : 11 - remainder);
491
+ };
332
492
  /**
333
493
  * Country specifications
334
494
  */
@@ -337,6 +497,7 @@ exports.countrySpecs = {
337
497
  chars: 24,
338
498
  bban_regexp: '^[0-9]{8}[A-Z0-9]{12}$',
339
499
  IBANRegistry: true,
500
+ SEPA: true,
340
501
  },
341
502
  AE: {
342
503
  chars: 23,
@@ -381,13 +542,14 @@ exports.countrySpecs = {
381
542
  BD: {},
382
543
  BE: { chars: 16, bban_regexp: '^[0-9]{12}$', IBANRegistry: true, SEPA: true },
383
544
  BF: {
384
- chars: 27,
385
- bban_regexp: '^[0-9]{23}$',
545
+ chars: 28,
546
+ bban_regexp: '^[A-Z0-9]{2}[0-9]{22}$',
386
547
  },
387
548
  BG: {
388
549
  chars: 22,
389
550
  bban_regexp: '^[A-Z]{4}[0-9]{6}[A-Z0-9]{8}$',
390
551
  IBANRegistry: true,
552
+ SEPA: true,
391
553
  },
392
554
  BH: {
393
555
  chars: 22,
@@ -395,12 +557,12 @@ exports.countrySpecs = {
395
557
  IBANRegistry: true,
396
558
  },
397
559
  BI: {
398
- chars: 16,
399
- bban_regexp: '^[0-9]{12}$',
560
+ chars: 27,
561
+ bban_regexp: '^[0-9]{23}$',
400
562
  },
401
563
  BJ: {
402
564
  chars: 28,
403
- bban_regexp: '^[A-Z]{1}[0-9]{23}$',
565
+ bban_regexp: '^[A-Z0-9]{2}[0-9]{22}$',
404
566
  },
405
567
  BL: {
406
568
  chars: 27,
@@ -484,21 +646,21 @@ exports.countrySpecs = {
484
646
  IBANRegistry: true,
485
647
  },
486
648
  DZ: {
487
- chars: 24,
488
- bban_regexp: '^[0-9]{20}$',
649
+ chars: 26,
650
+ bban_regexp: '^[0-9]{22}$',
489
651
  },
490
652
  EC: {},
491
653
  EE: { chars: 20, bban_regexp: '^[0-9]{16}$', IBANRegistry: true, SEPA: true },
492
654
  EG: { chars: 29, bban_regexp: '^[0-9]{25}', IBANRegistry: true },
493
655
  EH: {},
494
656
  ER: {},
495
- ES: { chars: 24, bban_regexp: '^[0-9]{20}$', IBANRegistry: true, SEPA: true },
657
+ ES: { chars: 24, bban_validation_func: checkSpainBBAN, bban_regexp: '^[0-9]{20}$', IBANRegistry: true, SEPA: true },
496
658
  ET: {},
497
659
  FI: { chars: 18, bban_regexp: '^[0-9]{14}$', IBANRegistry: true, SEPA: true },
498
660
  FJ: {},
499
661
  FK: {},
500
662
  FM: {},
501
- FO: { chars: 18, bban_regexp: '^[0-9]{14}$', IBANRegistry: true, SEPA: true },
663
+ FO: { chars: 18, bban_regexp: '^[0-9]{14}$', IBANRegistry: true },
502
664
  FR: {
503
665
  chars: 27,
504
666
  bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
@@ -534,7 +696,7 @@ exports.countrySpecs = {
534
696
  IBANRegistry: true,
535
697
  SEPA: true,
536
698
  },
537
- GL: { chars: 18, bban_regexp: '^[0-9]{14}$', IBANRegistry: true, SEPA: true },
699
+ GL: { chars: 18, bban_regexp: '^[0-9]{14}$', IBANRegistry: true },
538
700
  GM: {},
539
701
  GN: {},
540
702
  GP: {
@@ -709,7 +871,7 @@ exports.countrySpecs = {
709
871
  },
710
872
  ML: {
711
873
  chars: 28,
712
- bban_regexp: '^[A-Z]{1}[0-9]{23}$',
874
+ bban_regexp: '^[A-Z0-9]{2}[0-9]{22}$',
713
875
  },
714
876
  MM: {},
715
877
  MN: {},
@@ -767,7 +929,7 @@ exports.countrySpecs = {
767
929
  IBANRegistry: true,
768
930
  SEPA: true,
769
931
  },
770
- NO: { chars: 15, bban_regexp: '^[0-9]{11}$', IBANRegistry: true, SEPA: true },
932
+ NO: { chars: 15, bban_regexp: '^[0-9]{11}$', bban_validation_func: checkNorwayBBAN, IBANRegistry: true, SEPA: true },
771
933
  NP: {},
772
934
  NR: {},
773
935
  NU: {},
@@ -787,7 +949,7 @@ exports.countrySpecs = {
787
949
  bban_regexp: '^[A-Z0-9]{4}[0-9]{16}$',
788
950
  IBANRegistry: true,
789
951
  },
790
- PL: { chars: 28, bban_regexp: '^[0-9]{24}$', IBANRegistry: true, SEPA: true },
952
+ PL: { chars: 28, bban_validation_func: checkPolandBBAN, bban_regexp: '^[0-9]{24}$', IBANRegistry: true, SEPA: true },
791
953
  PM: {
792
954
  chars: 27,
793
955
  bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
@@ -853,7 +1015,7 @@ exports.countrySpecs = {
853
1015
  },
854
1016
  SN: {
855
1017
  chars: 28,
856
- bban_regexp: '^[A-Z]{1}[0-9]{23}$',
1018
+ bban_regexp: '^[A-Z]{2}[0-9]{22}$',
857
1019
  },
858
1020
  SO: {},
859
1021
  SR: {},
@@ -5,10 +5,10 @@
5
5
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
6
  /**
7
7
  * Validation, extraction and creation of IBAN, BBAN, BIC/SWIFT numbers plus some other helpful stuff
8
- * @packageDocumentation
8
+ * @package Documentation
9
9
  * @author Saša Jovanić
10
10
  * @module ibantools
11
- * @version 3.2.4
11
+ * @version 4.0.0
12
12
  * @license MPL-2.0
13
13
  * @preferred
14
14
  */
@@ -23,7 +23,7 @@
23
23
  * // returns false
24
24
  * ibantools.isValidIBAN("NL92ABNA0517164300");
25
25
  * ```
26
- */
26
+ v */
27
27
  export function isValidIBAN(iban) {
28
28
  if (iban !== undefined && iban !== null) {
29
29
  var reg = new RegExp('^[0-9]{2}$', '');
@@ -34,13 +34,64 @@ export function isValidIBAN(iban) {
34
34
  spec.chars &&
35
35
  spec.chars === iban.length &&
36
36
  reg.test(iban.slice(2, 4)) &&
37
- checkFormatBBAN(iban.slice(4), spec.bban_regexp) &&
37
+ isValidBBAN(iban.slice(4), iban.slice(0, 2)) &&
38
38
  isValidIBANChecksum(iban)) {
39
39
  return true;
40
40
  }
41
41
  }
42
42
  return false;
43
43
  }
44
+ /**
45
+ * IBAM validation errors
46
+ */
47
+ export var ValidationErrorsIBAN;
48
+ (function (ValidationErrorsIBAN) {
49
+ ValidationErrorsIBAN[ValidationErrorsIBAN["NoIBANProvided"] = 0] = "NoIBANProvided";
50
+ ValidationErrorsIBAN[ValidationErrorsIBAN["NoIBANCountry"] = 1] = "NoIBANCountry";
51
+ ValidationErrorsIBAN[ValidationErrorsIBAN["WrongBBANLength"] = 2] = "WrongBBANLength";
52
+ ValidationErrorsIBAN[ValidationErrorsIBAN["WrongBBANFormat"] = 3] = "WrongBBANFormat";
53
+ ValidationErrorsIBAN[ValidationErrorsIBAN["ChecksumNotNumber"] = 4] = "ChecksumNotNumber";
54
+ ValidationErrorsIBAN[ValidationErrorsIBAN["WrongIBANChecksum"] = 5] = "WrongIBANChecksum";
55
+ })(ValidationErrorsIBAN || (ValidationErrorsIBAN = {}));
56
+ /**
57
+ * validateIBAN
58
+ * ```
59
+ * // returns {errorCodes: [], valid: true}
60
+ * ibantools.validateIBAN("NL91 ABNA 0417 1643 00");
61
+ * ```
62
+ */
63
+ export function validateIBAN(iban) {
64
+ var result = { errorCodes: [], valid: true };
65
+ if (iban !== undefined && iban !== null && iban !== '') {
66
+ var spec = countrySpecs[iban.slice(0, 2)];
67
+ if (!spec || !(spec.bban_regexp || spec.chars)) {
68
+ result.valid = false;
69
+ result.errorCodes.push(ValidationErrorsIBAN.NoIBANCountry);
70
+ }
71
+ if (spec && spec.chars && spec.chars !== iban.length) {
72
+ result.valid = false;
73
+ result.errorCodes.push(ValidationErrorsIBAN.WrongBBANLength);
74
+ }
75
+ if (spec && spec.bban_regexp && !isValidBBAN(iban.slice(4), iban.slice(0, 2))) {
76
+ result.valid = false;
77
+ result.errorCodes.push(ValidationErrorsIBAN.WrongBBANFormat);
78
+ }
79
+ var reg = new RegExp('^[0-9]{2}$', '');
80
+ if (!reg.test(iban.slice(2, 4))) {
81
+ result.valid = false;
82
+ result.errorCodes.push(ValidationErrorsIBAN.ChecksumNotNumber);
83
+ }
84
+ if (!isValidIBANChecksum(iban)) {
85
+ result.valid = false;
86
+ result.errorCodes.push(ValidationErrorsIBAN.WrongIBANChecksum);
87
+ }
88
+ }
89
+ else {
90
+ result.valid = false;
91
+ result.errorCodes.push(ValidationErrorsIBAN.NoIBANProvided);
92
+ }
93
+ return result;
94
+ }
44
95
  /**
45
96
  * Validate BBAN
46
97
  *
@@ -64,6 +115,9 @@ export function isValidBBAN(bban, countryCode) {
64
115
  spec.chars !== null &&
65
116
  spec.chars - 4 === bban.length &&
66
117
  checkFormatBBAN(bban, spec.bban_regexp)) {
118
+ if (spec.bban_validation_func) {
119
+ return spec.bban_validation_func(bban.replace(/[\s.]+/g, ''));
120
+ }
67
121
  return true;
68
122
  }
69
123
  }
@@ -94,7 +148,7 @@ export function isSEPACountry(countryCode) {
94
148
  *
95
149
  * ```
96
150
  * // returns NL91ABNA0417164300
97
- * ibantools.composeIBAN("NL", "ABNA0417164300");
151
+ * ibantools.composeIBAN({ countryCode: "NL", bban: "ABNA0417164300" });
98
152
  * ```
99
153
  */
100
154
  export function composeIBAN(params) {
@@ -181,6 +235,7 @@ export function friendlyFormatIBAN(iban, separator) {
181
235
  separator = ' ';
182
236
  }
183
237
  var electronic_iban = electronicFormatIBAN(iban);
238
+ /* istanbul ignore if */
184
239
  if (electronic_iban === null) {
185
240
  return null;
186
241
  }
@@ -251,7 +306,7 @@ function mod9710(iban) {
251
306
  * let country = ibantools.getCountrySpecifications()[$(this).val()];
252
307
  * // Add country code letters to IBAN form field
253
308
  * $("input#iban").value($(this).val());
254
- * // Add new value to "pattern" attribute to #iban input text field
309
+ * // Add New value to "pattern" attribute to #iban input text field
255
310
  * $("input#iban").attr("pattern", $(this).val() + "[0-9]{2}" + country.bban_regexp.slice(1).replace("$",""));
256
311
  * });
257
312
  * ```
@@ -294,6 +349,44 @@ export function isValidBIC(bic) {
294
349
  var spec = countrySpecs[bic.toUpperCase().slice(4, 6)];
295
350
  return reg.test(bic) && spec !== undefined;
296
351
  }
352
+ /**
353
+ * BIC validation errors
354
+ */
355
+ export var ValidationErrorsBIC;
356
+ (function (ValidationErrorsBIC) {
357
+ ValidationErrorsBIC[ValidationErrorsBIC["NoBICProvided"] = 0] = "NoBICProvided";
358
+ ValidationErrorsBIC[ValidationErrorsBIC["NoBICCountry"] = 1] = "NoBICCountry";
359
+ ValidationErrorsBIC[ValidationErrorsBIC["WrongBICFormat"] = 2] = "WrongBICFormat";
360
+ })(ValidationErrorsBIC || (ValidationErrorsBIC = {}));
361
+ /**
362
+ * validateBIC
363
+ * ```
364
+ * // returns {errorCodes: [], valid: true}
365
+ * ibantools.validateBIC("NEDSZAJJXXX");
366
+ * ```
367
+ */
368
+ export function validateBIC(bic) {
369
+ var result = { errorCodes: [], valid: true };
370
+ if (bic !== undefined && bic !== null && bic !== '') {
371
+ var spec = countrySpecs[bic.toUpperCase().slice(4, 6)];
372
+ if (spec === undefined) {
373
+ result.valid = false;
374
+ result.errorCodes.push(ValidationErrorsBIC.NoBICCountry);
375
+ }
376
+ else {
377
+ var reg = new RegExp('^[a-zA-Z]{6}[a-zA-Z0-9]{2}([a-zA-Z0-9]{3})?$', '');
378
+ if (!reg.test(bic)) {
379
+ result.valid = false;
380
+ result.errorCodes.push(ValidationErrorsBIC.WrongBICFormat);
381
+ }
382
+ }
383
+ }
384
+ else {
385
+ result.valid = false;
386
+ result.errorCodes.push(ValidationErrorsBIC.NoBICProvided);
387
+ }
388
+ return result;
389
+ }
297
390
  /**
298
391
  * extractBIC
299
392
  * ```
@@ -317,6 +410,71 @@ export function extractBIC(inputBic) {
317
410
  }
318
411
  return result;
319
412
  }
413
+ /**
414
+ * Used for Norway BBAN check
415
+ *
416
+ * @ignore
417
+ */
418
+ var checkNorwayBBAN = function (bban) {
419
+ var weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
420
+ var bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, '');
421
+ if (bbanWithoutSpacesAndPeriods.length !== 11) {
422
+ return false;
423
+ }
424
+ else {
425
+ var controlDigit = parseInt(bbanWithoutSpacesAndPeriods.charAt(10), 10);
426
+ var bbanWithoutControlDigit = bbanWithoutSpacesAndPeriods.substring(0, 10);
427
+ var sum = 0;
428
+ for (var index = 0; index < 10; index++) {
429
+ sum += parseInt(bbanWithoutControlDigit.charAt(index), 10) * weights[index];
430
+ }
431
+ var remainder = sum % 11;
432
+ return controlDigit === (remainder === 0 ? 0 : 11 - remainder);
433
+ }
434
+ };
435
+ /**
436
+ * Used for Poland BBAN check
437
+ *
438
+ * @ignore
439
+ */
440
+ var checkPolandBBAN = function (bban) {
441
+ var weights = [3, 9, 7, 1, 3, 9, 7];
442
+ var controlDigit = parseInt(bban.charAt(7), 10);
443
+ var toCheck = bban.substring(0, 7);
444
+ var sum = 0;
445
+ for (var index = 0; index < 7; index++) {
446
+ sum += parseInt(toCheck.charAt(index), 10) * weights[index];
447
+ }
448
+ var remainder = sum % 10;
449
+ return controlDigit === (remainder === 0 ? 0 : 10 - remainder);
450
+ };
451
+ /**
452
+ * Spain (ES) BBAN check
453
+ *
454
+ * @ignore
455
+ */
456
+ var checkSpainBBAN = function (bban) {
457
+ var weightsBankBranch = [4, 8, 5, 10, 9, 7, 3, 6];
458
+ var weightsAccount = [1, 2, 4, 8, 5, 10, 9, 7, 3, 6];
459
+ var controlBankBranch = parseInt(bban.charAt(8), 10);
460
+ var controlAccount = parseInt(bban.charAt(9), 10);
461
+ var bankBranch = bban.substring(0, 8);
462
+ var account = bban.substring(10, 20);
463
+ var sum = 0;
464
+ for (var index = 0; index < 8; index++) {
465
+ sum += parseInt(bankBranch.charAt(index), 10) * weightsBankBranch[index];
466
+ }
467
+ var remainder = sum % 11;
468
+ if (controlBankBranch !== (remainder === 0 ? 0 : 11 - remainder)) {
469
+ return false;
470
+ }
471
+ sum = 0;
472
+ for (var index = 0; index < 10; index++) {
473
+ sum += parseInt(account.charAt(index), 10) * weightsAccount[index];
474
+ }
475
+ remainder = sum % 11;
476
+ return controlAccount === (remainder === 0 ? 0 : 11 - remainder);
477
+ };
320
478
  /**
321
479
  * Country specifications
322
480
  */
@@ -325,6 +483,7 @@ export var countrySpecs = {
325
483
  chars: 24,
326
484
  bban_regexp: '^[0-9]{8}[A-Z0-9]{12}$',
327
485
  IBANRegistry: true,
486
+ SEPA: true,
328
487
  },
329
488
  AE: {
330
489
  chars: 23,
@@ -369,13 +528,14 @@ export var countrySpecs = {
369
528
  BD: {},
370
529
  BE: { chars: 16, bban_regexp: '^[0-9]{12}$', IBANRegistry: true, SEPA: true },
371
530
  BF: {
372
- chars: 27,
373
- bban_regexp: '^[0-9]{23}$',
531
+ chars: 28,
532
+ bban_regexp: '^[A-Z0-9]{2}[0-9]{22}$',
374
533
  },
375
534
  BG: {
376
535
  chars: 22,
377
536
  bban_regexp: '^[A-Z]{4}[0-9]{6}[A-Z0-9]{8}$',
378
537
  IBANRegistry: true,
538
+ SEPA: true,
379
539
  },
380
540
  BH: {
381
541
  chars: 22,
@@ -383,12 +543,12 @@ export var countrySpecs = {
383
543
  IBANRegistry: true,
384
544
  },
385
545
  BI: {
386
- chars: 16,
387
- bban_regexp: '^[0-9]{12}$',
546
+ chars: 27,
547
+ bban_regexp: '^[0-9]{23}$',
388
548
  },
389
549
  BJ: {
390
550
  chars: 28,
391
- bban_regexp: '^[A-Z]{1}[0-9]{23}$',
551
+ bban_regexp: '^[A-Z0-9]{2}[0-9]{22}$',
392
552
  },
393
553
  BL: {
394
554
  chars: 27,
@@ -472,21 +632,21 @@ export var countrySpecs = {
472
632
  IBANRegistry: true,
473
633
  },
474
634
  DZ: {
475
- chars: 24,
476
- bban_regexp: '^[0-9]{20}$',
635
+ chars: 26,
636
+ bban_regexp: '^[0-9]{22}$',
477
637
  },
478
638
  EC: {},
479
639
  EE: { chars: 20, bban_regexp: '^[0-9]{16}$', IBANRegistry: true, SEPA: true },
480
640
  EG: { chars: 29, bban_regexp: '^[0-9]{25}', IBANRegistry: true },
481
641
  EH: {},
482
642
  ER: {},
483
- ES: { chars: 24, bban_regexp: '^[0-9]{20}$', IBANRegistry: true, SEPA: true },
643
+ ES: { chars: 24, bban_validation_func: checkSpainBBAN, bban_regexp: '^[0-9]{20}$', IBANRegistry: true, SEPA: true },
484
644
  ET: {},
485
645
  FI: { chars: 18, bban_regexp: '^[0-9]{14}$', IBANRegistry: true, SEPA: true },
486
646
  FJ: {},
487
647
  FK: {},
488
648
  FM: {},
489
- FO: { chars: 18, bban_regexp: '^[0-9]{14}$', IBANRegistry: true, SEPA: true },
649
+ FO: { chars: 18, bban_regexp: '^[0-9]{14}$', IBANRegistry: true },
490
650
  FR: {
491
651
  chars: 27,
492
652
  bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
@@ -522,7 +682,7 @@ export var countrySpecs = {
522
682
  IBANRegistry: true,
523
683
  SEPA: true,
524
684
  },
525
- GL: { chars: 18, bban_regexp: '^[0-9]{14}$', IBANRegistry: true, SEPA: true },
685
+ GL: { chars: 18, bban_regexp: '^[0-9]{14}$', IBANRegistry: true },
526
686
  GM: {},
527
687
  GN: {},
528
688
  GP: {
@@ -697,7 +857,7 @@ export var countrySpecs = {
697
857
  },
698
858
  ML: {
699
859
  chars: 28,
700
- bban_regexp: '^[A-Z]{1}[0-9]{23}$',
860
+ bban_regexp: '^[A-Z0-9]{2}[0-9]{22}$',
701
861
  },
702
862
  MM: {},
703
863
  MN: {},
@@ -755,7 +915,7 @@ export var countrySpecs = {
755
915
  IBANRegistry: true,
756
916
  SEPA: true,
757
917
  },
758
- NO: { chars: 15, bban_regexp: '^[0-9]{11}$', IBANRegistry: true, SEPA: true },
918
+ NO: { chars: 15, bban_regexp: '^[0-9]{11}$', bban_validation_func: checkNorwayBBAN, IBANRegistry: true, SEPA: true },
759
919
  NP: {},
760
920
  NR: {},
761
921
  NU: {},
@@ -775,7 +935,7 @@ export var countrySpecs = {
775
935
  bban_regexp: '^[A-Z0-9]{4}[0-9]{16}$',
776
936
  IBANRegistry: true,
777
937
  },
778
- PL: { chars: 28, bban_regexp: '^[0-9]{24}$', IBANRegistry: true, SEPA: true },
938
+ PL: { chars: 28, bban_validation_func: checkPolandBBAN, bban_regexp: '^[0-9]{24}$', IBANRegistry: true, SEPA: true },
779
939
  PM: {
780
940
  chars: 27,
781
941
  bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
@@ -841,7 +1001,7 @@ export var countrySpecs = {
841
1001
  },
842
1002
  SN: {
843
1003
  chars: 28,
844
- bban_regexp: '^[A-Z]{1}[0-9]{23}$',
1004
+ bban_regexp: '^[A-Z]{2}[0-9]{22}$',
845
1005
  },
846
1006
  SO: {},
847
1007
  SR: {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ibantools",
3
- "version": "3.2.4",
3
+ "version": "4.0.0",
4
4
  "description": "Validation, extraction and creation of IBAN, BBAN, BIC/SWIFT numbers plus some other helpful stuff like ISO 3136-1 alpha 2 country list",
5
5
  "keywords": [
6
6
  "IBAN",
@@ -50,33 +50,32 @@
50
50
  },
51
51
  "license": "MPL-2.0",
52
52
  "devDependencies": {
53
- "@typescript-eslint/eslint-plugin": "^4.7.0",
54
- "@typescript-eslint/parser": "^4.7.0",
55
- "chai": "^4.2.0",
53
+ "@typescript-eslint/eslint-plugin": "^4.28.4",
54
+ "@typescript-eslint/parser": "^4.28.4",
55
+ "chai": "^4.3.4",
56
56
  "cheerio": "^0.22",
57
- "coveralls": "^3.1.0",
57
+ "coveralls": "^3.1.1",
58
58
  "docdash": "^1.2.0",
59
- "eslint": "^7.13.0",
60
- "eslint-config-prettier": "^6.15.0",
61
- "eslint-plugin-prettier": "^3.1.4",
59
+ "eslint": "^7.31.0",
60
+ "eslint-config-prettier": "^8.3.0",
61
+ "eslint-plugin-prettier": "^3.4.0",
62
62
  "gulp": "^4.0.2",
63
- "gulp-mocha": "^7.0",
63
+ "gulp-mocha": "^8.0",
64
64
  "gulp-rename": "^2.0",
65
65
  "gulp-shell": "^0.8.0",
66
- "gulp-typedoc": "^2.2.5",
67
66
  "gulp-typescript": "^5.0",
68
- "jasmine-core": "^3.6.0",
69
- "karma": "^5.2.3",
67
+ "jasmine-core": "^3.8.0",
68
+ "karma": "^6.3.4",
70
69
  "karma-chrome-launcher": "^3.1",
71
70
  "karma-jasmine": "^4.0",
72
71
  "karma-requirejs": "^1.1",
73
72
  "merge2": "^1.4.1",
74
- "mocha": "^8.2.0",
73
+ "mocha": "^9.0.2",
75
74
  "mocha-lcov-reporter": "^1.2.0",
76
75
  "nyc": "^15.1.0",
77
- "prettier": "^2.1.2",
76
+ "prettier": "^2.3.2",
78
77
  "requirejs": "^2.3.6",
79
- "typedoc": "^0.17.0-3",
80
- "typescript": "^4.0"
78
+ "typedoc": "^0.21.4",
79
+ "typescript": "^4.3.5"
81
80
  }
82
81
  }