8583报文解析
来源:互联网 发布:sql if两个判断 编辑:程序博客网 时间:2024/05/22 03:14
8583报文解析
By it_zujun(JK Landy)
一个人的战争(http://blog.csdn.net/u013634862/)
在金融行业中数据的传递、安全尤为重要,本文根据8583协议对任意交易进行了报文的一个解析,报文解析设计逻辑仅供参考。首先需要分析报文的组成:报文:报文长度(2) + TPDU(5) + 报文头(6) + 应用数据(.....)应用数据包含各个域的值,不同交易由不同的域组成,其中有的域是固定长度,有的域是可变长度域域的组成:长度固定域:根据银联规范,其长度固定可变域:长度值+数据值交易的分布由Bitmap标识,因此我们可以更具一个完整的域表来维护我们的报文解析,就思路如下。首先我们将我们的接收交易数据存放到一个数组中,由于报文长度、TPDU、报文头的长度固定,我们直接可以直接定位到数据域中,直接获取Bitmap值,我们用一个结构体来指定各个域的位置和长度就可以任意提取我们的数据值了。/报文域的属性描述。
struct data_config { unsigned int seat; //域的启始位置 unsigned int len; //域的长度};
通过统计阅读银联文档,统计每个域的属性(定长、长度可变、压缩BCD码、ASSIC码等)。
unsigned char Area[65] = { 0, 100, 53, 3, 6, 100, 100, 100, 100, // 1-8 100,100, 3, 3, 2, 2, 2, 100, // 9-16 100,100, 100,100,100, 2, 2, 100, // 17-24mZ 1, 1, 100,100,100, 100, 100, 53, // 25-32 100,100, 53, 63, 12, 6, 2, 100, // 33-40 8, 15, 100,52, 100, 100, 100, 63, // 41-48 3, 100, 100,8, 8, 62, 63, 100, // 49-56 100,62, 100,63, 63, 62, 62, 8}; // 57-64
上图为银联规范中的各个域的长度值,为了方便我们做了一下约定,其中数组的位置代表每一个域,定义了65个char,我们采取Area[1]—Area[64]
100:银联中还没有定义的域1-30:固定长度域,值代表域的长度值,如Area[41]的值为8,则41域为定长为8个字节的域52:代表可变域,1个字节代表长度,数据域为ASSIC码存放53:代表可变域,1个字节代表长度,数据域为BCD码存放62:代表可变域,2个字节代表长度,数据域为ASSIC码存放, 如:58域63:代表可变域,2个字节代表长度,数据域为BCD码存放, 如60域通过解析Bitmap将64个data_config完整填写,就能进行随时调用各个域的值。struct data_config config[65]; //64个域的属性数组下面是我写的代码:
/*************************************************************************> File Name: data_8583> Author: it_zujun> Mail: > Created Time: 2015年09月04日 星期五 09时22分08秒 ************************************************************************/#include<stdio.h>struct data_config { unsigned int seat; unsigned int len;};int main(int argc, char *argv[]){ //报文长度查阅表 //100 表示未定有 //<20的代表定长 //52 其中5代表长度可变域中1个字节代表长度,2代表数据域为ASSIC码,3代表BCD压缩数据 //63 其中6代表长度可变域中2个字节代表长度,<span style="font-family: Arial, Helvetica, sans-serif;">2代表数据域为ASSIC码,3代表BCD压缩数据</span> //............................ unsigned char Area[65] = { 0, 100, 53, 3, 6, 100, 100, 100, 100, // 1-8 100,100, 3, 3, 2, 2, 2, 100, // 9-16 100,100, 100,100,100, 2, 2, 100, // 17-24mZ 1, 1, 100,100,100, 100, 100, 53, // 25-32 100,100, 53, 63, 12, 6, 2, 100, // 33-40 8, 15, 100,52, 100, 100, 100, 63, // 41-48 3, 100, 100,8, 8, 62, 63, 100, // 49-56 100,62, 100,63, 63, 62, 62, 8}; // 57-64 unsigned data_8583[1024] = { 0x01, 0x1A, 0x60, 0x00, 0x00, 0x00, 0x02, 0x60, 0x31, 0x00, //1 0x31, 0x10, 0x04, 0x02, 0x10, 0x70, 0x3E, 0x00, 0xC1, 0x0E, //2 0xD0, 0x8C, 0x17, 0x19, 0x62, 0x28, 0x48, 0x02, 0x11, 0x39, //3 0x79, 0x24, 0x91, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x29, 0x09, 0x39, 0x29, 0x09, 0x04, 0x49, 0x12, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x30, 0x30, 0x00 ,0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31, 0x35, 0x36, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x39, 0x30, 0x30, 0x32, 0x31, 0x35, 0x36, 0x43, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x35, 0x36, 0x33, 0x32, 0x31, 0x35, 0x00, 0x14, 0x22, 0x00, 0x00, 0x01, 0x00, 0x06, 0x01, 0x00, 0x72, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x32, 0x35, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x33, 0x43, 0x55, 0x50, 0x41, 0x4E, 0xB8, 0xF1, 0xCD, 0xDF, 0xC0, 0xAD, 0xD1, 0xA1, 0x41, 0x42, 0xD2, 0xF8, 0xC1, 0xAA, 0xD4, 0xDA, 0xCF, 0xDF, 0xD6, 0xA7, 0xB8, 0xB6, 0xCD, 0xDF, 0xC0, 0xAD, 0xD1, 0xA1, 0x45, 0x31, 0x33, 0x35, //28 0x35, 0x32, 0x41, 0x32 //29 }; unsigned char i, j, seek_i, num, check, count; struct data_config tab; unsigned char location_data[8]; struct data_config config[65]; unsigned int temp; tab.seat = 10; tab.len = 11; int all_size; // the size of 8583_data all_size = data_8583[0]*256 + data_8583[1]; printf("the sizeof 8583 = %d\n",all_size); printf("TPDU:"); for (i=0; i<5; i++) { printf("%02x",data_8583[2+i]); } printf("\nhead:"); for (i=0; i<6; i++) { printf("%02x",data_8583[i+7]); } printf("\n"); printf("tpye:"); for (i=0; i<2; i++) { printf("%02x",data_8583[i+13]); } printf("\nlocation data:"); for (i=0; i<8; i++) { location_data[i] = data_8583[15+i]; printf("%02x",location_data[i]); } printf("\n"); for (i=0; i<64; i++) { config[i].seat = 0; config[i].len = 0; } temp = 23; printf("the first data temp = %02x\n",data_8583[temp]); for (i=0; i<8; i++) { seek_i = location_data[i]; for (j=0; j<8; j++) { check = 0x00; check = seek_i & 0x80; if(check == 0x80) { if (Area[i*8+j+1] == 100) { continue; } else if (Area[i*8+j+1] == 52 || Area[i*8+j+1] == 53) { if(Area[i*8+j+1] == 52) { count = 0; count = (data_8583[temp]>>4)*10 + (data_8583[temp]&0x0f); config[i*8+j+1].seat = temp; config[i*8+j+1].len = count+1; temp = temp + count + 1; } if(Area[i*8+j+1] == 53) { count = 0; count = ( (data_8583[temp]>>4)*10 + (data_8583[temp] & 0x0f) + 1) / 2; config[i*8+j+1].seat = temp; config[i*8+j+1].len = count+1; temp = temp + count + 1; } } else if(Area[i*8+j+1] == 62 || Area[8*i+j+1] == 63) { if(Area[i*8+j+1] == 62) { count = 0; count = (data_8583[temp]&0x0f)*100 + (data_8583[temp+1]>>4)*10 + (data_8583[temp+1]&0x0f); config[i*8+j+1].seat = temp; config[i*8+j+1].len = count+2; temp = temp + count +2; } if(Area[i*8+j+1] == 63) { count = 0; count = ( (data_8583[temp]&0x0f)*100 + (data_8583[temp+1]>>4)*10 + (data_8583[temp+1]&0x0f) ) / 2; config[i*8+j+1].seat = temp; config[i*8+j+1].len = count + 2; temp = temp + count + 2; } } else { count = Area[i*8+j+1]; config[i*8+j+1].len = count; config[i*8+j+1].seat = temp; temp = temp + count; } } seek_i = seek_i<<1; } } for (i=1; i<65; i++) { if(config[i].len != 0) { printf("%d:",i); for (j=0; j<config[i].len; j++) { printf(" %02x", data_8583[config[i].seat + j] ); } printf("\n"); } } return;} //
为了达到移植通用性,报文解析做了一下修改:
/*参数介绍:struct data_config* config :报文指针unsigned char* location_data: bitmap指针char* Area: 报文域属性表调用 eg: data_8583_config(config_8583, location_data_8583, Area_8583);*/void data_8583_config(struct data_config* config, unsigned char* location_data, char* Area){unsigned char i, j, count, seek_i, check; int all_size; // the size of 8583_dataunsigned int temp; // all_size = data_8583[0]*256 + data_8583[1]; printf("the sizeof 8583 = %d\n",all_size); printf("TPDU:"); for (i=0; i<5; i++) { printf("%02x",data_8583[2+i]); } printf("\nhead:"); for (i=0; i<6; i++) { printf("%02x",data_8583[i+7]); } printf("\n"); printf("tpye:"); for (i=0; i<2; i++) { printf("%02x",data_8583[i+13]); } printf("\nlocation data:"); for (i=0; i<8; i++) { location_data[i] = data_8583[15+i]; printf("%02x",location_data[i]); } printf("\n"); for (i=0; i<64; i++) { config[i].seat = 0; config[i].len = 0; } temp = 23; printf("the first data temp = %02x\n",data_8583[temp]); for (i=0; i<8; i++) { seek_i = location_data[i]; for (j=0; j<8; j++) { check = 0x00; check = seek_i & 0x80; if(check == 0x80) { if (Area[i*8+j+1] == 100) { continue; } else if (Area[i*8+j+1] == 52 || Area[i*8+j+1] == 53) { if(Area[i*8+j+1] == 52) { count = 0; count = (data_8583[temp]>>4)*10 + (data_8583[temp]&0x0f); config[i*8+j+1].seat = temp; config[i*8+j+1].len = count+1; temp = temp + count + 1; } if(Area[i*8+j+1] == 53) { count = 0; count = ( (data_8583[temp]>>4)*10 + (data_8583[temp] & 0x0f) + 1) / 2; config[i*8+j+1].seat = temp; config[i*8+j+1].len = count+1; temp = temp + count + 1; } } else if(Area[i*8+j+1] == 62 || Area[8*i+j+1] == 63) { if(Area[i*8+j+1] == 62) { count = 0; count = (data_8583[temp]&0x0f)*100 + (data_8583[temp+1]>>4)*10 + (data_8583[temp+1]&0x0f); config[i*8+j+1].seat = temp; config[i*8+j+1].len = count+2; temp = temp + count +2; } if(Area[i*8+j+1] == 63) { count = 0; count = ( (data_8583[temp]&0x0f)*100 + (data_8583[temp+1]>>4)*10 + (data_8583[temp+1]&0x0f) ) / 2; config[i*8+j+1].seat = temp; config[i*8+j+1].len = count + 2; temp = temp + count + 2; } } else { count = Area[i*8+j+1]; config[i*8+j+1].len = count; config[i*8+j+1].seat = temp; temp = temp + count; } } seek_i = seek_i<<1; } }}
//代码备注较少请大家谅解
图1 代码展示
图2 报文解析运行结果
银联处理中心报文:接收报文:======================================01 1A 60 00 00 00 02 60 31 00 31 10 04 02 10 70 3E 00 C1 0E D0 8C 17 19 62 28 48 02 11 39 79 24 91 40 00 00 00 00 00 00 00 50 00 00 00 29 09 39 29 09 04 49 12 00 00 00 00 08 00 01 00 00 31 32 33 34 35 36 37 38 39 30 31 32 31 32 33 34 35 36 30 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 19 30 31 30 33 30 30 30 30 20 20 20 30 31 30 33 30 30 30 30 31 35 36 26 00 00 00 00 00 00 00 00 20 39 30 30 32 31 35 36 43 30 30 30 30 30 32 35 36 33 32 31 35 00 14 22 00 00 01 00 06 01 00 72 30 30 30 30 30 30 32 35 30 30 30 30 30 30 30 30 30 30 31 32 30 30 30 30 30 30 30 31 32 35 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 00 33 43 55 50 41 4E B8 F1 CD DF C0 AD D1 A1 41 42 D2 F8 C1 AA D4 DA CF DF D6 A7 B8 B6 CD DF C0 AD D1 A1 45 31 33 35 35 32 41 32标准结果:MSG TYPE:0210BITMAP:703E00C10ED08C172域:19622848021139792491403域:0000004域:00000000500011域:00002912域:09392913域:090414域:491215域:000025域:0026域:0032域:080001000037域:31323334353637383930313238域:31323334353639域:303041域:000000000000000042域:00000000000000000000000000000044域:193031303330303030202020303130333030303049域:31353653域:260000000000000054域:0020393030323135364330303030303235363332313560域:00142200000100060162域:007230303030303032353030303030303030303031323030303030303031323530303030303030303030303030303030303030303030303030303030303030303030303030303030303063域:0033435550414EB8F1CDDFC0ADD1A14142D2F8C1AAD4DACFDFD6A7B8B6CDDFC0ADD1A164域:4531333535324132
0 0
- 解析8583报文
- 8583报文解析
- 8583报文解析程序
- 8583报文解析实例
- 8583报文解析实例
- 8583 报文解析过程
- 第一章 银联8583报文解析
- 金融类8583报文解析器
- 8583报文解析实例介绍
- 报文解析
- 报文解析
- 报文解析
- 8583报文 55域JAVA的解析
- java解析8583报文55域
- C解析8583报文55域
- DNS报文解析
- xml报文解析例子
- 解析HTTP报文头
- 第10章 信号
- 野人学Android基础篇之四大组件第一课--Activity的Intent传递
- 条款17 以独立语句将new对象置入智能指针
- 《剑指Offer》面试题:合并两个排序的链表
- quick-cocos2d-x数据存储之GameState
- 8583报文解析
- 联考1day1总结
- [C++11/14] 自动类型推导——auto
- poj 3415
- 纯CSS气泡框实现方法探究
- 和为s的连续正数序列
- centos安装jdk环境yum
- 部分手机RadioButton作为Tab键不居中问题
- quick-cocos2d-x基于源码加密打包功能的更新