当前位置: 首页 > news >正文

ISO8583开发注意事项和心得体会

本文迁移自CSDN的本人账号billzong2012, 考虑精(比)力(较)有(懒)限(惰), 后续不会再在多个平台更新文章. XD


前阵时间(2015年3月), 有幸参与公司的社保类项目. 其中, 本人负责的是银联对接的部分接口, 主要参考协议为ISO8583, 而银联就此提供了<多渠道平台接入接口规范>等接口文档供开发参考. 鉴于本人忘性较大, 悟性也较低, 所以整理记录下来以便后续开发维护, 希望能对后来者也提供些许帮助.

本文全文原创, 可供参考和引用, 仅希望引用者注明出处, 已是不甚感激; 如果能在引用的时候, 再适当添加自己的见解并帮助更多童鞋获取知识, 就是对本人的最大褒奖.
支持开源,谢绝伸手. 尊重作者就是尊重自己.

一. 全局概述
1. <多渠道平台接入接口规范>这个标准规定了各种接入端(主要包括直联多渠道平台的终端, 包括这里主要关注的POS机)与中国银联多渠道平台之间进行联机交易时使用的报文接口, 包括联机交易报文的结构/格式以及报文域.


2. 报文结构说明
报文长度TPDU头拨号监控数据报文头应用数据
2字节十六进制表示的报文长度(不包括本身)5字节33字节12字节交易数据(不定长度)


3. 报文长度
0x2B: 整个报文(不包括TPDU/拨号监控数据/报文头)的长度为: 0x2 * 256 + 0xB = 512 + 11 = 523字节.


4. TPDU头
Transport Protocol Data Unit,传输协议数据单元, 包括ID项(一个字节, 用于标识报文类型), Destination Address项(NII, 两个字节, 标识该报文的目的地址, 一般情况下, 用来标识不同银行的前置机), Originator Addreess(两个字节, 标识该报文从哪一个POS接入端口收到的报文). 一般需要根据实际情况来设置, 这个具体可以在跟收单行洽谈并设置前置机的过程中获取.


5. 拨号监控数据
LRI首标志ANIDNISLRI尾标志
5个字节, 固定取值为: \x4C\x52\x49\x00\x1C8个字节(数字)8个字节(数字)12个字节, 固定取值为: \x58\x00\x09\x49\x00\x06\x00\x00\x00\x22\x00\x30


拨号监控数据又称拨号监控头, 如果TPDU中指明有拨号监控要求, 需要添加, 拨号监控头的报文格式参见标准. 因为本次开发并未使用, 所以无需填入, 暂不加以总结.


6. 报文头
总长度为12字节, 压缩时用BCD码表示为6个字节长度的数值. 相对固定, 具体的设置可以参考银联接口文档, 不多做解释.


7. 重点难点
7.1 TPDU头
TPDU头是报文中容易被忽视的地方, 银联接入测试环境时, 会详细对TPDU头/拨号监控头和报文头进行校验. 如果匹配不上或解析失败, 会直接将该报文丢弃不做任何处理, 难以获取调试信息.


7.2 BCD码的理解.
BCD为二进码十进数或二-十进制代码, 用4位二进制数来表示1位十进制数中的0~9这10个数码; 是一种二进制的数字编码形式, 用二进制编码的十进制代码. 这里采用的是8421编码的BCD码.


例如, 一条十进制数据的字符串"1234567890", 十六进制字节为\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30, 压缩BCD码为\x12\x34\x56\x78\x90. 反之, 从BCD到ASCII再到十进制数字, 逆向处理即可.

二. 报文域属性和数据格式
1. 报文整体描述
ISO8583终端报文一共包含64个报文域, 报文域属性/数据格式和压缩前后的数据长度, 在标准中都有说明.


2. 重点难点
2.1 报文域
报文域指详细的数据填充区间, 在标准中有详细的说明. 在填入了某报文域后, 需要修改报文的位图域对应标志位为1, 以便多终端正确识别和解析该报文. 如: 在2域填入主账号后, 需要修改位图域第二个二进制位为1, 整个位图域结果从0x0000 0000变为0x4000 0000.


