PHP处理iso8583报文

前文

前段时间对接一个第三方公司的接口,其他部分或简单、或麻烦,总之没有花很多功夫都完成了。最后在着手交易接口时,犯了难。报文格式区别另外接口,需使用iso8583报文,咋一看文档,很让人懵逼,又是bcd,又是ascii,两个字节压缩成一个字节。
用了将近一周时间慢慢懂了报文规则,开始准备写代码时又有了麻烦事。可能查资料的姿势不对,没找到PHP的DEMO,基本上都是Java实现。PHP又没有字节操作概念,当时迫于无奈都准备申请这块用Java来做。最后感谢我的小伙伴,讨论帮我打开了思路,具体内容记不太清了。主要一个点是,数据传输是流的方式,和图片流又是不一样的。继而想到能不能试试对数据进行压缩,又想着数据传输无关语言,那么PHP没有理由实现不了。鼓捣到最后,虽然个别片段兼容性没那么好,终于是通了,记录下实现的代码。

我的语言真是太苍白了。


iso8583介绍

先来介绍下iso8583报文部分,网上介绍的很详细,此处仅针对项目做简单说明。
报文由三部分组成。

  1. 第一部分消息类型,长度为4,比如交易请求是0200,交易响应是0210,,签到请求是0800,签到响应是0810,直接拼接字符串作为首部。
  2. 第二部分位图定义,用于预设可能存在的数据。有两种不同的位图,若第一位值为1,说明使用扩展位图(128个域数据);若为0,则仅使用64个域的位图。64位位图组合内容如:01001100……,按每四位转换成十六进制格式,拼装到字符串中。
  3. 第三部分拼装域规定格式的数据报文
    域格式有以下几种类型
    BCD:处理上拼接即可
    BIN:二进制数据
    ASCII:需对字符转ASCII十六进制
    LLVAR:非定长域,需占位两位来记录长度
    LLLVAR:非定长域,需占位三位来记录长度
    要注意的是,报文无处不存在补0操作,三位长度需用四位填充,而且不同的域填充0的位置有的在左侧,有的在右侧。
    每种消息类型,位图内各个域的格式都已规定好。

以交易请求为例,
第3域是BCD、长度6的固定字符串000000,则直接拼接到字符串尾部。
第22域BCD、长度3的字符串,如022,左侧拼接0,最后拼接0051到字符串尾部。
第48域ASCII,长度LLVAR的字符串,如TP,转换后5450,最后拼接025450到字符串尾部。

如何发送

经过非常简单的说明,数据报文终于拼接成了一个字符串,且已根据BCD、ASCII等特殊处理。剩下最重要的就是如何发送报文了。
重点强调:pack()函数

pack — 将数据打包成二进制字符串
H 十六进制字符串,高位在前(涉及到压缩的方式)

$in = pack( "H*", $in);
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, $in);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
     'Content-Type:application/octet-stream',
     'Content-Length: ' . strlen($in))
);
$out = curl_exec($ch);

经过pack(“H*”)的压缩处理,再在请求中,设置Content-Type:application/octet-stream头部,实现数据转流+传输功能。


总结

iso8583内容能讲的有很多,研究这玩意儿着实花了好大功能,只是总结出来就是少了些味道,文字匮乏,网上写的好的文章很多,这里我就不乱说明了。仅贴出自己的代码吧,后续自己使用也可对需要的人提供一丝思路。
代码地址:PHP-iso8583

你可能感兴趣的:(PHP)