2. 信用卡号码的前缀数字能告诉我们什么?

主账号(PAN)就是信用卡号码的另一种叫法。

PAN通常为16位数字,但具体长度可能因发卡机构而异。

目前,发卡机构识别号码(IIN)是PAN的前六位数字,由一个前导数字加五位后续数字组成。

需要强调的是这是当前情况,未来可能变化——早在2015年就开始筹备将IIN扩展到前八位数字。

让我们看看如何仅通过IIN确定信用卡类型。

2.1. 前导数字有什么含义?

主要行业标识符(MII)是卡号的第一位数字

顾名思义,通过首位数字就能判断卡片所属行业:

  • 1、2 - 航空公司(等)
  • 3 - 旅游娱乐
  • 4、5 - 银行业
  • 6 - 零售和银行
  • 7 - 燃料行业
  • 8 - 医疗和电信
  • 9 - 国家政府机构
  • 0 - 其他(预留)

2.2. 如何通过IIN确定卡类型?

自1989年起就有国际标准规范PAN分配,但IIN官方注册表不公开。

好在主流发卡机构的IIN范围众所周知,我们可以用正则表达式匹配发卡机构

使用正则表达式前要注意:IIN范围列表是动态变化的

开发相关应用时必须考虑如何保持更新。或者直接引入成熟的第三方库(比如使用Stripe API),比自己维护更靠谱。

2.3. 用正则表达式识别发卡机构

以Visa卡为例:其卡号以4开头,简单正则表达式为^4[0-9]{0,}$

注意:这里没验证卡号长度(假设卡号有效)。

类似地识别美国运通卡(以34/37开头):^3[47][0-9]{0,}$

有些发卡机构IIN范围较广,比如万事达卡:

  • 传统范围:51-55开头
  • 新增范围:222100-272099

正则表达式要复杂些:^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$

只要知道IIN范围,任何发卡机构都能用类似模式识别。

3. 卡号中间数字有什么含义?

完整PAN由三部分组成:IIN、个人账户识别码和校验位

IIN和校验位之间的数字就是个人账户识别码。

这部分含义由发卡机构定义,不同机构规则不同,通常包含账户类型等信息。

4. 卡号最后一位数字有什么含义?

校验位是卡号最后一位数字

它的存在让我们能用Luhn算法快速识别无效卡号。

Luhn算法由Hans Peter Luhn在1950年代末开发,现代信用卡都采用此规则生成卡号。

Luhn算法涉及卡号所有数字,即使输错一位也能检测出来——这对按交易收费的系统特别重要!

4.1. 用Luhn算法验证卡号

验证步骤如下(需完整卡号含IIN):

从右向左遍历数字,对偶数位数字特殊处理

for (int i = cardNumber.length() - 1; i >= 0; i--) {
    int digit = Integer.parseInt(cardNumber.substring(i, i + 1));

    if ((cardNumber.length() - i) % 2 == 0) {
        digit = doubleAndSumDigits(digit);
    }

    sum += digit;
}

对偶数位数字:先翻倍,若结果为两位数则拆分相加(等价于减9):

private static int doubleAndSumDigits(int digit) {
    int ret = digit * 2;

    if (ret > 9) {
        ret = digit - 9; // 等价于拆分相加(如16→1+6=7)
    }

    return ret;
}

举个简单例子(用4位数代替16位):验证8642

  1. 从右向左处理:
    • 2(奇数位):不变 → 2
    • 4(偶数位):翻倍 → 8
    • 6(奇数位):不变 → 6
    • 8(偶数位):翻倍→16→拆分→1+6=7
  2. 求和:2+8+6+7=23

最终结果能被10整除则卡号可能有效

return sum % 10 == 0;

本例中23%10≠0 → 8642无效。若改为8649:

  • 校验位计算:2→9
  • 重新求和:9+8+6+7=30 → 30%10=0 → 通过验证

4.2. Luhn算法有什么局限?

需要注意:通过Luhn验证不等于卡号真实存在!8649虽然通过算法验证,但可能从未被发行。

唯一确认卡号真实性的方法是询问发卡机构

算法局限性:

  1. 极少数情况无法检测输入错误(如交换相邻数字:09→90)
  2. 不验证卡号长度(8649虽通过验证但明显过短)

实际应用中需结合长度校验(不同发卡机构长度可能不同)。

5. 总结

本文拆解了信用卡号码各部分的含义:

  • 前缀数字:通过正则表达式识别发卡机构
  • 中间数字:由发卡机构定义账户信息
  • 校验位:用Luhn算法验证有效性

Luhn算法虽不能保证卡号真实存在,但能快速拦截无效输入,减少无效交易请求。

完整示例代码见GitHub项目


原始标题:Algorithm to Identify and Validate a Credit Card Number