2.2 域属性
一些域属性存在补齐说明(如: 左靠/右靠/左补零/右补空格/压缩后字节补齐等), 即规定了指定长度的域或子域, 如果填入内容不足的情况下, 需要根据该域属性的说明, 靠齐/填充补齐足够长度.


2.3 VAR
可变长数据元(VAR), 表示该数据域的长度可变, 一般搭配LL/LLL使用. 如: LLVAR..16, 表示该数据域的可变长度最大为16个字符. 当你填入数据时, 不可超过16个字符, 且需要在前方填入其长度. 如"05Hello".


三. 报文域详解
详细的内容也没啥好说的, 参考标准就是了. 直接就本人理解的重点难点说说吧.


1. 类型域
注意借贷记的区别, 交易报文说明有提及.


2. 域2 主账号
"若终端通过刷卡获取客户磁条卡的第二和第三磁道信息,则不置该域的值。主账号将由多渠道平台从终端请求消息中的第二磁道或第三磁道信息上截取,填入此域,并转发给下一节点。终端可从应答消息中得到主账号信息。
若交易时操作员在终端手输卡号或者通过读IC卡得到卡号,终端无法获取客户磁条卡的第二和第三磁道信息,则需在请求消息中置入该域的值,多渠道平台将以此域为准,并在请求和应答消息中保持不变。"


鉴于本地测试时, 不上送磁条卡号的报文解析失败, 建议填入此可选域; 如果为磁条卡, 并设置了安全控制信息域为不包含主账号信息, 那么返回报文中不带主账号, 需要另行存储处理.


3. 域4 交易金额
不存在小数点, 交易单位由币种决定(如人民币交易时单位为分), 需要将其转换. 这也制约了交易金额的上限. 当然, 在POS机上, 这个金额限度已经完全足够.


4. 域11 系统跟踪号
即俗称的终端流水号, 编号从000000~999999循环使用. 因为多终端平台是根据系统跟踪号和清算日共同决定该终端一笔交易的唯一性, 所以其值在一个清算日内不能重复.


但是, 对于重发的冲正报文, 要求该系统跟踪号的值与原冲正交易一致, 以便多终端平台进行识别.


5. 域14 卡有效期
磁条卡一般无需填入此域, 磁条信息上送后由多平台终端进行处理.


6. 域22 服务店输入方式码
"n3, 3位定长数字字符,压缩时用左靠BCD码表示的2个字节的定长域。"
当我们填入报文后, 内容为\x02\x1, 但是不足一个字节. 需要在后面补0. 即\x02\x10. 该原则在这里都适用.


"本域第1、2位的取值与60.6域(终端读取能力)相关", 这点需要根据自己的实际情况进行填入, 如读取磁条卡/IC卡/非接触式芯片卡, 是否带PIN等.


7. 域23 卡序列号
理解其使用范畴, 主要是IC卡可能存在主卡/副卡的情况, 这个域就是为此而备.


8. 域25 服务点条件码
"服务点条件码主要用于第3域的补充,用来区分交易处理码相同而交易类型不同的交易"
鉴于本人一直用到的都是同一类的交易操作, 所以在代码中进行了"硬编码". 但如果你的业务涉及到大量不同的操作时, 建议使用枚举减少错误的发生. 该原则在这里都适用.


9. 域26 服务点PIN获取码
这个域指定了设备接收PIN的最大长度. 即最大的密码长度.


10. 域32 受理机构标识码
"受理机构标识码。该代理机构应是已被批准入网,能为ATM提供取现服务或为商户提供收单服务的入网机构"


一般是收单行的标识码, 具体在跟收单行洽谈时确认.


11. 域35 第二磁道数据
在读取第二/三磁道时, 段分隔符"="不用担心, 其十六进制(0x3D)转换为BCD(0xD)的时候一样可以还原.


12. 检索参考号
是根据交易时间 + 多渠道业务流水构成检索参考号, 本域一般在冲正交易使用, 并填入原始交易的值.


13. 授权标识应答码
发卡方对交易的授权标识应答码,在一定时间段内保持唯一. 如果原交易没有应答码, 在冲正交易中也不用填入, 否则会引起解析错误. 该原则其他域一样适用.


