ibankit
Version:
Validation, field extraction and creation of IBAN, BBAN, BIC numbers
198 lines • 17.9 kB
JavaScript
import { countryByCode } from "./country";
import { BbanStructure } from "./bbanStructure";
import { PartType } from "./structurePart";
import { InvalidCheckDigitException, FormatViolation, FormatException, UnsupportedCountryException, } from "./exceptions";
const ucRegex = /^[A-Z]+$/;
const numRegex = /^[0-9]+$/;
export const DEFAULT_CHECK_DIGIT = "00";
const MOD = 97;
const MAX = 999999999;
const COUNTRY_CODE_INDEX = 0;
const COUNTRY_CODE_LENGTH = 2;
const CHECK_DIGIT_INDEX = COUNTRY_CODE_LENGTH;
const CHECK_DIGIT_LENGTH = 2;
const BBAN_INDEX = CHECK_DIGIT_INDEX + CHECK_DIGIT_LENGTH;
export function calculateCheckDigit(iban) {
const reformattedIban = replaceCheckDigit(iban, DEFAULT_CHECK_DIGIT);
const modResult = calculateMod(reformattedIban);
const checkDigit = String(98 - modResult);
return checkDigit.padStart(2, "0");
}
export function validate(iban) {
validateNotEmpty(iban);
validateCountryCode(iban, true);
validateCheckDigitPresence(iban);
validateBban(getCountryCode(iban), getBban(iban));
validateCheckDigitChecksum(iban);
}
export function validateCheckDigit(iban) {
validateNotEmpty(iban);
validateCheckDigitPresence(iban);
validateCountryCode(iban, false);
validateCheckDigitChecksum(iban);
}
export function validateBban(countryCode, bban) {
validateCountryCode(countryCode, true);
const structure = getBbanStructure(countryCode);
if (!structure) {
throw new Error("Internal error, expected structure");
}
structure.validate(bban);
}
export function isSupportedCountry(countryCode) {
return BbanStructure.forCountry(countryCode) != null;
}
export function getIbanLength(countryCode) {
const structure = getBbanStructure(countryCode);
if (structure === null) {
throw new UnsupportedCountryException("Unsuppored country", countryCode);
}
return COUNTRY_CODE_LENGTH + CHECK_DIGIT_LENGTH + structure.getBbanLength();
}
export function getCheckDigit(iban) {
return iban.substring(CHECK_DIGIT_INDEX, CHECK_DIGIT_INDEX + CHECK_DIGIT_LENGTH);
}
export function getCountryCode(iban) {
return iban.substring(COUNTRY_CODE_INDEX, COUNTRY_CODE_INDEX + COUNTRY_CODE_LENGTH);
}
export function getCountryCodeAndCheckDigit(iban) {
return iban.substring(COUNTRY_CODE_INDEX, COUNTRY_CODE_INDEX + COUNTRY_CODE_LENGTH + CHECK_DIGIT_LENGTH);
}
export function getBban(iban) {
return iban.substring(BBAN_INDEX);
}
export function getAccountNumber(iban) {
return extractBbanEntry(iban, PartType.ACCOUNT_NUMBER);
}
export function getBankCode(iban) {
return extractBbanEntry(iban, PartType.BANK_CODE);
}
export function getBranchCode(iban) {
return extractBbanEntry(iban, PartType.BRANCH_CODE);
}
export function getNationalCheckDigit(iban) {
return extractBbanEntry(iban, PartType.NATIONAL_CHECK_DIGIT);
}
export function getBranchCheckDigit(iban) {
return extractBbanEntry(iban, PartType.BRANCH_CHECK_DIGIT);
}
export function getCurrencyType(iban) {
return extractBbanEntry(iban, PartType.CURRENCY_TYPE);
}
export function getAccountType(iban) {
return extractBbanEntry(iban, PartType.ACCOUNT_TYPE);
}
export function getOwnerAccountType(iban) {
return extractBbanEntry(iban, PartType.OWNER_ACCOUNT_NUMBER);
}
export function getIdentificationNumber(iban) {
return extractBbanEntry(iban, PartType.IDENTIFICATION_NUMBER);
}
export function replaceCheckDigit(iban, checkDigit) {
return getCountryCode(iban) + checkDigit + getBban(iban);
}
export function toFormattedString(iban, separator = " ") {
return iban.replace(/(.{4})/g, `$1${separator}`).trim();
}
export function toFormattedStringBBAN(iban, separator = " ") {
const structure = getBbanStructure(iban);
if (structure === null) {
throw new Error("should't happen - already validated IBAN");
}
const bban = getBban(iban);
const parts = structure.getParts().reduce((acc, part) => {
const value = structure.extractValue(bban, part.getPartType());
return acc.concat(value || "", part.trailingSeparator ? separator : "");
}, []);
parts.pop();
return parts.join("");
}
export function validateCheckDigitChecksum(iban) {
if (calculateMod(iban) != 1) {
const checkDigit = getCheckDigit(iban);
const expectedCheckDigit = calculateCheckDigit(iban);
throw new InvalidCheckDigitException(`[${iban}] has invalid check digit: ${checkDigit}, expected check digit is: ${expectedCheckDigit}`, checkDigit, expectedCheckDigit);
}
}
function validateNotEmpty(iban) {
if (iban == null) {
throw new FormatException(FormatViolation.NOT_NULL, "Null can't be a valid Iban.");
}
if (iban.length === 0) {
throw new FormatException(FormatViolation.NOT_EMPTY, "Empty string can't be a valid Iban.");
}
}
function validateCountryCode(iban, hasStructure = true) {
if (iban.length < COUNTRY_CODE_LENGTH) {
throw new FormatException(FormatViolation.COUNTRY_CODE_TWO_LETTERS, "Iban must contain 2 char country code.", iban);
}
const countryCode = getCountryCode(iban);
if (countryCode !== countryCode.toUpperCase() || !ucRegex.test(countryCode)) {
throw new FormatException(FormatViolation.COUNTRY_CODE_ONLY_UPPER_CASE_LETTERS, "Iban country code must contain upper case letters.", countryCode);
}
const country = countryByCode(countryCode);
if (country == null) {
throw new FormatException(FormatViolation.COUNTRY_CODE_EXISTS, "Iban contains non existing country code.", countryCode);
}
if (hasStructure) {
const structure = BbanStructure.forCountry(country);
if (structure == null) {
throw new UnsupportedCountryException("Country code is not supported.", countryCode);
}
}
}
function validateCheckDigitPresence(iban) {
if (iban.length < COUNTRY_CODE_LENGTH + CHECK_DIGIT_LENGTH) {
throw new FormatException(FormatViolation.CHECK_DIGIT_TWO_DIGITS, "Iban must contain 2 digit check digit.", iban.substring(COUNTRY_CODE_LENGTH));
}
const checkDigit = getCheckDigit(iban);
if (!numRegex.test(checkDigit)) {
throw new FormatException(FormatViolation.CHECK_DIGIT_ONLY_DIGITS, "Iban's check digit should contain only digits.", checkDigit);
}
}
function calculateMod(iban) {
const reformattedIban = getBban(iban) + getCountryCodeAndCheckDigit(iban);
const VA = "A".charCodeAt(0);
const VZ = "Z".charCodeAt(0);
const V0 = "0".charCodeAt(0);
const V9 = "9".charCodeAt(0);
function addSum(total, value) {
const newTotal = (value > 9 ? total * 100 : total * 10) + value;
return newTotal > MAX ? newTotal % MOD : newTotal;
}
const total = reformattedIban
.toUpperCase()
.split("")
.reduce((totalValue, ch) => {
const code = ch.charCodeAt(0);
if (VA <= code && code <= VZ) {
return addSum(totalValue, code - VA + 10);
}
else if (V0 <= code && code <= V9) {
return addSum(totalValue, code - V0);
}
else {
throw new FormatException(FormatViolation.IBAN_VALID_CHARACTERS, `Invalid Character[${ch}] = '${code}'`, ch);
}
}, 0);
return total % MOD;
}
function getBbanStructure(iban) {
const countryCode = countryByCode(getCountryCode(iban));
if (!countryCode) {
return null;
}
return getBbanStructureByCountry(countryCode);
}
function getBbanStructureByCountry(countryCode) {
return BbanStructure.forCountry(countryCode);
}
function extractBbanEntry(iban, partType) {
const bban = getBban(iban);
const structure = getBbanStructure(iban);
if (structure === null) {
return null;
}
return structure.extractValue(bban, partType);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWJhblV0aWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaWJhblV0aWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFlLGFBQWEsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUN2RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFDTCwwQkFBMEIsRUFDMUIsZUFBZSxFQUNmLGVBQWUsRUFDZiwyQkFBMkIsR0FDNUIsTUFBTSxjQUFjLENBQUM7QUFFdEIsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDO0FBQzNCLE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQztBQUs1QixNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUM7QUFDeEMsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDO0FBQ2YsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDO0FBRXRCLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxDQUFDO0FBQzdCLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO0FBQzlCLE1BQU0saUJBQWlCLEdBQUcsbUJBQW1CLENBQUM7QUFDOUMsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLENBQUM7QUFDN0IsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLEdBQUcsa0JBQWtCLENBQUM7QUFXMUQsTUFBTSxVQUFVLG1CQUFtQixDQUFDLElBQVk7SUFDOUMsTUFBTSxlQUFlLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxFQUFFLG1CQUFtQixDQUFDLENBQUM7SUFDckUsTUFBTSxTQUFTLEdBQUcsWUFBWSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQ2hELE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxFQUFFLEdBQUcsU0FBUyxDQUFDLENBQUM7SUFFMUMsT0FBTyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLENB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