ISO8583报文是一种标准报文格式,主要用于金融等领域,网上有很多讲解此报文的文章,需要使用的可以查资料看一下,这里就不浪费空间了。 下面贴出读写该报文的类,需者自取!
/* ISO8583.h */
/* Create by jojoke */
/* ISO8583.cpp */
/* Create by jojoke */
/* 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
#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;
}
#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;
}
来源:https://www.cnblogs.com/jojoke/archive/2007/12/14/995146.html