14. 域48 自定义域
这个域填入时, 需要跟银联工作人员进行沟通, 确保符合你的业务实际场景. 就缴费业务而言: 如果是本省内交易业务, 一般使用旧的填法; 如果是跨省的交易业务, 一般使用新的填法.


因为涉及不少子域, 需要明确子域是否必须填入, 后续是否还有子域. 不需要时, 在该报文域数据最后添加"#"结束标识, 并在报文域最前面添加数据长度(包括结束标识).


15. 域49 交易货币代码
一般使用数字, 如人民币的货币代码156. 银联多终端平台目前仅支持人民币作为交易币种.


16. 域52 个人标识码数据
一般采用ANSI98C的算法, 需要将银行卡号/密码明文一起使用主密钥进行加密, 并通过密码键盘读出. 具体的实现方式, 可以找密码键盘生产厂商了解, 或者参考相关文档.


17. 域53 安全控制信息
磁条卡一般来说, 填写"1600000000000000". 不过, 具体还要根据实际确定. 目前大部分主密钥是32位的, 所以多采用3DES算法. 而磁条卡自身的第二磁道信息携带了主账号信息, 理论上可以不添加2域内容. 但在本地Moss实际测试中, 不上传2域信息会导致报文解析失败, 具体原因未明.


18. 域55 基于PBOC借贷记标准的IC卡数据域
这个是IC卡交易最繁琐也最重要的域, 由于编辑此文档时, 本人也未完成此工作, 所以以下结论属于推断, 仅供参考.


由于此域的子域众多, 但相对固定(每个子域由Tag-Length-Value构成), 所以一般建议是封装一个类来完成该数据域填充.


其中Tag占1~2个字节长度.
一个字节的tag, 如"95";
两个字节的tag, 第一个字节后4个bit为"1111"(即十六进制"F"), 如"9F33", 表示占2个字节.


Length占1~3个字节长度.
其中最左bit位为0, 表示该字段占一个字节. 长度在1~-127字节之间: 如"00011000", 表示24个字节;
如果最左bit位为1, 则由最左bit位的后续7个bit位的十进制取值表示占几个字节: 如"10000010", 表示L字段除该字节外, 后面还有两个字节. 而这后续字节的十进制取值表示子域取值的长度. 如L字段为"1000 0001 1111 1111", 表示该子域取值占255个字节;
L可以取值为"0", 此时, V值不出现.


由于各机构都是采用的EMV2000标准, 所以tag都是一致的, 只是L和V的取值会有所不同; 另外, 不同的标准在不同的时期也会有所调整. 开发时要根据具体的标准进行设置.


这些子域的设置和解析, 要求封装的时候, 需要正确解析Tag. 所以考虑到扩容的可能性, 应该使用枚举将不同的标准作为不同的大类区分, 而后不同tag对应的长度/属性/内容等应该作为配置的方式进行处理, 这样才能在同一标准不同时期调整时进行灵活地设定. 工作量较大, 应采用测试驱动开发以保证正确性和稳定性. 本地Moss通过合理配置应该可以协助完成.


19. 域59 明细查询数据
实际开发过程中, 暂时未使用上该域. 同55域差不多, 一样采用TLV用法. 由于开发中未使用到, 所以不做太多总结.


20. 域60 自定义域
60.2 批次号, 虽然Pos机接入时意义不大, 但在撤销和冲正时很重要. 一般是在签到返回时获取到的, 可以是自己填入, 原样返回的.


60.3 网络管理信息码, 磁条卡一般填入000, IC卡在公钥下载/TC值上送/终端IC卡参数下载/TMS参数下载等操作中要根据实际情况填入.


60.6 终端读取能力, 目前, 第二代社保卡一般要求密码键盘能支持非接触式读取IC卡的能力(即"6").


60.7 基于PBOC借/贷记标准的IC卡条件代码. 基本上就是在程序中添加一个全局的标志变量, 根据实际交易操作情况修改即可, 建议用枚举提高可读性.


21. 域61 原始交易信息域/持卡人身份认证信息域
开发中仅用到冲正/撤销, 填入原始交易信息.


持卡人身份认证信息, 主要是在建立/撤销委托关系, 如代缴等操作中, 目前暂未考虑, 后续可以根据业务需要调整.


