174 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
| import assertString from './util/assertString';
 | |
| import includes from './util/includesArray';
 | |
| 
 | |
| /**
 | |
|  * List of country codes with
 | |
|  * corresponding IBAN regular expression
 | |
|  * Reference: https://en.wikipedia.org/wiki/International_Bank_Account_Number
 | |
|  */
 | |
| var ibanRegexThroughCountryCode = {
 | |
|   AD: /^(AD[0-9]{2})\d{8}[A-Z0-9]{12}$/,
 | |
|   AE: /^(AE[0-9]{2})\d{3}\d{16}$/,
 | |
|   AL: /^(AL[0-9]{2})\d{8}[A-Z0-9]{16}$/,
 | |
|   AT: /^(AT[0-9]{2})\d{16}$/,
 | |
|   AZ: /^(AZ[0-9]{2})[A-Z0-9]{4}\d{20}$/,
 | |
|   BA: /^(BA[0-9]{2})\d{16}$/,
 | |
|   BE: /^(BE[0-9]{2})\d{12}$/,
 | |
|   BG: /^(BG[0-9]{2})[A-Z]{4}\d{6}[A-Z0-9]{8}$/,
 | |
|   BH: /^(BH[0-9]{2})[A-Z]{4}[A-Z0-9]{14}$/,
 | |
|   BR: /^(BR[0-9]{2})\d{23}[A-Z]{1}[A-Z0-9]{1}$/,
 | |
|   BY: /^(BY[0-9]{2})[A-Z0-9]{4}\d{20}$/,
 | |
|   CH: /^(CH[0-9]{2})\d{5}[A-Z0-9]{12}$/,
 | |
|   CR: /^(CR[0-9]{2})\d{18}$/,
 | |
|   CY: /^(CY[0-9]{2})\d{8}[A-Z0-9]{16}$/,
 | |
|   CZ: /^(CZ[0-9]{2})\d{20}$/,
 | |
|   DE: /^(DE[0-9]{2})\d{18}$/,
 | |
|   DK: /^(DK[0-9]{2})\d{14}$/,
 | |
|   DO: /^(DO[0-9]{2})[A-Z]{4}\d{20}$/,
 | |
|   DZ: /^(DZ\d{24})$/,
 | |
|   EE: /^(EE[0-9]{2})\d{16}$/,
 | |
|   EG: /^(EG[0-9]{2})\d{25}$/,
 | |
|   ES: /^(ES[0-9]{2})\d{20}$/,
 | |
|   FI: /^(FI[0-9]{2})\d{14}$/,
 | |
|   FO: /^(FO[0-9]{2})\d{14}$/,
 | |
|   FR: /^(FR[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/,
 | |
|   GB: /^(GB[0-9]{2})[A-Z]{4}\d{14}$/,
 | |
|   GE: /^(GE[0-9]{2})[A-Z0-9]{2}\d{16}$/,
 | |
|   GI: /^(GI[0-9]{2})[A-Z]{4}[A-Z0-9]{15}$/,
 | |
|   GL: /^(GL[0-9]{2})\d{14}$/,
 | |
|   GR: /^(GR[0-9]{2})\d{7}[A-Z0-9]{16}$/,
 | |
|   GT: /^(GT[0-9]{2})[A-Z0-9]{4}[A-Z0-9]{20}$/,
 | |
|   HR: /^(HR[0-9]{2})\d{17}$/,
 | |
|   HU: /^(HU[0-9]{2})\d{24}$/,
 | |
|   IE: /^(IE[0-9]{2})[A-Z]{4}\d{14}$/,
 | |
|   IL: /^(IL[0-9]{2})\d{19}$/,
 | |
|   IQ: /^(IQ[0-9]{2})[A-Z]{4}\d{15}$/,
 | |
|   IR: /^(IR[0-9]{2})0\d{2}0\d{18}$/,
 | |
|   IS: /^(IS[0-9]{2})\d{22}$/,
 | |
|   IT: /^(IT[0-9]{2})[A-Z]{1}\d{10}[A-Z0-9]{12}$/,
 | |
|   JO: /^(JO[0-9]{2})[A-Z]{4}\d{22}$/,
 | |
|   KW: /^(KW[0-9]{2})[A-Z]{4}[A-Z0-9]{22}$/,
 | |
|   KZ: /^(KZ[0-9]{2})\d{3}[A-Z0-9]{13}$/,
 | |
|   LB: /^(LB[0-9]{2})\d{4}[A-Z0-9]{20}$/,
 | |
|   LC: /^(LC[0-9]{2})[A-Z]{4}[A-Z0-9]{24}$/,
 | |
|   LI: /^(LI[0-9]{2})\d{5}[A-Z0-9]{12}$/,
 | |
|   LT: /^(LT[0-9]{2})\d{16}$/,
 | |
|   LU: /^(LU[0-9]{2})\d{3}[A-Z0-9]{13}$/,
 | |
|   LV: /^(LV[0-9]{2})[A-Z]{4}[A-Z0-9]{13}$/,
 | |
|   MA: /^(MA[0-9]{26})$/,
 | |
|   MC: /^(MC[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/,
 | |
|   MD: /^(MD[0-9]{2})[A-Z0-9]{20}$/,
 | |
|   ME: /^(ME[0-9]{2})\d{18}$/,
 | |
|   MK: /^(MK[0-9]{2})\d{3}[A-Z0-9]{10}\d{2}$/,
 | |
|   MR: /^(MR[0-9]{2})\d{23}$/,
 | |
|   MT: /^(MT[0-9]{2})[A-Z]{4}\d{5}[A-Z0-9]{18}$/,
 | |
|   MU: /^(MU[0-9]{2})[A-Z]{4}\d{19}[A-Z]{3}$/,
 | |
|   MZ: /^(MZ[0-9]{2})\d{21}$/,
 | |
|   NL: /^(NL[0-9]{2})[A-Z]{4}\d{10}$/,
 | |
|   NO: /^(NO[0-9]{2})\d{11}$/,
 | |
|   PK: /^(PK[0-9]{2})[A-Z0-9]{4}\d{16}$/,
 | |
|   PL: /^(PL[0-9]{2})\d{24}$/,
 | |
|   PS: /^(PS[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/,
 | |
|   PT: /^(PT[0-9]{2})\d{21}$/,
 | |
|   QA: /^(QA[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/,
 | |
|   RO: /^(RO[0-9]{2})[A-Z]{4}[A-Z0-9]{16}$/,
 | |
|   RS: /^(RS[0-9]{2})\d{18}$/,
 | |
|   SA: /^(SA[0-9]{2})\d{2}[A-Z0-9]{18}$/,
 | |
|   SC: /^(SC[0-9]{2})[A-Z]{4}\d{20}[A-Z]{3}$/,
 | |
|   SE: /^(SE[0-9]{2})\d{20}$/,
 | |
|   SI: /^(SI[0-9]{2})\d{15}$/,
 | |
|   SK: /^(SK[0-9]{2})\d{20}$/,
 | |
|   SM: /^(SM[0-9]{2})[A-Z]{1}\d{10}[A-Z0-9]{12}$/,
 | |
|   SV: /^(SV[0-9]{2})[A-Z0-9]{4}\d{20}$/,
 | |
|   TL: /^(TL[0-9]{2})\d{19}$/,
 | |
|   TN: /^(TN[0-9]{2})\d{20}$/,
 | |
|   TR: /^(TR[0-9]{2})\d{5}[A-Z0-9]{17}$/,
 | |
|   UA: /^(UA[0-9]{2})\d{6}[A-Z0-9]{19}$/,
 | |
|   VA: /^(VA[0-9]{2})\d{18}$/,
 | |
|   VG: /^(VG[0-9]{2})[A-Z]{4}\d{16}$/,
 | |
|   XK: /^(XK[0-9]{2})\d{16}$/
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Check if the country codes passed are valid using the
 | |
|  * ibanRegexThroughCountryCode as a reference
 | |
|  *
 | |
|  * @param {array} countryCodeArray
 | |
|  * @return {boolean}
 | |
|  */
 | |
| 
 | |
| function hasOnlyValidCountryCodes(countryCodeArray) {
 | |
|   var countryCodeArrayFilteredWithObjectIbanCode = countryCodeArray.filter(function (countryCode) {
 | |
|     return !(countryCode in ibanRegexThroughCountryCode);
 | |
|   });
 | |
|   if (countryCodeArrayFilteredWithObjectIbanCode.length > 0) {
 | |
|     return false;
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Check whether string has correct universal IBAN format
 | |
|  * The IBAN consists of up to 34 alphanumeric characters, as follows:
 | |
|  * Country Code using ISO 3166-1 alpha-2, two letters
 | |
|  * check digits, two digits and
 | |
|  * Basic Bank Account Number (BBAN), up to 30 alphanumeric characters.
 | |
|  * NOTE: Permitted IBAN characters are: digits [0-9] and the 26 latin alphabetic [A-Z]
 | |
|  *
 | |
|  * @param {string} str - string under validation
 | |
|  * @param {object} options - object to pass the countries to be either whitelisted or blacklisted
 | |
|  * @return {boolean}
 | |
|  */
 | |
| function hasValidIbanFormat(str, options) {
 | |
|   // Strip white spaces and hyphens
 | |
|   var strippedStr = str.replace(/[\s\-]+/gi, '').toUpperCase();
 | |
|   var isoCountryCode = strippedStr.slice(0, 2).toUpperCase();
 | |
|   var isoCountryCodeInIbanRegexCodeObject = isoCountryCode in ibanRegexThroughCountryCode;
 | |
|   if (options.whitelist) {
 | |
|     if (!hasOnlyValidCountryCodes(options.whitelist)) {
 | |
|       return false;
 | |
|     }
 | |
|     var isoCountryCodeInWhiteList = includes(options.whitelist, isoCountryCode);
 | |
|     if (!isoCountryCodeInWhiteList) {
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
|   if (options.blacklist) {
 | |
|     var isoCountryCodeInBlackList = includes(options.blacklist, isoCountryCode);
 | |
|     if (isoCountryCodeInBlackList) {
 | |
|       return false;
 | |
|     }
 | |
|   }
 | |
|   return isoCountryCodeInIbanRegexCodeObject && ibanRegexThroughCountryCode[isoCountryCode].test(strippedStr);
 | |
| }
 | |
| 
 | |
| /**
 | |
|    * Check whether string has valid IBAN Checksum
 | |
|    * by performing basic mod-97 operation and
 | |
|    * the remainder should equal 1
 | |
|    * -- Start by rearranging the IBAN by moving the four initial characters to the end of the string
 | |
|    * -- Replace each letter in the string with two digits, A -> 10, B = 11, Z = 35
 | |
|    * -- Interpret the string as a decimal integer and
 | |
|    * -- compute the remainder on division by 97 (mod 97)
 | |
|    * Reference: https://en.wikipedia.org/wiki/International_Bank_Account_Number
 | |
|    *
 | |
|    * @param {string} str
 | |
|    * @return {boolean}
 | |
|    */
 | |
| function hasValidIbanChecksum(str) {
 | |
|   var strippedStr = str.replace(/[^A-Z0-9]+/gi, '').toUpperCase(); // Keep only digits and A-Z latin alphabetic
 | |
|   var rearranged = strippedStr.slice(4) + strippedStr.slice(0, 4);
 | |
|   var alphaCapsReplacedWithDigits = rearranged.replace(/[A-Z]/g, function (_char) {
 | |
|     return _char.charCodeAt(0) - 55;
 | |
|   });
 | |
|   var remainder = alphaCapsReplacedWithDigits.match(/\d{1,7}/g).reduce(function (acc, value) {
 | |
|     return Number(acc + value) % 97;
 | |
|   }, '');
 | |
|   return remainder === 1;
 | |
| }
 | |
| export default function isIBAN(str) {
 | |
|   var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
 | |
|   assertString(str);
 | |
|   return hasValidIbanFormat(str, options) && hasValidIbanChecksum(str);
 | |
| }
 | |
| export var locales = Object.keys(ibanRegexThroughCountryCode); |