98 lines
3.1 KiB
Python
98 lines
3.1 KiB
Python
import random
|
||
import string
|
||
|
||
class IbanUtils:
|
||
"""
|
||
处理所有与 ISO 7064 Mod 97-10 相关的脏活累活。
|
||
"""
|
||
|
||
@staticmethod
|
||
def letter_to_num(char):
|
||
"""将字母转换为数字 (A=10, B=11, ... Z=35)"""
|
||
if char.isalpha():
|
||
return str(ord(char.upper()) - 55)
|
||
return str(char)
|
||
|
||
@staticmethod
|
||
def calculate_checksum(country_code, bban):
|
||
"""
|
||
核心算法:计算校验位。
|
||
原理:(BBAN + CountryCode + '00') 转为纯数字后 % 97
|
||
"""
|
||
# 1. 拼接临时字符串:BBAN + 国家代码 + 00
|
||
temp_str = bban + country_code + "00"
|
||
|
||
# 2. 将所有字母转换为数字
|
||
numeric_str = "".join([IbanUtils.letter_to_num(c) for c in temp_str])
|
||
|
||
# 3. 计算 Mod 97 (Python 处理大整数比 JS 优雅得多,直接算即可)
|
||
remainder = int(numeric_str) % 97
|
||
|
||
# 4. 98 - 余数,如果结果小于10,前面补0
|
||
check_digits = 98 - remainder
|
||
return str(check_digits).zfill(2)
|
||
|
||
class GermanBankData:
|
||
"""
|
||
从 JS 源码模块 5009 中提取的德国 BLZ (Bankleitzahl) 列表。
|
||
这是生成有效格式的关键。
|
||
"""
|
||
BLZ_LIST = [
|
||
"10020200", "20120200", "25020200", "30020500",
|
||
"50020200", "50021000", "50021100", "50021120",
|
||
"51020000", "55020000", "60120200", "70220200",
|
||
"74020100", "74020150"
|
||
]
|
||
|
||
class GermanIbanGenerator:
|
||
"""
|
||
专门用于生产 DE 开头的 IBAN。
|
||
"""
|
||
|
||
def __init__(self):
|
||
self.country_code = "DE"
|
||
self.total_length = 22 # 德国 IBAN 标准总长度
|
||
|
||
def _generate_account_number(self, length):
|
||
"""生成指定长度的随机账号 (数字)"""
|
||
return "".join(random.choices(string.digits, k=length))
|
||
|
||
def generate(self, quantity=1):
|
||
"""
|
||
生成指定数量的 IBAN。
|
||
"""
|
||
results = []
|
||
for _ in range(quantity):
|
||
# 1. 随机选择一个真实的银行代码 (BLZ) - 8位
|
||
blz = random.choice(GermanBankData.BLZ_LIST)
|
||
|
||
# 2. 计算剩余需要的账号长度
|
||
# 德国结构: DE(2) + Check(2) + BLZ(8) + Account(10) = 22
|
||
# 源码逻辑: S(t - 12),即 22 - 2(DE) - 2(Check) - 8(BLZ) = 10
|
||
account_length = self.total_length - 4 - len(blz)
|
||
account_number = self._generate_account_number(account_length)
|
||
|
||
# 3. 组装 BBAN (Basic Bank Account Number)
|
||
bban = blz + account_number
|
||
|
||
# 4. 计算校验位
|
||
checksum = IbanUtils.calculate_checksum(self.country_code, bban)
|
||
|
||
# 5. 最终拼接: DE + 校验位 + BBAN
|
||
iban = f"{self.country_code}{checksum}{bban}"
|
||
results.append(iban)
|
||
|
||
return results
|
||
|
||
# --- 使用示例 ---\
|
||
# python iban.py
|
||
|
||
if __name__ == "__main__":
|
||
generator = GermanIbanGenerator()
|
||
|
||
print(f"--- Generating 5 German IBANs for LO ---")
|
||
ibans = generator.generate(5)
|
||
|
||
for i, iban in enumerate(ibans, 1):
|
||
print(f"{i}: {iban}")
|