22. 域62 交换中心数据
用法一: 多渠道平台向终端约定的新工作密钥, 长度为48/64/80个字节.
组成为:加密的 PIN密钥(8/16/24) + PIN密钥的验证码(4) + 加密的MAC密钥(8) + MAC密钥的验证码(4)
取出后扩展为2倍长度的ASCII字符, 存入工作密钥槽位并进行加密(与8字节即16个0加密, 然后与8位验证码对比是否一致)校验. 如果失败, 可以认定该报文非法, 直接返回不予处理.


用法二: 转入卡信息
主要是转账时需要, 开发中暂未用到.


23. 域63 自定义域
用来存放IC卡相关参数信息. 也是采用TLV格式表示. 开发中暂未用到, 具体请参考接口规范.


24. 域64 报文鉴别码(Message Authentication Code)
使用主密钥将全部报文信息域进行加密计算MAC得到. 在这里, 需要注意的是, 不包括MAC域本身, 但MAC域需要提前填入全0, 生成报文后再进行计算, 以确保MAC的正常校验.


四. 交易发起方报文格式说明
1. 约定
非常重要, 提示如下:
符号含义
M不管该字段是否为空, 它必须在记录中出现
C某条件成立时必须填写的字段
C+某条件成立时增加的字段
C-某条件成立时删除的字段
M+必须增加的字段
O受理方和发卡方自选填写的字段
->由网络中心转发或再编辑的字段
必须与交易发起方发出的消息中对应字段相同的字段
00自定义数据元中须填充0的字段

必须去除的字段


2. 委托类交易
涉及建立/撤销委托, 修改/重置支付密码. 暂未涉及.


3. 查询服务类交易
委托关系查询/银行卡余额查询/账单费用查询/行业信息查询/银行卡账户验证. 暂未涉及.


4. 金融支付类交易
缴费/缴费撤销/退货/消费/消费撤销/消费退货/IC卡脱机消费交易上送/单笔代收/单笔代收撤销/(实时)代付/代付确认


缴费和消费之间的最大差别在于缴费等交易存在48域, 而消费不存在. 另外25域, 缴费等交易为"81", 消费等交易为"82", 主要是借记/贷记的区别. 本人开发中使用的是缴费类操作. 所以基本可以覆盖消费. 另外, 进行撤销交易时, 要求11域填入新的系统跟踪号, 52域/53域因为不用输入PIN, 所以都不用填写.


5. 转账服务类交易
委托终端转账/卡卡转账/圈存交易. 暂未涉及.


6. 冲正交易
受卡方系统跟踪号, 要求跟原交易相同. 应答码, 为请求时交易原因, 要根据实际情况填写, 大部分为98(超时). 某些C字段如不存在时, 不应该填入. IC卡冲正时, 55域要重点填写.


7. 网络管理类交易
终端签到. 60域可不填入, 多终端平台会根据主密钥的长度自动分配DES/3DES算法, 并下发批次号. 建议是自行填入60域, 要求3DES算法.


8. 辅助服务类交易
票据打印/脚本结果通知/基于PBOC借/贷记IC卡TC值上送, IC卡公钥/参数下载查询/请求, IC卡公钥/参数下载, IC卡公钥/参数下载结束. 暂未涉及.


五. 附录一
已上传到局域网ftp服务器上, 有需要的同仁请自行下载. 其他朋友请到网络查找或直接联系银联工作人员.


六. 附录二

测试工具Moss说明
详细的使用说明参考附录一<多渠道离线仿真工具使用手册>/<多渠道离线仿真工具FAQ>.
这里仅提及一些容易忽略或为误导的状况. 


1.笔记本无线接入无法完成通信.
因为无线网卡不支持双工模式, 而Moss要求通信双方必须在双工模式下才能进行. 可以在开发阶段使用127.0.0.1环路地址进行本地通信, 跳过双工模式的制约. 在测试阶段, 则必须使用有线网络接入, 以便跟实际情况接轨.


2.主密钥配置究竟为16位还是32位
具体要根据银行系统的实际情况来定. 目前来说, 银联POS系统很多都采用3DES加密算法, 所以设置32位主密钥更为合理. 这种情况下, 需要将主密钥/终端密钥/PIN密钥都设置为32位.


