pmillio
pmillio

Reputation: 1139

IBAN Validation check

I need to do an IBAN validation check using JavaScript. The rules I need to follow are:

Validating the IBAN An IBAN is validated by converting it into an integer and performing a basic mod-97 operation (as described in ISO 7064) on it. If the IBAN is valid, the remainder equals 1.

  1. Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid

  2. Move the four initial characters to the end of the string

  3. Replace each letter in the string with two digits, thereby expanding the string, where A = 10, B = 11, ..., Z = 35

  4. Interpret the string as a decimal integer and compute the remainder of that number on division by 97

I am doing this for a Belarusian IBAN so it has to follow the following format

2C 31N -

RU1230000000000000000000000000000

How do I modify the following to meet the above rules;

function validateIBAN(iban) {
  var newIban = iban.toUpperCase(),
    modulo = function(divident, divisor) {
      var cDivident = '';
      var cRest = '';

      for (var i in divident) {
        var cChar = divident[i];
        var cOperator = cRest + '' + cDivident + '' + cChar;

        if (cOperator < parseInt(divisor)) {
          cDivident += '' + cChar;
        } else {
          cRest = cOperator % divisor;
          if (cRest == 0) {
            cRest = '';
          }
          cDivident = '';
        }

      }
      cRest += '' + cDivident;
      if (cRest == '') {
        cRest = 0;
      }
      return cRest;
    };

  if (newIban.search(/^[A-Z]{2}/gi) < 0) {
    return false;
  }

  newIban = newIban.substring(4) + newIban.substring(0, 4);

  newIban = newIban.replace(/[A-Z]/g, function(match) {
    return match.charCodeAt(0) - 55;
  });

  return parseInt(modulo(newIban, 97), 10) === 1;
}


console.log(validateIBAN("RU1230000000000000000000000000000"));

Upvotes: 65

Views: 155354

Answers (12)

Derek Henderson
Derek Henderson

Reputation: 9706

Based on https://math.stackexchange.com/questions/1918217/the-mod97-operation-in-iban-validation, this should be pretty straightforward. No need to overcomplicate or use regular expressions.

Here's what I came up with:

const mod97 = str => {
  const first9 = str.substring(0, 9);
  const remainingStr = str.substring(9);
  const remainder = Number(first9) % 97;
  const newString = remainder.toString() + remainingStr;

  if (newString.length > 2) {
    return mod97(newString);
  }

  return remainder;
};

const validateIBAN = iban => {
  const reorderedString = iban.substring(4) + iban.substring(0, 4);
  const replacedString = reorderedString.replaceAll(/[a-z]{1}/gi, match =>
    (match.toUpperCase().charCodeAt(0) - 55).toString(),
  );

  return mod97(replacedString) === 1;
};

Upvotes: 1

MaVRoSCy
MaVRoSCy

Reputation: 17839

Based on the work of http://toms-cafe.de/iban/iban.js I have developed my version of an IBAN validation check.

You can modify the country support by modifying the variable CODE_LENGTHS.

Here is my implementation:

function alertValidIBAN(iban) {
    alert(isValidIBANNumber(iban));
}

/*
 * Returns 1 if the IBAN is valid 
 * Returns FALSE if the IBAN's length is not as should be (for CY the IBAN Should be 28 chars long starting with CY )
 * Returns any other number (checksum) when the IBAN is invalid (check digits do not match)
 */
