Skip to content

Validation of IBAN (Internation Bank Account Number) #630

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions additional-methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,128 @@ jQuery.validator.addMethod("dateNL", function(value, element) {
return this.optional(element) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(value);
}, "Vul hier een geldige datum in.");

/**
* IBAN is the international bank account number.
* It has a country - specific format, that is checked here too
*/
jQuery.validator.addMethod("iban", function(value, element) {
// some quick simple tests to prevent needless work
if (this.optional(element)) {
return true;
}
if (!(/^([a-zA-Z0-9]{4} ){2,8}[a-zA-Z0-9]{1,4}|[a-zA-Z0-9]{12,34}$/.test(value))) {
return false;
}

// check the country code and find the country specific format
var iban = value.replace(/ /g,'').toUpperCase(); // remove spaces and to upper case
var countrycode = iban.substring(0,2);
var bbancountrypatterns = {
'AL': "\\d{8}[\\dA-Z]{16}",
'AD': "\\d{8}[\\dA-Z]{12}",
'AT': "\\d{16}",
'AZ': "[\\dA-Z]{4}\\d{20}",
'BE': "\\d{12}",
'BH': "[A-Z]{4}[\\dA-Z]{14}",
'BA': "\\d{16}",
'BR': "\\d{23}[A-Z][\\dA-Z]",
'BG': "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
'CR': "\\d{17}",
'HR': "\\d{17}",
'CY': "\\d{8}[\\dA-Z]{16}",
'CZ': "\\d{20}",
'DK': "\\d{14}",
'DO': "[A-Z]{4}\\d{20}",
'EE': "\\d{16}",
'FO': "\\d{14}",
'FI': "\\d{14}",
'FR': "\\d{10}[\\dA-Z]{11}\\d{2}",
'GE': "[\\dA-Z]{2}\\d{16}",
'DE': "\\d{18}",
'GI': "[A-Z]{4}[\\dA-Z]{15}",
'GR': "\\d{7}[\\dA-Z]{16}",
'GL': "\\d{14}",
'GT': "[\\dA-Z]{4}[\\dA-Z]{20}",
'HU': "\\d{24}",
'IS': "\\d{22}",
'IE': "[\\dA-Z]{4}\\d{14}",
'IL': "\\d{19}",
'IT': "[A-Z]\\d{10}[\\dA-Z]{12}",
'KZ': "\\d{3}[\\dA-Z]{13}",
'KW': "[A-Z]{4}[\\dA-Z]{22}",
'LV': "[A-Z]{4}[\\dA-Z]{13}",
'LB': "\\d{4}[\\dA-Z]{20}",
'LI': "\\d{5}[\\dA-Z]{12}",
'LT': "\\d{16}",
'LU': "\\d{3}[\\dA-Z]{13}",
'MK': "\\d{3}[\\dA-Z]{10}\\d{2}",
'MT': "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
'MR': "\\d{23}",
'MU': "[A-Z]{4}\\d{19}[A-Z]{3}",
'MC': "\\d{10}[\\dA-Z]{11}\\d{2}",
'MD': "[\\dA-Z]{2}\\d{18}",
'ME': "\\d{18}",
'NL': "[A-Z]{4}\\d{10}",
'NO': "\\d{11}",
'PK': "[\\dA-Z]{4}\\d{16}",
'PS': "[\\dA-Z]{4}\\d{21}",
'PL': "\\d{24}",
'PT': "\\d{21}",
'RO': "[A-Z]{4}[\\dA-Z]{16}",
'SM': "[A-Z]\\d{10}[\\dA-Z]{12}",
'SA': "\\d{2}[\\dA-Z]{18}",
'RS': "\\d{18}",
'SK': "\\d{20}",
'SI': "\\d{15}",
'ES': "\\d{20}",
'SE': "\\d{20}",
'CH': "\\d{5}[\\dA-Z]{12}",
'TN': "\\d{20}",
'TR': "\\d{5}[\\dA-Z]{17}",
'AE': "\\d{3}\\d{16}",
'GB': "[A-Z]{4}\\d{14}",
'VG': "[\\dA-Z]{4}\\d{16}"
};
var bbanpattern = bbancountrypatterns[countrycode];
// As new countries will start using IBAN in the
// future, we only check if the countrycode is known.
// This prevents false negatives, while almost all
// false positives introduced by this, will be caught
// by the checksum validation below anyway.
// Strict checking should return FALSE for unknown
// countries.
if (typeof bbanpattern !== 'undefined') {
var ibanregexp = new RegExp("^[A-Z]{2}\\d{2}" + bbanpattern + "$", "");
if (!(ibanregexp.test(iban))) {
return false; // invalid country specific format
}
}

// now check the checksum, first convert to digits
var ibancheck = iban.substring(4,iban.length) + iban.substring(0,4);
var ibancheckdigits = "";
var leadingZeroes = true;
for (var i =0; i<ibancheck.length; i++) {
var char = ibancheck.charAt(i);
if (char !== "0") {
leadingZeroes = false;
}
if (!leadingZeroes) {
ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(char);
}
}

// calculate the result of: ibancheckdigits % 97
var cRest = '';
var cOperator = '';
for (var p=0; p<ibancheckdigits.length; p++) {
var cChar = ibancheckdigits.charAt(p);
cOperator = '' + cRest + '' + cChar;
cRest = cOperator % 97;
}
return cRest === 1;
}, "Please specify a valid IBAN");

