它是一份关于银行卡交易报文的国际标准。它规定的是「字节该怎么排」:两个从没打过交道的系统照它排字节,就能对同一条支付请求的含义达成一致。网络、接口、产品形态都不在它的范围里。1987 版至今仍在跑:联机卡授权大多用它,Mastercard IPM 这类清算格式用 1993 版。
现行版本是 ISO 8583:2023,它把 2003 年分三册出的内容合回了一份文档。但实际工作里你遇到的多得多的是老版本:联机卡授权大多还跑 1987 版,而 Mastercard IPM 这类清算格式是 1993 版的。版本之间的差别在于有哪些域、某些域多宽,所以版本不是无关紧要的细节:同样的字节在两个版本下可以解出不同结果。MTI 的第一位就告诉你这是哪一版。
几乎没人跑纯粹的 ISO 8583。Visa、Mastercard、各国本地转接机构都有自己的一套:域号相同,但私有域各填各的、各自还有额外的码值,有时字符编码也不一样。标准给的是信封,卡组织的规范才告诉你信里写了什么。两者说法不一致时,以你手上那份接口规范为准。
从左往右分三段读。
每一位各管一件事:
| 位置 | 含义 | 取值举例 |
|---|---|---|
第 1 位 | 版本 | 0 = 1987、1 = 1993、2 = 2003 |
第 2 位 | 报文类别 | 1 授权、2 金融、3 文件操作、4 冲正 / 拒付、5 对账、6 管理、7 费用收取、8 网络管理 |
第 3 位 | 报文功能 | 0 请求、1 请求响应、2 通知(advice)、3 通知响应、4 单向通知 |
第 4 位 | 报文来源 | 0 收单方、2 发卡行、4 其他,以及 1/3/5 同上但是重发 |
所以 0100 是 1987 版、收单方发出的授权请求,0110 是它的响应。0400 是冲正请求,0800 是签到、心跳这类网络管理报文。把四位分开读,比背一张 MTI 清单快得多。
上面这张表是 1987 和 1993 版的。2003 版把类别体系改过——冲正和拒付拆成了两个独立类别,还新增了别的——所以别把这张表套到 2003 版的链路上。完整的表在 MTI 解码 和 MTI 码值清单。
位图是 64 个二进制位,通常写成 16 个十六进制字符。第 n 位是 1,就表示第 n 个数据域出现了,按域号从小到大排列;没出现的域就是真的不在报文里,不补位、不留占位符。这就是这个格式的诀窍:不需要额外的结构说明也能很紧凑,因为位图本身就是结构说明。
第 1 位是特殊的:它不表示 DE1,而表示后面还跟着第二个位图,把范围扩到 DE128。第 1 位是 0 的话,报文到 DE64 就结束,位图也只有 16 个十六进制字符。
还可能有第三个位图。Visa 现行规范定义了覆盖 130–192 域的第三位图,它由第二个位图的第一位——也就是第 65 位来指示,机制和第 1 位指示第二位图完全一样;没有第三位图时那一位必须是 0。所以第 65 位也不是数据域,它同样只是个开关。按「到 DE128 结束」写的解析器,在用到第三位图的链路上会从第 130 域起全部读错。
位图相关的问题大多出自两个地方:从 0 开始数位,以及忘了位图可能是 8 个原始字节而不是 16 个十六进制字符。两种情况都会让后面的域整体错开一位。
每个域要么是定长,要么自己带长度前缀:
| 类型 | 前缀 | 怎么读 |
|---|---|---|
FIX | 没有 | 取正好声明的那么多个字符。DE4 永远是 12 位。 |
LLVAR | 2 位 | 先读两位当长度,再取那么多个字符。那两位不属于值本身。 |
LLLVAR | 3 位 | 同理,长度占三位。用在可能超过 99 个字符的域上,比如 DE55。 |
声明的长度算的是值的字符数,而不总是字节数:Hex/BCD 下两个数字压进一个字节,而二进制域的长度按字节还是按位算,取决于具体规范。解析器出现「一个域一个域地往后错」时,先查长度的单位。
下面是一条完整的授权请求,用的是测试卡号和占位终端号,不含任何真实持卡人数据。
010072200000008080001641111111111111110000000000000010000821143000123456TERM0001702
从左往右拆开:
| 字节 | 域 | 读出来是什么 |
|---|---|---|
0100 | MTI | 1987 版、授权、请求、来自收单方 |
7220000000808000 | 位图 | 第 2、3、4、7、11、41、49 位是 1——这七个域按此顺序跟在后面。第 1 位是 0,所以没有第二个位图。 |
16 4111111111111111 | DE2 卡号 | LLVAR:16 是长度,后面 16 位才是卡号 |
000000 | DE3 处理码 | 消费,付方和收方账户都未指定 |
000000001000 | DE4 金额 | 1000 个最小货币单位。结合 DE49 = 702(新加坡元,两位小数)就是 10.00 新元 |
0821143000 | DE7 传输时间 | 8 月 21 日 14:30:00 GMT。域里不带年份。 |
123456 | DE11 系统跟踪号 | 收单方当天用的流水号 |
TERM0001 | DE41 终端号 | 只在这个商户内部唯一,不是全局唯一 |
702 | DE49 币种 | 新加坡元的 ISO 4217 数字码 |
注意:DE49 没读之前,DE4 是没有含义的。先币种、后金额这个顺序,是金额差出一百倍最常见的来源。
上面这条报文可以直接粘进首页的解析器,看它逐域拆开。
1987 版寻址 128 个数据域;带第三位图时范围到 192。但实际工作中的问题几乎都集中在这十来个上:
| 域 | 名称 | 为什么总被问到 |
|---|---|---|
DE2 | 卡号 | 前 6–8 位决定路由给哪家发卡行;日志里一律掩码。 |
DE3 | 处理码 | 是消费还是取现,决定计价、额度和利息。 |
DE4 | 交易金额 | 最小货币单位、无小数点。不看 DE49 就没有含义。 |
DE11 | 系统跟踪号 | 只在当天、只在该收单方范围内唯一,会回绕重用。 |
DE22 | 输入方式 | 卡是怎么读进来的,牵涉责任划分。 |
DE37 | 检索参考号 | 整个交易生命周期不变,对账时实际可用的关联键。 |
DE39 | 响应码 | 00 是成功,其余都是原因。 |
DE41/DE42 | 终端号 / 商户号 | 交易发生在哪,也是持卡人发起争议时针对的对象。 |
DE49 | 币种 | 决定 DE4 的小数位。要先读它。 |
DE55 | 芯片数据 | TLV 格式的芯片数据——芯片交易被拒的原因就在这里面。 |
域字典里有全部 128 个域的长度、格式和说明。
ISO 8583 的日常工作里,查码值含义的时间通常多过解析报文。值得存下来的几张表:
有四个地方,标准到此为止、接下来得看别人的文档。每一个都让人花过一整周。
在用。卡授权链路目前仍以 8583 为主;ISO 20022 在账户间转账和实时支付上增长很快,也有面向卡交易的消息集(ATICA),两者现在是并存关系。
8583 是按位置排布的紧凑字节,是为 1980 年代的线路设计的;20022 是 XML 或 JSON,数据模型丰富得多。8583 用少得多的字节表达少一些的信息,这正是它能在对时延敏感的卡组织网络上活下来的原因。它们是两种格式做部分重叠的事,不是同一个东西的两个版本。完整对比见 ISO 8583 与 ISO 20022:卡域到底变了什么。
基础结构——MTI、位图、域号、长度——不需要,这部分公开资料很充分,本站也讲了。但有一点要注意:公开流传的字段表多是第三方重建的,而且普遍不写自己描述的是哪一版,偏偏有几个域的宽度是跟版本挂钩的(DE22 就是典型)。凡是长度或名称跟版本有关的地方,以你这条链路实际跑的那一版为准。但你的报文里出现的那些私有域和额外码值,得拿到你所在卡组织或处理机构的规范。那部分不公开,也推不出来。
基本上都是长度单位或者编码问题:二进制域的长度按字节给、却当成字符读;Hex/BCD 的域被当成 ASCII 读;或者位图发的是 8 个原始字节、却按 16 个十六进制字符读。找到最后一个解对的域,查它的长度规则。