function isValidIBANNumber(input) {
    var CODE_LENGTHS = {
        AD: 24, AE: 23, AT: 20, AZ: 28, BA: 20, BE: 16, BG: 22, BH: 22, BR: 29,
        CH: 21, CR: 21, CY: 28, CZ: 24, DE: 22, DK: 18, DO: 28, EE: 20, ES: 24,
        FI: 18, FO: 18, FR: 27, GB: 22, GI: 23, GL: 18, GR: 27, GT: 28, HR: 21,
        HU: 28, IE: 22, IL: 23, IS: 26, IT: 27, JO: 30, KW: 30, KZ: 20, LB: 28,
        LI: 21, LT: 20, LU: 20, LV: 21, MC: 27, MD: 24, ME: 22, MK: 19, MR: 27,
        MT: 31, MU: 30, NL: 18, NO: 15, PK: 24, PL: 28, PS: 29, PT: 25, QA: 29,
        RO: 24, RS: 22, SA: 24, SE: 24, SI: 19, SK: 24, SM: 27, TN: 24, TR: 26,   
        AL: 28, BY: 28, CR: 22, EG: 29, GE: 22, IQ: 23, LC: 32, SC: 31, ST: 25,
        SV: 28, TL: 23, UA: 29, VA: 22, VG: 24, XK: 20
    };
    var iban = String(input).toUpperCase().replace(/[^A-Z0-9]/g, ''), // keep only alphanumeric characters
            code = iban.match(/^([A-Z]{2})(\d{2})([A-Z\d]+)$/), // match and capture (1) the country code, (2) the check digits, and (3) the rest
            digits;
    // check syntax and length
    if (!code || iban.length !== CODE_LENGTHS[code[1]]) {
        return false;
    }
    // rearrange country code and check digits, and convert chars to ints
    digits = (code[3] + code[1] + code[2]).replace(/[A-Z]/g, function (letter) {
        return letter.charCodeAt(0) - 55;
    });
    // final check
    return mod97(digits) === 1;
}

function mod97(string) {
    var checksum = string.slice(0, 2), fragment;
    for (var offset = 2; offset < string.length; offset += 7) {
        fragment = String(checksum) + string.substring(offset, offset + 7);
        checksum = parseInt(fragment, 10) % 97;
    }
    return checksum;
}
input { width:300px; }
Enter IBAN 
<input type="test" id="iban"/>
<button onclick="alertValidIBAN(document.getElementById('iban').value);">check IBAN</button>

Upvotes: 63

Florian Hoss
Florian Hoss

Reputation: 31

Copy/Paste ready Typescript code for all countries mentioned here:

function validateIban(input: string) {
  const codeLengths = {
    AD: 24,
    AE: 23,
    AL: 28,
    AT: 20,
    AZ: 28,
    BA: 20,
    BE: 16,
    BG: 22,
    BH: 22,
    BI: 28,
    BR: 29,
    BY: 28,
    CH: 21,
    CR: 22,
    CY: 28,
    CZ: 24,
    DE: 22,
    DK: 18,
    DO: 28,
    EE: 20,
    EG: 29,
    ES: 24,
    LC: 32,
    FI: 18,
    FO: 18,
    FR: 27,
    GB: 22,
    GE: 22,
    GI: 23,
    GL: 18,
    GR: 27,
    GT: 28,
    HR: 21,
    HU: 28,
    IE: 22,
    IL: 23,
    IQ: 23,
    IS: 26,
    IT: 27,
    JO: 30,
    KW: 30,
    KZ: 20,
    LB: 28,
    LI: 21,
    LT: 20,
    LU: 20,
    LV: 21,
    LY: 25,
    MC: 27,
    MD: 24,
    ME: 22,
    MK: 19,
    MR: 27,
    MT: 31,
    MU: 30,
    NL: 18,
    NO: 15,
    PK: 24,
    PL: 28,
    PS: 29,
    PT: 25,
    QA: 29,
    RO: 24,
    RS: 22,
    SA: 24,
    SC: 31,
    SD: 18,
    SE: 24,
    SI: 19,
    SK: 24,
    SM: 27,
    ST: 25,
    SV: 28,
    TL: 23,
    TN: 24,
    TR: 26,
    UA: 29,
    VA: 22,
    VG: 24,
    XK: 20,
  };
  const iban = input.toUpperCase().replace(/[^A-Z0-9]/g, "");
  const code = iban.match(/^([A-Z]{2})(\d{2})([A-Z\d]+)$/);
  if (!code || iban.length !== (codeLengths as any)[code[1]]) {
    return false;
  }
  const digits = (code[3] + code[1] + code[2]).replace(/[A-Z]/g, (letter: string) => {
    return (letter.charCodeAt(0) - 55).toString();
  });
  return mod97(digits) === 1;
}

