import random import datetime import re class CardGenerator: def __init__(self): self.current_year = datetime.datetime.now().year def luhn_checksum(self, card_number_str): """计算 Luhn 校验和""" digits = [int(d) for d in card_number_str] checksum = 0 is_second = False for digit in reversed(digits): if is_second: digit *= 2 if digit > 9: digit -= 9 checksum += digit is_second = not is_second return checksum def calculate_check_digit(self, card_number_without_check): """计算最后一位校验位""" temp_number = card_number_without_check + "0" checksum = self.luhn_checksum(temp_number) if checksum % 10 == 0: return "0" else: return str(10 - (checksum % 10)) def generate_card_number(self, pattern): """ 核心生成逻辑:支持任意位置的 'x' """ # 1. 确定卡号长度标准 (Amex 15位,其他 16位) # 如果 pattern 已经很长,就用 pattern 的长度,否则根据卡头判断 target_len = 16 if pattern.startswith(('34', '37')): target_len = 15 # 2. 补全 pattern 到目标长度 (减去最后一位校验位) # 如果输入的 pattern 比如是 "547958" (长度6),需要补 x 到 15位 (留一位给校验) # 如果输入已经包含了 x 且长度足够,则保留原样 working_pattern = pattern.lower() # 移除可能存在的非数字/x字符 working_pattern = re.sub(r'[^0-9x]', '', working_pattern) # 自动填充 x if len(working_pattern) < target_len: working_pattern += 'x' * (target_len - len(working_pattern)) # 截断到 倒数第二位 (最后一位是校验位) # 注意:如果用户输入了完整的 16位 pattern 且最后一位不是 x,我们会覆盖它, # 因为 Luhn 算法要求最后一位必须是计算出来的。 # 除非用户就是想校验?但在生成逻辑里,我们通常假设最后一位是计算的。 base_pattern = working_pattern[:target_len-1] generated_prefix = "" for char in base_pattern: if char == 'x': generated_prefix += str(random.randint(0, 9)) else: generated_prefix += char # 计算校验位 check_digit = self.calculate_check_digit(generated_prefix) return generated_prefix + check_digit def parse_date_cvv(self, card_num, m_req, y_req, c_req): """ 处理日期和CVV的占位符逻辑 """ # --- Month --- if m_req in ['(m)', 'rnd', '', None]: month = str(random.randint(1, 12)).zfill(2) else: month = m_req.strip() # 使用用户指定的静态值,如 '05' # --- Year --- if y_req in ['(y)', 'rnd', '', None]: year = str(self.current_year + random.randint(2, 5)) else: year = y_req.strip() # 使用用户指定的静态值,如 '2023' 或 '23' # --- CVV --- if c_req in ['(cvv)', 'rnd', '', None]: if card_num.startswith(('34', '37')): cvv = str(random.randint(1102, 9999)) else: cvv = str(random.randint(112, 999)) else: cvv = c_req.strip() return month, year, cvv def process_line(self, raw_input, count=1): """ 智能解析输入字符串并生成 支持格式: - BIN only: 547958 - Pattern: 460723xxxxxxxxxx - Complex: 5319719xxx5xxx87 - Full: 434256|11|2022|212 - Templates: 434256|(m)|(y)|(cvv) """ # 默认值 parts = raw_input.split('|') # 提取各个部分,没有的就设为 None,交给 parse_date_cvv 处理默认逻辑 pattern_part = parts[0] if len(parts) > 0 else "" month_part = parts[1] if len(parts) > 1 else None year_part = parts[2] if len(parts) > 2 else None cvv_part = parts[3] if len(parts) > 3 else None results = [] for _ in range(count): # 1. 生成卡号 card_num = self.generate_card_number(pattern_part) # 2. 处理附属信息 m, y, c = self.parse_date_cvv(card_num, month_part, year_part, cvv_part) results.append(f"{card_num}|{m}|{y}|{c}") return results # --- 测试与演示 --- if __name__ == "__main__": gen = CardGenerator() # 你列出的所有测试用例 test_cases = [ "547958", # 仅 BIN "460723xxxxxxxxxx", # 带图案 "5319719xxx5xxx87", # 专业用户 (混合 pattern) "434256|11|2022|212", # 你自己的固定模式 "559917|11|2022|(cvv)", # 随机 CVV "434256|(m)|(y)|(cvv)", # 全随机占位符 "434256240669|(m)|(y)|(cvv)", # 短卡号 (没有最后4位) -> 会自动补全 "53673712123xxxxx|05|2023|", # 指定长年份 "53673712123xxxxx|05|23|" # 指定短年份 ] print(f"{'INPUT FORMAT':<35} | {'GENERATED OUTPUT'}") print("-" * 80) for case in test_cases: # 每个案例生成 1 条作为演示 output = gen.process_line(case, count=1)[0] print(f"{case:<35} -> {output}")