jQuery.validator.addMethod("time", function(value, element) {
return this.optional(element) || /^([01]\d|2[0-3])(:[0-5]\d){1,2}$/.test(value);
}, "Please enter a valid time, between 00:00 and 23:59");
Expand Down
5 changes: 4 additions & 1 deletion localization/messages_nl.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
rangelength: $.validator.format("Vul hier een waarde in van minimaal {0} en maximaal {1} tekens."),
range: $.validator.format("Vul hier een waarde in van minimaal {0} en maximaal {1}."),
max: $.validator.format("Vul hier een waarde in kleiner dan of gelijk aan {0}."),
min: $.validator.format("Vul hier een waarde in groter dan of gelijk aan {0}.")
min: $.validator.format("Vul hier een waarde in groter dan of gelijk aan {0}."),

// for validations in additional-methods.js
iban: "Vul hier een geldig IBAN in."
});
}(jQuery));
77 changes: 77 additions & 0 deletions test/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,83 @@ test("dateNL", function() {
ok(!method( "01.01.190" ), "Invalid date NL" );
});

test("iban", function() {
var method = methodTest("iban");
ok( method( "NL20INGB0001234567"), "Valid IBAN");
ok( method( "DE68 2105 0170 0012 3456 78"), "Valid IBAN");
ok( method( "NL20 INGB0001234567"), "Valid IBAN: invalid spacing");
ok( method( "NL20 INGB 00 0123 4567"), "Valid IBAN: invalid spacing");
ok( method( "XX40INGB000123456712341234"), "Valid (more or less) IBAN: unknown country, but checksum OK");

ok(!method( "NL20INGB000123456"), "Invalid IBAN: too short");
ok(!method( "NL20INGB00012345678"), "Invalid IBAN: too long");
ok(!method( "NL20INGB0001234566"), "Invalid IBAN: checksum incorrect");
ok(!method( "DE68 2105 0170 0012 3456 7"), "Invalid IBAN: too short");
ok(!method( "DE68 2105 0170 0012 3456 789"), "Invalid IBAN: too long");
ok(!method( "DE68 2105 0170 0012 3456 79"), "Invalid IBAN: checksum incorrect");

ok(!method( "NL54INGB00012345671234"), "Invalid IBAN too long, BUT CORRECT CHECKSUM");
ok(!method( "XX00INGB000123456712341234"), "Invalid IBAN: unknown country and checksum incorrect");

// sample IBANs for different countries
ok( method( "AL47 2121 1009 0000 0002 3569 8741"), "Valid IBAN - AL");
ok( method( "AD12 0001 2030 2003 5910 0100"), "Valid IBAN - AD");
ok( method( "AT61 1904 3002 3457 3201"), "Valid IBAN - AT");
ok( method( "AZ21 NABZ 0000 0000 1370 1000 1944"), "Valid IBAN - AZ");
ok( method( "BH67 BMAG 0000 1299 1234 56"), "Valid IBAN - BH");
ok( method( "BE62 5100 0754 7061"), "Valid IBAN - BE");
ok( method( "BA39 1290 0794 0102 8494"), "Valid IBAN - BA");
ok( method( "BG80 BNBG 9661 1020 3456 78"), "Valid IBAN - BG");
ok( method( "HR12 1001 0051 8630 0016 0"), "Valid IBAN - HR");
ok( method( "CH93 0076 2011 6238 5295 7"), "Valid IBAN - CH");
ok( method( "CY17 0020 0128 0000 0012 0052 7600"), "Valid IBAN - CY");
ok( method( "CZ65 0800 0000 1920 0014 5399"), "Valid IBAN - CZ");
ok( method( "DK50 0040 0440 1162 43"), "Valid IBAN - DK");
ok( method( "EE38 2200 2210 2014 5685"), "Valid IBAN - EE");
ok( method( "FO97 5432 0388 8999 44"), "Valid IBAN - FO");
ok( method( "FI21 1234 5600 0007 85"), "Valid IBAN - FI");
ok( method( "FR14 2004 1010 0505 0001 3M02 606"), "Valid IBAN - FR");
ok( method( "GE29 NB00 0000 0101 9049 17"), "Valid IBAN - GE");
ok( method( "DE89 3704 0044 0532 0130 00"), "Valid IBAN - DE");
ok( method( "GI75 NWBK 0000 0000 7099 453"), "Valid IBAN - GI");
ok( method( "GR16 0110 1250 0000 0001 2300 695"), "Valid IBAN - GR");
ok( method( "GL56 0444 9876 5432 10"), "Valid IBAN - GL");
ok( method( "HU42 1177 3016 1111 1018 0000 0000"), "Valid IBAN - HU");
ok( method( "IS14 0159 2600 7654 5510 7303 39"), "Valid IBAN - IS");
ok( method( "IE29 AIBK 9311 5212 3456 78"), "Valid IBAN - IE");
ok( method( "IL62 0108 0000 0009 9999 999"), "Valid IBAN - IL");
ok( method( "IT40 S054 2811 1010 0000 0123 456"), "Valid IBAN - IT");
ok( method( "LV80 BANK 0000 4351 9500 1"), "Valid IBAN - LV");
ok( method( "LB62 0999 0000 0001 0019 0122 9114"), "Valid IBAN - LB");
ok( method( "LI21 0881 0000 2324 013A A"), "Valid IBAN - LI");
ok( method( "LT12 1000 0111 0100 1000"), "Valid IBAN - LT");
ok( method( "LU28 0019 4006 4475 0000"), "Valid IBAN - LU");
ok( method( "MK07 2501 2000 0058 984"), "Valid IBAN - MK");
ok( method( "MT84 MALT 0110 0001 2345 MTLC AST0 01S"), "Valid IBAN - MT");
ok( method( "MU17 BOMM 0101 1010 3030 0200 000M UR"), "Valid IBAN - MU");
ok( method( "MD24 AG00 0225 1000 1310 4168"), "Valid IBAN - MD");
ok( method( "MC93 2005 2222 1001 1223 3M44 555"), "Valid IBAN - MC");
ok( method( "ME25 5050 0001 2345 6789 51"), "Valid IBAN - ME");
ok( method( "NL39 RABO 0300 0652 64"), "Valid IBAN - NL");
ok( method( "NO93 8601 1117 947"), "Valid IBAN - NO");
ok( method( "PK36 SCBL 0000 0011 2345 6702"), "Valid IBAN - PK");
ok( method( "PL60 1020 1026 0000 0422 7020 1111"), "Valid IBAN - PL");
ok( method( "PT50 0002 0123 1234 5678 9015 4"), "Valid IBAN - PT");
ok( method( "RO49 AAAA 1B31 0075 9384 0000"), "Valid IBAN - RO");
ok( method( "SM86 U032 2509 8000 0000 0270 100"), "Valid IBAN - SM");
ok( method( "SA03 8000 0000 6080 1016 7519"), "Valid IBAN - SA");
ok( method( "RS35 2600 0560 1001 6113 79"), "Valid IBAN - RS");
ok( method( "SK31 1200 0000 1987 4263 7541"), "Valid IBAN - SK");
ok( method( "SI56 1910 0000 0123 438"), "Valid IBAN - SI");
ok( method( "ES80 2310 0001 1800 0001 2345"), "Valid IBAN - ES");
ok( method( "SE35 5000 0000 0549 1000 0003"), "Valid IBAN - SE");
ok( method( "CH93 0076 2011 6238 5295 7"), "Valid IBAN - CH");
ok( method( "TN59 1000 6035 1835 9847 8831"), "Valid IBAN - TN");
ok( method( "TR33 0006 1005 1978 6457 8413 26"), "Valid IBAN - TR");
ok( method( "AE07 0331 2345 6789 0123 456"), "Valid IBAN - AE");
ok( method( "GB29 NWBK 6016 1331 9268 19"), "Valid IBAN - GB");
});

test("time", function() {
var method = methodTest("time");
ok( method("00:00"), "Valid time, lower bound" );
Expand Down