51,余额不足;另一种结局是部分批准(Partial Approval):发卡行批准 30.00,在响应里明说,剩下的 20.00 留给终端用别的方式收。这在礼品卡、预付卡上是家常便饭 —— 但凡系统里有一处默认「响应的 DE 4 一定等于请求的 DE 4」,它就会悄悄坏在那里。
普通授权是全有或全无:发卡行要么按 DE 4 全额批准,要么整笔拒绝。部分批准是第三种结局:账户能覆盖一部分但不够全额时,发卡行按余额能给的上限批准,并把实际批准的数字告诉终端。
最典型的用户,是那些没人记得住余额的卡:礼品卡(谁记得卡里还剩 7.42?)、预付卡、快见底的借记卡。对商户来说,这把一笔注定失败的交易变成了「先收下大头」—— 30.00 当场入账,差的 20.00 收现金或刷另一张卡。正因为如此,卡组织在预付产品上对常见商户类别大力推动这项能力的受理。
报文层面没有任何新鲜东西:没有新的报文类型,没有特殊 MTI,还是你熟悉的 0100/0110 授权对(或 0200/0210 金融交易对),整个故事由三个字段讲完:
发卡行绝不会对一台没准备好的终端突然来一手部分批准。只有当授权请求里先声明了支持 —— 终端或受理方置起部分批准支持标识 —— 它才会这样应答。不带标识,同一张卡在同一家店,得到的就是一个普普通通的 DE 39 = 51 余额不足拒绝:明明卡里躺着 30.00,这单还是死了。(有些发卡行会在拒绝响应的 DE 54 里附上可用余额,但那只是告知,什么都没批。)
这个支持标识放在哪?这恰好是 ISO 8583 通用层面不管的部分:各个网络在自己的附加数据域(DE 48 / DE 60 一族)里定义了各自的子域,具体标签和位置以你的接口规范为准。通用的只有这条契约:请求里的这面旗,才能解锁响应里的响应码 10。
置这面旗是承诺,不是摆设。它意味着 POS 侧必须做到三件事:向收银员和客户展示、打印的是批准金额而不是请求金额;能走「一单多付」(split tender)流程去收差额;客户放弃时能把授权冲掉。三件有一件做不到,就别置这个标识。
先看全景 —— 同一笔消费的请求和响应并排放在一起:
三个字段,各记一件事:
10,不是 00。在 1987 系接口通用的两位响应码表里,10 就是「部分批准」—— 可以在 DE39 响应码查询里核对。任何写成 if (de39 == "00") 的批准判断,都会把这笔交易送进拒绝分支 —— 而发卡行那边 30.00 的占用已经落下了。客户看到「交易失败」,钱却被冻住,POS 以为什么都没批成,自然也不会发冲正。它的近亲是 87(只批消费金额、不给返现)—— 同属「批了,但不是你要的那样」一族。000000005000,回来 000000003000。凡是拿响应 DE 4 和原请求做相等校验的逻辑,都会把一条完全健康的响应当成报文损坏;凡是拿请求金额去记账、清算的环节,记的都是从未被授权过的钱。完成交易和清算都必须按 30.00 走 —— 清 50.00,等着输一场拒付。0002840C000000000000:批准之后可用余额正好 0.00 —— 卡里有的全给你了。这串字符怎么读,是下一节的事。想亲手拆一遍?把下面两条 ASCII 报文依次贴进解析工具,先请求后响应,盯着 DE 4 在两条报文之间变化:
01007020000000808000164000001234567890000000000000005000123456TERM0001840
0110302000000680840000000000000000300012345665432110TERM00018400200002840C000000000000
DE 54 是变长域(LLL,最长 120 字符),内容是 1 到 6 组定长 20 字符,首尾相接、没有任何分隔符。所以它的长度必然是 20 的倍数,唯一正确的解析方式是按下标算:拿 LLL 长度除以 20,逐组切开。每组的读法:
| 位置 | 子域 | 含义 |
|---|---|---|
1–2 | 账户类型 | 和 DE 3 处理码第 3–4 位同一套代码:00 默认、10 储蓄、20 支票、30 信用 |
3–4 | 金额类型 | 这笔金额是什么。实际最常遇到的两个:01 账面余额、02 可用余额。完整代码表以接口规范为准 |
5–7 | 货币代码 | ISO 4217 数字码 —— 可在货币码与小数位查询里核对。注意按组读:它不必等于 DE 49,比如发卡行按持卡人账单币种报余额时 |
8 | 借贷标志 | C 贷记(正数)、D 借记(负数,比如透支) |
9–20 | 金额 | 12 位数字,右对齐补零,按该组币种的最小货币单位计 —— 和 DE 4 一个约定(见金额为什么没有小数点) |
套在我们响应里的值上:
0002840C000000000000
│ │ │ │└───────────┘
│ │ │ │ 金额:000000000000 → 0.00
│ │ │ └ 借贷标志:C(正数)
│ │ └ 货币:840 = 美元,2 位小数
│ └ 金额类型:02 = 可用余额
└ 账户类型:00 = 默认账户
连起来读就是:「默认账户的可用余额现在是 USD 0.00」。两组的值不过是两段背靠背 —— 40 个字符,比如账面余额加可用余额:
0001840C000000003000 ← 账面余额 30.00
0002840C000000003000 ← 可用余额 30.00
(报文里是连成一串的 40 字符,没有分隔)
同一副骨架、换个金额类型,也正是 ATM 余额查询响应、带余额的拒绝响应里 DE 54 的长相。学会切一次,全都能读。
部分批准天生留了个尾巴,两件收尾的事都归终端:
10 应答,把 DE 4 改写成批准金额,并在 DE 54 里按 20 字符一组报告剩余余额。响应里的 DE 4 才是真正存在的钱,请求里的 DE 4 只是你的愿望。差额换个方式收;这单要是黄了,把占用冲掉,别让它烂在客户账上。