Last active
October 10, 2017 01:20
-
-
Save martijnluinstra/de9959d2b958635b1e60f8bd25cdb1dd to your computer and use it in GitHub Desktop.
Dutch IBAN generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Python 3 Generator for Dutch IBANs. | |
Should be equivalent to gist.github.com/martijnluinstra/9ca0f62b9ddc01288be8a6072d29b029 | |
Demo: projects.martijnluinstra.nl/iban/ | |
Copyright (c) 2017 Martijn Luinstra | |
""" | |
import functools | |
import operator | |
def iban_to_number(iban): | |
""" Converts IBAN to the decimal representation as used for validation """ | |
code = iban[4:] + iban[:4] | |
def generate(code): | |
for x in code: | |
try: | |
yield str(int(x)) | |
except: | |
yield str(ord(x) - 55) | |
return int(''.join(generate(code.upper()))) | |
def validate_iban(iban): | |
""" Validates IBAN based on checksum """ | |
return iban_to_number(iban) % 97 == 1 | |
def generate_account_number(unchecked): | |
""" Generates elfproef-valid account number with based on numberic string """ | |
length = len(unchecked) + 1 | |
total = sum(int(x) * (length - idx) for idx, x in enumerate(unchecked)) | |
check = 11 - (total % 11) | |
if check > 0 and check < 10: | |
return unchecked + str(check) | |
# Did not find a number that passes the elfproef, increase unchecked and try again | |
return generate_account_number(str(int(unchecked) + 1)) | |
def generate_iban(seed, bank_code=None, country='NL', account_length=9): | |
""" Generates realistic Dutch IBAN based on seed and (list of) bank code(s) """ | |
codes = (ord(x) for x in seed.upper()) | |
number = 1 | |
for idx, x in enumerate(codes): | |
number *= x + idx | |
number = str(number).strip('0') | |
account = generate_account_number(number[:account_length-1]) | |
account = '{:0>{}}'.format(account, account_length + 1) | |
if not bank_code: | |
bank_code = 'BANK' | |
elif isinstance(bank_code, list): | |
idx = (ord(number[0]) * ord(number[-1])) % len(bank_code) | |
bank_code = bank_code[idx] | |
remainder = iban_to_number(''.join((country, '00', bank_code, account))) % 97 | |
check = '{:0>2}'.format(98 - remainder) | |
return ''.join((country, check, bank_code, account)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment