ibantools 4.0.0 → 4.1.2
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 +43 -0
- package/README.md +15 -4
- package/build/ibantools.d.ts +3 -2
- package/build/ibantools.js +338 -32
- package/jsnext/ibantools.js +338 -32
- package/package.json +3 -3
package/ChangeLog
CHANGED
|
@@ -1,3 +1,46 @@
|
|
|
1
|
+
2021-12-14 Saša Jovanić <sasa@simplify.ba>
|
|
2
|
+
* Version 4.1.2
|
|
3
|
+
* Fix issue #83 - Fix problem when country can not be found when calling `validateIBAN`
|
|
4
|
+
|
|
5
|
+
2021-12-05 Saša Jovanić <sasa@simplify.ba>
|
|
6
|
+
* Version 4.1.1
|
|
7
|
+
* Added Hungarian (HU) BBAN validation
|
|
8
|
+
|
|
9
|
+
2021-12-01 Saša Jovanić <sasa@simplify.ba>
|
|
10
|
+
* Improve test coverage
|
|
11
|
+
|
|
12
|
+
2021-11-30 Saša Jovanić <sasa@simplify.ba>
|
|
13
|
+
* Added Estonian (EE) BBAN validation
|
|
14
|
+
* Added Finland (FI) BBAN validation
|
|
15
|
+
* Aland Islands (AX) uses BBAN valkidation from Finland
|
|
16
|
+
* Added French (FR) and Monaco (MC) BBAN validation
|
|
17
|
+
|
|
18
|
+
2021-11-28 Saša Jovanić <sasa@simplify.ba>
|
|
19
|
+
* Added Czech (CZ) BBAN validation
|
|
20
|
+
|
|
21
|
+
2021-11-27 Saša Jovanić <sasa@simplify.ba>
|
|
22
|
+
* Added Croatian (HR) BBAN validation
|
|
23
|
+
|
|
24
|
+
2021-11-25 Saša Jovanić <sasa@simplify.ba>
|
|
25
|
+
* Version 4.1.0
|
|
26
|
+
* Added Belgian (BE) extra BBAN validation
|
|
27
|
+
* Added mod97/10 BBAN validation for countries that do it that way: BA, ME, MK, PT, RS and SI
|
|
28
|
+
|
|
29
|
+
2021-11-24 Saša Jovanić <sasa@simplify.ba>
|
|
30
|
+
* Added Netherlands (NL) extra BBAN validation
|
|
31
|
+
* Added extra error code when validating IBAN `WrongAccountBankBranchChecksum` that indicates when checksum for account number or bank or branch code is incorrect
|
|
32
|
+
|
|
33
|
+
2021-11-23 Saša Jovanić <sasa@simplify.ba>
|
|
34
|
+
* Version 4.0.1
|
|
35
|
+
* Fixed bug when validating Spain IBAN
|
|
36
|
+
|
|
37
|
+
2021-11-18 Saša Jovanić <sasa@simplify.ba>
|
|
38
|
+
* Updated README with new and updated badges
|
|
39
|
+
* Fixed documentation on GH pages
|
|
40
|
+
* Added dependabot dependency updates and merged some created dependency pull requests
|
|
41
|
+
* Added Node 17 to build version on GitHub actions
|
|
42
|
+
* Added GitHub CodeQL workflow
|
|
43
|
+
|
|
1
44
|
2021-11-17 Saša Jovanić <sasa@simplify.ba>
|
|
2
45
|
* Version 4.0.0
|
|
3
46
|
* Fixed Senegal (SN) regular expression
|
package/README.md
CHANGED
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
# IBANTools
|
|
2
2
|
|
|
3
|
-
[](https://github.com/Simplify/ibantools/blob/master/LICENSE)
|
|
4
4
|
|
|
5
5
|
[](https://badge.fury.io/bo/ibantools)
|
|
6
6
|
[](https://badge.fury.io/js/ibantools)
|
|
7
|
+
[](https://www.npmjs.com/package/ibantools)
|
|
8
|
+

|
|
7
9
|
|
|
8
10
|
/badge.svg?branch=master)
|
|
9
11
|

|
|
10
12
|
[](https://coveralls.io/github/Simplify/ibantools?branch=master)
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+

|
|
15
|
+

|
|
16
|
+

|
|
17
|
+

|
|
18
|
+

|
|
19
|
+

|
|
20
|
+
|
|
21
|
+

|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
## About
|
|
14
25
|
|
|
15
26
|
IBANTools is TypeScript/JavaScript library for validation, creation and extraction of IBAN, BBAN and BIC/SWIFT numbers.
|
|
16
27
|
|
|
@@ -19,7 +30,7 @@ For more information about IBAN/BBAN see [wikipedia page](https://en.wikipedia.o
|
|
|
19
30
|
|
|
20
31
|
For more information about BIC/SWIFT see [this wikipedia page](https://en.wikipedia.org/wiki/ISO_9362).
|
|
21
32
|
|
|
22
|
-
## Installation
|
|
33
|
+
## Installation
|
|
23
34
|
|
|
24
35
|
### Node (Common JS ES5 and ES6)
|
|
25
36
|
|
package/build/ibantools.d.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* // returns false
|
|
14
14
|
* ibantools.isValidIBAN("NL92ABNA0517164300");
|
|
15
15
|
* ```
|
|
16
|
-
|
|
16
|
+
*/
|
|
17
17
|
export declare function isValidIBAN(iban: string): boolean;
|
|
18
18
|
/**
|
|
19
19
|
* IBAM validation errors
|
|
@@ -24,7 +24,8 @@ export declare enum ValidationErrorsIBAN {
|
|
|
24
24
|
WrongBBANLength = 2,
|
|
25
25
|
WrongBBANFormat = 3,
|
|
26
26
|
ChecksumNotNumber = 4,
|
|
27
|
-
WrongIBANChecksum = 5
|
|
27
|
+
WrongIBANChecksum = 5,
|
|
28
|
+
WrongAccountBankBranchChecksum = 6
|
|
28
29
|
}
|
|
29
30
|
/**
|
|
30
31
|
* Interface for ValidateIBAN result
|
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.
|
|
11
|
+
* @version 4.1.2
|
|
12
12
|
* @license MPL-2.0
|
|
13
13
|
* @preferred
|
|
14
14
|
*/
|
|
@@ -25,7 +25,7 @@ exports.countrySpecs = exports.extractBIC = exports.validateBIC = exports.Valida
|
|
|
25
25
|
* // returns false
|
|
26
26
|
* ibantools.isValidIBAN("NL92ABNA0517164300");
|
|
27
27
|
* ```
|
|
28
|
-
|
|
28
|
+
*/
|
|
29
29
|
function isValidIBAN(iban) {
|
|
30
30
|
if (iban !== undefined && iban !== null) {
|
|
31
31
|
var reg = new RegExp('^[0-9]{2}$', '');
|
|
@@ -55,6 +55,7 @@ var ValidationErrorsIBAN;
|
|
|
55
55
|
ValidationErrorsIBAN[ValidationErrorsIBAN["WrongBBANFormat"] = 3] = "WrongBBANFormat";
|
|
56
56
|
ValidationErrorsIBAN[ValidationErrorsIBAN["ChecksumNotNumber"] = 4] = "ChecksumNotNumber";
|
|
57
57
|
ValidationErrorsIBAN[ValidationErrorsIBAN["WrongIBANChecksum"] = 5] = "WrongIBANChecksum";
|
|
58
|
+
ValidationErrorsIBAN[ValidationErrorsIBAN["WrongAccountBankBranchChecksum"] = 6] = "WrongAccountBankBranchChecksum";
|
|
58
59
|
})(ValidationErrorsIBAN = exports.ValidationErrorsIBAN || (exports.ValidationErrorsIBAN = {}));
|
|
59
60
|
/**
|
|
60
61
|
* validateIBAN
|
|
@@ -70,15 +71,20 @@ function validateIBAN(iban) {
|
|
|
70
71
|
if (!spec || !(spec.bban_regexp || spec.chars)) {
|
|
71
72
|
result.valid = false;
|
|
72
73
|
result.errorCodes.push(ValidationErrorsIBAN.NoIBANCountry);
|
|
74
|
+
return result;
|
|
73
75
|
}
|
|
74
76
|
if (spec && spec.chars && spec.chars !== iban.length) {
|
|
75
77
|
result.valid = false;
|
|
76
78
|
result.errorCodes.push(ValidationErrorsIBAN.WrongBBANLength);
|
|
77
79
|
}
|
|
78
|
-
if (spec && spec.bban_regexp && !
|
|
80
|
+
if (spec && spec.bban_regexp && !checkFormatBBAN(iban.slice(4), spec.bban_regexp)) {
|
|
79
81
|
result.valid = false;
|
|
80
82
|
result.errorCodes.push(ValidationErrorsIBAN.WrongBBANFormat);
|
|
81
83
|
}
|
|
84
|
+
if (spec && spec.bban_validation_func && !spec.bban_validation_func(iban.slice(4))) {
|
|
85
|
+
result.valid = false;
|
|
86
|
+
result.errorCodes.push(ValidationErrorsIBAN.WrongAccountBankBranchChecksum);
|
|
87
|
+
}
|
|
82
88
|
var reg = new RegExp('^[0-9]{2}$', '');
|
|
83
89
|
if (!reg.test(iban.slice(2, 4))) {
|
|
84
90
|
result.valid = false;
|
|
@@ -171,7 +177,7 @@ function composeIBAN(params) {
|
|
|
171
177
|
spec.bban_regexp &&
|
|
172
178
|
spec.bban_regexp !== null &&
|
|
173
179
|
checkFormatBBAN(formated_bban, spec.bban_regexp)) {
|
|
174
|
-
var checksom =
|
|
180
|
+
var checksom = mod9710Iban(params.countryCode + '00' + formated_bban);
|
|
175
181
|
return params.countryCode + ('0' + (98 - checksom)).slice(-2) + formated_bban;
|
|
176
182
|
}
|
|
177
183
|
return null;
|
|
@@ -281,7 +287,7 @@ function isValidIBANChecksum(iban) {
|
|
|
281
287
|
*
|
|
282
288
|
* @ignore
|
|
283
289
|
*/
|
|
284
|
-
function
|
|
290
|
+
function mod9710Iban(iban) {
|
|
285
291
|
iban = iban.slice(3) + iban.slice(0, 4);
|
|
286
292
|
var validationString = '';
|
|
287
293
|
for (var n = 1; n < iban.length; n++) {
|
|
@@ -293,11 +299,7 @@ function mod9710(iban) {
|
|
|
293
299
|
validationString += iban[n];
|
|
294
300
|
}
|
|
295
301
|
}
|
|
296
|
-
|
|
297
|
-
var part = validationString.slice(0, 6);
|
|
298
|
-
validationString = (parseInt(part, 10) % 97).toString() + validationString.slice(part.length);
|
|
299
|
-
}
|
|
300
|
-
return parseInt(validationString, 10) % 97;
|
|
302
|
+
return mod9710(validationString);
|
|
301
303
|
}
|
|
302
304
|
/**
|
|
303
305
|
* Returns specifications for all countries, even those who are not
|
|
@@ -432,19 +434,66 @@ exports.extractBIC = extractBIC;
|
|
|
432
434
|
var checkNorwayBBAN = function (bban) {
|
|
433
435
|
var weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
|
|
434
436
|
var bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, '');
|
|
435
|
-
|
|
436
|
-
|
|
437
|
+
var controlDigit = parseInt(bbanWithoutSpacesAndPeriods.charAt(10), 10);
|
|
438
|
+
var bbanWithoutControlDigit = bbanWithoutSpacesAndPeriods.substring(0, 10);
|
|
439
|
+
var sum = 0;
|
|
440
|
+
for (var index = 0; index < 10; index++) {
|
|
441
|
+
sum += parseInt(bbanWithoutControlDigit.charAt(index), 10) * weights[index];
|
|
437
442
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
443
|
+
var remainder = sum % 11;
|
|
444
|
+
return controlDigit === (remainder === 0 ? 0 : 11 - remainder);
|
|
445
|
+
};
|
|
446
|
+
/**
|
|
447
|
+
* Used for Netherlands BBAN check
|
|
448
|
+
*
|
|
449
|
+
* @ignore
|
|
450
|
+
*/
|
|
451
|
+
var checkDutchBBAN = function (bban) {
|
|
452
|
+
var bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, '');
|
|
453
|
+
var accountNumber = bbanWithoutSpacesAndPeriods.substring(4, 14);
|
|
454
|
+
if (accountNumber.startsWith('000')) {
|
|
455
|
+
return true; // Postbank account, no `elfproef` possible
|
|
447
456
|
}
|
|
457
|
+
var sum = 0;
|
|
458
|
+
for (var index = 0; index < 10; index++) {
|
|
459
|
+
sum += parseInt(accountNumber.charAt(index), 10) * (10 - index);
|
|
460
|
+
}
|
|
461
|
+
return sum % 11 === 0;
|
|
462
|
+
};
|
|
463
|
+
/**
|
|
464
|
+
* Used for Belgian BBAN check
|
|
465
|
+
*
|
|
466
|
+
* @ignore
|
|
467
|
+
*/
|
|
468
|
+
var checkBelgianBBAN = function (bban) {
|
|
469
|
+
var stripped = bban.replace(/[\s.]+/g, '');
|
|
470
|
+
var checkingPart = parseInt(stripped.substring(0, stripped.length - 2), 10);
|
|
471
|
+
var checksum = parseInt(stripped.substring(stripped.length - 2, stripped.length), 10);
|
|
472
|
+
var remainder = checkingPart % 97 === 0 ? 97 : checkingPart % 97;
|
|
473
|
+
return remainder === checksum;
|
|
474
|
+
};
|
|
475
|
+
/**
|
|
476
|
+
* Mod 97/10 calculation
|
|
477
|
+
*
|
|
478
|
+
* @ignore
|
|
479
|
+
*/
|
|
480
|
+
var mod9710 = function (validationString) {
|
|
481
|
+
while (validationString.length > 2) {
|
|
482
|
+
var part = validationString.slice(0, 6);
|
|
483
|
+
validationString = (parseInt(part, 10) % 97).toString() + validationString.slice(part.length);
|
|
484
|
+
}
|
|
485
|
+
return parseInt(validationString, 10) % 97;
|
|
486
|
+
};
|
|
487
|
+
/**
|
|
488
|
+
* Check BBAN based on Mod97/10 calculation for countries that support it:
|
|
489
|
+
* BA, ME, MK, PT, RS, SI
|
|
490
|
+
*
|
|
491
|
+
* @ignore
|
|
492
|
+
*/
|
|
493
|
+
var checkMod9710BBAN = function (bban) {
|
|
494
|
+
var stripped = bban.replace(/[\s.]+/g, '');
|
|
495
|
+
var reminder = mod9710(stripped);
|
|
496
|
+
return reminder === 1;
|
|
448
497
|
};
|
|
449
498
|
/**
|
|
450
499
|
* Used for Poland BBAN check
|
|
@@ -479,7 +528,7 @@ var checkSpainBBAN = function (bban) {
|
|
|
479
528
|
sum += parseInt(bankBranch.charAt(index), 10) * weightsBankBranch[index];
|
|
480
529
|
}
|
|
481
530
|
var remainder = sum % 11;
|
|
482
|
-
if (controlBankBranch !== (remainder === 0 ? 0 : 11 - remainder)) {
|
|
531
|
+
if (controlBankBranch !== (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder)) {
|
|
483
532
|
return false;
|
|
484
533
|
}
|
|
485
534
|
sum = 0;
|
|
@@ -487,7 +536,214 @@ var checkSpainBBAN = function (bban) {
|
|
|
487
536
|
sum += parseInt(account.charAt(index), 10) * weightsAccount[index];
|
|
488
537
|
}
|
|
489
538
|
remainder = sum % 11;
|
|
490
|
-
return controlAccount === (remainder === 0 ? 0 : 11 - remainder);
|
|
539
|
+
return controlAccount === (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder);
|
|
540
|
+
};
|
|
541
|
+
/**
|
|
542
|
+
* Mod 11/10 check
|
|
543
|
+
*
|
|
544
|
+
* @ignore
|
|
545
|
+
*/
|
|
546
|
+
var checkMod1110 = function (toCheck, control) {
|
|
547
|
+
var nr = 10;
|
|
548
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
549
|
+
nr += parseInt(toCheck.charAt(index), 10);
|
|
550
|
+
if (nr % 10 !== 0) {
|
|
551
|
+
nr = nr % 10;
|
|
552
|
+
}
|
|
553
|
+
nr = nr * 2;
|
|
554
|
+
nr = nr % 11;
|
|
555
|
+
}
|
|
556
|
+
return control === (11 - nr === 10 ? 0 : 11 - nr);
|
|
557
|
+
};
|
|
558
|
+
/**
|
|
559
|
+
* Croatian (HR) BBAN check
|
|
560
|
+
*
|
|
561
|
+
* @ignore
|
|
562
|
+
*/
|
|
563
|
+
var checkCroatianBBAN = function (bban) {
|
|
564
|
+
var controlBankBranch = parseInt(bban.charAt(6), 10);
|
|
565
|
+
var controlAccount = parseInt(bban.charAt(16), 10);
|
|
566
|
+
var bankBranch = bban.substring(0, 6);
|
|
567
|
+
var account = bban.substring(7, 16);
|
|
568
|
+
return checkMod1110(bankBranch, controlBankBranch) && checkMod1110(account, controlAccount);
|
|
569
|
+
};
|
|
570
|
+
/**
|
|
571
|
+
* Czech (CZ) BBAN check
|
|
572
|
+
*
|
|
573
|
+
* @ignore
|
|
574
|
+
*/
|
|
575
|
+
var checkCzechBBAN = function (bban) {
|
|
576
|
+
var weightsPrefix = [10, 5, 8, 4, 2, 1];
|
|
577
|
+
var weightsSuffix = [6, 3, 7, 9, 10, 5, 8, 4, 2, 1];
|
|
578
|
+
var controlPrefix = parseInt(bban.charAt(9), 10);
|
|
579
|
+
var controlSuffix = parseInt(bban.charAt(19), 10);
|
|
580
|
+
var prefix = bban.substring(4, 9);
|
|
581
|
+
var suffix = bban.substring(10, 19);
|
|
582
|
+
var sum = 0;
|
|
583
|
+
for (var index = 0; index < prefix.length; index++) {
|
|
584
|
+
sum += parseInt(prefix.charAt(index), 10) * weightsPrefix[index];
|
|
585
|
+
}
|
|
586
|
+
var remainder = sum % 11;
|
|
587
|
+
if (controlPrefix !== (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder)) {
|
|
588
|
+
return false;
|
|
589
|
+
}
|
|
590
|
+
sum = 0;
|
|
591
|
+
for (var index = 0; index < suffix.length; index++) {
|
|
592
|
+
sum += parseInt(suffix.charAt(index), 10) * weightsSuffix[index];
|
|
593
|
+
}
|
|
594
|
+
remainder = sum % 11;
|
|
595
|
+
return controlSuffix === (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder);
|
|
596
|
+
};
|
|
597
|
+
/**
|
|
598
|
+
* Estonian (EE) BBAN check
|
|
599
|
+
*
|
|
600
|
+
* @ignore
|
|
601
|
+
*/
|
|
602
|
+
var checkEstonianBBAN = function (bban) {
|
|
603
|
+
var weights = [7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1, 3, 7];
|
|
604
|
+
var controlDigit = parseInt(bban.charAt(15), 10);
|
|
605
|
+
var toCheck = bban.substring(2, 15);
|
|
606
|
+
var sum = 0;
|
|
607
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
608
|
+
sum += parseInt(toCheck.charAt(index), 10) * weights[index];
|
|
609
|
+
}
|
|
610
|
+
var remainder = sum % 10;
|
|
611
|
+
return controlDigit === (remainder === 0 ? 0 : 10 - remainder);
|
|
612
|
+
};
|
|
613
|
+
/**
|
|
614
|
+
* Finland (FI) BBAN check
|
|
615
|
+
*
|
|
616
|
+
* @ignore
|
|
617
|
+
*/
|
|
618
|
+
var checkFinlandBBAN = function (bban) {
|
|
619
|
+
var weightsMethod1 = [2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2];
|
|
620
|
+
var weightsMethod2 = [0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 1, 3, 7];
|
|
621
|
+
var controlDigit = parseInt(bban.charAt(13), 10);
|
|
622
|
+
var toCheck = bban.substring(0, 13);
|
|
623
|
+
var sum = 0;
|
|
624
|
+
if (toCheck.startsWith('88')) {
|
|
625
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
626
|
+
sum += parseInt(toCheck.charAt(index), 10) * weightsMethod2[index];
|
|
627
|
+
}
|
|
628
|
+
var remainder = sum % 10;
|
|
629
|
+
return controlDigit === (remainder === 0 ? 0 : 10 - remainder);
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
633
|
+
if (weightsMethod1[index] === 1) {
|
|
634
|
+
sum += parseInt(toCheck.charAt(index), 10) * weightsMethod1[index];
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
var value = parseInt(toCheck.charAt(index), 10) * weightsMethod1[index];
|
|
638
|
+
sum += Math.floor(value / 10) + (value % 10);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
var extraSum = sum + controlDigit;
|
|
642
|
+
var multiDigit = Math.floor(extraSum / 10);
|
|
643
|
+
var result = multiDigit * 10;
|
|
644
|
+
var remainder = result - sum;
|
|
645
|
+
return remainder === controlDigit;
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
/**
|
|
649
|
+
* Check French (FR) BBAN
|
|
650
|
+
* Also for Monaco (MC)
|
|
651
|
+
*
|
|
652
|
+
* @ignore
|
|
653
|
+
*/
|
|
654
|
+
var checkFrenchBBAN = function (bban) {
|
|
655
|
+
var stripped = bban.replace(/[\s.]+/g, '');
|
|
656
|
+
var normalized = Array.from(stripped);
|
|
657
|
+
for (var index = 0; index < stripped.length; index++) {
|
|
658
|
+
var c = normalized[index].charCodeAt(0);
|
|
659
|
+
if (c >= 65) {
|
|
660
|
+
switch (c) {
|
|
661
|
+
case 65:
|
|
662
|
+
case 74:
|
|
663
|
+
normalized[index] = '1';
|
|
664
|
+
break;
|
|
665
|
+
case 66:
|
|
666
|
+
case 75:
|
|
667
|
+
case 83:
|
|
668
|
+
normalized[index] = '2';
|
|
669
|
+
break;
|
|
670
|
+
case 67:
|
|
671
|
+
case 76:
|
|
672
|
+
case 84:
|
|
673
|
+
normalized[index] = '3';
|
|
674
|
+
break;
|
|
675
|
+
case 68:
|
|
676
|
+
case 77:
|
|
677
|
+
case 85:
|
|
678
|
+
normalized[index] = '4';
|
|
679
|
+
break;
|
|
680
|
+
case 69:
|
|
681
|
+
case 78:
|
|
682
|
+
case 86:
|
|
683
|
+
normalized[index] = '5';
|
|
684
|
+
break;
|
|
685
|
+
case 70:
|
|
686
|
+
case 79:
|
|
687
|
+
case 87:
|
|
688
|
+
normalized[index] = '6';
|
|
689
|
+
break;
|
|
690
|
+
case 71:
|
|
691
|
+
case 80:
|
|
692
|
+
case 88:
|
|
693
|
+
normalized[index] = '7';
|
|
694
|
+
break;
|
|
695
|
+
case 72:
|
|
696
|
+
case 81:
|
|
697
|
+
case 89:
|
|
698
|
+
normalized[index] = '8';
|
|
699
|
+
break;
|
|
700
|
+
case 73:
|
|
701
|
+
case 82:
|
|
702
|
+
case 90:
|
|
703
|
+
normalized[index] = '9';
|
|
704
|
+
break;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
var remainder = mod9710(normalized.join(''));
|
|
709
|
+
return remainder === 0;
|
|
710
|
+
};
|
|
711
|
+
/**
|
|
712
|
+
* Hungarian (HU) BBAN check
|
|
713
|
+
*
|
|
714
|
+
* @ignore
|
|
715
|
+
*/
|
|
716
|
+
var checkHungarianBBAN = function (bban) {
|
|
717
|
+
var weights = [9, 7, 3, 1, 9, 7, 3, 1, 9, 7, 3, 1, 9, 7, 3];
|
|
718
|
+
var controlDigitBankBranch = parseInt(bban.charAt(7), 10);
|
|
719
|
+
var toCheckBankBranch = bban.substring(0, 7);
|
|
720
|
+
var sum = 0;
|
|
721
|
+
for (var index = 0; index < toCheckBankBranch.length; index++) {
|
|
722
|
+
sum += parseInt(toCheckBankBranch.charAt(index), 10) * weights[index];
|
|
723
|
+
}
|
|
724
|
+
var remainder = sum % 10;
|
|
725
|
+
if (controlDigitBankBranch !== (remainder === 0 ? 0 : 10 - remainder)) {
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
sum = 0;
|
|
729
|
+
if (bban.endsWith('00000000')) {
|
|
730
|
+
var toCheckAccount = bban.substring(8, 15);
|
|
731
|
+
var controlDigitAccount = parseInt(bban.charAt(15), 10);
|
|
732
|
+
for (var index = 0; index < toCheckAccount.length; index++) {
|
|
733
|
+
sum += parseInt(toCheckAccount.charAt(index), 10) * weights[index];
|
|
734
|
+
}
|
|
735
|
+
var remainder_1 = sum % 10;
|
|
736
|
+
return controlDigitAccount === (remainder_1 === 0 ? 0 : 10 - remainder_1);
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
var toCheckAccount = bban.substring(8, 23);
|
|
740
|
+
var controlDigitAccount = parseInt(bban.charAt(23), 10);
|
|
741
|
+
for (var index = 0; index < toCheckAccount.length; index++) {
|
|
742
|
+
sum += parseInt(toCheckAccount.charAt(index), 10) * weights[index];
|
|
743
|
+
}
|
|
744
|
+
var remainder_2 = sum % 10;
|
|
745
|
+
return controlDigitAccount === (remainder_2 === 0 ? 0 : 10 - remainder_2);
|
|
746
|
+
}
|
|
491
747
|
};
|
|
492
748
|
/**
|
|
493
749
|
* Country specifications
|
|
@@ -526,6 +782,7 @@ exports.countrySpecs = {
|
|
|
526
782
|
AX: {
|
|
527
783
|
chars: 18,
|
|
528
784
|
bban_regexp: '^[0-9]{14}$',
|
|
785
|
+
bban_validation_func: checkFinlandBBAN,
|
|
529
786
|
IBANRegistry: true,
|
|
530
787
|
},
|
|
531
788
|
AZ: {
|
|
@@ -536,11 +793,12 @@ exports.countrySpecs = {
|
|
|
536
793
|
BA: {
|
|
537
794
|
chars: 20,
|
|
538
795
|
bban_regexp: '^[0-9]{16}$',
|
|
796
|
+
bban_validation_func: checkMod9710BBAN,
|
|
539
797
|
IBANRegistry: true,
|
|
540
798
|
},
|
|
541
799
|
BB: {},
|
|
542
800
|
BD: {},
|
|
543
|
-
BE: { chars: 16, bban_regexp: '^[0-9]{12}$', IBANRegistry: true, SEPA: true },
|
|
801
|
+
BE: { chars: 16, bban_regexp: '^[0-9]{12}$', bban_validation_func: checkBelgianBBAN, IBANRegistry: true, SEPA: true },
|
|
544
802
|
BF: {
|
|
545
803
|
chars: 28,
|
|
546
804
|
bban_regexp: '^[A-Z0-9]{2}[0-9]{22}$',
|
|
@@ -632,7 +890,13 @@ exports.countrySpecs = {
|
|
|
632
890
|
IBANRegistry: true,
|
|
633
891
|
SEPA: true,
|
|
634
892
|
},
|
|
635
|
-
CZ: {
|
|
893
|
+
CZ: {
|
|
894
|
+
chars: 24,
|
|
895
|
+
bban_regexp: '^[0-9]{20}$',
|
|
896
|
+
bban_validation_func: checkCzechBBAN,
|
|
897
|
+
IBANRegistry: true,
|
|
898
|
+
SEPA: true,
|
|
899
|
+
},
|
|
636
900
|
DE: { chars: 22, bban_regexp: '^[0-9]{18}$', IBANRegistry: true, SEPA: true },
|
|
637
901
|
DJ: {
|
|
638
902
|
chars: 27,
|
|
@@ -650,13 +914,31 @@ exports.countrySpecs = {
|
|
|
650
914
|
bban_regexp: '^[0-9]{22}$',
|
|
651
915
|
},
|
|
652
916
|
EC: {},
|
|
653
|
-
EE: {
|
|
917
|
+
EE: {
|
|
918
|
+
chars: 20,
|
|
919
|
+
bban_regexp: '^[0-9]{16}$',
|
|
920
|
+
bban_validation_func: checkEstonianBBAN,
|
|
921
|
+
IBANRegistry: true,
|
|
922
|
+
SEPA: true,
|
|
923
|
+
},
|
|
654
924
|
EG: { chars: 29, bban_regexp: '^[0-9]{25}', IBANRegistry: true },
|
|
655
925
|
EH: {},
|
|
656
926
|
ER: {},
|
|
657
|
-
ES: {
|
|
927
|
+
ES: {
|
|
928
|
+
chars: 24,
|
|
929
|
+
bban_validation_func: checkSpainBBAN,
|
|
930
|
+
bban_regexp: '^[0-9]{20}$',
|
|
931
|
+
IBANRegistry: true,
|
|
932
|
+
SEPA: true,
|
|
933
|
+
},
|
|
658
934
|
ET: {},
|
|
659
|
-
FI: {
|
|
935
|
+
FI: {
|
|
936
|
+
chars: 18,
|
|
937
|
+
bban_regexp: '^[0-9]{14}$',
|
|
938
|
+
bban_validation_func: checkFinlandBBAN,
|
|
939
|
+
IBANRegistry: true,
|
|
940
|
+
SEPA: true,
|
|
941
|
+
},
|
|
660
942
|
FJ: {},
|
|
661
943
|
FK: {},
|
|
662
944
|
FM: {},
|
|
@@ -664,6 +946,7 @@ exports.countrySpecs = {
|
|
|
664
946
|
FR: {
|
|
665
947
|
chars: 27,
|
|
666
948
|
bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
|
|
949
|
+
bban_validation_func: checkFrenchBBAN,
|
|
667
950
|
IBANRegistry: true,
|
|
668
951
|
SEPA: true,
|
|
669
952
|
},
|
|
@@ -732,9 +1015,21 @@ exports.countrySpecs = {
|
|
|
732
1015
|
chars: 28,
|
|
733
1016
|
bban_regexp: '^[A-Z]{4}[0-9]{20}$',
|
|
734
1017
|
},
|
|
735
|
-
HR: {
|
|
1018
|
+
HR: {
|
|
1019
|
+
chars: 21,
|
|
1020
|
+
bban_regexp: '^[0-9]{17}$',
|
|
1021
|
+
bban_validation_func: checkCroatianBBAN,
|
|
1022
|
+
IBANRegistry: true,
|
|
1023
|
+
SEPA: true,
|
|
1024
|
+
},
|
|
736
1025
|
HT: {},
|
|
737
|
-
HU: {
|
|
1026
|
+
HU: {
|
|
1027
|
+
chars: 28,
|
|
1028
|
+
bban_regexp: '^[0-9]{24}$',
|
|
1029
|
+
bban_validation_func: checkHungarianBBAN,
|
|
1030
|
+
IBANRegistry: true,
|
|
1031
|
+
SEPA: true,
|
|
1032
|
+
},
|
|
738
1033
|
ID: {},
|
|
739
1034
|
IE: {
|
|
740
1035
|
chars: 22,
|
|
@@ -841,6 +1136,7 @@ exports.countrySpecs = {
|
|
|
841
1136
|
MC: {
|
|
842
1137
|
chars: 27,
|
|
843
1138
|
bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
|
|
1139
|
+
bban_validation_func: checkFrenchBBAN,
|
|
844
1140
|
IBANRegistry: true,
|
|
845
1141
|
SEPA: true,
|
|
846
1142
|
},
|
|
@@ -852,6 +1148,7 @@ exports.countrySpecs = {
|
|
|
852
1148
|
ME: {
|
|
853
1149
|
chars: 22,
|
|
854
1150
|
bban_regexp: '^[0-9]{18}$',
|
|
1151
|
+
bban_validation_func: checkMod9710BBAN,
|
|
855
1152
|
IBANRegistry: true,
|
|
856
1153
|
},
|
|
857
1154
|
MF: {
|
|
@@ -867,6 +1164,7 @@ exports.countrySpecs = {
|
|
|
867
1164
|
MK: {
|
|
868
1165
|
chars: 19,
|
|
869
1166
|
bban_regexp: '^[0-9]{3}[A-Z0-9]{10}[0-9]{2}$',
|
|
1167
|
+
bban_validation_func: checkMod9710BBAN,
|
|
870
1168
|
IBANRegistry: true,
|
|
871
1169
|
},
|
|
872
1170
|
ML: {
|
|
@@ -926,6 +1224,7 @@ exports.countrySpecs = {
|
|
|
926
1224
|
NL: {
|
|
927
1225
|
chars: 18,
|
|
928
1226
|
bban_regexp: '^[A-Z]{4}[0-9]{10}$',
|
|
1227
|
+
bban_validation_func: checkDutchBBAN,
|
|
929
1228
|
IBANRegistry: true,
|
|
930
1229
|
SEPA: true,
|
|
931
1230
|
},
|
|
@@ -962,7 +1261,7 @@ exports.countrySpecs = {
|
|
|
962
1261
|
bban_regexp: '^[A-Z0-9]{4}[0-9]{21}$',
|
|
963
1262
|
IBANRegistry: true,
|
|
964
1263
|
},
|
|
965
|
-
PT: { chars: 25, bban_regexp: '^[0-9]{21}$', IBANRegistry: true, SEPA: true },
|
|
1264
|
+
PT: { chars: 25, bban_regexp: '^[0-9]{21}$', bban_validation_func: checkMod9710BBAN, IBANRegistry: true, SEPA: true },
|
|
966
1265
|
PW: {},
|
|
967
1266
|
PY: {},
|
|
968
1267
|
QA: {
|
|
@@ -984,6 +1283,7 @@ exports.countrySpecs = {
|
|
|
984
1283
|
RS: {
|
|
985
1284
|
chars: 22,
|
|
986
1285
|
bban_regexp: '^[0-9]{18}$',
|
|
1286
|
+
bban_validation_func: checkMod9710BBAN,
|
|
987
1287
|
IBANRegistry: true,
|
|
988
1288
|
},
|
|
989
1289
|
RU: {},
|
|
@@ -1003,7 +1303,13 @@ exports.countrySpecs = {
|
|
|
1003
1303
|
SE: { chars: 24, bban_regexp: '^[0-9]{20}$', IBANRegistry: true, SEPA: true },
|
|
1004
1304
|
SG: {},
|
|
1005
1305
|
SH: {},
|
|
1006
|
-
SI: {
|
|
1306
|
+
SI: {
|
|
1307
|
+
chars: 19,
|
|
1308
|
+
bban_regexp: '^[0-9]{15}$',
|
|
1309
|
+
bban_validation_func: checkMod9710BBAN,
|
|
1310
|
+
IBANRegistry: true,
|
|
1311
|
+
SEPA: true,
|
|
1312
|
+
},
|
|
1007
1313
|
SJ: {},
|
|
1008
1314
|
SK: { chars: 24, bban_regexp: '^[0-9]{20}$', IBANRegistry: true, SEPA: true },
|
|
1009
1315
|
SL: {},
|
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.
|
|
11
|
+
* @version 4.1.2
|
|
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
|
+
*/
|
|
27
27
|
export function isValidIBAN(iban) {
|
|
28
28
|
if (iban !== undefined && iban !== null) {
|
|
29
29
|
var reg = new RegExp('^[0-9]{2}$', '');
|
|
@@ -52,6 +52,7 @@ export var ValidationErrorsIBAN;
|
|
|
52
52
|
ValidationErrorsIBAN[ValidationErrorsIBAN["WrongBBANFormat"] = 3] = "WrongBBANFormat";
|
|
53
53
|
ValidationErrorsIBAN[ValidationErrorsIBAN["ChecksumNotNumber"] = 4] = "ChecksumNotNumber";
|
|
54
54
|
ValidationErrorsIBAN[ValidationErrorsIBAN["WrongIBANChecksum"] = 5] = "WrongIBANChecksum";
|
|
55
|
+
ValidationErrorsIBAN[ValidationErrorsIBAN["WrongAccountBankBranchChecksum"] = 6] = "WrongAccountBankBranchChecksum";
|
|
55
56
|
})(ValidationErrorsIBAN || (ValidationErrorsIBAN = {}));
|
|
56
57
|
/**
|
|
57
58
|
* validateIBAN
|
|
@@ -67,15 +68,20 @@ export function validateIBAN(iban) {
|
|
|
67
68
|
if (!spec || !(spec.bban_regexp || spec.chars)) {
|
|
68
69
|
result.valid = false;
|
|
69
70
|
result.errorCodes.push(ValidationErrorsIBAN.NoIBANCountry);
|
|
71
|
+
return result;
|
|
70
72
|
}
|
|
71
73
|
if (spec && spec.chars && spec.chars !== iban.length) {
|
|
72
74
|
result.valid = false;
|
|
73
75
|
result.errorCodes.push(ValidationErrorsIBAN.WrongBBANLength);
|
|
74
76
|
}
|
|
75
|
-
if (spec && spec.bban_regexp && !
|
|
77
|
+
if (spec && spec.bban_regexp && !checkFormatBBAN(iban.slice(4), spec.bban_regexp)) {
|
|
76
78
|
result.valid = false;
|
|
77
79
|
result.errorCodes.push(ValidationErrorsIBAN.WrongBBANFormat);
|
|
78
80
|
}
|
|
81
|
+
if (spec && spec.bban_validation_func && !spec.bban_validation_func(iban.slice(4))) {
|
|
82
|
+
result.valid = false;
|
|
83
|
+
result.errorCodes.push(ValidationErrorsIBAN.WrongAccountBankBranchChecksum);
|
|
84
|
+
}
|
|
79
85
|
var reg = new RegExp('^[0-9]{2}$', '');
|
|
80
86
|
if (!reg.test(iban.slice(2, 4))) {
|
|
81
87
|
result.valid = false;
|
|
@@ -165,7 +171,7 @@ export function composeIBAN(params) {
|
|
|
165
171
|
spec.bban_regexp &&
|
|
166
172
|
spec.bban_regexp !== null &&
|
|
167
173
|
checkFormatBBAN(formated_bban, spec.bban_regexp)) {
|
|
168
|
-
var checksom =
|
|
174
|
+
var checksom = mod9710Iban(params.countryCode + '00' + formated_bban);
|
|
169
175
|
return params.countryCode + ('0' + (98 - checksom)).slice(-2) + formated_bban;
|
|
170
176
|
}
|
|
171
177
|
return null;
|
|
@@ -271,7 +277,7 @@ function isValidIBANChecksum(iban) {
|
|
|
271
277
|
*
|
|
272
278
|
* @ignore
|
|
273
279
|
*/
|
|
274
|
-
function
|
|
280
|
+
function mod9710Iban(iban) {
|
|
275
281
|
iban = iban.slice(3) + iban.slice(0, 4);
|
|
276
282
|
var validationString = '';
|
|
277
283
|
for (var n = 1; n < iban.length; n++) {
|
|
@@ -283,11 +289,7 @@ function mod9710(iban) {
|
|
|
283
289
|
validationString += iban[n];
|
|
284
290
|
}
|
|
285
291
|
}
|
|
286
|
-
|
|
287
|
-
var part = validationString.slice(0, 6);
|
|
288
|
-
validationString = (parseInt(part, 10) % 97).toString() + validationString.slice(part.length);
|
|
289
|
-
}
|
|
290
|
-
return parseInt(validationString, 10) % 97;
|
|
292
|
+
return mod9710(validationString);
|
|
291
293
|
}
|
|
292
294
|
/**
|
|
293
295
|
* Returns specifications for all countries, even those who are not
|
|
@@ -418,19 +420,66 @@ export function extractBIC(inputBic) {
|
|
|
418
420
|
var checkNorwayBBAN = function (bban) {
|
|
419
421
|
var weights = [5, 4, 3, 2, 7, 6, 5, 4, 3, 2];
|
|
420
422
|
var bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, '');
|
|
421
|
-
|
|
422
|
-
|
|
423
|
+
var controlDigit = parseInt(bbanWithoutSpacesAndPeriods.charAt(10), 10);
|
|
424
|
+
var bbanWithoutControlDigit = bbanWithoutSpacesAndPeriods.substring(0, 10);
|
|
425
|
+
var sum = 0;
|
|
426
|
+
for (var index = 0; index < 10; index++) {
|
|
427
|
+
sum += parseInt(bbanWithoutControlDigit.charAt(index), 10) * weights[index];
|
|
423
428
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
429
|
+
var remainder = sum % 11;
|
|
430
|
+
return controlDigit === (remainder === 0 ? 0 : 11 - remainder);
|
|
431
|
+
};
|
|
432
|
+
/**
|
|
433
|
+
* Used for Netherlands BBAN check
|
|
434
|
+
*
|
|
435
|
+
* @ignore
|
|
436
|
+
*/
|
|
437
|
+
var checkDutchBBAN = function (bban) {
|
|
438
|
+
var bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, '');
|
|
439
|
+
var accountNumber = bbanWithoutSpacesAndPeriods.substring(4, 14);
|
|
440
|
+
if (accountNumber.startsWith('000')) {
|
|
441
|
+
return true; // Postbank account, no `elfproef` possible
|
|
433
442
|
}
|
|
443
|
+
var sum = 0;
|
|
444
|
+
for (var index = 0; index < 10; index++) {
|
|
445
|
+
sum += parseInt(accountNumber.charAt(index), 10) * (10 - index);
|
|
446
|
+
}
|
|
447
|
+
return sum % 11 === 0;
|
|
448
|
+
};
|
|
449
|
+
/**
|
|
450
|
+
* Used for Belgian BBAN check
|
|
451
|
+
*
|
|
452
|
+
* @ignore
|
|
453
|
+
*/
|
|
454
|
+
var checkBelgianBBAN = function (bban) {
|
|
455
|
+
var stripped = bban.replace(/[\s.]+/g, '');
|
|
456
|
+
var checkingPart = parseInt(stripped.substring(0, stripped.length - 2), 10);
|
|
457
|
+
var checksum = parseInt(stripped.substring(stripped.length - 2, stripped.length), 10);
|
|
458
|
+
var remainder = checkingPart % 97 === 0 ? 97 : checkingPart % 97;
|
|
459
|
+
return remainder === checksum;
|
|
460
|
+
};
|
|
461
|
+
/**
|
|
462
|
+
* Mod 97/10 calculation
|
|
463
|
+
*
|
|
464
|
+
* @ignore
|
|
465
|
+
*/
|
|
466
|
+
var mod9710 = function (validationString) {
|
|
467
|
+
while (validationString.length > 2) {
|
|
468
|
+
var part = validationString.slice(0, 6);
|
|
469
|
+
validationString = (parseInt(part, 10) % 97).toString() + validationString.slice(part.length);
|
|
470
|
+
}
|
|
471
|
+
return parseInt(validationString, 10) % 97;
|
|
472
|
+
};
|
|
473
|
+
/**
|
|
474
|
+
* Check BBAN based on Mod97/10 calculation for countries that support it:
|
|
475
|
+
* BA, ME, MK, PT, RS, SI
|
|
476
|
+
*
|
|
477
|
+
* @ignore
|
|
478
|
+
*/
|
|
479
|
+
var checkMod9710BBAN = function (bban) {
|
|
480
|
+
var stripped = bban.replace(/[\s.]+/g, '');
|
|
481
|
+
var reminder = mod9710(stripped);
|
|
482
|
+
return reminder === 1;
|
|
434
483
|
};
|
|
435
484
|
/**
|
|
436
485
|
* Used for Poland BBAN check
|
|
@@ -465,7 +514,7 @@ var checkSpainBBAN = function (bban) {
|
|
|
465
514
|
sum += parseInt(bankBranch.charAt(index), 10) * weightsBankBranch[index];
|
|
466
515
|
}
|
|
467
516
|
var remainder = sum % 11;
|
|
468
|
-
if (controlBankBranch !== (remainder === 0 ? 0 : 11 - remainder)) {
|
|
517
|
+
if (controlBankBranch !== (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder)) {
|
|
469
518
|
return false;
|
|
470
519
|
}
|
|
471
520
|
sum = 0;
|
|
@@ -473,7 +522,214 @@ var checkSpainBBAN = function (bban) {
|
|
|
473
522
|
sum += parseInt(account.charAt(index), 10) * weightsAccount[index];
|
|
474
523
|
}
|
|
475
524
|
remainder = sum % 11;
|
|
476
|
-
return controlAccount === (remainder === 0 ? 0 : 11 - remainder);
|
|
525
|
+
return controlAccount === (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder);
|
|
526
|
+
};
|
|
527
|
+
/**
|
|
528
|
+
* Mod 11/10 check
|
|
529
|
+
*
|
|
530
|
+
* @ignore
|
|
531
|
+
*/
|
|
532
|
+
var checkMod1110 = function (toCheck, control) {
|
|
533
|
+
var nr = 10;
|
|
534
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
535
|
+
nr += parseInt(toCheck.charAt(index), 10);
|
|
536
|
+
if (nr % 10 !== 0) {
|
|
537
|
+
nr = nr % 10;
|
|
538
|
+
}
|
|
539
|
+
nr = nr * 2;
|
|
540
|
+
nr = nr % 11;
|
|
541
|
+
}
|
|
542
|
+
return control === (11 - nr === 10 ? 0 : 11 - nr);
|
|
543
|
+
};
|
|
544
|
+
/**
|
|
545
|
+
* Croatian (HR) BBAN check
|
|
546
|
+
*
|
|
547
|
+
* @ignore
|
|
548
|
+
*/
|
|
549
|
+
var checkCroatianBBAN = function (bban) {
|
|
550
|
+
var controlBankBranch = parseInt(bban.charAt(6), 10);
|
|
551
|
+
var controlAccount = parseInt(bban.charAt(16), 10);
|
|
552
|
+
var bankBranch = bban.substring(0, 6);
|
|
553
|
+
var account = bban.substring(7, 16);
|
|
554
|
+
return checkMod1110(bankBranch, controlBankBranch) && checkMod1110(account, controlAccount);
|
|
555
|
+
};
|
|
556
|
+
/**
|
|
557
|
+
* Czech (CZ) BBAN check
|
|
558
|
+
*
|
|
559
|
+
* @ignore
|
|
560
|
+
*/
|
|
561
|
+
var checkCzechBBAN = function (bban) {
|
|
562
|
+
var weightsPrefix = [10, 5, 8, 4, 2, 1];
|
|
563
|
+
var weightsSuffix = [6, 3, 7, 9, 10, 5, 8, 4, 2, 1];
|
|
564
|
+
var controlPrefix = parseInt(bban.charAt(9), 10);
|
|
565
|
+
var controlSuffix = parseInt(bban.charAt(19), 10);
|
|
566
|
+
var prefix = bban.substring(4, 9);
|
|
567
|
+
var suffix = bban.substring(10, 19);
|
|
568
|
+
var sum = 0;
|
|
569
|
+
for (var index = 0; index < prefix.length; index++) {
|
|
570
|
+
sum += parseInt(prefix.charAt(index), 10) * weightsPrefix[index];
|
|
571
|
+
}
|
|
572
|
+
var remainder = sum % 11;
|
|
573
|
+
if (controlPrefix !== (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder)) {
|
|
574
|
+
return false;
|
|
575
|
+
}
|
|
576
|
+
sum = 0;
|
|
577
|
+
for (var index = 0; index < suffix.length; index++) {
|
|
578
|
+
sum += parseInt(suffix.charAt(index), 10) * weightsSuffix[index];
|
|
579
|
+
}
|
|
580
|
+
remainder = sum % 11;
|
|
581
|
+
return controlSuffix === (remainder === 0 ? 0 : remainder === 1 ? 1 : 11 - remainder);
|
|
582
|
+
};
|
|
583
|
+
/**
|
|
584
|
+
* Estonian (EE) BBAN check
|
|
585
|
+
*
|
|
586
|
+
* @ignore
|
|
587
|
+
*/
|
|
588
|
+
var checkEstonianBBAN = function (bban) {
|
|
589
|
+
var weights = [7, 1, 3, 7, 1, 3, 7, 1, 3, 7, 1, 3, 7];
|
|
590
|
+
var controlDigit = parseInt(bban.charAt(15), 10);
|
|
591
|
+
var toCheck = bban.substring(2, 15);
|
|
592
|
+
var sum = 0;
|
|
593
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
594
|
+
sum += parseInt(toCheck.charAt(index), 10) * weights[index];
|
|
595
|
+
}
|
|
596
|
+
var remainder = sum % 10;
|
|
597
|
+
return controlDigit === (remainder === 0 ? 0 : 10 - remainder);
|
|
598
|
+
};
|
|
599
|
+
/**
|
|
600
|
+
* Finland (FI) BBAN check
|
|
601
|
+
*
|
|
602
|
+
* @ignore
|
|
603
|
+
*/
|
|
604
|
+
var checkFinlandBBAN = function (bban) {
|
|
605
|
+
var weightsMethod1 = [2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2];
|
|
606
|
+
var weightsMethod2 = [0, 0, 0, 0, 0, 0, 0, 1, 3, 7, 1, 3, 7];
|
|
607
|
+
var controlDigit = parseInt(bban.charAt(13), 10);
|
|
608
|
+
var toCheck = bban.substring(0, 13);
|
|
609
|
+
var sum = 0;
|
|
610
|
+
if (toCheck.startsWith('88')) {
|
|
611
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
612
|
+
sum += parseInt(toCheck.charAt(index), 10) * weightsMethod2[index];
|
|
613
|
+
}
|
|
614
|
+
var remainder = sum % 10;
|
|
615
|
+
return controlDigit === (remainder === 0 ? 0 : 10 - remainder);
|
|
616
|
+
}
|
|
617
|
+
else {
|
|
618
|
+
for (var index = 0; index < toCheck.length; index++) {
|
|
619
|
+
if (weightsMethod1[index] === 1) {
|
|
620
|
+
sum += parseInt(toCheck.charAt(index), 10) * weightsMethod1[index];
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
var value = parseInt(toCheck.charAt(index), 10) * weightsMethod1[index];
|
|
624
|
+
sum += Math.floor(value / 10) + (value % 10);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
var extraSum = sum + controlDigit;
|
|
628
|
+
var multiDigit = Math.floor(extraSum / 10);
|
|
629
|
+
var result = multiDigit * 10;
|
|
630
|
+
var remainder = result - sum;
|
|
631
|
+
return remainder === controlDigit;
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
/**
|
|
635
|
+
* Check French (FR) BBAN
|
|
636
|
+
* Also for Monaco (MC)
|
|
637
|
+
*
|
|
638
|
+
* @ignore
|
|
639
|
+
*/
|
|
640
|
+
var checkFrenchBBAN = function (bban) {
|
|
641
|
+
var stripped = bban.replace(/[\s.]+/g, '');
|
|
642
|
+
var normalized = Array.from(stripped);
|
|
643
|
+
for (var index = 0; index < stripped.length; index++) {
|
|
644
|
+
var c = normalized[index].charCodeAt(0);
|
|
645
|
+
if (c >= 65) {
|
|
646
|
+
switch (c) {
|
|
647
|
+
case 65:
|
|
648
|
+
case 74:
|
|
649
|
+
normalized[index] = '1';
|
|
650
|
+
break;
|
|
651
|
+
case 66:
|
|
652
|
+
case 75:
|
|
653
|
+
case 83:
|
|
654
|
+
normalized[index] = '2';
|
|
655
|
+
break;
|
|
656
|
+
case 67:
|
|
657
|
+
case 76:
|
|
658
|
+
case 84:
|
|
659
|
+
normalized[index] = '3';
|
|
660
|
+
break;
|
|
661
|
+
case 68:
|
|
662
|
+
case 77:
|
|
663
|
+
case 85:
|
|
664
|
+
normalized[index] = '4';
|
|
665
|
+
break;
|
|
666
|
+
case 69:
|
|
667
|
+
case 78:
|
|
668
|
+
case 86:
|
|
669
|
+
normalized[index] = '5';
|
|
670
|
+
break;
|
|
671
|
+
case 70:
|
|
672
|
+
case 79:
|
|
673
|
+
case 87:
|
|
674
|
+
normalized[index] = '6';
|
|
675
|
+
break;
|
|
676
|
+
case 71:
|
|
677
|
+
case 80:
|
|
678
|
+
case 88:
|
|
679
|
+
normalized[index] = '7';
|
|
680
|
+
break;
|
|
681
|
+
case 72:
|
|
682
|
+
case 81:
|
|
683
|
+
case 89:
|
|
684
|
+
normalized[index] = '8';
|
|
685
|
+
break;
|
|
686
|
+
case 73:
|
|
687
|
+
case 82:
|
|
688
|
+
case 90:
|
|
689
|
+
normalized[index] = '9';
|
|
690
|
+
break;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
var remainder = mod9710(normalized.join(''));
|
|
695
|
+
return remainder === 0;
|
|
696
|
+
};
|
|
697
|
+
/**
|
|
698
|
+
* Hungarian (HU) BBAN check
|
|
699
|
+
*
|
|
700
|
+
* @ignore
|
|
701
|
+
*/
|
|
702
|
+
var checkHungarianBBAN = function (bban) {
|
|
703
|
+
var weights = [9, 7, 3, 1, 9, 7, 3, 1, 9, 7, 3, 1, 9, 7, 3];
|
|
704
|
+
var controlDigitBankBranch = parseInt(bban.charAt(7), 10);
|
|
705
|
+
var toCheckBankBranch = bban.substring(0, 7);
|
|
706
|
+
var sum = 0;
|
|
707
|
+
for (var index = 0; index < toCheckBankBranch.length; index++) {
|
|
708
|
+
sum += parseInt(toCheckBankBranch.charAt(index), 10) * weights[index];
|
|
709
|
+
}
|
|
710
|
+
var remainder = sum % 10;
|
|
711
|
+
if (controlDigitBankBranch !== (remainder === 0 ? 0 : 10 - remainder)) {
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
sum = 0;
|
|
715
|
+
if (bban.endsWith('00000000')) {
|
|
716
|
+
var toCheckAccount = bban.substring(8, 15);
|
|
717
|
+
var controlDigitAccount = parseInt(bban.charAt(15), 10);
|
|
718
|
+
for (var index = 0; index < toCheckAccount.length; index++) {
|
|
719
|
+
sum += parseInt(toCheckAccount.charAt(index), 10) * weights[index];
|
|
720
|
+
}
|
|
721
|
+
var remainder_1 = sum % 10;
|
|
722
|
+
return controlDigitAccount === (remainder_1 === 0 ? 0 : 10 - remainder_1);
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
var toCheckAccount = bban.substring(8, 23);
|
|
726
|
+
var controlDigitAccount = parseInt(bban.charAt(23), 10);
|
|
727
|
+
for (var index = 0; index < toCheckAccount.length; index++) {
|
|
728
|
+
sum += parseInt(toCheckAccount.charAt(index), 10) * weights[index];
|
|
729
|
+
}
|
|
730
|
+
var remainder_2 = sum % 10;
|
|
731
|
+
return controlDigitAccount === (remainder_2 === 0 ? 0 : 10 - remainder_2);
|
|
732
|
+
}
|
|
477
733
|
};
|
|
478
734
|
/**
|
|
479
735
|
* Country specifications
|
|
@@ -512,6 +768,7 @@ export var countrySpecs = {
|
|
|
512
768
|
AX: {
|
|
513
769
|
chars: 18,
|
|
514
770
|
bban_regexp: '^[0-9]{14}$',
|
|
771
|
+
bban_validation_func: checkFinlandBBAN,
|
|
515
772
|
IBANRegistry: true,
|
|
516
773
|
},
|
|
517
774
|
AZ: {
|
|
@@ -522,11 +779,12 @@ export var countrySpecs = {
|
|
|
522
779
|
BA: {
|
|
523
780
|
chars: 20,
|
|
524
781
|
bban_regexp: '^[0-9]{16}$',
|
|
782
|
+
bban_validation_func: checkMod9710BBAN,
|
|
525
783
|
IBANRegistry: true,
|
|
526
784
|
},
|
|
527
785
|
BB: {},
|
|
528
786
|
BD: {},
|
|
529
|
-
BE: { chars: 16, bban_regexp: '^[0-9]{12}$', IBANRegistry: true, SEPA: true },
|
|
787
|
+
BE: { chars: 16, bban_regexp: '^[0-9]{12}$', bban_validation_func: checkBelgianBBAN, IBANRegistry: true, SEPA: true },
|
|
530
788
|
BF: {
|
|
531
789
|
chars: 28,
|
|
532
790
|
bban_regexp: '^[A-Z0-9]{2}[0-9]{22}$',
|
|
@@ -618,7 +876,13 @@ export var countrySpecs = {
|
|
|
618
876
|
IBANRegistry: true,
|
|
619
877
|
SEPA: true,
|
|
620
878
|
},
|
|
621
|
-
CZ: {
|
|
879
|
+
CZ: {
|
|
880
|
+
chars: 24,
|
|
881
|
+
bban_regexp: '^[0-9]{20}$',
|
|
882
|
+
bban_validation_func: checkCzechBBAN,
|
|
883
|
+
IBANRegistry: true,
|
|
884
|
+
SEPA: true,
|
|
885
|
+
},
|
|
622
886
|
DE: { chars: 22, bban_regexp: '^[0-9]{18}$', IBANRegistry: true, SEPA: true },
|
|
623
887
|
DJ: {
|
|
624
888
|
chars: 27,
|
|
@@ -636,13 +900,31 @@ export var countrySpecs = {
|
|
|
636
900
|
bban_regexp: '^[0-9]{22}$',
|
|
637
901
|
},
|
|
638
902
|
EC: {},
|
|
639
|
-
EE: {
|
|
903
|
+
EE: {
|
|
904
|
+
chars: 20,
|
|
905
|
+
bban_regexp: '^[0-9]{16}$',
|
|
906
|
+
bban_validation_func: checkEstonianBBAN,
|
|
907
|
+
IBANRegistry: true,
|
|
908
|
+
SEPA: true,
|
|
909
|
+
},
|
|
640
910
|
EG: { chars: 29, bban_regexp: '^[0-9]{25}', IBANRegistry: true },
|
|
641
911
|
EH: {},
|
|
642
912
|
ER: {},
|
|
643
|
-
ES: {
|
|
913
|
+
ES: {
|
|
914
|
+
chars: 24,
|
|
915
|
+
bban_validation_func: checkSpainBBAN,
|
|
916
|
+
bban_regexp: '^[0-9]{20}$',
|
|
917
|
+
IBANRegistry: true,
|
|
918
|
+
SEPA: true,
|
|
919
|
+
},
|
|
644
920
|
ET: {},
|
|
645
|
-
FI: {
|
|
921
|
+
FI: {
|
|
922
|
+
chars: 18,
|
|
923
|
+
bban_regexp: '^[0-9]{14}$',
|
|
924
|
+
bban_validation_func: checkFinlandBBAN,
|
|
925
|
+
IBANRegistry: true,
|
|
926
|
+
SEPA: true,
|
|
927
|
+
},
|
|
646
928
|
FJ: {},
|
|
647
929
|
FK: {},
|
|
648
930
|
FM: {},
|
|
@@ -650,6 +932,7 @@ export var countrySpecs = {
|
|
|
650
932
|
FR: {
|
|
651
933
|
chars: 27,
|
|
652
934
|
bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
|
|
935
|
+
bban_validation_func: checkFrenchBBAN,
|
|
653
936
|
IBANRegistry: true,
|
|
654
937
|
SEPA: true,
|
|
655
938
|
},
|
|
@@ -718,9 +1001,21 @@ export var countrySpecs = {
|
|
|
718
1001
|
chars: 28,
|
|
719
1002
|
bban_regexp: '^[A-Z]{4}[0-9]{20}$',
|
|
720
1003
|
},
|
|
721
|
-
HR: {
|
|
1004
|
+
HR: {
|
|
1005
|
+
chars: 21,
|
|
1006
|
+
bban_regexp: '^[0-9]{17}$',
|
|
1007
|
+
bban_validation_func: checkCroatianBBAN,
|
|
1008
|
+
IBANRegistry: true,
|
|
1009
|
+
SEPA: true,
|
|
1010
|
+
},
|
|
722
1011
|
HT: {},
|
|
723
|
-
HU: {
|
|
1012
|
+
HU: {
|
|
1013
|
+
chars: 28,
|
|
1014
|
+
bban_regexp: '^[0-9]{24}$',
|
|
1015
|
+
bban_validation_func: checkHungarianBBAN,
|
|
1016
|
+
IBANRegistry: true,
|
|
1017
|
+
SEPA: true,
|
|
1018
|
+
},
|
|
724
1019
|
ID: {},
|
|
725
1020
|
IE: {
|
|
726
1021
|
chars: 22,
|
|
@@ -827,6 +1122,7 @@ export var countrySpecs = {
|
|
|
827
1122
|
MC: {
|
|
828
1123
|
chars: 27,
|
|
829
1124
|
bban_regexp: '^[0-9]{10}[A-Z0-9]{11}[0-9]{2}$',
|
|
1125
|
+
bban_validation_func: checkFrenchBBAN,
|
|
830
1126
|
IBANRegistry: true,
|
|
831
1127
|
SEPA: true,
|
|
832
1128
|
},
|
|
@@ -838,6 +1134,7 @@ export var countrySpecs = {
|
|
|
838
1134
|
ME: {
|
|
839
1135
|
chars: 22,
|
|
840
1136
|
bban_regexp: '^[0-9]{18}$',
|
|
1137
|
+
bban_validation_func: checkMod9710BBAN,
|
|
841
1138
|
IBANRegistry: true,
|
|
842
1139
|
},
|
|
843
1140
|
MF: {
|
|
@@ -853,6 +1150,7 @@ export var countrySpecs = {
|
|
|
853
1150
|
MK: {
|
|
854
1151
|
chars: 19,
|
|
855
1152
|
bban_regexp: '^[0-9]{3}[A-Z0-9]{10}[0-9]{2}$',
|
|
1153
|
+
bban_validation_func: checkMod9710BBAN,
|
|
856
1154
|
IBANRegistry: true,
|
|
857
1155
|
},
|
|
858
1156
|
ML: {
|
|
@@ -912,6 +1210,7 @@ export var countrySpecs = {
|
|
|
912
1210
|
NL: {
|
|
913
1211
|
chars: 18,
|
|
914
1212
|
bban_regexp: '^[A-Z]{4}[0-9]{10}$',
|
|
1213
|
+
bban_validation_func: checkDutchBBAN,
|
|
915
1214
|
IBANRegistry: true,
|
|
916
1215
|
SEPA: true,
|
|
917
1216
|
},
|
|
@@ -948,7 +1247,7 @@ export var countrySpecs = {
|
|
|
948
1247
|
bban_regexp: '^[A-Z0-9]{4}[0-9]{21}$',
|
|
949
1248
|
IBANRegistry: true,
|
|
950
1249
|
},
|
|
951
|
-
PT: { chars: 25, bban_regexp: '^[0-9]{21}$', IBANRegistry: true, SEPA: true },
|
|
1250
|
+
PT: { chars: 25, bban_regexp: '^[0-9]{21}$', bban_validation_func: checkMod9710BBAN, IBANRegistry: true, SEPA: true },
|
|
952
1251
|
PW: {},
|
|
953
1252
|
PY: {},
|
|
954
1253
|
QA: {
|
|
@@ -970,6 +1269,7 @@ export var countrySpecs = {
|
|
|
970
1269
|
RS: {
|
|
971
1270
|
chars: 22,
|
|
972
1271
|
bban_regexp: '^[0-9]{18}$',
|
|
1272
|
+
bban_validation_func: checkMod9710BBAN,
|
|
973
1273
|
IBANRegistry: true,
|
|
974
1274
|
},
|
|
975
1275
|
RU: {},
|
|
@@ -989,7 +1289,13 @@ export var countrySpecs = {
|
|
|
989
1289
|
SE: { chars: 24, bban_regexp: '^[0-9]{20}$', IBANRegistry: true, SEPA: true },
|
|
990
1290
|
SG: {},
|
|
991
1291
|
SH: {},
|
|
992
|
-
SI: {
|
|
1292
|
+
SI: {
|
|
1293
|
+
chars: 19,
|
|
1294
|
+
bban_regexp: '^[0-9]{15}$',
|
|
1295
|
+
bban_validation_func: checkMod9710BBAN,
|
|
1296
|
+
IBANRegistry: true,
|
|
1297
|
+
SEPA: true,
|
|
1298
|
+
},
|
|
993
1299
|
SJ: {},
|
|
994
1300
|
SK: { chars: 24, bban_regexp: '^[0-9]{20}$', IBANRegistry: true, SEPA: true },
|
|
995
1301
|
SL: {},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ibantools",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.2",
|
|
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",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"docdash": "^1.2.0",
|
|
59
59
|
"eslint": "^7.31.0",
|
|
60
60
|
"eslint-config-prettier": "^8.3.0",
|
|
61
|
-
"eslint-plugin-prettier": "^
|
|
61
|
+
"eslint-plugin-prettier": "^4.0.0",
|
|
62
62
|
"gulp": "^4.0.2",
|
|
63
63
|
"gulp-mocha": "^8.0",
|
|
64
64
|
"gulp-rename": "^2.0",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"nyc": "^15.1.0",
|
|
76
76
|
"prettier": "^2.3.2",
|
|
77
77
|
"requirejs": "^2.3.6",
|
|
78
|
-
"typedoc": "^0.
|
|
78
|
+
"typedoc": "^0.22.9",
|
|
79
79
|
"typescript": "^4.3.5"
|
|
80
80
|
}
|
|
81
81
|
}
|