and the checksum:

function mod97(digital: number | string) {
  digital = digital.toString();
  let checksum: number | string = digital.slice(0, 2);
  let fragment = "";
  for (let offset = 2; offset < digital.length; offset += 7) {
    fragment = checksum + digital.substring(offset, offset + 7);
    checksum = parseInt(fragment, 10) % 97;
  }
  return checksum;
}

Upvotes: 3

KING-CODE
KING-CODE

Reputation: 39

Just using this website api : go to https://api.ibanapi.com and get apk_key

iban    = SA4705000068203056854000
api_key = ea649b36c1d1648bf0f12df82a8da475e2ee3447
url     = 'https://api.ibanapi.com/v1/validate/'iban+'?api_key='+api_key+''

The IBAN Checker

  • Check the structure of the IBAN and prepare it for the validation engine
  • Make sure the country supports the IBAN as per the Swift public registery
  • Validate the IBAN using the check digits.
  • If the country level validation is supported, it will run through it
  • Get the bank information for this IBAN from our registery

Upvotes: 2

Vadorequest
Vadorequest

Reputation: 18009

I wrote 2 regexes, the first one is for SEPA-only countries, the other is for all countries that support IBAN, as of 2021-10.

IBAN regex for within-SEPA area countries

The first one checks if an IBAN is valid within the SEPA area, the IBAN must belong to a country that is within the SEPA area. (it considers IBAN outside the SEPA area as invalid)

^(?:((?:IT|SM)\d{2}[A-Z]{1}\d{22})|(NL\d{2}[A-Z]{4}\d{10})|(LV\d{2}[A-Z]{4}\d{13})|((?:BG|GB|IE)\d{2}[A-Z]{4}\d{14})|(GI\d{2}[A-Z]{4}\d{15})|(RO\d{2}[A-Z]{4}\d{16})|(MT\d{2}[A-Z]{4}\d{23})|(NO\d{13})|((?:DK|FI)\d{16})|((?:SI)\d{17})|((?:AT|EE|LU|LT)\d{18})|((?:HR|LI|CH)\d{19})|((?:DE|VA)\d{20})|((?:AD|CZ|ES|MD|SK|SE)\d{22})|(PT\d{23})|((?:IS)\d{24})|((?:BE)\d{14})|((?:FR|MC|GR)\d{25})|((?:PL|HU|CY)\d{26}))$

Specifications:

Testing: https://regex101.com/r/oLRltj/1/

IBAN regex for any country

