ibantools 4.1.0 → 4.1.4
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 +32 -0
- package/build/ibantools.js +266 -41
- package/jsnext/ibantools.js +266 -41
- package/package.json +2 -2
package/ChangeLog
CHANGED
|
@@ -1,3 +1,35 @@
|
|
|
1
|
+
2022-02-03 Saša Jovanić <sasa@simplify.ba>
|
|
2
|
+
* Version 4.1.4
|
|
3
|
+
* Fix issue #103 - Remove Dutch BBAN validation
|
|
4
|
+
* Various development dependencies upgrades
|
|
5
|
+
|
|
6
|
+
2021-12-17 Saša Jovanić <sasa@simplify.ba>
|
|
7
|
+
* Version 4.1.3
|
|
8
|
+
* Fix issue #85 - Fix NaN issue when calling `validateIBAN`
|
|
9
|
+
|
|
10
|
+
2021-12-14 Saša Jovanić <sasa@simplify.ba>
|
|
11
|
+
* Version 4.1.2
|
|
12
|
+
* Fix issue #83 - Fix problem when country can not be found when calling `validateIBAN`
|
|
13
|
+
|
|
14
|
+
2021-12-05 Saša Jovanić <sasa@simplify.ba>
|
|
15
|
+
* Version 4.1.1
|
|
16
|
+
* Added Hungarian (HU) BBAN validation
|
|
17
|
+
|
|
18
|
+
2021-12-01 Saša Jovanić <sasa@simplify.ba>
|
|
19
|
+
* Improve test coverage
|
|
20
|
+
|
|
21
|
+
2021-11-30 Saša Jovanić <sasa@simplify.ba>
|
|
22
|
+
* Added Estonian (EE) BBAN validation
|
|
23
|
+
* Added Finland (FI) BBAN validation
|
|
24
|
+
* Aland Islands (AX) uses BBAN valkidation from Finland
|
|
25
|
+
* Added French (FR) and Monaco (MC) BBAN validation
|
|
26
|
+
|
|
27
|
+
2021-11-28 Saša Jovanić <sasa@simplify.ba>
|
|
28
|
+
* Added Czech (CZ) BBAN validation
|
|
29
|
+
|
|
30
|
+
2021-11-27 Saša Jovanić <sasa@simplify.ba>
|
|
31
|
+
* Added Croatian (HR) BBAN validation
|
|
32
|
+
|
|
1
33
|
2021-11-25 Saša Jovanić <sasa@simplify.ba>
|
|
2
34
|
* Version 4.1.0
|
|
3
35
|
* Added Belgian (BE) extra BBAN validation
|
package/build/ibantools.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @package Documentation
|
|
9
9
|
* @author Saša Jovanić
|
|
10
10
|
* @module ibantools
|
|
11
|
-
* @version 4.1.
|
|
11
|
+
* @version 4.1.4
|
|
12
12
|
* @license MPL-2.0
|
|
13
13
|
* @preferred
|
|
14
14
|
*/
|
|
@@ -71,6 +71,7 @@ function validateIBAN(iban) {
|
|
|
71
71
|
if (!spec || !(spec.bban_regexp || spec.chars)) {
|
|
72
72
|
result.valid = false;
|
|
73
73
|
result.errorCodes.push(ValidationErrorsIBAN.NoIBANCountry);
|
|
74
|
+
return result;
|
|
74
75
|
}
|
|
75
76
|
if (spec && spec.chars && spec.chars !== iban.length) {
|
|
76
77
|
result.valid = false;
|
|
@@ -433,36 +434,14 @@ exports.extractBIC = extractBIC;
|
|
|
433
434
|
var checkNorwayBBAN = function (bban) {
|
|
434
435
|
var weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
|
|
435
436
|
var bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, '');
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
}
|
|
439
|
-
else {
|
|
440
|
-
var controlDigit = parseInt(bbanWithoutSpacesAndPeriods.charAt(10), 10);
|
|
441
|
-
var bbanWithoutControlDigit = bbanWithoutSpacesAndPeriods.substring(0, 10);
|
|
442
|
-
var sum = 0;
|
|
443
|
-
for (var index = 0; index < 10; index++) {
|
|
444
|
-
sum += parseInt(bbanWithoutControlDigit.charAt(index), 10) * weights[index];
|
|
445
|
-
}
|
|
446
|
-
var remainder = sum % 11;
|
|
447
|
-
return controlDigit === (remainder === 0 ? 0 : 11 - remainder);
|
|
448
|
-
}
|
|
449
|
-
};
|
|
450
|
-
/**
|
|
451
|
-
* Used for Netherlands BBAN check
|
|
452
|
-
*
|
|
453
|
-
* @ignore
|
|
454
|
-
*/
|
|
455
|
-
var checkDutchBBAN = function (bban) {
|
|
456
|
-
var bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, '');
|
|
457
|
-
var accountNumber = bbanWithoutSpacesAndPeriods.substring(4, 14);
|
|
458
|
-
if (accountNumber.startsWith('000')) {
|
|
459
|
-
return true; // Postbank account, no `elfproef` possible
|
|
460
|
-
}
|
|
437
|
+
var controlDigit = parseInt(bbanWithoutSpacesAndPeriods.charAt(10), 10);
|
|
438
|
+
var bbanWithoutControlDigit = bbanWithoutSpacesAndPeriods.substring(0, 10);
|
|
461
439
|
var sum = 0;
|
|
462
440
|
for (var index = 0; index < 10; index++) {
|
|
463
|
-
sum += parseInt(
|
|
441
|
+
sum += parseInt(bbanWithoutControlDigit.charAt(index), 10) * weights[index];
|
|
464
442
|
}
|
|
465
|
-
|
|
443
|
+
var remainder = sum % 11;
|
|
444
|
+
return controlDigit === (remainder === 0 ? 0 : 11 - remainder);
|
|
466
445
|
};
|
|
467
446
|
/**
|
|
468
447
|
* Used for Belgian BBAN check
|
|
@@ -473,11 +452,8 @@ var checkBelgianBBAN = function (bban) {
|
|
|
473
452
|
var stripped = bban.replace(/[\s.]+/g, '');
|
|
474
453
|
var checkingPart = parseInt(stripped.substring(0, stripped.length - 2), 10);
|
|
475
454
|
var checksum = parseInt(stripped.substring(stripped.length - 2, stripped.length), 10);
|
|
476
|
-
var
|
|
477
|
-
|
|
478
|
-
reminder = 97;
|
|
479
|
-
}
|
|
480
|
-
return reminder === checksum;
|
|
455
|
+
var remainder = checkingPart % 97 === 0 ? 97 : checkingPart % 97;
|
|
456
|
+
return remainder === checksum;
|
|
481
457
|
};
|
|
482
458
|
/**
|
|
483
459
|
* Mod 97/10 calculation
|
|
@@ -487,7 +463,11 @@ var checkBelgianBBAN = function (bban) {
|
|
|
487
463
|
var mod9710 = function (validationString) {
|
|
488
464
|
while (validationString.length > 2) {
|
|
489
465
|
var part = validationString.slice(0, 6);
|
|
490
|
-
|
|
466
|
+
var value = parseInt(part, 10) % 97;
|
|
467
|
+
if (isNaN(value)) {
|
|
468
|
+
return NaN;
|
|
469
|
+
}
|
|
470
|
+
validationString = value.toString() + validationString.slice(part.length);
|
|
491
471
|
}
|
|
492
472
|
return parseInt(validationString, 10) % 97;
|
|
493
473
|
};
|
|
@@ -545,6 +525,213 @@ var checkSpainBBAN = function (bban) {
|
|
|
545
525
|
remainder = sum % 11;
|
|
546
526
|
return controlAccount === (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder);
|
|
547
527
|
};
|
|
528
|
+
/**
|
|
529
|
+
* Mod 11/10 check
|
|
530
|
+
*
|
|
531
|
+
* @ignore
|
|
532
|
+
*/
|
|
533
|
+
var checkMod1110 = function (toCheck, control) {
|
|
534
|
+
var nr = 10;
|
|
535
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
536
|
+
nr += parseInt(toCheck.charAt(index), 10);
|
|
537
|
+
if (nr % 10 !== 0) {
|
|
538
|
+
nr = nr % 10;
|
|
539
|
+
}
|
|
540
|
+
nr = nr * 2;
|
|
541
|
+
nr = nr % 11;
|
|
542
|
+
}
|
|
543
|
+
return control === (11 - nr === 10 ? 0 : 11 - nr);
|
|
544
|
+
};
|
|
545
|
+
/**
|
|
546
|
+
* Croatian (HR) BBAN check
|
|
547
|
+
*
|
|
548
|
+
* @ignore
|
|
549
|
+
*/
|
|
550
|
+
var checkCroatianBBAN = function (bban) {
|
|
551
|
+
var controlBankBranch = parseInt(bban.charAt(6), 10);
|
|
552
|
+
var controlAccount = parseInt(bban.charAt(16), 10);
|
|
553
|
+
var bankBranch = bban.substring(0, 6);
|
|
554
|
+
var account = bban.substring(7, 16);
|
|
555
|
+
return checkMod1110(bankBranch, controlBankBranch) && checkMod1110(account, controlAccount);
|
|
556
|
+
};
|
|
557
|
+
/**
|
|
558
|
+
* Czech (CZ) BBAN check
|
|
559
|
+
*
|
|
560
|
+
* @ignore
|
|
561
|
+
*/
|
|
562
|
+
var checkCzechBBAN = function (bban) {
|
|
563
|
+
var weightsPrefix = [10, 5, 8, 4, 2, 1];
|
|
564
|
+
var weightsSuffix = [6, 3, 7, 9, 10, 5, 8, 4, 2, 1];
|
|
565
|
+
var controlPrefix = parseInt(bban.charAt(9), 10);
|
|
566
|
+
var controlSuffix = parseInt(bban.charAt(19), 10);
|
|
567
|
+
var prefix = bban.substring(4, 9);
|
|
568
|
+
var suffix = bban.substring(10, 19);
|
|
569
|
+
var sum = 0;
|
|
570
|
+
for (var index = 0; index < prefix.length; index++) {
|
|
571
|
+
sum += parseInt(prefix.charAt(index), 10) * weightsPrefix[index];
|
|
572
|
+
}
|
|
573
|
+
var remainder = sum % 11;
|
|
574
|
+
if (controlPrefix !== (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder)) {
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
sum = 0;
|
|
578
|
+
for (var index = 0; index < suffix.length; index++) {
|
|
579
|
+
sum += parseInt(suffix.charAt(index), 10) * weightsSuffix[index];
|
|
580
|
+
}
|
|
581
|
+
remainder = sum % 11;
|
|
582
|
+
return controlSuffix === (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder);
|
|
583
|
+
};
|
|
584
|
+
/**
|
|
585
|
+
* Estonian (EE) BBAN check
|
|
586
|
+
*
|
|
587
|
+
* @ignore
|
|
588
|
+
*/
|
|
589
|
+
var checkEstonianBBAN = function (bban) {
|
|
590
|
+
var weights = [7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1, 3, 7];
|
|
591
|
+
var controlDigit = parseInt(bban.charAt(15), 10);
|
|
592
|
+
var toCheck = bban.substring(2, 15);
|
|
593
|
+
var sum = 0;
|
|
594
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
595
|
+
sum += parseInt(toCheck.charAt(index), 10) * weights[index];
|
|
596
|
+
}
|
|
597
|
+
var remainder = sum % 10;
|
|
598
|
+
return controlDigit === (remainder === 0 ? 0 : 10 - remainder);
|
|
599
|
+
};
|
|
600
|
+
/**
|
|
601
|
+
* Finland (FI) BBAN check
|
|
602
|
+
*
|
|
603
|
+
* @ignore
|
|
604
|
+
*/
|
|
605
|
+
var checkFinlandBBAN = function (bban) {
|
|
606
|
+
var weightsMethod1 = [2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2];
|
|
607
|
+
var weightsMethod2 = [0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 1, 3, 7];
|
|
608
|
+
var controlDigit = parseInt(bban.charAt(13), 10);
|
|
609
|
+
var toCheck = bban.substring(0, 13);
|
|
610
|
+
var sum = 0;
|
|
611
|
+
if (toCheck.startsWith('88')) {
|
|
612
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
613
|
+
sum += parseInt(toCheck.charAt(index), 10) * weightsMethod2[index];
|
|
614
|
+
}
|
|
615
|
+
var remainder = sum % 10;
|
|
616
|
+
return controlDigit === (remainder === 0 ? 0 : 10 - remainder);
|
|
617
|
+
}
|
|
618
|
+
else {
|
|
619
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
620
|
+
if (weightsMethod1[index] === 1) {
|
|
621
|
+
sum += parseInt(toCheck.charAt(index), 10) * weightsMethod1[index];
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
var value = parseInt(toCheck.charAt(index), 10) * weightsMethod1[index];
|
|
625
|
+
sum += Math.floor(value / 10) + (value % 10);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
var extraSum = sum + controlDigit;
|
|
629
|
+
var multiDigit = Math.floor(extraSum / 10);
|
|
630
|
+
var result = multiDigit * 10;
|
|
631
|
+
var remainder = result - sum;
|
|
632
|
+
return remainder === controlDigit;
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
/**
|
|
636
|
+
* Check French (FR) BBAN
|
|
637
|
+
* Also for Monaco (MC)
|
|
638
|
+
*
|
|
639
|
+
* @ignore
|
|
640
|
+
*/
|
|
641
|
+
var checkFrenchBBAN = function (bban) {
|
|
642
|
+
var stripped = bban.replace(/[\s.]+/g, '');
|
|
643
|
+
var normalized = Array.from(stripped);
|
|
644
|
+
for (var index = 0; index < stripped.length; index++) {
|
|
645
|
+
var c = normalized[index].charCodeAt(0);
|
|
646
|
+
if (c >= 65) {
|
|
647
|
+
switch (c) {
|
|
648
|
+
case 65:
|
|
649
|
+
case 74:
|
|
650
|
+
normalized[index] = '1';
|
|
651
|
+
break;
|
|
652
|
+
case 66:
|
|
653
|
+
case 75:
|
|
654
|
+
case 83:
|
|
655
|
+
normalized[index] = '2';
|
|
656
|
+
break;
|
|
657
|
+
case 67:
|
|
658
|
+
case 76:
|
|
659
|
+
case 84:
|
|
660
|
+
normalized[index] = '3';
|
|
661
|
+
break;
|
|
662
|
+
case 68:
|
|
663
|
+
case 77:
|
|
664
|
+
case 85:
|
|
665
|
+
normalized[index] = '4';
|
|
666
|
+
break;
|
|
667
|
+
case 69:
|
|
668
|
+
case 78:
|
|
669
|
+
case 86:
|
|
670
|
+
normalized[index] = '5';
|
|
671
|
+
break;
|
|
672
|
+
case 70:
|
|
673
|
+
case 79:
|
|
674
|
+
case 87:
|
|
675
|
+
normalized[index] = '6';
|
|
676
|
+
break;
|
|
677
|
+
case 71:
|
|
678
|
+
case 80:
|
|
679
|
+
case 88:
|
|
680
|
+
normalized[index] = '7';
|
|
681
|
+
break;
|
|
682
|
+
case 72:
|
|
683
|
+
case 81:
|
|
684
|
+
case 89:
|
|
685
|
+
normalized[index] = '8';
|
|
686
|
+
break;
|
|
687
|
+
case 73:
|
|
688
|
+
case 82:
|
|
689
|
+
case 90:
|
|
690
|
+
normalized[index] = '9';
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
var remainder = mod9710(normalized.join(''));
|
|
696
|
+
return remainder === 0;
|
|
697
|
+
};
|
|
698
|
+
/**
|
|
699
|
+
* Hungarian (HU) BBAN check
|
|
700
|
+
*
|
|
701
|
+
* @ignore
|
|
702
|
+
*/
|
|
703
|
+
var checkHungarianBBAN = function (bban) {
|
|
704
|
+
var weights = [9, 7, 3, 1, 9, 7, 3, 1, 9, 7, 3, 1, 9, 7, 3];
|
|
705
|
+
var controlDigitBankBranch = parseInt(bban.charAt(7), 10);
|
|
706
|
+
var toCheckBankBranch = bban.substring(0, 7);
|
|
707
|
+
var sum = 0;
|
|
708
|
+
for (var index = 0; index < toCheckBankBranch.length; index++) {
|
|
709
|
+
sum += parseInt(toCheckBankBranch.charAt(index), 10) * weights[index];
|
|
710
|
+
}
|
|
711
|
+
var remainder = sum % 10;
|
|
712
|
+
if (controlDigitBankBranch !== (remainder === 0 ? 0 : 10 - remainder)) {
|
|
713
|
+
return false;
|
|
714
|
+
}
|
|
715
|
+
sum = 0;
|
|
716
|
+
if (bban.endsWith('00000000')) {
|
|
717
|
+
var toCheckAccount = bban.substring(8, 15);
|
|
718
|
+
var controlDigitAccount = parseInt(bban.charAt(15), 10);
|
|
719
|
+
for (var index = 0; index < toCheckAccount.length; index++) {
|
|
720
|
+
sum += parseInt(toCheckAccount.charAt(index), 10) * weights[index];
|
|
721
|
+
}
|
|
722
|
+
var remainder_1 = sum % 10;
|
|
723
|
+
return controlDigitAccount === (remainder_1 === 0 ? 0 : 10 - remainder_1);
|
|
724
|
+
}
|
|
725
|
+
else {
|
|
726
|
+
var toCheckAccount = bban.substring(8, 23);
|
|
727
|
+
var controlDigitAccount = parseInt(bban.charAt(23), 10);
|
|
728
|
+
for (var index = 0; index < toCheckAccount.length; index++) {
|
|
729
|
+
sum += parseInt(toCheckAccount.charAt(index), 10) * weights[index];
|
|
730
|
+
}
|
|
731
|
+
var remainder_2 = sum % 10;
|
|
732
|
+
return controlDigitAccount === (remainder_2 === 0 ? 0 : 10 - remainder_2);
|
|
733
|
+
}
|
|
734
|
+
};
|
|
548
735
|
/**
|
|
549
736
|
* Country specifications
|
|
550
737
|
*/
|
|
@@ -582,6 +769,7 @@ exports.countrySpecs = {
|
|
|
582
769
|
AX: {
|
|
583
770
|
chars: 18,
|
|
584
771
|
bban_regexp: '^[0-9]{14}$',
|
|
772
|
+
bban_validation_func: checkFinlandBBAN,
|
|
585
773
|
IBANRegistry: true,
|
|
586
774
|
},
|
|
587
775
|
AZ: {
|
|
@@ -689,7 +877,13 @@ exports.countrySpecs = {
|
|
|
689
877
|
IBANRegistry: true,
|
|
690
878
|
SEPA: true,
|
|
691
879
|
},
|
|
692
|
-
CZ: {
|
|
880
|
+
CZ: {
|
|
881
|
+
chars: 24,
|
|
882
|
+
bban_regexp: '^[0-9]{20}$',
|
|
883
|
+
bban_validation_func: checkCzechBBAN,
|
|
884
|
+
IBANRegistry: true,
|
|
885
|
+
SEPA: true,
|
|
886
|
+
},
|
|
693
887
|
DE: { chars: 22, bban_regexp: '^[0-9]{18}$', IBANRegistry: true, SEPA: true },
|
|
694
888
|
DJ: {
|
|
695
889
|
chars: 27,
|
|
@@ -707,13 +901,31 @@ exports.countrySpecs = {
|
|
|
707
901
|
bban_regexp: '^[0-9]{22}$',
|
|
708
902
|
},
|
|
709
903
|
EC: {},
|
|
710
|
-
EE: {
|
|
904
|
+
EE: {
|
|
905
|
+
chars: 20,
|
|
906
|
+
bban_regexp: '^[0-9]{16}$',
|
|
907
|
+
bban_validation_func: checkEstonianBBAN,
|
|
908
|
+
IBANRegistry: true,
|
|
909
|
+
SEPA: true,
|
|
910
|
+
},
|
|
711
911
|
EG: { chars: 29, bban_regexp: '^[0-9]{25}', IBANRegistry: true },
|
|
712
912
|
EH: {},
|
|
713
913
|
ER: {},
|
|
714
|
-
ES: {
|
|
914
|
+
ES: {
|
|
915
|
+
chars: 24,
|
|
916
|
+
bban_validation_func: checkSpainBBAN,
|
|
917
|
+
bban_regexp: '^[0-9]{20}$',
|
|
918
|
+
IBANRegistry: true,
|
|
919
|
+
SEPA: true,
|
|
920
|
+
},
|
|
715
921
|
ET: {},
|
|
716
|
-
FI: {
|
|
922
|
+
FI: {
|
|
923
|
+
chars: 18,
|
|
924
|
+
bban_regexp: '^[0-9]{14}$',
|
|
925
|
+
bban_validation_func: checkFinlandBBAN,
|
|
926
|
+
IBANRegistry: true,
|
|
927
|
+
SEPA: true,
|
|
928
|
+
},
|
|
717
929
|
FJ: {},
|
|
718
930
|
FK: {},
|
|
719
931
|
FM: {},
|
|
@@ -721,6 +933,7 @@ exports.countrySpecs = {
|
|
|
721
933
|
FR: {
|
|
722
934
|
chars: 27,
|
|
723
935
|
bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
|
|
936
|
+
bban_validation_func: checkFrenchBBAN,
|
|
724
937
|
IBANRegistry: true,
|
|
725
938
|
SEPA: true,
|
|
726
939
|
},
|
|
@@ -789,9 +1002,21 @@ exports.countrySpecs = {
|
|
|
789
1002
|
chars: 28,
|
|
790
1003
|
bban_regexp: '^[A-Z]{4}[0-9]{20}$',
|
|
791
1004
|
},
|
|
792
|
-
HR: {
|
|
1005
|
+
HR: {
|
|
1006
|
+
chars: 21,
|
|
1007
|
+
bban_regexp: '^[0-9]{17}$',
|
|
1008
|
+
bban_validation_func: checkCroatianBBAN,
|
|
1009
|
+
IBANRegistry: true,
|
|
1010
|
+
SEPA: true,
|
|
1011
|
+
},
|
|
793
1012
|
HT: {},
|
|
794
|
-
HU: {
|
|
1013
|
+
HU: {
|
|
1014
|
+
chars: 28,
|
|
1015
|
+
bban_regexp: '^[0-9]{24}$',
|
|
1016
|
+
bban_validation_func: checkHungarianBBAN,
|
|
1017
|
+
IBANRegistry: true,
|
|
1018
|
+
SEPA: true,
|
|
1019
|
+
},
|
|
795
1020
|
ID: {},
|
|
796
1021
|
IE: {
|
|
797
1022
|
chars: 22,
|
|
@@ -898,6 +1123,7 @@ exports.countrySpecs = {
|
|
|
898
1123
|
MC: {
|
|
899
1124
|
chars: 27,
|
|
900
1125
|
bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
|
|
1126
|
+
bban_validation_func: checkFrenchBBAN,
|
|
901
1127
|
IBANRegistry: true,
|
|
902
1128
|
SEPA: true,
|
|
903
1129
|
},
|
|
@@ -985,7 +1211,6 @@ exports.countrySpecs = {
|
|
|
985
1211
|
NL: {
|
|
986
1212
|
chars: 18,
|
|
987
1213
|
bban_regexp: '^[A-Z]{4}[0-9]{10}$',
|
|
988
|
-
bban_validation_func: checkDutchBBAN,
|
|
989
1214
|
IBANRegistry: true,
|
|
990
1215
|
SEPA: true,
|
|
991
1216
|
},
|
package/jsnext/ibantools.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @package Documentation
|
|
9
9
|
* @author Saša Jovanić
|
|
10
10
|
* @module ibantools
|
|
11
|
-
* @version 4.1.
|
|
11
|
+
* @version 4.1.4
|
|
12
12
|
* @license MPL-2.0
|
|
13
13
|
* @preferred
|
|
14
14
|
*/
|
|
@@ -68,6 +68,7 @@ export function validateIBAN(iban) {
|
|
|
68
68
|
if (!spec || !(spec.bban_regexp || spec.chars)) {
|
|
69
69
|
result.valid = false;
|
|
70
70
|
result.errorCodes.push(ValidationErrorsIBAN.NoIBANCountry);
|
|
71
|
+
return result;
|
|
71
72
|
}
|
|
72
73
|
if (spec && spec.chars && spec.chars !== iban.length) {
|
|
73
74
|
result.valid = false;
|
|
@@ -419,36 +420,14 @@ export function extractBIC(inputBic) {
|
|
|
419
420
|
var checkNorwayBBAN = function (bban) {
|
|
420
421
|
var weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
|
|
421
422
|
var bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, '');
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
}
|
|
425
|
-
else {
|
|
426
|
-
var controlDigit = parseInt(bbanWithoutSpacesAndPeriods.charAt(10), 10);
|
|
427
|
-
var bbanWithoutControlDigit = bbanWithoutSpacesAndPeriods.substring(0, 10);
|
|
428
|
-
var sum = 0;
|
|
429
|
-
for (var index = 0; index < 10; index++) {
|
|
430
|
-
sum += parseInt(bbanWithoutControlDigit.charAt(index), 10) * weights[index];
|
|
431
|
-
}
|
|
432
|
-
var remainder = sum % 11;
|
|
433
|
-
return controlDigit === (remainder === 0 ? 0 : 11 - remainder);
|
|
434
|
-
}
|
|
435
|
-
};
|
|
436
|
-
/**
|
|
437
|
-
* Used for Netherlands BBAN check
|
|
438
|
-
*
|
|
439
|
-
* @ignore
|
|
440
|
-
*/
|
|
441
|
-
var checkDutchBBAN = function (bban) {
|
|
442
|
-
var bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, '');
|
|
443
|
-
var accountNumber = bbanWithoutSpacesAndPeriods.substring(4, 14);
|
|
444
|
-
if (accountNumber.startsWith('000')) {
|
|
445
|
-
return true; // Postbank account, no `elfproef` possible
|
|
446
|
-
}
|
|
423
|
+
var controlDigit = parseInt(bbanWithoutSpacesAndPeriods.charAt(10), 10);
|
|
424
|
+
var bbanWithoutControlDigit = bbanWithoutSpacesAndPeriods.substring(0, 10);
|
|
447
425
|
var sum = 0;
|
|
448
426
|
for (var index = 0; index < 10; index++) {
|
|
449
|
-
sum += parseInt(
|
|
427
|
+
sum += parseInt(bbanWithoutControlDigit.charAt(index), 10) * weights[index];
|
|
450
428
|
}
|
|
451
|
-
|
|
429
|
+
var remainder = sum % 11;
|
|
430
|
+
return controlDigit === (remainder === 0 ? 0 : 11 - remainder);
|
|
452
431
|
};
|
|
453
432
|
/**
|
|
454
433
|
* Used for Belgian BBAN check
|
|
@@ -459,11 +438,8 @@ var checkBelgianBBAN = function (bban) {
|
|
|
459
438
|
var stripped = bban.replace(/[\s.]+/g, '');
|
|
460
439
|
var checkingPart = parseInt(stripped.substring(0, stripped.length - 2), 10);
|
|
461
440
|
var checksum = parseInt(stripped.substring(stripped.length - 2, stripped.length), 10);
|
|
462
|
-
var
|
|
463
|
-
|
|
464
|
-
reminder = 97;
|
|
465
|
-
}
|
|
466
|
-
return reminder === checksum;
|
|
441
|
+
var remainder = checkingPart % 97 === 0 ? 97 : checkingPart % 97;
|
|
442
|
+
return remainder === checksum;
|
|
467
443
|
};
|
|
468
444
|
/**
|
|
469
445
|
* Mod 97/10 calculation
|
|
@@ -473,7 +449,11 @@ var checkBelgianBBAN = function (bban) {
|
|
|
473
449
|
var mod9710 = function (validationString) {
|
|
474
450
|
while (validationString.length > 2) {
|
|
475
451
|
var part = validationString.slice(0, 6);
|
|
476
|
-
|
|
452
|
+
var value = parseInt(part, 10) % 97;
|
|
453
|
+
if (isNaN(value)) {
|
|
454
|
+
return NaN;
|
|
455
|
+
}
|
|
456
|
+
validationString = value.toString() + validationString.slice(part.length);
|
|
477
457
|
}
|
|
478
458
|
return parseInt(validationString, 10) % 97;
|
|
479
459
|
};
|
|
@@ -531,6 +511,213 @@ var checkSpainBBAN = function (bban) {
|
|
|
531
511
|
remainder = sum % 11;
|
|
532
512
|
return controlAccount === (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder);
|
|
533
513
|
};
|
|
514
|
+
/**
|
|
515
|
+
* Mod 11/10 check
|
|
516
|
+
*
|
|
517
|
+
* @ignore
|
|
518
|
+
*/
|
|
519
|
+
var checkMod1110 = function (toCheck, control) {
|
|
520
|
+
var nr = 10;
|
|
521
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
522
|
+
nr += parseInt(toCheck.charAt(index), 10);
|
|
523
|
+
if (nr % 10 !== 0) {
|
|
524
|
+
nr = nr % 10;
|
|
525
|
+
}
|
|
526
|
+
nr = nr * 2;
|
|
527
|
+
nr = nr % 11;
|
|
528
|
+
}
|
|
529
|
+
return control === (11 - nr === 10 ? 0 : 11 - nr);
|
|
530
|
+
};
|
|
531
|
+
/**
|
|
532
|
+
* Croatian (HR) BBAN check
|
|
533
|
+
*
|
|
534
|
+
* @ignore
|
|
535
|
+
*/
|
|
536
|
+
var checkCroatianBBAN = function (bban) {
|
|
537
|
+
var controlBankBranch = parseInt(bban.charAt(6), 10);
|
|
538
|
+
var controlAccount = parseInt(bban.charAt(16), 10);
|
|
539
|
+
var bankBranch = bban.substring(0, 6);
|
|
540
|
+
var account = bban.substring(7, 16);
|
|
541
|
+
return checkMod1110(bankBranch, controlBankBranch) && checkMod1110(account, controlAccount);
|
|
542
|
+
};
|
|
543
|
+
/**
|
|
544
|
+
* Czech (CZ) BBAN check
|
|
545
|
+
*
|
|
546
|
+
* @ignore
|
|
547
|
+
*/
|
|
548
|
+
var checkCzechBBAN = function (bban) {
|
|
549
|
+
var weightsPrefix = [10, 5, 8, 4, 2, 1];
|
|
550
|
+
var weightsSuffix = [6, 3, 7, 9, 10, 5, 8, 4, 2, 1];
|
|
551
|
+
var controlPrefix = parseInt(bban.charAt(9), 10);
|
|
552
|
+
var controlSuffix = parseInt(bban.charAt(19), 10);
|
|
553
|
+
var prefix = bban.substring(4, 9);
|
|
554
|
+
var suffix = bban.substring(10, 19);
|
|
555
|
+
var sum = 0;
|
|
556
|
+
for (var index = 0; index < prefix.length; index++) {
|
|
557
|
+
sum += parseInt(prefix.charAt(index), 10) * weightsPrefix[index];
|
|
558
|
+
}
|
|
559
|
+
var remainder = sum % 11;
|
|
560
|
+
if (controlPrefix !== (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder)) {
|
|
561
|
+
return false;
|
|
562
|
+
}
|
|
563
|
+
sum = 0;
|
|
564
|
+
for (var index = 0; index < suffix.length; index++) {
|
|
565
|
+
sum += parseInt(suffix.charAt(index), 10) * weightsSuffix[index];
|
|
566
|
+
}
|
|
567
|
+
remainder = sum % 11;
|
|
568
|
+
return controlSuffix === (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder);
|
|
569
|
+
};
|
|
570
|
+
/**
|
|
571
|
+
* Estonian (EE) BBAN check
|
|
572
|
+
*
|
|
573
|
+
* @ignore
|
|
574
|
+
*/
|
|
575
|
+
var checkEstonianBBAN = function (bban) {
|
|
576
|
+
var weights = [7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1, 3, 7];
|
|
577
|
+
var controlDigit = parseInt(bban.charAt(15), 10);
|
|
578
|
+
var toCheck = bban.substring(2, 15);
|
|
579
|
+
var sum = 0;
|
|
580
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
581
|
+
sum += parseInt(toCheck.charAt(index), 10) * weights[index];
|
|
582
|
+
}
|
|
583
|
+
var remainder = sum % 10;
|
|
584
|
+
return controlDigit === (remainder === 0 ? 0 : 10 - remainder);
|
|
585
|
+
};
|
|
586
|
+
/**
|
|
587
|
+
* Finland (FI) BBAN check
|
|
588
|
+
*
|
|
589
|
+
* @ignore
|
|
590
|
+
*/
|
|
591
|
+
var checkFinlandBBAN = function (bban) {
|
|
592
|
+
var weightsMethod1 = [2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2];
|
|
593
|
+
var weightsMethod2 = [0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 1, 3, 7];
|
|
594
|
+
var controlDigit = parseInt(bban.charAt(13), 10);
|
|
595
|
+
var toCheck = bban.substring(0, 13);
|
|
596
|
+
var sum = 0;
|
|
597
|
+
if (toCheck.startsWith('88')) {
|
|
598
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
599
|
+
sum += parseInt(toCheck.charAt(index), 10) * weightsMethod2[index];
|
|
600
|
+
}
|
|
601
|
+
var remainder = sum % 10;
|
|
602
|
+
return controlDigit === (remainder === 0 ? 0 : 10 - remainder);
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
606
|
+
if (weightsMethod1[index] === 1) {
|
|
607
|
+
sum += parseInt(toCheck.charAt(index), 10) * weightsMethod1[index];
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
var value = parseInt(toCheck.charAt(index), 10) * weightsMethod1[index];
|
|
611
|
+
sum += Math.floor(value / 10) + (value % 10);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
var extraSum = sum + controlDigit;
|
|
615
|
+
var multiDigit = Math.floor(extraSum / 10);
|
|
616
|
+
var result = multiDigit * 10;
|
|
617
|
+
var remainder = result - sum;
|
|
618
|
+
return remainder === controlDigit;
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
/**
|
|
622
|
+
* Check French (FR) BBAN
|
|
623
|
+
* Also for Monaco (MC)
|
|
624
|
+
*
|
|
625
|
+
* @ignore
|
|
626
|
+
*/
|
|
627
|
+
var checkFrenchBBAN = function (bban) {
|
|
628
|
+
var stripped = bban.replace(/[\s.]+/g, '');
|
|
629
|
+
var normalized = Array.from(stripped);
|
|
630
|
+
for (var index = 0; index < stripped.length; index++) {
|
|
631
|
+
var c = normalized[index].charCodeAt(0);
|
|
632
|
+
if (c >= 65) {
|
|
633
|
+
switch (c) {
|
|
634
|
+
case 65:
|
|
635
|
+
case 74:
|
|
636
|
+
normalized[index] = '1';
|
|
637
|
+
break;
|
|
638
|
+
case 66:
|
|
639
|
+
case 75:
|
|
640
|
+
case 83:
|
|
641
|
+
normalized[index] = '2';
|
|
642
|
+
break;
|
|
643
|
+
case 67:
|
|
644
|
+
case 76:
|
|
645
|
+
case 84:
|
|
646
|
+
normalized[index] = '3';
|
|
647
|
+
break;
|
|
648
|
+
case 68:
|
|
649
|
+
case 77:
|
|
650
|
+
case 85:
|
|
651
|
+
normalized[index] = '4';
|
|
652
|
+
break;
|
|
653
|
+
case 69:
|
|
654
|
+
case 78:
|
|
655
|
+
case 86:
|
|
656
|
+
normalized[index] = '5';
|
|
657
|
+
break;
|
|
658
|
+
case 70:
|
|
659
|
+
case 79:
|
|
660
|
+
case 87:
|
|
661
|
+
normalized[index] = '6';
|
|
662
|
+
break;
|
|
663
|
+
case 71:
|
|
664
|
+
case 80:
|
|
665
|
+
case 88:
|
|
666
|
+
normalized[index] = '7';
|
|
667
|
+
break;
|
|
668
|
+
case 72:
|
|
669
|
+
case 81:
|
|
670
|
+
case 89:
|
|
671
|
+
normalized[index] = '8';
|
|
672
|
+
break;
|
|
673
|
+
case 73:
|
|
674
|
+
case 82:
|
|
675
|
+
case 90:
|
|
676
|
+
normalized[index] = '9';
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
var remainder = mod9710(normalized.join(''));
|
|
682
|
+
return remainder === 0;
|
|
683
|
+
};
|
|
684
|
+
/**
|
|
685
|
+
* Hungarian (HU) BBAN check
|
|
686
|
+
*
|
|
687
|
+
* @ignore
|
|
688
|
+
*/
|
|
689
|
+
var checkHungarianBBAN = function (bban) {
|
|
690
|
+
var weights = [9, 7, 3, 1, 9, 7, 3, 1, 9, 7, 3, 1, 9, 7, 3];
|
|
691
|
+
var controlDigitBankBranch = parseInt(bban.charAt(7), 10);
|
|
692
|
+
var toCheckBankBranch = bban.substring(0, 7);
|
|
693
|
+
var sum = 0;
|
|
694
|
+
for (var index = 0; index < toCheckBankBranch.length; index++) {
|
|
695
|
+
sum += parseInt(toCheckBankBranch.charAt(index), 10) * weights[index];
|
|
696
|
+
}
|
|
697
|
+
var remainder = sum % 10;
|
|
698
|
+
if (controlDigitBankBranch !== (remainder === 0 ? 0 : 10 - remainder)) {
|
|
699
|
+
return false;
|
|
700
|
+
}
|
|
701
|
+
sum = 0;
|
|
702
|
+
if (bban.endsWith('00000000')) {
|
|
703
|
+
var toCheckAccount = bban.substring(8, 15);
|
|
704
|
+
var controlDigitAccount = parseInt(bban.charAt(15), 10);
|
|
705
|
+
for (var index = 0; index < toCheckAccount.length; index++) {
|
|
706
|
+
sum += parseInt(toCheckAccount.charAt(index), 10) * weights[index];
|
|
707
|
+
}
|
|
708
|
+
var remainder_1 = sum % 10;
|
|
709
|
+
return controlDigitAccount === (remainder_1 === 0 ? 0 : 10 - remainder_1);
|
|
710
|
+
}
|
|
711
|
+
else {
|
|
712
|
+
var toCheckAccount = bban.substring(8, 23);
|
|
713
|
+
var controlDigitAccount = parseInt(bban.charAt(23), 10);
|
|
714
|
+
for (var index = 0; index < toCheckAccount.length; index++) {
|
|
715
|
+
sum += parseInt(toCheckAccount.charAt(index), 10) * weights[index];
|
|
716
|
+
}
|
|
717
|
+
var remainder_2 = sum % 10;
|
|
718
|
+
return controlDigitAccount === (remainder_2 === 0 ? 0 : 10 - remainder_2);
|
|
719
|
+
}
|
|
720
|
+
};
|
|
534
721
|
/**
|
|
535
722
|
* Country specifications
|
|
536
723
|
*/
|
|
@@ -568,6 +755,7 @@ export var countrySpecs = {
|
|
|
568
755
|
AX: {
|
|
569
756
|
chars: 18,
|
|
570
757
|
bban_regexp: '^[0-9]{14}$',
|
|
758
|
+
bban_validation_func: checkFinlandBBAN,
|
|
571
759
|
IBANRegistry: true,
|
|
572
760
|
},
|
|
573
761
|
AZ: {
|
|
@@ -675,7 +863,13 @@ export var countrySpecs = {
|
|
|
675
863
|
IBANRegistry: true,
|
|
676
864
|
SEPA: true,
|
|
677
865
|
},
|
|
678
|
-
CZ: {
|
|
866
|
+
CZ: {
|
|
867
|
+
chars: 24,
|
|
868
|
+
bban_regexp: '^[0-9]{20}$',
|
|
869
|
+
bban_validation_func: checkCzechBBAN,
|
|
870
|
+
IBANRegistry: true,
|
|
871
|
+
SEPA: true,
|
|
872
|
+
},
|
|
679
873
|
DE: { chars: 22, bban_regexp: '^[0-9]{18}$', IBANRegistry: true, SEPA: true },
|
|
680
874
|
DJ: {
|
|
681
875
|
chars: 27,
|
|
@@ -693,13 +887,31 @@ export var countrySpecs = {
|
|
|
693
887
|
bban_regexp: '^[0-9]{22}$',
|
|
694
888
|
},
|
|
695
889
|
EC: {},
|
|
696
|
-
EE: {
|
|
890
|
+
EE: {
|
|
891
|
+
chars: 20,
|
|
892
|
+
bban_regexp: '^[0-9]{16}$',
|
|
893
|
+
bban_validation_func: checkEstonianBBAN,
|
|
894
|
+
IBANRegistry: true,
|
|
895
|
+
SEPA: true,
|
|
896
|
+
},
|
|
697
897
|
EG: { chars: 29, bban_regexp: '^[0-9]{25}', IBANRegistry: true },
|
|
698
898
|
EH: {},
|
|
699
899
|
ER: {},
|
|
700
|
-
ES: {
|
|
900
|
+
ES: {
|
|
901
|
+
chars: 24,
|
|
902
|
+
bban_validation_func: checkSpainBBAN,
|
|
903
|
+
bban_regexp: '^[0-9]{20}$',
|
|
904
|
+
IBANRegistry: true,
|
|
905
|
+
SEPA: true,
|
|
906
|
+
},
|
|
701
907
|
ET: {},
|
|
702
|
-
FI: {
|
|
908
|
+
FI: {
|
|
909
|
+
chars: 18,
|
|
910
|
+
bban_regexp: '^[0-9]{14}$',
|
|
911
|
+
bban_validation_func: checkFinlandBBAN,
|
|
912
|
+
IBANRegistry: true,
|
|
913
|
+
SEPA: true,
|
|
914
|
+
},
|
|
703
915
|
FJ: {},
|
|
704
916
|
FK: {},
|
|
705
917
|
FM: {},
|
|
@@ -707,6 +919,7 @@ export var countrySpecs = {
|
|
|
707
919
|
FR: {
|
|
708
920
|
chars: 27,
|
|
709
921
|
bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
|
|
922
|
+
bban_validation_func: checkFrenchBBAN,
|
|
710
923
|
IBANRegistry: true,
|
|
711
924
|
SEPA: true,
|
|
712
925
|
},
|
|
@@ -775,9 +988,21 @@ export var countrySpecs = {
|
|
|
775
988
|
chars: 28,
|
|
776
989
|
bban_regexp: '^[A-Z]{4}[0-9]{20}$',
|
|
777
990
|
},
|
|
778
|
-
HR: {
|
|
991
|
+
HR: {
|
|
992
|
+
chars: 21,
|
|
993
|
+
bban_regexp: '^[0-9]{17}$',
|
|
994
|
+
bban_validation_func: checkCroatianBBAN,
|
|
995
|
+
IBANRegistry: true,
|
|
996
|
+
SEPA: true,
|
|
997
|
+
},
|
|
779
998
|
HT: {},
|
|
780
|
-
HU: {
|
|
999
|
+
HU: {
|
|
1000
|
+
chars: 28,
|
|
1001
|
+
bban_regexp: '^[0-9]{24}$',
|
|
1002
|
+
bban_validation_func: checkHungarianBBAN,
|
|
1003
|
+
IBANRegistry: true,
|
|
1004
|
+
SEPA: true,
|
|
1005
|
+
},
|
|
781
1006
|
ID: {},
|
|
782
1007
|
IE: {
|
|
783
1008
|
chars: 22,
|
|
@@ -884,6 +1109,7 @@ export var countrySpecs = {
|
|
|
884
1109
|
MC: {
|
|
885
1110
|
chars: 27,
|
|
886
1111
|
bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
|
|
1112
|
+
bban_validation_func: checkFrenchBBAN,
|
|
887
1113
|
IBANRegistry: true,
|
|
888
1114
|
SEPA: true,
|
|
889
1115
|
},
|
|
@@ -971,7 +1197,6 @@ export var countrySpecs = {
|
|
|
971
1197
|
NL: {
|
|
972
1198
|
chars: 18,
|
|
973
1199
|
bban_regexp: '^[A-Z]{4}[0-9]{10}$',
|
|
974
|
-
bban_validation_func: checkDutchBBAN,
|
|
975
1200
|
IBANRegistry: true,
|
|
976
1201
|
SEPA: true,
|
|
977
1202
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ibantools",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.4",
|
|
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",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"gulp-rename": "^2.0",
|
|
65
65
|
"gulp-shell": "^0.8.0",
|
|
66
66
|
"gulp-typescript": "^5.0",
|
|
67
|
-
"jasmine-core": "^
|
|
67
|
+
"jasmine-core": "^4.0.0",
|
|
68
68
|
"karma": "^6.3.4",
|
|
69
69
|
"karma-chrome-launcher": "^3.1",
|
|
70
70
|
"karma-jasmine": "^4.0",
|