ISO8583报文是一种标准报文格式,主要用于金融等领域,网上有很多讲解此报文的文章,需要使用的可以查资料看一下,这里就不浪费空间了。 下面贴出读写该报文的类,需者自取!
/* ISO8583.h */
/* Create by jojoke */
#ifndef __ISO_8583_H__
#define
__ISO_8583_H__
#include
<
map
>
using
namespace
std;
typedef
struct
{
int
bit_flag;
/*
域数据类型0 -- string, 1 -- int, 2 -- binary
*/
char
*
data_name;
/*
域名
*/
int
length;
/*
数据域长度
*/
int
length_in_byte;
/*
实际长度(如果是变长)
*/
int
variable_flag;
/*
是否变长标志0:否 2:2位变长, 3:3位变长
*/
int
datatype;
/*
0 -- string, 1 -- int, 2 -- binary
*/
char
*
data;
/*
存放具体值
*/
int
attribute;
/*
保留
*/
} ISO8583Field;
typedef
struct
{
int
len;
BYTE
*
data;
} ISO8583FieldData;
class
CISO8583
{
public
:
enum
FileType
{
XML,
BIN,
HEX
};
/*
Get message length in bytes
*/
int
GetMessageLength();
/*
Write message out in xml format
*/
virtual
bool
WriteToFile(LPCTSTR pszFile, FileType type);
protected
:
bool
writeXML(LPCTSTR pszXMLFile);
bool
writeBIN(LPCTSTR pszBINFile);
bool
writeHEX(LPCTSTR pszHEXFile);
void
setBit(BYTE
*
pBytes,
int
nPos);
bool
testBit(
const
BYTE
*
pBytes,
int
nPos);
map
<
int
, ISO8583FieldData
>
m_fields;
};
class
CISO8583Writer :
public
CISO8583
{
public
:
CISO8583Writer();
~
CISO8583Writer();
/*
Copy message out
*/
int
CopyOut(BYTE
*
pOutBuf,
int
nBufLen);
/*
write specified field, if pFieldBuf is NULL then this field will be cleared
*/
const
BYTE
*
WriteField(
int
nField,
int
nFieldLen, BYTE
*
pFieldBuf);
};
class
CISO8583Reader :
public
CISO8583
{
public
:
CISO8583Reader();
~
CISO8583Reader();
/*
Read the message
*/
bool
ReadMessage(
const
BYTE
*
pMessage);
/*
Get field data
*/
int
GetFields(
int
*
fields,
int
count);
/*
Findout whether specified field exists
*/
bool
FieldExist(
int
nField);
/*
Findout whether specified fields exist.
*/
int
FieldsExist(
int
*
fields,
int
nCount);
/*
Get fields total count
*/
int
FieldsCount();
/*
Get specified field length
*/
int
FieldLength(
int
nField);
/*
Get specified field data
*/
int
ReadField(
int
nField, BYTE
*
pOutBuf,
int
nBufLen);
protected
:
bool
parseFields(
const
BYTE
*
pMessage);
};
#endif
/* ISO8583.cpp */
/* Create by jojoke */
#include
"
StdAfx.h
"
#include
"
ISO8583.h
"
#include
"
math.h
"
#include
"
assert.h
"
ISO8583Field Tbl8583[
128
]
=
{
/*
FLD 01
*/
{
0
,
"
BIT MAP,EXTENDED
"
,
8
,
0
,
0
,
2
, NULL,
0
},
/*
FLD 02
*/
{
0
,
"
PRIMARY ACCOUNT NUMBER
"
,
22
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 03
*/
{
0
,
"
PROCESSING CODE
"
,
6
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 04
*/
{
0
,
"
AMOUNT, TRANSACTION
"
,
12
,
0
,
0
,
1
, NULL,
0
},
/*
FLD 05
*/
{
0
,
"
NO USE
"
,
12
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 06
*/
{
0
,
"
NO USE
"
,
12
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 07
*/
{
0
,
"
TRANSACTION DATE AND TIME
"
,
10
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 08
*/
{
0
,
"
NO USE
"
,
8
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 09
*/
{
0
,
"
NO USE
"
,
8
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 10
*/
{
0
,
"
NO USE
"
,
8
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 11
*/
{
0
,
"
SYSTEM TRACE AUDIT NUMBER
"
,
6
,
0
,
0
,
1
, NULL,
0
},
/*
FLD 12
*/
{
0
,
"
TIME, LOCAL TRANSACTION
"
,
6
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 13
*/
{
0
,
"
DATE, LOCAL TRANSACTION
"
,
4
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 14
*/
{
0
,
"
DATE, EXPIRATION
"
,
4
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 15
*/
{
0
,
"
DATE, SETTLEMENT
"
,
4
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 16
*/
{
0
,
"
NO USE
"
,
4
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 17
*/
{
0
,
"
DATE, CAPTURE
"
,
4
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 18
*/
{
0
,
"
MERCHANT'S TYPE
"
,
4
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 19
*/
{
0
,
"
NO USE
"
,
3
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 20
*/
{
0
,
"
NO USE
"
,
3
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 21
*/
{
0
,
"
NO USE
"
,
3
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 22
*/
{
0
,
"
POINT OF SERVICE ENTRY MODE
"
,
3
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 23
*/
{
0
,
"
NO USE
"
,
3
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 24
*/
{
0
,
"
NO USE
"
,
3
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 25
*/
{
0
,
"
POINT OF SERVICE CONDITION CODE
"
,
2
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 26
*/
{
0
,
"
NO USE
"
,
2
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 27
*/
{
0
,
"
NO USE
"
,
1
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 28
*/
{
0
,
"
field27
"
,
6
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 29
*/
{
0
,
"
NO USE
"
,
8
,
0
,
1
,
0
, NULL,
0
},
/*
FLD 30
*/
{
0
,
"
NO USE
"
,
8
,
0
,
1
,
0
, NULL,
0
},
/*
FLD 31
*/
{
0
,
"
NO USE
"
,
8
,
0
,
1
,
0
, NULL,
0
},
/*
FLD 32
*/
{
0
,
"
ACQUIRER INSTITUTION ID. CODE
"
,
11
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 33
*/
{
0
,
"
FORWARDING INSTITUTION ID. CODE
"
,
11
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 34
*/
{
0
,
"
NO USE
"
,
28
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 35
*/
{
0
,
"
TRACK 2 DATA
"
,
37
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 36
*/
{
0
,
"
TRACK 3 DATA
"
,
104
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 37
*/
{
0
,
"
RETRIEVAL REFERENCE NUMBER
"
,
12
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 38
*/
{
0
,
"
AUTH. IDENTIFICATION RESPONSE
"
,
6
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 39
*/
{
0
,
"
RESPONSE CODE
"
,
2
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 40
*/
{
0
,
"
NO USE
"
,
3
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 41
*/
{
0
,
"
CARD ACCEPTOR TERMINAL ID.
"
,
8
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 42
*/
{
0
,
"
CARD ACCEPTOR IDENTIFICATION CODE
"
,
15
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 43
*/
{
0
,
"
CARD ACCEPTOR NAME LOCATION
"
,
40
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 44
*/
{
0
,
"
ADDITIONAL RESPONSE DATA
"
,
25
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 45
*/
{
0
,
"
NO USE
"
,
76
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 46
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 47
*/
{
0
,
"
field47
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 48
*/
{
0
,
"
ADDITIONAL DATA --- PRIVATE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 49
*/
{
0
,
"
CURRENCY CODE,TRANSACTION
"
,
3
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 50
*/
{
0
,
"
CURRENCY CODE,SETTLEMENT
"
,
3
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 51
*/
{
0
,
"
NO USE
"
,
3
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 52
*/
{
0
,
"
PERSONAL IDENTIFICATION NUMBER DATA
"
,
8
,
0
,
0
,
2
, NULL,
0
},
/*
FLD 53
*/
{
0
,
"
SECURITY RELATED CONTROL INformATION
"
,
16
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 54
*/
{
0
,
"
ADDITIONAL AMOUNTS
"
,
120
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 55
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 56
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 57
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 58
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 59
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 60
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 61
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 62
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 63
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 64
*/
{
0
,
"
MESSAGE AUTHENTICATION CODE FIELD
"
,
8
,
0
,
0
,
2
, NULL,
0
},
/*
FLD 65
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 66
*/
{
0
,
"
NO USE
"
,
1
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 67
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 68
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 69
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 70
*/
{
0
,
"
SYSTEM MANAGEMENT INformATION CODE
"
,
3
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 71
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 72
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 73
*/
{
0
,
"
NO USE
"
,
6
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 74
*/
{
0
,
"
NUMBER OF CREDITS
"
,
10
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 75
*/
{
0
,
"
REVERSAL NUMBER OF CREDITS
"
,
10
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 76
*/
{
0
,
"
NUMBER OF DEBITS
"
,
10
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 77
*/
{
0
,
"
REVERSAL NUMBER OF DEBITS
"
,
10
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 78
*/
{
0
,
"
NUMBER OF TRANSFER
"
,
10
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 79
*/
{
0
,
"
REVERSAL NUMBER OF TRANSFER
"
,
10
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 80
*/
{
0
,
"
NUMBER OF INQUIRS
"
,
10
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 81
*/
{
0
,
"
AUTHORIZATION NUMBER
"
,
10
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 82
*/
{
0
,
"
NO USE
"
,
12
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 83
*/
{
0
,
"
CREDITS,TRANSCATION FEEAMOUNT
"
,
12
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 84
*/
{
0
,
"
NO USE
"
,
12
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 85
*/
{
0
,
"
DEBITS,TRANSCATION FEEAMOUNT
"
,
12
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 86
*/
{
0
,
"
AMOUNT OF CREDITS
"
,
16
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 87
*/
{
0
,
"
REVERSAL AMOUNT OF CREDITS
"
,
16
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 88
*/
{
0
,
"
AMOUNT OF DEBITS
"
,
16
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 89
*/
{
0
,
"
REVERSAL AMOUNT OF DEBITS
"
,
16
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 90
*/
{
0
,
"
ORIGINAL DATA ELEMENTS
"
,
42
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 91
*/
{
0
,
"
FILE UPDATE CODE
"
,
1
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 92
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 93
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 94
*/
{
0
,
"
SERVICE INDICATOR
"
,
7
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 95
*/
{
0
,
"
REPLACEMENT AMOUNTS
"
,
42
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 96
*/
{
0
,
"
NO USE
"
,
8
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 97
*/
{
0
,
"
AMOUNT OF NET SETTLEMENT
"
,
16
,
0
,
0
,
0
, NULL,
0
},
/*
FLD 98
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 99
*/
{
0
,
"
SETTLEMENT INSTITUTION ID
"
,
11
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 100
*/
{
0
,
"
RECVEING INSTITUTION ID
"
,
11
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 101
*/
{
0
,
"
FILENAME
"
,
17
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 102
*/
{
0
,
"
ACCOUNT IDENTIFICATION1
"
,
28
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 103
*/
{
0
,
"
ACCOUNT IDENTIFICATION2
"
,
28
,
0
,
2
,
0
, NULL,
0
},
/*
FLD 104
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 105
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 106
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 107
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 108
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 109
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 110
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 111
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 112
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 113
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 114
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 115
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 116
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 117
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 118
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 119
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 120
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 121
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 122
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 123
*/
{
0
,
"
NEW PIN DATA
"
,
8
,
0
,
3
,
2
, NULL,
0
},
/*
FLD 124
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 125
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 126
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 127
*/
{
0
,
"
NO USE
"
,
999
,
0
,
3
,
0
, NULL,
0
},
/*
FLD 128
*/
{
0
,
"
MESSAGE AUTHENTICATION CODE FIELD
"
,
8
,
0
,
0
,
2
, NULL,
0
},
};
/*
Set bit in specified position
*/
void
CISO8583::setBit(BYTE
*
pBytes,
int
nPos)
{
if
(nPos
%
8
==
0
)
pBytes[nPos
/
8
-
1
]
|=
0x01
;
else
pBytes[(unsigned
int
)floor(nPos
/
8
)]
|=
(
0x80
>>
(nPos
%
8
-
1
));
if
(nPos
>
64
)
setBit(pBytes,
1
);
}
/*
Test to see if bit position of p is set
*/
bool
CISO8583::testBit(
const
BYTE
*
pBytes,
int
nPos)
{
unsigned
int
nOffset;
BYTE nMask;
nOffset
=
nPos
%
8
==
0
?
nPos
/
8
-
1
: (unsigned
int
)floor(nPos
/
8
);
nMask
=
nPos
%
8
==
0
?
0x01
: (
0x80
>>
(nPos
%
8
-
1
));
return
(pBytes[nOffset]
&
nMask)
==
nMask;
}
/*
Write message in xml format
*/
bool
CISO8583::writeXML(LPCTSTR pszXMLFile)
{
int
i
=
0
;
BYTE bitmap[
16
];
char
sBitMap[
33
]
=
{
'
\0
'
};
TCHAR
*
szFieldType[
3
]
=
{
"
string
"
,
"
int
"
,
"
binary
"
};
FILE
*
fp
=
fopen(pszXMLFile,
"
w
"
);
if
(NULL
==
fp)
return
false
;
/*
write bitmap
*/
memset(bitmap,
0
,
sizeof
(bitmap));
map
<
int
, ISO8583FieldData
>
::iterator it
=
m_fields.begin();
while
(it
!=
m_fields.end()) {
setBit(bitmap, it
->
first);
it
++
;
}
for
(i
=
0
; i
<
16
; i
++
)
_snprintf(sBitMap
+
2
*
i,
2
,
"
%02x
"
, bitmap[i]);
fprintf(fp,
"
<?xml version=\
"
1.0
\
"
encoding=\
"
GB2312\
"
?>\r\n
"
);
fprintf(fp,
"
<ISO8583 fieldscount=\
"
%
d\
"
totalbytes=\
"
%
d\
"
bitmap=\
"
%
s\
"
>
"
, m_fields.size(),
this
->
GetMessageLength(), sBitMap);
/*
write fields
*/
it
=
m_fields.begin();
while
(it
!=
m_fields.end()) {
fprintf(fp,
"
\r\n\t<Field no=\
"
%
d\
"
type=\
"
%
s\
"
fieldlength=\
"
%
d\
"
datalength=\
"
%
d\
"
>\n
"
, it
->
first, szFieldType[Tbl8583[it
->
first
-
1
].datatype], Tbl8583[it
->
first
-
1
].length, it
->
second.len);
if
(Tbl8583[it
->
first
-
1
].datatype
==
1
)
fprintf(fp,
"
\t\t%s
"
, (
char
*
)it
->
second.data);
else
{
fprintf(fp,
"
\t\t
"
);
for
(i
=
0
; i
<
it
->
second.len; i
++
)
fprintf(fp,
"
%02X
"
, (BYTE)it
->
second.data[i]);
}
fprintf(fp,
"
\n\t</Field>
"
);
it
++
;
}
fprintf(fp,
"
\n</ISO8583>
"
);
fclose(fp);
return
true
;
}
bool
CISO8583::writeBIN(LPCTSTR pszBINFile)
{
int
i
=
0
;
BYTE bitmap[
16
];
FILE
*
fp
=
fopen(pszBINFile,
"
wb
"
);
if
(NULL
==
fp)
return
false
;
/*
write bitmap
*/
memset(bitmap,
0
,
sizeof
(bitmap));
map
<
int
, ISO8583FieldData
>
::iterator it
=
m_fields.begin();
while
(it
!=
m_fields.end()) {
setBit(bitmap, it
->
first);
it
++
;
}
fwrite(bitmap,
1
,
sizeof
(bitmap), fp);
/*
write fields
*/
it
=
m_fields.begin();
while
(it
!=
m_fields.end()) {
if
(Tbl8583[it
->
first
-
1
].variable_flag
==
0
)
fwrite(it
->
second.data,
1
, it
->
second.len, fp);
else
if
(Tbl8583[it
->
first
-
1
].variable_flag
==
2
) {
fprintf(fp,
"
%02d
"
, it
->
second.len);
fwrite(it
->
second.data,
1
, it
->
second.len, fp);
}
else
if
(Tbl8583[it
->
first
-
1
].variable_flag
==
3
) {
fprintf(fp,
"
%03d
"
, it
->
second.len);
fwrite(it
->
second.data,
1
, it
->
second.len, fp);
}
it
++
;
}
fclose(fp);
return
true
;
}
bool
CISO8583::writeHEX(LPCTSTR pszHEXFile)
{
int
i
=
0
, j
=
0
, round
=
0
, length
=
this
->
GetMessageLength();
FILE
*
fp
=
fopen(pszHEXFile,
"
wb
"
);
if
(NULL
==
fp)
return
false
;
BYTE
*
pBytes
=
new
BYTE[length];
BYTE
*
p
=
pBytes;
if
(NULL
==
pBytes)
return
false
;
memset(pBytes,
0
, length);
/*
write bitmap
*/
map
<
int
, ISO8583FieldData
>
::iterator it
=
m_fields.begin();
while
(it
!=
m_fields.end()) {
setBit(pBytes, it
->
first);
it
++
;
}
p
+=
16
;
/*
write fields
*/
it
=
m_fields.begin();
while
(it
!=
m_fields.end()) {
if
(Tbl8583[it
->
first
-
1
].variable_flag
==
0
) {
memcpy(p, it
->
second.data, it
->
second.len);
}
else
if
(Tbl8583[it
->
first
-
1
].variable_flag
==
2
) {
_snprintf((
char
*
)p,
2
,
"
%02d
"
, it
->
second.len);
p
+=
2
;
memcpy(p, it
->
second.data, it
->
second.len);
}
else
if
(Tbl8583[it
->
first
-
1
].variable_flag
==
3
) {
_snprintf((
char
*
)p,
3
,
"
%03d
"
, it
->
second.len);
p
+=
3
;
memcpy(p, it
->
second.data, it
->
second.len);
}
p
+=
it
->
second.len;
it
++
;
}
/*
write to file in ultraedit hex-view format
*/
for
(i
=
0
; i
<
length; i
++
) {
if
(i
==
0
)
fprintf(fp,
"
%08Xh:
"
, round);
fprintf(fp,
"
%02X
"
, pBytes[i]);
if
(
++
round
%
16
==
0
&&
i
!=
length
-
1
) {
fwrite(
"
;
"
,
1
,
3
, fp);
p
=
pBytes
+
i
-
15
;
for
(j
=
0
; j
<
16
; j
++
)
fprintf(fp,
"
%c
"
, (p[j]
==
0
||
p[j]
==
'
\r
'
||
p[j]
==
'
\n
'
)
?
'
.
'
: p[j]);
fprintf(fp,
"
\r\n%08Xh:
"
, round);
}
}
if
((round
=
length
%
16
)
!=
0
) {
for
(i
=
0
; i
<
16
-
round; i
++
)
fwrite(
"
"
,
1
,
3
, fp);
fwrite(
"
;
"
,
1
,
3
, fp);
p
=
pBytes
+
length
-
round;
for
(i
=
0
; i
<
round; i
++
)
fprintf(fp,
"
%c
"
, (p[i]
==
0
||
p[i]
==
'
\r
'
||
p[i]
==
'
\n
'
)
?
'
.
'
: p[i]);
}
delete pBytes;
fclose(fp);
return
true
;
}
bool
CISO8583::WriteToFile(LPCTSTR pszFile, FileType type)
{
if
(type
==
CISO8583::XML)
return
writeXML(pszFile);
else
if
(type
==
CISO8583::BIN)
return
writeBIN(pszFile);
else
if
(type
==
CISO8583::HEX)
return
writeHEX(pszFile);
return
false
;
}
/*
Get message length in bytes
*/
int
CISO8583::GetMessageLength()
{
int
len
=
0
;
map
<
int
, ISO8583FieldData
>
::iterator it
=
m_fields.begin();
while
(it
!=
m_fields.end()) {
len
=
len
+
it
->
second.len
+
Tbl8583[it
->
first
-
1
].variable_flag;
it
++
;
}
return
len
+
16
;
}
CISO8583Writer::CISO8583Writer()
{
}
CISO8583Writer::
~
CISO8583Writer()
{
map
<
int
, ISO8583FieldData
>
::iterator it
=
m_fields.begin();
while
(it
!=
m_fields.end()) {
delete it
->
second.data;
it
++
;
}
}
/*
Copy message out
*/
int
CISO8583Writer::CopyOut(BYTE
*
pOutBuf,
int
nBufLen)
{
int
offset
=
16
;
if
(NULL
==
pOutBuf
||
nBufLen
<
GetMessageLength())
return
-
1
;
/*
clear bitmap
*/
memset((
void
*
)pOutBuf,
0
,
16
);
map
<
int
, ISO8583FieldData
>
::iterator it
=
m_fields.begin();
while
(it
!=
m_fields.end()) {
/*
set bitmap
*/
setBit(pOutBuf, it
->
first);
/*
copy data
*/
if
(Tbl8583[it
->
first
-
1
].variable_flag
==
0
) {
memcpy(pOutBuf
+
offset, it
->
second.data, it
->
second.len);
offset
+=
it
->
second.len;
}
else
if
(Tbl8583[it
->
first
-
1
].variable_flag
==
2
) {
_snprintf((
char
*
)(pOutBuf
+
offset),
2
,
"
%02d
"
, it
->
second.len);
memcpy(pOutBuf
+
offset
+
2
, it
->
second.data, it
->
second.len);
offset
=
offset
+
it
->
second.len
+
2
;
}
else
if
(Tbl8583[it
->
first
-
1
].variable_flag
==
3
) {
_snprintf((
char
*
)(pOutBuf
+
offset),
3
,
"
%03d
"
, it
->
second.len);
memcpy(pOutBuf
+
offset
+
3
, it
->
second.data, it
->
second.len);
offset
=
offset
+
it
->
second.len
+
3
;
}
it
++
;
}
return
offset;
}
/*
write specified field, if pFieldBuf is NULL then this field will be cleared
*/
const
BYTE
*
CISO8583Writer::WriteField(
int
nField,
int
nFieldLen, BYTE
*
pFieldBuf)
{
if
(nField
>
128
||
nField
<
1
)
throw
"
field should between 1 and 128
"
;
map
<
int
, ISO8583FieldData
>
::iterator it
=
m_fields.find(nField);
/*
delete the specified field if it exists
*/
if
(it
!=
m_fields.end()) {
delete it
->
second.data;
m_fields.erase(it);
}
/*
clear the specified field and return if pFieldBuf is NULL
*/
if
(NULL
==
pFieldBuf)
return
NULL;
/*
copy data
*/
ISO8583FieldData field;
field.len
=
nFieldLen;
field.data
=
new
BYTE[field.len];
if
(NULL
==
field.data)
return
NULL;
memcpy(field.data, pFieldBuf, field.len);
/*
add field
*/
m_fields[nField]
=
field;
return
field.data;
}
CISO8583Reader::CISO8583Reader()
{
}
CISO8583Reader::
~
CISO8583Reader()
{
m_fields.clear();
}
bool
CISO8583Reader::ReadMessage(
const
BYTE
*
pMessage)
{
try
{
return
parseFields(pMessage);
}
catch
(
) {
return
false
;
}
}
/*
Get position and length for each field
*/
bool
CISO8583Reader::parseFields(
const
BYTE
*
pMessage)
{
bool
extensionMode
=
testBit(pMessage,
1
);
DWORD dwOffset
=
16
;
BYTE len[
4
];
/*
Test bit pos 2 - 128 or 2 - 64
*/
for
(
int
i
=
2
; i
<=
128
&&
extensionMode; i
++
) {
if
(
!
testBit(pMessage, i))
continue
;
/*
find data position and length for each field
*/
ISO8583FieldData field;
if
(Tbl8583[i
-
1
].variable_flag
==
0
) {
field.len
=
Tbl8583[i
-
1
].length;
field.data
=
(BYTE
*
)pMessage
+
dwOffset;
dwOffset
+=
field.len;
}
else
{
memset(len,
0
,
sizeof
(len));
memcpy((
void
*
)len, (
void
*
)(pMessage
+
dwOffset), Tbl8583[i
-
1
].variable_flag);
field.len
=
atol((
char
*
)len);
field.data
=
(BYTE
*
)(pMessage
+
dwOffset
+
Tbl8583[i
-
1
].variable_flag);
dwOffset
=
dwOffset
+
field.len
+
Tbl8583[i
-
1
].variable_flag;
}
m_fields[i]
=
field;
}
return
true
;
}
/*
Get fields number that is set in the bitmap, count should large than value return by FieldsCount()
*/
int
CISO8583Reader::GetFields(
int
*
fields,
int
count)
{
int
fcount
=
m_fields.size()
>
count
?
count : m_fields.size();
map
<
int
, ISO8583FieldData
>
::iterator it
=
m_fields.begin();
for
(
int
i
=
0
; i
<
fcount; i
++
) {
fields[i]
=
it
->
first;
it
++
;
}
return
fcount;
}
/*
Get fields count
*/
int
CISO8583Reader::FieldsCount()
{
return
m_fields.size();
}
/*
Find to see whether the specified field exist
*/
bool
CISO8583Reader::FieldExist(
int
nField)
{
return
m_fields.find(nField)
!=
m_fields.end();
}
/*
Find to see whether all fields in pFields array exist
*/
int
CISO8583Reader::FieldsExist(
int
*
fields,
int
nCount)
{
for
(
int
i
=
0
; i
<
nCount; i
++
) {
if
(
!
FieldExist(fields[i]))
return
fields[i];
}
return
0
;
}
/*
Get field length exclusive the LLLVAR or LLVAR part
*/
int
CISO8583Reader::FieldLength(
int
nField)
{
if
(nField
>
128
)
return
-
1
;
map
<
int
, ISO8583FieldData
>
::iterator it
=
m_fields.find(nField);
if
(it
==
m_fields.end())
return
-
1
;
/*
substract the LLL or LL length
*/
return
it
->
second.len
-
Tbl8583[nField
-
1
].variable_flag;
}
/*
Get Field's data, not include the LL or LLL length value if it is varlength field
*/
int
CISO8583Reader::ReadField(
int
nField, BYTE
*
pOutBuf,
int
nBufLen)
{
map
<
int
, ISO8583FieldData
>
::iterator it
=
m_fields.find(nField);
if
(it
==
m_fields.end())
return
-
1
;
int
nFieldLen
=
it
->
second.len;
//
- Tbl8583[nField - 1].variable_flag;
if
(nBufLen
<
it
->
second.len)
return
-
1
;
memcpy(pOutBuf, it
->
second.data, nFieldLen);
return
nFieldLen;
}