^(?:(?:CR|DE|ME|RS|VA)\d{20}|(?:CZ|ES|SE|SK|TN)\d{22}|(?:DK|FI|FO|GL|SD)\d{16}|(?:AT|BA|EE|LT|XK)\d{18}|(?:AE|IL|TL)\d{21}|(?:LY|PT|ST)\d{23}|(?:IT|SM)\d{2}[A-Z]\d{10}[A-Za-z0-9]{12}|(?:HU|PL)\d{26}|(?:AL|CY)\d{10}[A-Za-z0-9]{16}|(?:CH|LI)\d{7}[A-Za-z0-9]{12}|(?:FR|MC)\d{12}[A-Za-z0-9]{11}\d{2}|(?:GB|IE)\d{2}[A-Z]{4}\d{14}|(?:KZ|LU)\d{5}[A-Za-z0-9]{13}|(?:GI|IQ)\d{2}[A-Z]{4}[A-Za-z0-9]{15}|(?:PK|RO)\d{2}[A-Z]{4}[A-Za-z0-9]{16}|(?:PS|QA)\d{2}[A-Z]{4}[A-Za-z0-9]{21}|AD\d{10}[A-Za-z0-9]{12}|AZ\d{2}[A-Z]{4}[A-Za-z0-9]{20}|BE\d{14}|BG\d{2}[A-Z]{4}\d{6}[A-Za-z0-9]{8}|BH\d{2}[A-Z]{4}[A-Za-z0-9]{14}|BR\d{25}[A-Z][A-Za-z0-9]|BY\d{2}[A-Za-z0-9]{4}\d{4}[A-Za-z0-9]{16}|DO\d{2}[A-Za-z0-9]{4}\d{20}|EG\d{27}|GE\d{2}[A-Z]\d{16}|GT\d{2}[A-Za-z0-9]{24}|GR\d{9}[A-Za-z0-9]{16}|HR\d{19}|IS\d{24}|JO\d{2}[A-Z]{4}\d{4}[A-Za-z0-9]{18}|KW\d{2}[A-Z]{4}[A-Za-z0-9]{22}|LC\d{2}[A-Z]{4}[A-Za-z0-9]{24}|LB\d{6}[A-Za-z0-9]{20}|LV\d{2}[A-Z]{4}\d{13}|MD\d{2}[A-Za-z0-9]{20}|MK\d{5}[A-Za-z0-9]{10}\d{2}|MR\d{25}|MT\d{2}[A-Z]{4}\d{5}[A-Za-z0-9]{18}|MU\d{2}[A-Z]{4}\d{19}[A-Z]{3}|NL\d{2}[A-Z]{4}\d{10}|NO\d{13}|SA\d{4}[A-Za-z0-9]{18}|SC\d{2}[A-Z]{4}\d{20}[A-Z]{3}|SI\d{17}|SV\d{2}[A-Z]{4}\d{20}|TR\d{8}[A-Za-z0-9]{16}|UA\d{8}[A-Za-z0-9]{19}|VG\d{2}[A-Z]{4}\d{16}|GE\d{2}[A-Z]{2}\d{16})$

This second regex was taken from https://stackoverflow.com/a/69068004/2391795, and slightly modified to add proper support for GE (Georgia) country.

Testing: https://regex101.com/r/I3oiuo/1/

Upvotes: 3

Numa Roch
Numa Roch

Reputation: 9

Based on the last SWIFT IBAN Registrar publication (June 2021), available here, I updated Rony Nasr's REGEX proposal. It includes 79 countries and checks country-specific IBAN structure and length. (It does NOT, however, do a checksum MOD97 verification).

