UNPKG

ibankit

Version:

Validation, field extraction and creation of IBAN, BBAN, BIC numbers

198 lines 17.9 kB
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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