bezahlbrudi/iban_validator_gen.py
Ricardo (XenGi) Band 340cbf447b
add iban validation
2025-08-29 19:39:28 +02:00

95 lines
3.6 KiB
Python
Executable file

#!/usr/bin/env python3
import re
import csv
import json
#import httpx
#iban_registry_url = "https://www.swift.com/sites/default/files/files/iban-registry_1.txt"
#iban_registry_raw = httpx.get(iban_registry_url)
data = []
with open("iban-registry_1.txt", encoding="cp437") as csvfile:
reader = csv.reader(csvfile, delimiter="\t", quotechar='"')
for row in reader:
match row[0]:
case "Name of country":
for col in row[1:]:
data.append({"name": " ".join(reversed(col.split(", ")))})
case "IBAN prefix country code (ISO 3166)":
for i, col in enumerate(row[1:]):
data[i]["prefix"] = col
case "SEPA country":
for i, col in enumerate(row[1:]):
data[i]["sepa"] = True if col == "Yes" else False
case "IBAN structure":
for i, col in enumerate(row[1:]):
data[i]["format"] = col
case "BBAN structure":
for i, col in enumerate(row[1:]):
data[i]["regex"] = f"/^{data[i]['prefix']}[0-9]{{2}}"
for match in re.findall(r"(\d+)(!?)([ance])", col):
match match[2]:
case "a":
data[i]["regex"] += "[A-Z]"
case "n":
data[i]["regex"] += "[0-9]"
case "c":
data[i]["regex"] += "[0-9a-zA-Z]"
case "e":
data[i]["regex"] += "[ ]"
print(f"{data[i]['prefix']} has spaces")
if match[1] == "!":
data[i]["regex"] += f"{{{match[0]}}}"
else:
data[i]["regex"] += f"{{1,{match[0]}}}"
print(f"{data[i]['prefix']} has no !")
data[i]["regex"] += "$/"
case "IBAN length":
for i, col in enumerate(row[1:]):
data[i]["length"] = int(col)
case "Effective date":
for i, col in enumerate(row[1:]):
data[i]["since"] = col
case "Last update date":
for i, col in enumerate(row[1:]):
data[i]["updated"] = col
#print(json.dumps(data))
print("""/*
* function generated with iban_validator_gen.py
* with iban registry text file from:
* https://www.swift.com/standards/data-standards/iban-international-bank-account-number
*/
export function testIban(iban) {
let re = /^$/;
let error = "IBAN is not ISO 13616 compliant";
// Also validate lower case country codes but display error int the end
switch (iban.substring(0,2).toUpperCase()) {""")
for country in data:
print(f""" case "{country['prefix']}":
re = {country['regex']};
error = "IBAN for {country['name']} must have the format {country['format']}.";
break;""")
print(""" }
if (re.test(iban)) {
console.log("IBAN regex evaluates");
/*
* ISO/IEC 7064 checksum evaluation
* 1. shift first 4 chars of IBAN to the end
* 2. replace letter with numbers where a=10, b=11, ..., z=35
* 3. modulo the resulting number by 97
* 4. IBAN is valid if the result is 1
*/
return BigInt((iban.slice(4) + iban.slice(0, 4)).split("").map(ch => {
return isNaN(Number(ch)) ? ch.toLowerCase().charCodeAt(0) - 87 : ch
}).join("")) % 97n === 1n ? "" : `IBAN checksum not correct. ${error}`;
} else {
return error
}
};
""")