/^(?:(?:CR|DE|ME|RS|VA)\d{20}|(?:CZ|ES|SE|SK|TN)\d{22}|(?:DK|FI|FO|GL|SD)\d{16}|(?:AT|BA|EE|LT|XK)\d{18}|(?:AE|IL|TL)\d{21}|(?:LY|PT|ST)\d{23}|(?:IT|SM)\d{2}[A-Z]\d{10}[A-Za-z0-9]{12}|(?:HU|PL)\d{26}|(?:AL|CY)\d{10}[A-Za-z0-9]{16}|(?:CH|LI)\d{7}[A-Za-z0-9]{12}|(?:FR|MC)\d{12}[A-Za-z0-9]{11}\d{2}|(?:GB|IE)\d{2}[A-Z]{4}\d{14}|(?:KZ|LU)\d{5}[A-Za-z0-9]{13}|(?:GI|IQ)\d{2}[A-Z]{4}[A-Za-z0-9]{15}|(?:PK|RO)\d{2}[A-Z]{4}[A-Za-z0-9]{16}|(?:PS|QA)\d{2}[A-Z]{4}[A-Za-z0-9]{21}|AD\d{10}[A-Za-z0-9]{12}|AZ\d{2}[A-Z]{4}[A-Za-z0-9]{20}|BE\d{14}|BG\d{2}[A-Z]{4}\d{6}[A-Za-z0-9]{8}|BH\d{2}[A-Z]{4}[A-Za-z0-9]{14}|BR\d{25}[A-Z][A-Za-z0-9]|BY\d{2}[A-Za-z0-9]{4}\d{4}[A-Za-z0-9]{16}|DO\d{2}[A-Za-z0-9]{4}\d{20}|EG\d{27}|GE\d{2}[A-Z]\d{16}|GT\d{2}[A-Za-z0-9]{24}|GR\d{9}[A-Za-z0-9]{16}|HR\d{19}|IS\d{24}|JO\d{2}[A-Z]{4}\d{4}[A-Za-z0-9]{18}|KW\d{2}[A-Z]{4}[A-Za-z0-9]{22}|LC\d{2}[A-Z]{4}[A-Za-z0-9]{24}|LB\d{6}[A-Za-z0-9]{20}|LV\d{2}[A-Z]{4}\d{13}|MD\d{2}[A-Za-z0-9]{20}|MK\d{5}[A-Za-z0-9]{10}\d{2}|MR\d{25}|MT\d{2}[A-Z]{4}\d{5}[A-Za-z0-9]{18}|MU\d{2}[A-Z]{4}\d{19}[A-Z]{3}|NL\d{2}[A-Z]{4}\d{10}|NO\d{13}|SA\d{4}[A-Za-z0-9]{18}|SC\d{2}[A-Z]{4}\d{20}[A-Z]{3}|SI\d{17}|SV\d{2}[A-Z]{4}\d{20}|TR\d{8}[A-Za-z0-9]{16}|UA\d{8}[A-Za-z0-9]{19}|VG\d{2}[A-Z]{4}\d{16}|GE\d{2}[A-Z]{2}\d{16})$/gm

Upvotes: 0

Rony Nasr
Rony Nasr

Reputation: 1

I have managed to create the below RegEx for quick validation based on the current format.

/^(?:(?:IT|SM)\d{2}[A-Z]\d{22}|NL\d{2}[A-Z]{4}\d{10}|RO\d{2}[A-Z]{4}\d[A-Z]\d{14}|LV\d{2}[A-Z]{4}\d{13}|FR\d{19}[A-Z]\d{5}|LI\d{17}[A-Z]{2}|MD\d{2}[A-Z]{2}\d{18}|(?:BG|GB|IE)\d{2}[A-Z]{4}\d{14}|BH\d{2}[A-Z]{4}\d{10}[A-Z]{2}\d{2}|GE\d{2}[A-Z]{2}\d{16}|GI\d{2}[A-Z]{4}\d{15}|BR\d{25}[A-Z]\d|MU\d{2}[A-Z]{4}\d{19}[A-Z]{3}|PS\d{2}[A-Z]{4}\d{21}|QA\d{2}[A-Z]{4}\d{14}[A-Z]{7}|(?:AZ|DO|GT)\d{2}[A-Z]{4}\d{20}|(?:BJ|ML|SN|CI)\d{2}[A-Z]\d{23}|(?:PK|VG)\d{2}[A-Z]{4}\d{16}|(?:KW|JO)\d{2}[A-Z]{4}\d{22}|MT\d{2}[A-Z]{4}\d{12}[A-Z]{7}\d{3}[A-Z]|NO\d{13}|(?:BE|BI)\d{14}|(?:DK|FI|GL|FO)\d{16}|(?:MK|SI)\d{17}|(?:BA|LT|AT|EE|KZ|LU|XK)\d{18}|(?:HR|CH|CR)\d{19}|(?:DE|ME|RS)\d{20}|(?:AE|IL|TL)\d{21}|(?:AD|CZ|ES|SA|DZ|SK|SE|TN)\d{22}|(?:PT|AO|CV|MZ)\d{23}|(?:IS|IR|TR)\d{24}|(?:MR|MC|BF|CM|GR|MG)\d{25}|(?:AL|DO|LB|PL|CY|HU)\d{26})$/i

Upvotes: -2

Sandwell
Sandwell

Reputation: 1457

Based on previous answers I created a Directive that implements Angular Validator method.
I also added the types.

