82)、TVR(标签 95)、TSI(标签 9B)。三个都是十六进制、都按位定义、看上去都在讲「这笔交易怎么样」,所以经常被混为一谈。其实它们各答一个问题:卡片能做什么、终端看到了什么、这笔交易实际做了什么。
把三者分开最省事的办法,是记住谁写的、什么时候写的:
| 标签 | 名称 | 长度 | 谁写 | 什么时候写、回答什么 |
|---|---|---|---|---|
82 | 应用交互特征(AIP) | 2 字节 | 卡片 | 事前,随 GPO 响应返回 —— 「我支持哪些功能」 |
95 | 终端验证结果(TVR) | 5 字节 | 终端 | 事中,逐位记录 —— 「我观察到了哪些异常」 |
9B | 交易状态信息(TSI) | 2 字节 | 终端 | 事后,处理结束时定格 —— 「实际执行了哪些功能」 |
一句话框架:能力 → 过程 → 结果。也可以记成:一份承诺、一本异常台账、一张完成清单。
为了不停留在抽象层面,本文用同一笔交易的三个取值贯穿到底 —— 一笔转联机后批准的芯片消费:
3D000400048000F800AIP 在 GET PROCESSING OPTIONS 的响应里由卡片返回,此时终端还什么都没检查。它基本上是静态的个人化数据:发卡行在制卡时就定好了这个应用支持哪些功能,每一笔交易看到的声明都一样。有意义的位集中在字节 1:
| 位置 | 含义 |
|---|---|
字节 1 · b8 | RFU 保留 |
字节 1 · b7 | 支持 SDA |
字节 1 · b6 | 支持 DDA |
字节 1 · b5 | 支持持卡人验证 |
字节 1 · b4 | 需要执行终端风险管理 |
字节 1 · b3 | 支持发卡行认证 |
字节 1 · b2 | RFU 保留(部分非接内核借用作设备端 CVM) |
字节 1 · b1 | 支持 CDA |
字节 2 在接触式 EMV 里整体保留;一些非接内核会借用它的位,所以挥卡交易偶尔能见到第二字节非零。
例子里的 3D00,字节 1 是 0011 1101:支持 DDA、支持持卡人验证、要求终端风险管理、支持发卡行认证、支持 CDA —— 不支持 SDA。把它丢进 AIP 解析工具,得到的就是这份清单。
更要紧的是 AIP 不记什么:它不含任何关于「这一笔」的信息。CDA 后来当场失败的交易,和 CDA 一路顺利的交易,AIP 一模一样。AIP 是菜单,不是这顿饭。
交易开始时 TVR 是五个字节的全零。终端依次做脱机数据认证、应用检查、持卡人验证、风险管理、处理发卡行应答,每遇到一个异常情况就把对应的位置起。它记录的是观察,不是决策——某个观察要不要导致拒绝,是之后拿 TVR 和终端/发卡行行为码比对才定的。五个字节的完整位定义见 TVR 各位含义。
例子里的 TVR 是 0400048000。放进 TVR 解析工具,亮起来的是三个位:
这个组合很有代表性:一个真问题、一个中性记录、一个例行的风控触发。把 TVR 当成「事故清单」逐条恐慌,是最常见的误读方式。
TSI 是三者里最小的:两个字节,只有六个位有定义。某项功能一经执行,终端就把对应位置起,所以处理结束时 TSI 就是这笔交易的完成清单:
| 位置 | 含义 |
|---|---|
字节 1 · b8 | 已执行脱机数据认证 |
字节 1 · b7 | 已执行持卡人验证 |
字节 1 · b6 | 已执行卡片风险管理 |
字节 1 · b5 | 已执行发卡行认证 |
字节 1 · b4 | 已执行终端风险管理 |
字节 1 · b3 | 已执行脚本处理 |
字节 1 · b2–b1 | RFU 保留 |
字节 2 | RFU 保留 —— 应为 00 |
例子里的 F800,字节 1 是 1111 1000:脱机数据认证、持卡人验证、卡片风险管理、发卡行认证、终端风险管理都执行了;没有收到发卡行脚本。TSI 解析工具读出来就是这几行。
所有人都栽过的一个坑:「已执行」不等于「通过了」。TSI 的 b8 只说脱机数据认证做过,做得怎么样它一个字不提——成败写在 TVR 里。这正是这两个标签必须成对读的原因。
把三个值排在一起,这笔交易的故事就用三种口吻各讲了一遍:
排查时先翻哪个标签,取决于手头的问题:
再记两个值得背下来的错位模式:AIP 置位而 TSI 没置,是支持但被跳过(该问终端为什么绕开);TSI 置位加上 TVR 的失败位,是执行了但失败(该问为什么失败)。顺着 DE55 往下翻碰到别的标签,查 EMV 标签查询 就够了。
82 是卡片的承诺,标签 95 是终端的异常台账,标签 9B 是完成清单。能力 → 过程 → 结果。TSI 告诉你功能跑过了,跑得怎么样只有 TVR 知道。