DE 2 装的是 PAN,变长字段,格式 n ..19:先是 2 位长度前缀(LLVAR),后面跟最多 19 位数字。(点号记法不熟的话,先看字段格式记号怎么读。)线上字节长这样——为了看清,长度前缀和数据之间加了空格,示例用的是合成测试号段:
16 4000001234567899
| 字节 | 含义 |
|---|---|
16 | LLVAR 长度前缀——后面跟 16 位 PAN |
40000012 | IIN / BIN——最多前 8 位,标识发卡机构 |
3456789 | 个人账户标识,由发卡行自己分配 |
9 | Luhn 校验位 |
ISO/IEC 7812 的正式叫法是 IIN(Issuer Identification Number,发卡行识别码);BIN(Bank Identification Number)是行业里更早的习惯叫法。两个词指的是同一段数字——卡组织手册、处理机构文档、BIN 文件里混着用,不是两个东西。
IIN 的第一位数字是 MII(Major Industry Identifier,主要行业标识符),说明发卡机构属于哪个行业:
| MII | 行业 |
|---|---|
1、2 | 航空 |
3 | 旅行与娱乐(Amex、JCB、Diners 都在这) |
4、5 | 银行与金融(Visa、Mastercard) |
6 | 商业与银行/金融(银联在这) |
7 | 石油 |
8 | 医疗、电信 |
9 | 各国标准机构分配 |
在字段速查里,DE 2 就一行:n ..19,主账号。本文说的所有事,都发生在这最多 19 位数字的前 8 位里。
ISO/IEC 7812 最初把 IIN 定为 6 位。2017 年修订版扩到 8 位——6 位号段快分完了——各卡组织要求发卡、收单和处理机构从 2022 年 4 月起支持 8 位 IIN。现在两种长度同时在流通。
没变的是什么:PAN 本身。卡号还是 13~19 位,DE 2 还是 n ..19,线上的字节一个都没动。只按 LLVAR 前缀读 DE 2 的解析器,一行代码都不用改。变的是一条只存在于你业务逻辑里的分界线:这串数字里,哪几位算发卡行标识。
要改的是所有把前缀当键用的地方:
substring(0, 6) 建的内存映射和前缀树。现在号段按不同长度混着发布,存就按 8 位存(或存成显式区间),匹配时最长前缀优先。最经典的翻车方式就是代码还在截 6 位。同一个 6 位前缀下面,现在可能是不同的发卡行、不同的卡产品。举两个合成的例子:40000012… 和 40000013… 的 6 位前缀都是 400000,但可以属于完全不同的机构。整个链路不会报任何错——报文照常解析、路由照常找到、费率照常套上——只是套错了桶:发卡行归属错、费率归类错、卡种标志错、风控画像错。这是一个「静默给出错误答案」的 bug,所以测试很难拦住它。
要抓到这个 bug,基本得拿生产上的真实 DE 2 值来看,因为测试号段几乎不会出现两个发卡行挤在同一个 6 位前缀下面的情况。这些报文在你自己的浏览器里解析,不会传去任何地方——如果规定是真实卡号根本不能碰网站,离线版做的是同一件事,完全不需要网络。
4 是 Visa;51–55 和 2221–2720 是 Mastercard;34/37 是 American Express;62 是银联;35 是 JCB;36/38 是 Diners Club。注意这只能定位到卡组织,定位不到发卡行——发卡行级归属要靠授权的 BIN 文件。= 分隔符前那段)和 DE 45(一磁道)里的 PAN。对不上,要么报文组错了,要么——实践中更常见——上游某处解析器的字段边界已经错位了。DE 2 通常是整条报文里第一个变长字段,这里的长度一错,后面所有字段全部错位。几个能一眼认出来的模式:
16,后面却是 15 位数字加一个 =,通常是磁道数据漏进了 PAN 的位置,或者组包时长度算错了。确认这些问题最快的办法,是拿一条 DE 2 已知正确的报文对着看。下面这条合成授权报文(和报文示例里用的是同一条)DE 2 是 16 + 4000001234567899,DE 35 里带着同一个 PAN:
0100723C448028C08000164000001234567899000000000000005000081009302100012309302108102812541190200334000001234567899=2812101123450000622209000123TERM0001TESTMERCH000001840