iban-validator.directive.ts

import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms';
import { Directive } from '@angular/core';

@Directive({
  selector: '[ibanValidators]',
  providers: [{
    provide: NG_VALIDATORS,
    useExisting: IbanValidatorDirective,
    multi: true
  }]
})

export class IbanValidatorDirective implements Validator {

  validate(control: AbstractControl): object {
    const codeLengths = {
      AD: 24, AE: 23, AL: 28, AT: 20, AZ: 28, BA: 20, BE: 16, BG: 22, BH: 22, BR: 29, CH: 21, CR: 21, CY: 28, CZ: 24,
      DE: 22, DK: 18, DO: 28, EE: 20, ES: 24, LC: 30, FI: 18, FO: 18, FR: 27, GB: 22, GI: 23, GL: 18, GR: 27, GT: 28,
      HR: 21, HU: 28, IE: 22, IL: 23, IS: 26, IT: 27, JO: 30, KW: 30, KZ: 20, LB: 28, LI: 21, LT: 20, LU: 20, LV: 21,
      MC: 27, MD: 24, ME: 22, MK: 19, MR: 27, MT: 31, MU: 30, NL: 18, NO: 15, PK: 24, PL: 28, PS: 29, PT: 25, QA: 29,
      RO: 24, RS: 22, SA: 24, SE: 24, SI: 19, SK: 24, SM: 27, TN: 24, TR: 26
    };
    if (control.value) {
      const iban = control.value.toUpperCase().replace(/[^A-Z0-9]/g, '');
      const code = iban.match(/^([A-Z]{2})(\d{2})([A-Z\d]+)$/);
      let digits: number;
      if (!code || iban.length !== codeLengths[code[1]]) {
        return { ibanValid: false };
      }
      digits = (code[3] + code[1] + code[2]).replace(/[A-Z]/g, (letter: string) => {
        return letter.charCodeAt(0) - 55;
      });
      return this.mod97(digits) === 1 ? null : { ibanValid: false };
    }
  }

  private mod97(digital: number | string) {
    digital = digital.toString();
    let checksum: number | string = digital.slice(0, 2);
    let fragment = '';
    for (let offset = 2; offset < digital.length; offset += 7) {
      fragment = checksum + digital.substring(offset, offset + 7);
      checksum = parseInt(fragment, 10) % 97;
    }
    return checksum;
  }
}

Then just use the directive on an input.

Upvotes: 7

knif3r
knif3r

Reputation: 449

I know this is an old topic, but since it showed up on #1 place on Google, and since the solutions here aren't really refined I would like to show you my take on it:

export const validIban = (value) => {
    let rearrange =
        value.substring(4, value.length)
        + value.substring(0, 4);
    let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split('');
    let alphaMap = {};
    let number = [];

    alphabet.forEach((value, index) => {
        alphaMap[value] = index + 10;
    });

    rearrange.split('').forEach((value, index) => {
        number[index] = alphaMap[value] || value;
    });

    return modulo(number.join('').toString(), 97) === 1;
}

const modulo = (aNumStr, aDiv) => {
    var tmp = "";
    var i, r;
    for (i = 0; i < aNumStr.length; i++) {
        tmp += aNumStr.charAt(i);
        r = tmp % aDiv;
        tmp = r.toString();
    }
    return tmp / 1;
}

It works pretty well for me you can test it with validIban(testThis) / http://randomiban.com

Upvotes: 6

Pascal Zoleko
Pascal Zoleko

Reputation: 699

I answered a similar question. Use this list of Regular expressions to validate your IBANS. There are 70 countries, so in general you should be good to go.

