From 0343e7c670fd7d5726eaa030f4be19c75b3090f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sas=CC=8Ca=20Jovanic=CC=81?= Date: Wed, 24 Nov 2021 22:39:38 +0100 Subject: [PATCH] Added NL bank account validation --- ChangeLog | 4 ++++ dist/ibantools.d.ts | 3 ++- dist/ibantools.js | 27 +++++++++++++++++++++++++-- package.json | 2 +- src/IBANTools.ts | 28 ++++++++++++++++++++++++++-- test/ibantools_test.js | 12 +++++++++++- 6 files changed, 69 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index f623ecc..3bc52c2 100755 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2021-11-24 Saša Jovanić + * Added Netherlands (NL) extra BBAN validation + * Added extra error code when validating IBAN `WrongAccountBankBranchChecksum` that indicates when checksum for account number or bank or branch code is incorrect + 2021-11-23 Saša Jovanić * Version 4.0.1 * Fixed bug when validating Spain IBAN diff --git a/dist/ibantools.d.ts b/dist/ibantools.d.ts index cf01b58..956ff32 100644 --- a/dist/ibantools.d.ts +++ b/dist/ibantools.d.ts @@ -24,7 +24,8 @@ export declare enum ValidationErrorsIBAN { WrongBBANLength = 2, WrongBBANFormat = 3, ChecksumNotNumber = 4, - WrongIBANChecksum = 5 + WrongIBANChecksum = 5, + WrongAccountBankBranchChecksum = 6 } /** * Interface for ValidateIBAN result diff --git a/dist/ibantools.js b/dist/ibantools.js index 7fb2314..b7350fa 100644 --- a/dist/ibantools.js +++ b/dist/ibantools.js @@ -9,7 +9,7 @@ define(["require", "exports"], function (require, exports) { * @package Documentation * @author Saša Jovanić * @module ibantools - * @version 4.0.1 + * @version 4.1.0 * @license MPL-2.0 * @preferred */ @@ -56,6 +56,7 @@ define(["require", "exports"], function (require, exports) { ValidationErrorsIBAN[ValidationErrorsIBAN["WrongBBANFormat"] = 3] = "WrongBBANFormat"; ValidationErrorsIBAN[ValidationErrorsIBAN["ChecksumNotNumber"] = 4] = "ChecksumNotNumber"; ValidationErrorsIBAN[ValidationErrorsIBAN["WrongIBANChecksum"] = 5] = "WrongIBANChecksum"; + ValidationErrorsIBAN[ValidationErrorsIBAN["WrongAccountBankBranchChecksum"] = 6] = "WrongAccountBankBranchChecksum"; })(ValidationErrorsIBAN = exports.ValidationErrorsIBAN || (exports.ValidationErrorsIBAN = {})); /** * validateIBAN @@ -76,10 +77,14 @@ define(["require", "exports"], function (require, exports) { result.valid = false; result.errorCodes.push(ValidationErrorsIBAN.WrongBBANLength); } - if (spec && spec.bban_regexp && !isValidBBAN(iban.slice(4), iban.slice(0, 2))) { + if (spec && spec.bban_regexp && !checkFormatBBAN(iban.slice(4), spec.bban_regexp)) { result.valid = false; result.errorCodes.push(ValidationErrorsIBAN.WrongBBANFormat); } + if (spec && spec.bban_validation_func && !spec.bban_validation_func(iban.slice(4))) { + result.valid = false; + result.errorCodes.push(ValidationErrorsIBAN.WrongAccountBankBranchChecksum); + } var reg = new RegExp('^[0-9]{2}$', ''); if (!reg.test(iban.slice(2, 4))) { result.valid = false; @@ -447,6 +452,23 @@ define(["require", "exports"], function (require, exports) { return controlDigit === (remainder === 0 ? 0 : 11 - remainder); } }; + /** + * Used for Netherlands BBAN check + * + * @ignore + */ + var checkDutchBBAN = function (bban) { + var bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, ''); + var accountNumber = bbanWithoutSpacesAndPeriods.substring(4, 14); + if (accountNumber.startsWith('000')) { + return true; // Postbank account, no `elfproef` possible + } + var sum = 0; + for (var index = 0; index < 10; index++) { + sum += parseInt(accountNumber.charAt(index), 10) * (10 - index); + } + return sum % 11 === 0; + }; /** * Used for Poland BBAN check * @@ -927,6 +949,7 @@ define(["require", "exports"], function (require, exports) { NL: { chars: 18, bban_regexp: '^[A-Z]{4}[0-9]{10}$', + bban_validation_func: checkDutchBBAN, IBANRegistry: true, SEPA: true, }, diff --git a/package.json b/package.json index 8aee25e..bddfc88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ibantools", - "version": "4.0.1", + "version": "4.1.0", "description": "Validation, extraction and creation of IBAN, BBAN, BIC/SWIFT numbers plus some other helpful stuff like ISO 3136-1 alpha 2 country list", "keywords": [ "IBAN", diff --git a/src/IBANTools.ts b/src/IBANTools.ts index 43ba9fa..9645c1f 100755 --- a/src/IBANTools.ts +++ b/src/IBANTools.ts @@ -9,7 +9,7 @@ * @package Documentation * @author Saša Jovanić * @module ibantools - * @version 4.0.1 + * @version 4.1.0 * @license MPL-2.0 * @preferred */ @@ -56,6 +56,7 @@ export enum ValidationErrorsIBAN { WrongBBANFormat, ChecksumNotNumber, WrongIBANChecksum, + WrongAccountBankBranchChecksum, } /** @@ -85,10 +86,14 @@ export function validateIBAN(iban?: string): ValidateIBANResult { result.valid = false; result.errorCodes.push(ValidationErrorsIBAN.WrongBBANLength); } - if (spec && spec.bban_regexp && !isValidBBAN(iban.slice(4), iban.slice(0, 2))) { + if (spec && spec.bban_regexp && !checkFormatBBAN(iban.slice(4), spec.bban_regexp)) { result.valid = false; result.errorCodes.push(ValidationErrorsIBAN.WrongBBANFormat); } + if (spec && spec.bban_validation_func && !spec.bban_validation_func(iban.slice(4))) { + result.valid = false; + result.errorCodes.push(ValidationErrorsIBAN.WrongAccountBankBranchChecksum); + } const reg = new RegExp('^[0-9]{2}$', ''); if (!reg.test(iban.slice(2, 4))) { result.valid = false; @@ -529,6 +534,24 @@ const checkNorwayBBAN = (bban: string): boolean => { } }; +/** + * Used for Netherlands BBAN check + * + * @ignore + */ +const checkDutchBBAN = (bban: string): boolean => { + const bbanWithoutSpacesAndPeriods = bban.replace(/[\s.]+/g, ''); + const accountNumber = bbanWithoutSpacesAndPeriods.substring(4, 14); + if (accountNumber.startsWith('000')) { + return true; // Postbank account, no `elfproef` possible + } + let sum = 0; + for (let index = 0; index < 10; index++) { + sum += parseInt(accountNumber.charAt(index), 10) * (10 - index); + } + return sum % 11 === 0; +}; + /** * Used for Poland BBAN check * @@ -1011,6 +1034,7 @@ export const countrySpecs: CountryMapInternal = { NL: { chars: 18, bban_regexp: '^[A-Z]{4}[0-9]{10}$', + bban_validation_func: checkDutchBBAN, IBANRegistry: true, SEPA: true, }, diff --git a/test/ibantools_test.js b/test/ibantools_test.js index d57e2b2..6530dcd 100644 --- a/test/ibantools_test.js +++ b/test/ibantools_test.js @@ -17,6 +17,9 @@ describe('IBANTools', function() { it('with valid IBAN should return true', function() { expect(iban.isValidIBAN('NL91ABNA0417164300')).to.be.true; }); + it('with valid IBAN should return true', function() { + expect(iban.isValidIBAN('NL50PSTB0000054322')).to.be.true; + }); it('with invalid IBAN should return false', function() { expect(iban.isValidIBAN('NL91ABNA0517164300')).to.be.false; }); @@ -221,7 +224,10 @@ describe('IBANTools', function() { it('with invalid IBAN checksum should return false with correct code', function() { expect(iban.validateIBAN('NL91ABNA0517164300')).to.deep.equal({ valid: false, - errorCodes: [iban.ValidationErrorsIBAN.WrongIBANChecksum], + errorCodes: [ + iban.ValidationErrorsIBAN.WrongAccountBankBranchChecksum, + iban.ValidationErrorsIBAN.WrongIBANChecksum, + ], }); }); @@ -259,6 +265,7 @@ describe('IBANTools', function() { errorCodes: [ iban.ValidationErrorsIBAN.WrongBBANLength, iban.ValidationErrorsIBAN.WrongBBANFormat, + iban.ValidationErrorsIBAN.WrongAccountBankBranchChecksum, iban.ValidationErrorsIBAN.ChecksumNotNumber, iban.ValidationErrorsIBAN.WrongIBANChecksum, ], @@ -439,6 +446,9 @@ describe('IBANTools', function() { it('with valid BBAN and valid country code should return true', function() { expect(iban.isValidBBAN('ABNA0417164300', 'NL')).to.be.true; }); + it('with valid BBAN and valid country code should return true', function() { + expect(iban.isValidBBAN('PSTB0000054322', 'NL')).to.be.true; + }); it('with invalid BBAN and valid country code should return false', function() { expect(iban.isValidBBAN('A7NA0417164300', 'NL')).to.be.false; });