3. 通信密钥如何存入密码键盘
通信密钥(密文)通过网络传输, 下载到本地. 通过其长度(48/64/80位, 即24/32/40字节), 根据接口文档要求, 判断并截取对应的PIN/PIN CHECK/MAC/MAC CHECK, 转换为BCD码, 调用解密API直接存入对应的密码键盘Work Key槽位(0~7, 其中0-4/1-5/2-6/3-7分为4组, 可灌入不同的主密钥, 对应放PIN Key-Mac Key, 具体情况看代码和注释). 


由于密钥交换在网络传输有截取修改风险, 所以PIN CHECK/MAC CHECK是必须做的. 根据PIN Key的密钥长度(16/32位), 将”0000000000000000”(16位BCD码)与存入键盘PIN Key(明文, 不可见)进行DES/3DES加密, 跟PIN CHECK的前8位校验, 完全匹配, 则证明PIN Key合法; Mac Key原理类同, 由于Mac Key仅16位, 所以直接采用DES加密校验即可.


4.通信报文MAC校验失败
这个问题在”通信密钥如何存入密码键盘”中已经有所描述. 主要原因可能有以下几个:
1)Moss主密钥长度设置跟实际灌入密钥长度不匹配.
2)Moss主密钥明文与测试用密码键盘灌入主密钥不符.
3)加密和读取的Work Key槽位不匹配.
4)加密算法有问题(这个可能性很小, DES算法是通用的).
5)没有将ASC码转换为BCD码, 就存入密码键盘加密(密钥存储采用的是BCD码方式, 所以要加密的内容也得转化为BCD码才能处理).


5.Moss业务功能都有哪些
基本上银联接口相关的业务都覆盖上了. 我们需要涉及的业务配置中包括:
1)终端/渠道/测试用报文/案例的封装/修改.
2)主密钥/商户信息/卡信息/用户号码配置.
3)磁条卡/IC卡等子域的详细配置.
4)RSA密钥/动态密码配置.
5)生成对账文件/测试报告.


暂时就写这么多, 如果有需要补充或修改的, 可以直接处理并加以记录. 欢迎各位莅临指正. 


相关文章:

  • iOS 相册和网络图片的存取
  • beanshell获取响应结果数据
  • XYGame-网络同步3-防作弊
  • 红黑树 - C++代码实现
  • 自己定义iOS上双击Home键图切换
  • 数据预测的步骤
  • Elasticsearch学习笔记-04.2删除文档
  • 磁珠与电感的区别,看了就灰常明白了
  • Spring Quartz 集群动态创建任务
  • 考试题解集合
  • sublime Text3 插件
  • Http1.0和Http1.1的主要区别
  • DOM操作表格
  • BZOJ1486 最小圈 [分数规划+负权环]
  • 医疗成像领域引进人工智能: AI 帮助医生进行成像分析
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • CEF与代理
  • Docker 笔记(2):Dockerfile
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • JSONP原理
  • js继承的实现方法
  • Theano - 导数
  • 从setTimeout-setInterval看JS线程
  • 利用DataURL技术在网页上显示图片
  • 排序(1):冒泡排序
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 如何选择开源的机器学习框架?
  • 入口文件开始,分析Vue源码实现
  • 实战|智能家居行业移动应用性能分析
  • 说说动画卡顿的解决方案
  • 【云吞铺子】性能抖动剖析(二)
  • (bean配置类的注解开发)学习Spring的第十三天
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (十六)Flask之蓝图
  • (一) storm的集群安装与配置
  • (一)Linux+Windows下安装ffmpeg
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)Windows2003安全设置/维护
  • (转载)(官方)UE4--图像编程----着色器开发
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • .Family_物联网
  • .Mobi域名介绍
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • /var/log/cvslog 太大
  • ?
  • @Responsebody与@RequestBody
  • []T 还是 []*T, 这是一个问题
  • [20161214]如何确定dbid.txt
  • [acwing周赛复盘] 第 69 场周赛20220917
  • [APUE]进程关系(下)
  • [BZOJ 3680]吊打XXX(模拟退火)
  • [C puzzle book] types
  • [EULAR文摘] 利用蛋白组学技术开发一项蛋白评分用于预测TNFi疗效
  • [HNOI2006]鬼谷子的钱袋