AL[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){2}([a-zA-Z0-9]{4}\s?){4}\s?
AD[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){2}([a-zA-Z0-9]{4}\s?){3}\s?
AT[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){4}\s?
AZ[a-zA-Z0-9]{2}\s?([a-zA-Z0-9]{4}\s?){1}([0-9]{4}\s?){5}\s?
BH[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([a-zA-Z0-9]{4}\s?){3}([a-zA-Z0-9]{2})\s?
BY[a-zA-Z0-9]{2}\s?([a-zA-Z0-9]{4}\s?){1}([0-9]{4}\s?){5}\s?
BE[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){3}\s?
BA[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){4}\s?
BR[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){5}([0-9]{3})([a-zA-Z]{1}\s?)([a-zA-Z0-9]{1})\s?
BG[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([0-9]{4}\s?){1}([0-9]{2})([a-zA-Z0-9]{2}\s?)([a-zA-Z0-9]{4}\s?){1}([a-zA-Z0-9]{2})\s?
CR[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{2})\s?
HR[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{1})\s?
CY[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){2}([a-zA-Z0-9]{4}\s?){4}\s?
CZ[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){5}\s?
DK[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){3}([0-9]{2})\s?
DO[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([0-9]{4}\s?){5}\s?
TL[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{3})\s?
EE[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){4}\s?
FO[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){3}([0-9]{2})\s?
FI[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){3}([0-9]{2})\s?
FR[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){2}([0-9]{2})([a-zA-Z0-9]{2}\s?)([a-zA-Z0-9]{4}\s?){2}([a-zA-Z0-9]{1})([0-9]{2})\s?
GE[a-zA-Z0-9]{2}\s?([a-zA-Z0-9]{2})([0-9]{2}\s?)([0-9]{4}\s?){3}([0-9]{2})\s?
DE[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{2})\s?
GI[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([a-zA-Z0-9]{4}\s?){3}([a-zA-Z0-9]{3})\s?
GR[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){1}([0-9]{3})([a-zA-Z0-9]{1}\s?)([a-zA-Z0-9]{4}\s?){3}([a-zA-Z0-9]{3})\s?
GL[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){3}([0-9]{2})\s?
GT[a-zA-Z0-9]{2}\s?([a-zA-Z0-9]{4}\s?){1}([a-zA-Z0-9]{4}\s?){5}\s?
HU[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){6}\s?
IS[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){5}([0-9]{2})\s?
IE[a-zA-Z0-9]{2}\s?([a-zA-Z0-9]{4}\s?){1}([0-9]{4}\s?){3}([0-9]{2})\s?
IL[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{3})\s?
IT[a-zA-Z0-9]{2}\s?([a-zA-Z]{1})([0-9]{3}\s?)([0-9]{4}\s?){1}([0-9]{3})([a-zA-Z0-9]{1}\s?)([a-zA-Z0-9]{4}\s?){2}([a-zA-Z0-9]{3})\s?
JO[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([0-9]{4}\s?){5}([0-9]{2})\s?
KZ[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){3}([0-9]{1})([a-zA-Z0-9]{3}\s?)([a-zA-Z0-9]{4}\s?){2}([a-zA-Z0-9]{2})\s?
XK[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){1}([0-9]{4}\s?){2}([0-9]{2})([0-9]{2}\s?)\s?
KW[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([a-zA-Z0-9]{4}\s?){5}([a-zA-Z0-9]{2})\s?
LV[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([a-zA-Z0-9]{4}\s?){3}([a-zA-Z0-9]{1})\s?
LB[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){1}([a-zA-Z0-9]{4}\s?){5}\s?
LI[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){1}([0-9]{1})([a-zA-Z0-9]{3}\s?)([a-zA-Z0-9]{4}\s?){2}([a-zA-Z0-9]{1})\s?
LT[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){4}\s?
LU[a-zA-Z0-9]{2}\s?([0-9]{3})([a-zA-Z0-9]{1}\s?)([a-zA-Z0-9]{4}\s?){3}\s?
MK[a-zA-Z0-9]{2}\s?([0-9]{3})([a-zA-Z0-9]{1}\s?)([a-zA-Z0-9]{4}\s?){2}([a-zA-Z0-9]{1})([0-9]{2})\s?
MT[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([0-9]{4}\s?){1}([0-9]{1})([a-zA-Z0-9]{3}\s?)([a-zA-Z0-9]{4}\s?){3}([a-zA-Z0-9]{3})\s?
MR[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){5}([0-9]{3})\s?
MU[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([0-9]{4}\s?){4}([0-9]{3})([a-zA-Z]{1}\s?)([a-zA-Z]{2})\s?
MC[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){2}([0-9]{2})([a-zA-Z0-9]{2}\s?)([a-zA-Z0-9]{4}\s?){2}([a-zA-Z0-9]{1})([0-9]{2})\s?
MD[a-zA-Z0-9]{2}\s?([a-zA-Z0-9]{2})([a-zA-Z0-9]{2}\s?)([a-zA-Z0-9]{4}\s?){4}\s?
ME[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{2})\s?
NL[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([0-9]{4}\s?){2}([0-9]{2})\s?
NO[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){2}([0-9]{3})\s?
PK[a-zA-Z0-9]{2}\s?([a-zA-Z0-9]{4}\s?){1}([0-9]{4}\s?){4}\s?
PS[a-zA-Z0-9]{2}\s?([a-zA-Z0-9]{4}\s?){1}([0-9]{4}\s?){5}([0-9]{1})\s?
PL[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){6}\s?
PT[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){5}([0-9]{1})\s?
QA[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([a-zA-Z0-9]{4}\s?){5}([a-zA-Z0-9]{1})\s?
RO[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([a-zA-Z0-9]{4}\s?){4}\s?
SM[a-zA-Z0-9]{2}\s?([a-zA-Z]{1})([0-9]{3}\s?)([0-9]{4}\s?){1}([0-9]{3})([a-zA-Z0-9]{1}\s?)([a-zA-Z0-9]{4}\s?){2}([a-zA-Z0-9]{3})\s?
SA[a-zA-Z0-9]{2}\s?([0-9]{2})([a-zA-Z0-9]{2}\s?)([a-zA-Z0-9]{4}\s?){4}\s?
RS[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){4}([0-9]{2})\s?
SK[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){5}\s?
SI[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){3}([0-9]{3})\s?
ES[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){5}\s?
SE[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){5}\s?
CH[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){1}([0-9]{1})([a-zA-Z0-9]{3}\s?)([a-zA-Z0-9]{4}\s?){2}([a-zA-Z0-9]{1})\s?
TN[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){5}\s?
TR[a-zA-Z0-9]{2}\s?([0-9]{4}\s?){1}([0-9]{1})([a-zA-Z0-9]{3}\s?)([a-zA-Z0-9]{4}\s?){3}([a-zA-Z0-9]{2})\s?
AE[a-zA-Z0-9]{2}\s?([0-9]{3})([0-9]{1}\s?)([0-9]{4}\s?){3}([0-9]{3})\s?
GB[a-zA-Z0-9]{2}\s?([a-zA-Z]{4}\s?){1}([0-9]{4}\s?){3}([0-9]{2})\s?
VA[a-zA-Z0-9]{2}\s?([0-9]{3})([0-9]{1}\s?)([0-9]{4}\s?){3}([0-9]{2})\s?
VG[a-zA-Z0-9]{2}\s?([a-zA-Z0-9]{4}\s?){1}([0-9]{4}\s?){4}\s? 

Upvotes: 13

Haluk
Haluk

Reputation: 2099

"Jquery validation plugin" also supports iban check:

https://github.com/jzaefferer/jquery-validation/blob/master/src/additional/iban.js

Upvotes: 7

Laurent VB
Laurent VB

Reputation: 1207

You can use this library to validate and format an IBAN: https://github.com/arhs/iban.js (disclaimer: I wrote the library)

However, neither Russia nor Belarus are supported, as I can't find any mention of those countries on the IBAN page of wikipedia nor in the official IBAN registry so I'm afraid you'll have to modify the library code yourself to add it.

Upvotes: 36

Related Questions