From b5f818848ae01ea4a8b6a8d6e6867834ff10cb4f Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Wed, 26 Jun 2024 16:25:23 +0200 Subject: [PATCH] just save tests --- main/MessageHelper.cpp | 487 ++++++++++++++++++++++++++++++++++++++++- main/MessageHelper.h | 53 ++++- main/main.cpp | 265 ++++++++++++++++++++-- 3 files changed, 787 insertions(+), 18 deletions(-) diff --git a/main/MessageHelper.cpp b/main/MessageHelper.cpp index 8d34677..f3526df 100644 --- a/main/MessageHelper.cpp +++ b/main/MessageHelper.cpp @@ -46,6 +46,7 @@ // Messages that contain information normally of use only when debugging a program static int DBG_LEVEL = DBG_INFORMATION; +//static int DBG_LEVEL = DBG_DEBUG; struct MessageHeader { uint8_t packetType; @@ -54,6 +55,10 @@ struct MessageHeader { uint8_t POSID[MAX_POSID_LENGTH]; }; + +MessageHelper::AsynchBillData MessageHelper::m_asyncBillData; +MessageHelper::AuthorizationResult MessageHelper::m_authorizationResult; + MessageHelper::MessageHelper(QString const &posID, QString const &apak) : m_posID(posID.toUtf8().constData()) , m_posIDLength(m_posID.size()) @@ -96,6 +101,315 @@ MessageHelper::~MessageHelper() { } +void MessageHelper::handleMessage(char const *pData) { + +#if 0 + //unsigned char marker = pData[0]; +// unsigned int tagNameLength = pData[1]; + unsigned char tagName[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; +// unsigned int curElementLength = 0; + //unsigned char curElement[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; + //unsigned char receiptData[IUC_ASYNCHPOS_MAX_ARRAY_SIZE + 1]; + unsigned char rxBuf[20]; +// unsigned char flags[129]; +// unsigned char docNr[32]; + //unsigned char messageType = pData[1]; + + unsigned int uitmp = 0; + unsigned int uitmp2 = 0; + + iuc_asynchpos_sub_initArray(tagName, IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); + //iuc_asynchpos_sub_initArray(curElement, IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); + + uitmp = biox_FindStrInBufferInt("LoginResult",pData) | biox_FindStrInBuffer("LOGINRESULT",pData); + if (uitmp) { + asynchState = 0x02; //eingeloggt + /*rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0x00; + vmc_SendWithBuffer(rxBuf,40,0x69,0);*/ + } + + uitmp = biox_FindStrInBufferInt("AuthorizationStarted",pData) | biox_FindStrInBuffer("AUTHORIZATIONSTARTED",pData); + if (uitmp) { + iuc_asynchpos_sub_initArray(rxBuf,5); + rxBuf[0] = 0x53; + rxBuf[1] = 0x00; + rxBuf[2] = 0x00; + vmc_SendWithBuffer(rxBuf,5,0x69,0); + } + + uitmp = biox_FindStrInBufferInt("AuthorizationResult",pData) | biox_FindStrInBuffer("AUTHORIZATIONRESULT",pData); + if (uitmp) { + asynchState = 0x03; //successfully authorized + iuc_asynchpos_sub_clear_message(0x00); + uitmp = biox_FindStrInBufferInt("ID",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.id, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("DocNr",pData) | biox_FindStrInBuffer("DOCNR",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.docNr, 0, pData[uitmp + 1]); + //uitmp = biox_FindStrInBuffer("Result",pData) | biox_FindStrInBuffer("RESULT",pData); + //biox_CopyBlock(pData, uitmp + 2, asynchBill.result, 0, pData[uitmp + 1]); + + brd_SendDiagStr("->IUC ASYNCHPOS message ID: ",0); + brd_SendDiagBlock(asynchBill.id,1,36); + + /*if (iuc_asynch_PrintControl) { + brd_SendDiagStr("->IUC ASYNCHPOS print data send AUTH: ",1); + vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0); + iuc_asynch_PrintControl = 0x00; + //biox_delay_ms(750); + } else { + brd_SendDiagStr("->IUC ASYNCHPOS sending authorization: ",1); + iuc_asynch_PrintControl = 0x01; + }*/ + + uitmp = biox_FindStrInBufferInt("ERROR",pData); + if (!uitmp/*biox_FindStrInBuffer("OK",pData) | biox_FindStrInBuffer("Approved",pData) | biox_FindStrInBuffer("APPROVED",asynchBill.result)*/) { + iuc_asynch_PrintControl |= 0xF0; + /*uitmp = biox_FindStrInBufferInt("Amount",pData) | biox_FindStrInBufferInt("AMOUNT",pData); + //if (pData[uitmp + 1] <= 10) { + biox_CopyBlock(pData, uitmp + 2, asynchBill.amount, 0, pData[uitmp + 1]); + //} else { + //biox_CopyBlock(pData, uitmp + 2, asynchBill.amount, 0, 10); + //}*/ + + //uitmp = biox_FindStrInBuffer("Token",pData); + //biox_CopyBlock(pData, uitmp + 2, asynchBill.token, 0, pData[uitmp + 1]); + /*uitmp = biox_FindStrInBufferInt("Authcode",pData) | biox_FindStrInBufferInt("AUTHCODE",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.authCode, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("RRN",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.rrn, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("STAN",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.stan, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("CardType",pData) | biox_FindStrInBufferInt("CARDTYPE",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.cardtype, 0, pData[uitmp + 1]);*/ + asynchState = 0x04; + + brd_SendDiagStr("->IUC ASYNCHPOS authorization confirmed.",1); + + /*iuc_asynchpos_sub_initArray(rxBuf,20); + rxBuf[0] = 0x45; + rxBuf[1] = 0x00; + rxBuf[2] = 0x00; + vmc_SendWithBuffer(rxBuf,20,0x69,0);*/ + + //iuc_asynchpos_resetBuffers(0x01); + //iuc_asynchpos_command_close_Document(); + } else { + iuc_asynch_PrintControl |= 0xF0; + //uitmp = biox_FindStrInBufferInt("ErrCode",pData) | biox_FindStrInBufferInt("ERRCODE",pData); + //biox_CopyBlock(pData, uitmp + 2, asynchBill.errCode, 0, pData[uitmp + 1]); + + brd_SendDiagStr("->IUC ASYNCHPOS authorization failed.",1); + + /*iuc_asynchpos_sub_initArray(rxBuf,20); + rxBuf[0] = 0x45; + rxBuf[1] = 0xFF; + biox_CopyBlock(pData, uitmp + 2, rxBuf, 2, pData[uitmp + 1]); + vmc_SendWithBuffer(rxBuf,20,0x69,0);*/ + iuc_asynch_keepAlive = 0x00; + //VendRequest=0; + } + } + + uitmp = biox_FindStrInBufferInt("PrintReceipt",pData) | biox_FindStrInBufferInt("PRINTRECEIPT",pData); + if (uitmp) { + asynchState = 0x03; //Customer receipt recieved + //iuc_asynchpos_sub_initArray(flags,129); + //uitmp = biox_FindStrInBufferInt("Flag",pData) | biox_FindStrInBufferInt("FLAG",pData) | biox_FindStrInBufferInt("Flags",pData) | biox_FindStrInBufferInt("FLAGS",pData); + /*if (uitmp) { + biox_CopyBlock(pData, uitmp + 2, flags, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("CD",flags) | biox_FindStrInBufferInt("LR",flags); + }*/ + + /*iuc_asynchpos_sub_clear_message(0x00); + uitmp = biox_FindStrInBufferInt("ID",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.id, 0, pData[uitmp + 1]); + uitmp = biox_FindStrInBufferInt("DocNr",pData) | biox_FindStrInBuffer("DOCNR",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.docNr, 0, pData[uitmp + 1]);*/ + iuc_asynchpos_sub_initArray(asynchBill.printId,129); + uitmp = biox_FindStrInBufferInt("ID",pData); + biox_CopyBlock(pData, uitmp + 2, asynchBill.printId, 0, pData[uitmp + 1]); + + //if(asynchState == 0x02/* && uitmp biox_FindStrInBufferInt("CD",flags) || biox_FindStrInBufferInt("LR",flags)*/) { + if((!iuc_asynch_PRNrecieved) && (biox_FindStrInBufferInt("CD",pData) || biox_FindStrInBufferInt("LR",pData)) ) { + iuc_asynch_PRNrecieved = 0x01; + iuc_asynchpos_sub_initArray(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE + 1); + uitmp = /*biox_FindStrInBuffer("ReceiptText",pData) | */biox_FindStrInBufferInt("RECEIPTTEXT",pData); + uitmp2 = (pData[uitmp] * 256) + pData[uitmp + 1]; + + //if (uitmp2 <= IUC_ASYNCHPOS_MAX_ARRAY_SIZE) { + if (uitmp2 > IUC_ASYNCHPOS_MAX_ARRAY_SIZE) { + uitmp2 = IUC_ASYNCHPOS_MAX_ARRAY_SIZE; + brd_SendDiagStr("->IUC ASYNCHPOS receipt: ERROR. Receipt too large! Cutting off.",1); + /*receiptData[0] = 0x50; + biox_CopyBlock(pData, uitmp + 2, receiptData, 1, uitmp2/*IUC_ASYNCHPOS_MAX_ARRAY_SIZE*); + //uitmp += IUC_ASYNCHPOS_MAX_ARRAY_SIZE; + //uitmp2 -= IUC_ASYNCHPOS_MAX_ARRAY_SIZE; + + brd_SendDiagStr("->IUC ASYNCHPOS receipt: ",0); + brd_SendDiagBlock(receiptData,1,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + iuc_asynch_PrintControl |= 0x0F;*/ + + /*if (iuc_asynch_PrintControl) { + brd_SendDiagStr("->IUC ASYNCHPOS print data send: ",1); + vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0); + iuc_asynch_PrintControl = 0x00; + } else { + brd_SendDiagStr("->IUC ASYNCHPOS print data stored: ",1); + iuc_asynch_PrintControl = 0x01; + }*/ + //biox_delay_ms(750); + + //iuc_asynchpos_resetBuffers(0x01); + //iuc_asynchpos_command_close_Document(); + + //iuc_asynchpos_resetBuffers(0x02); + //iuc_asynchpos_command_print_Result(0x01); + } + + receiptData[0] = 0x50; + biox_CopyBlock(pData, uitmp + 2, receiptData, 1, uitmp2/*IUC_ASYNCHPOS_MAX_ARRAY_SIZE*/); + + brd_SendDiagStr("->IUC ASYNCHPOS receipt: ",0); + brd_SendDiagBlock(receiptData,1,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + iuc_asynch_PrintControl |= 0x0F; + + /* else { + //receiptData[0] = 0x50; + //iuc_asynchpos_sub_initZero(receiptData,1); + brd_SendDiagStr("->IUC ASYNCHPOS receipt: ERROR. Receipt too large!",1); + iuc_asynch_PrintControl |= 0x0E; + } */ + /* else { + //iuc_asynchpos_resetBuffers(0x02); + iuc_asynchpos_command_print_Result(0x00); + }*/ + } + + //++iuc_print_counter; + + //if(asynchState == 0x04 && iuc_asynch_PrintControl == 0) { + //iuc_asynchpos_resetBuffers(0x01); + //iuc_asynchpos_resetBuffers(0x00); + //iuc_asynchpos_command_print_Result(0x01); + /*} /else { + //iuc_asynchpos_resetBuffers(0x02); + iuc_asynchpos_command_print_Result(0x01); + }*/ + //iuc_asynchpos_command_print_Result(0x01); + + /*while (uitmp2 > IUC_ASYNCHPOS_MAX_ARRAY_SIZE) { + biox_CopyBlock(pData, uitmp + 2, receiptData, 0, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + uitmp += IUC_ASYNCHPOS_MAX_ARRAY_SIZE; + uitmp2 -= IUC_ASYNCHPOS_MAX_ARRAY_SIZE; + vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0); + } + + //Rest des Packets + biox_CopyBlock(pData, uitmp + 2, receiptData, 0, uitmp2); + vmc_SendWithBuffer(receiptData,uitmp2,0x69,0); + + //iuc_asynchpos_resetBuffers(0x02); + iuc_asynchpos_command_print_Result(0x01);*/ + } + + uitmp = biox_FindStrInBufferInt("VoidResult",pData) | biox_FindStrInBufferInt("VOIDRESULT",pData); + if (uitmp) { + asynchState = 0x01; //There was a cancel. Relogin and try again. + uitmp = biox_FindStrInBufferInt("ERROR",pData); + if (uitmp) { + rxBuf[0] = 0x45; + rxBuf[1] = 0x56; + rxBuf[2] = 0x45; + vmc_SendWithBuffer(rxBuf,3,0x69,0); + } + + uitmp = biox_FindStrInBufferInt("REFUND",pData); + if (uitmp) { + rxBuf[0] = 0x45; + rxBuf[1] = 0x56; + rxBuf[2] = 0x52; + vmc_SendWithBuffer(rxBuf,3,0x69,0); + //TODO refund bill here. Should not trigger, but it might. + } + } + + uitmp = biox_FindStrInBufferInt("DocClosed",pData); + if (uitmp) { + asynchState = 0x01; //Transaction successful + + //if (VendRequest) + GWstate.VendRequest=0; + } +#endif +} + +void MessageHelper::handleCommand(AsyncPosCommand command, char status) { + //r - registration, a - authorization, c - cancel, s - storno, k - kassenschnitt + +#if 0 + UCHAR tempBuf[3]; + UCHAR rxBuf[8]; +// UINT uitemp = 0; +UINT uitmp= 700; + + tempBuf[0] = 0x00; + tempBuf[1] = 0x00; + tempBuf[2] = 0x00; + + timeHoldISMAS = GWglobTime.SecOfDay; + + iuc_asynchpos_sub_initArray(rxBuf,8); + //iuc_asynchpos_resetBuffers(0x00); + + switch (command) { + case 0x72: //registration + //iuc_asynchpos_init(); + asynchState = 0x01; + iuc_asynchpos_command_Login(); + GWstate.VendRequest=1; + break; + case 0x61: //authorisation + iuc_asynch_keepAlive = 0x01; + iuc_asynch_PrintControl = 0; + iuc_asynchpos_sub_clear_message(0x01); + //VendRequest=1; + iuc_asynchpos_resetBuffers(0x00); + ///#ifdef IUC_ASYCHNPOS_TESTMODE + //iuc_asynchpos_command_authorize(uitmp); + //#else + iuc_asynchpos_command_authorize(Vend.Amount); + //#endif + break; + case 0x63: //cancel + case 0x73: //storno + /*if (asynchState <= 0x02 != 0) { //Authorization result recieved? + iuc_asynchpos_command_cancel_authorize(); + } else {*/ + iuc_asynchpos_command_close_Document(0x01); + //} + iuc_asynch_keepAlive = 0x00; + //VendRequest=0; + break; + case 0x6B: //kassenschnitt + iuc_asynchpos_command_Logout(); + break; + case 0x62: //get last bill + //iuc_zvt_getLastBill(tempBuf); + break; + case 0x01: iuc_asynchpos_command_close_Document(0x00); + iuc_asynch_keepAlive = 0x00; + //VendRequest=0; + break; + case 0x70: iuc_asynchpos_command_ping_terminal(); + break; + default: + break; + } +#endif +} + void MessageHelper::createRawPacket(PacketType packetType, QByteArray const &encryptedPacketID, QByteArray const &message) { @@ -142,6 +456,157 @@ bool MessageHelper::createMessageHeaderPrefix(PacketType packetType, QByteArray return false; } + +QByteArray const &MessageHelper::generateUniqueTransactionID(QString const &machineNr, + QString const &customerNr) { + + // TODO: wieder entfernen + QDateTime dt(QDateTime::fromString("2024-06-18T12:00:00", Qt::ISODate)); + + uint64_t const transID = MessageHelper::secsSinceJan2017(dt); + + m_uniqueTransactionID.clear(); + m_uniqueTransactionID = m_uniqueTransactionID.append(QByteArray(std::to_string(transID).c_str(), 9).rightJustified(10, '0')); + m_uniqueTransactionID = m_uniqueTransactionID.append(QByteArray(machineNr.toStdString().c_str()).rightJustified(5, '0')); + m_uniqueTransactionID = m_uniqueTransactionID.append(QByteArray(customerNr.toStdString().c_str()).rightJustified(4, '0')); + + return m_uniqueTransactionID; +} + +// actual payment. amount to pay is known. +void MessageHelper::createAuthorizeMessage() { + m_authorizeMessage.clear(); + + m_authorizeMessage.push_back((char)0x89); // 9 in 0x89 is the size + m_authorizeMessage = m_authorizeMessage.append(QByteArray("Authorize")); + + QString const &price= m_price.setNum(1000); + + m_authorizeMessage.push_back((char)0x06); + m_authorizeMessage = m_authorizeMessage.append(QByteArray("Amount")); + m_authorizeMessage.push_back((char)0x00); + m_authorizeMessage.push_back((char)price.size()); + m_authorizeMessage = m_authorizeMessage.append(QByteArray(price.toStdString().c_str())); + + m_authorizeMessage.push_back((char)0x04); + m_authorizeMessage = m_authorizeMessage.append(QByteArray("Cash")); + m_authorizeMessage.push_back((char)0x00); + m_authorizeMessage.push_back((char)0x01); + m_authorizeMessage.push_back((char)0x30); + + m_authorizeMessage.push_back((char)0x08); + m_authorizeMessage = m_authorizeMessage.append(QByteArray("Currency")); + m_authorizeMessage.push_back((char)0x00); + m_authorizeMessage.push_back((char)0x03); + m_authorizeMessage = m_authorizeMessage.append(QByteArray("978")); + + m_authorizeMessage.push_back((char)0x05); + m_authorizeMessage = m_authorizeMessage.append(QByteArray("DocNr")); + m_authorizeMessage.push_back((char)0x00); + m_authorizeMessage.push_back((char)0x13); + m_authorizeMessage = m_authorizeMessage.append(generateUniqueTransactionID("1000", "100")); + + m_authorizeMessage.push_back((char)0x04); + m_authorizeMessage = m_authorizeMessage.append(QByteArray("Time")); + m_authorizeMessage.push_back((char)0x00); + m_authorizeMessage.push_back((char)0x13); + + QDateTime current = QDateTime::currentDateTime(); + // TODO: wieder entfernen + current.setTime(QTime(12, 0, 0)); + current.setDate(QDate(2024, 6, 18)); + + QByteArray time(current.toString(Qt::ISODate).toStdString().c_str()); + time[10] = ' '; + m_authorizeMessage = m_authorizeMessage.append(QByteArray(time)); + + m_authorizeMessage.push_back((char)0x04); + m_authorizeMessage = m_authorizeMessage.append(QByteArray("Lang")); + m_authorizeMessage.push_back((char)0x00); + m_authorizeMessage.push_back((char)0x02); + m_authorizeMessage = m_authorizeMessage.append(QByteArray("lt")); + + m_authorizeMessage.push_back((char)0x00); +} + +void MessageHelper::createCancelAuthorizeMessage() { + m_cancelAuthorizeMessage.clear(); + + m_cancelAuthorizeMessage.push_back((char)0x96); // 0x80 + 0x16 + m_cancelAuthorizeMessage = m_cancelAuthorizeMessage.append(QByteArray("AuthorizationCancelled")); + + m_cancelAuthorizeMessage.push_back((char)0x02); + m_cancelAuthorizeMessage = m_authorizeMessage.append(QByteArray("ID")); + + m_cancelAuthorizeMessage.push_back((char)0x00); + m_cancelAuthorizeMessage.push_back((char)QByteArray(m_asyncBillData.id).size()); + m_cancelAuthorizeMessage = m_cancelAuthorizeMessage.append(QByteArray(m_asyncBillData.id)); + + m_cancelAuthorizeMessage.push_back((char)0x00); +} + +void MessageHelper::createPingMessage() { + m_pingMessage.clear(); + + m_pingMessage.push_back((char)0x84); // 4 in 0x84 is the size + m_pingMessage = m_pingMessage.append(QByteArray("Ping")); + + m_pingMessage.push_back((char)0x04); + m_pingMessage = m_authorizeMessage.append(QByteArray("Time")); + m_pingMessage.push_back((char)0x00); + m_pingMessage.push_back((char)0x13); + + QDateTime current = QDateTime::currentDateTime(); + // TODO: wieder entfernen + current.setTime(QTime(12, 0, 0)); + current.setDate(QDate(2024, 6, 18)); + + QByteArray time(current.toString(Qt::ISODate).toStdString().c_str()); + time[10] = ' '; + m_pingMessage = m_pingMessage.append(QByteArray(time)); + + m_pingMessage.push_back((char)0x00); +} + +void MessageHelper::createCloseDocumentMessage(bool storno) { + m_closeDocumentMessage.clear(); + + m_closeDocumentMessage.push_back((char)0x89); // 9 in 0x89 is the size + m_closeDocumentMessage = m_closeDocumentMessage.append(QByteArray("DocClosed")); + + m_closeDocumentMessage.push_back((char)0x05); + m_closeDocumentMessage = m_closeDocumentMessage.append(QByteArray("DocNr")); + + uint16_t const docNrSize = m_uniqueTransactionID.size(); + + m_closeDocumentMessage.push_back((char)(docNrSize >> 8)); + m_closeDocumentMessage.push_back((char)(docNrSize)); + m_closeDocumentMessage = m_closeDocumentMessage.append(m_uniqueTransactionID); + + if (!storno) { + m_closeDocumentMessage.push_back((char)0x06); + m_closeDocumentMessage = m_closeDocumentMessage.append(QByteArray("AuthID")); + + QByteArray ba(m_authorizationResult.m_id.toStdString().c_str()); + uint16_t const authIdSize = ba.size(); + + m_closeDocumentMessage.push_back((char)(authIdSize >> 8)); + m_closeDocumentMessage.push_back((char)(authIdSize)); + + m_closeDocumentMessage = m_closeDocumentMessage.append(ba); + } + + m_closeDocumentMessage.push_back((char)0x00); +} + +void MessageHelper::createPrintResultMessage() { + m_printResultMessage.clear(); +} + +uint32_t MessageHelper::secsSinceJan2017(QDateTime const &dt) { + return QDateTime(QDateTime::fromString("2017-01-01T00:00:00", Qt::ISODate)).secsTo(dt); +} + void MessageHelper::createLoginMessage() { m_loginMessage.clear(); @@ -156,7 +621,7 @@ void MessageHelper::createLoginMessage() { QDateTime current = QDateTime::currentDateTime(); // TODO: wieder entfernen current.setTime(QTime(12, 0, 0)); - current.setDate(QDate(2024, 6, 12)); + current.setDate(QDate(2024, 6, 18)); QByteArray time(current.toString(Qt::ISODate).toStdString().c_str()); time[10] = ' '; @@ -178,7 +643,7 @@ void MessageHelper::createLoginMessage() { void MessageHelper::createLogoutMessage() { m_logoutMessage.clear(); - m_logoutMessage.push_back((char)0x85); // 5 in 0x85 is the size + m_logoutMessage.push_back((char)0x86); // 6 in 0x86 is the size m_logoutMessage = m_loginMessage.append(QByteArray("Logout")); m_loginMessage.push_back((char)0x04); @@ -189,7 +654,7 @@ void MessageHelper::createLogoutMessage() { QDateTime current = QDateTime::currentDateTime(); // TODO: wieder entfernen current.setTime(QTime(12, 0, 0)); - current.setDate(QDate(2024, 6, 12)); + current.setDate(QDate(2024, 6, 18)); QByteArray time(current.toString(Qt::ISODate).toStdString().c_str()); time[10] = ' '; @@ -216,6 +681,14 @@ QByteArrayList const &MessageHelper::createMessageChunksToSend(AsyncPosCommand c createLogoutMessage(); createRawPacket(PacketType::POS_ECR, encryptedPacketID, m_logoutMessage); break; + case (int)MessageHelper::AsyncPosCommand::AUTHORIZE: + createAuthorizeMessage(); + createRawPacket(PacketType::POS_ECR, encryptedPacketID, m_authorizeMessage); + break; + case (int)MessageHelper::AsyncPosCommand::CLOSE_DOCUMENT: + createCloseDocumentMessage(); // actung: hier default parameter + createRawPacket(PacketType::POS_ECR, encryptedPacketID, m_closeDocumentMessage); + break; default:; } @@ -341,6 +814,14 @@ QByteArrayList MessageHelper::createLogoutMessageChunksToSend(char etx) { return createMessageChunksToSend(AsyncPosCommand::LOGOUT, etx); } +QByteArrayList MessageHelper::createAuthorizeMessageChunksToSend(char etx) { + return createMessageChunksToSend(AsyncPosCommand::AUTHORIZE, etx); +} + +QByteArrayList MessageHelper::createCloseDocumentMessageChunksToSend(char etx) { + return createMessageChunksToSend(AsyncPosCommand::CLOSE_DOCUMENT, etx); +} + bool MessageHelper::insertEncryptedPacketID(QByteArray const &encryptedPacketID) { if (encryptedPacketID.size() == PACKET_ID_SIZE) { // m_rawPacket has already full length diff --git a/main/MessageHelper.h b/main/MessageHelper.h index 3fc61b9..422112a 100644 --- a/main/MessageHelper.h +++ b/main/MessageHelper.h @@ -5,6 +5,7 @@ #include #include #include +#include class MessageHelper { public: @@ -19,7 +20,9 @@ public: enum AsyncPosCommand : std::uint8_t { LOGIN = 0, - LOGOUT = 1 + LOGOUT = 1, + AUTHORIZE = 2, + CLOSE_DOCUMENT = 3 }; explicit MessageHelper(QString const &posID = "T-TPS-SELF2002in", @@ -36,6 +39,8 @@ public: QByteArrayList createLoginMessageChunksToSend(char etx); QByteArrayList createLogoutMessageChunksToSend(char etx); + QByteArrayList createAuthorizeMessageChunksToSend(char etx); + QByteArrayList createCloseDocumentMessageChunksToSend(char etx); QByteArrayList const &createMessageChunksToSend(AsyncPosCommand cmd, char etx); // private: @@ -47,15 +52,61 @@ public: QByteArray m_rawPacket; // without leading STX and trailing [ETX(1/2), LRC] QByteArray m_loginMessage; QByteArray m_logoutMessage; + QByteArray m_authorizeMessage; + QByteArray m_cancelAuthorizeMessage; + QByteArray m_pingMessage; + QByteArray m_printResultMessage; + QByteArray m_closeDocumentMessage; + QByteArray m_uniqueTransactionID; + QString m_price; QByteArrayList m_messageChunkList; bool setMessageHeaderPacketType(PacketType packetType); + bool createMessageHeaderPrefix(PacketType packetType, QByteArray const &encryptedPacketID); void createLoginMessage(); void createLogoutMessage(); + void createAuthorizeMessage(); + void createCancelAuthorizeMessage(); + void createPingMessage(); + void createCloseDocumentMessage(bool storno = false); + void createPrintResultMessage(); + + void handleCommand(AsyncPosCommand command, char status); + //r - registration, a - authorization, c - cancel, s - storno, k - kassenschnitt + + void handleMessage(char const *pData); + + QByteArray const &generateUniqueTransactionID(QString const &machineNr, QString const &customerNumer); static QByteArray const &mask(QByteArray &messageChunk); static QByteArray const &unMask(QByteArray &messageChunk); + static uint32_t secsSinceJan2017(QDateTime const &dt = QDateTime::currentDateTime()); + + struct AsynchBillData { + char time[20]; + char id[37]; + char printId[129]; + char docNr[33]; + //unsigned char amount[10]; + //unsigned char token[25]; + //unsigned char result[8]; + //unsigned char authCode[7]; + //unsigned char rrn[13]; + //unsigned char stan[7]; + //unsigned char cardtype[33]; + char errCode[17]; + //unsigned char receiptData[IUC_ASYNCHPOS_RECEIPT_LENGTH]; + }; + + struct AuthorizationResult { + QString m_id; // max. 36 + QString m_docNr; // max. 32 + QString m_result; // "OK" or "ERROR" + }; + + static AsynchBillData m_asyncBillData; + static AuthorizationResult m_authorizationResult; }; #endif // MESSAGE_HELPER_H_INCLUDED diff --git a/main/main.cpp b/main/main.cpp index 2051b02..394e1f2 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -38,6 +38,7 @@ extern "C" char* strptime(const char* s, #include "aes128.h" #include "cc_iuc_asynchpos.h" #include "MessageHelper.h" +#include #define SZEGED (0) #define SCHOENAU_KOENIGSEE (0) @@ -48,8 +49,8 @@ extern "C" char* strptime(const char* s, #define BAD_NEUENAHR_AHRWEILER (0) #define NEUHAUSER_CHRISTOPH_REISEN (0) #define NEUHAUSER_PERNEGG_AN_DER_MUR (0) -#define NEUHAUSER_STOCKERAU (1) -#define KLEIPEDA_LITAUEN (0) +#define NEUHAUSER_STOCKERAU (0) +#define KLEIPEDA_LITAUEN (1) #if NEUHAUSER_KIRCHDORF==1 static bool test_neuhauser_kirchdorf(int step, double cost) { @@ -266,7 +267,7 @@ void iuc_asynchpos_sub_synchTime() { QDateTime current = QDateTime::currentDateTime(); current.setTime(QTime(12, 0, 0)); - current.setDate(QDate(2024, 6, 12)); + current.setDate(QDate(2024, 6, 18)); QString const &s = current.toString(Qt::ISODate); @@ -572,16 +573,17 @@ unsigned int iuc_asynchpos_send(unsigned char packetType, //Eyncrypt result with APAK, according to AES128 QByteArray x((char *)tempID, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); - QByteArray y((char *)tempID_, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); QByteArray z((char *)tempAPAK, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); - qCritical() << "X" << x.toHex(); - qCritical() << "Y" << y.toHex(); - qCritical() << "Z" << z.toHex(); + qCritical() << "AES-INPUT" << x.toHex(); + qCritical() << "APAK" << z.toHex(); aes_encrypt(tempID,tempID_,tempAPAK); + QByteArray y((char *)tempID_, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); + qCritical() << "AES-OUTPUT" << y.toHex(); + //get the leftmost 8 byte of that value and set then as Packet ID for (uitmp = 0; uitmp < 8; ++uitmp) { txData_[3 + uitmp] = tempID_[uitmp]; @@ -697,24 +699,250 @@ void iuc_asynchpos_command_Login() { //Kasse registrieren iuc_asynchpos_send(packetType,message,uitemp,0x01); } +void biox_ClearMem(UCHAR *targ, UCHAR FillByte, UINT Len) +{ + // fill buffer and terminate + + UINT zz=0; + + for (zz=0; zz0) + { + zi[pi++]=ltmp%10; + ltmp/=10; + } + + while (pi>0) + str[pp++]=zi[--pi]+0x30; +} + +void biox_MemCpPos(UCHAR *src, UCHAR *dest, UINT pos) +{ + // copy src to destination, start from position "pos". + // 1=start from beginning + // terminierung nicht eintragen, dest Puffer wird extern abgeschlossen + // dest must be long enough !!!! + + UINT zz, len, pp; + UCHAR uctmp; + + pp=pos; // unbedingt Zwischenspeichern, geht sonst verloren!!!!!!! + len=biox_StrLen(src); + zz=0; + do + { + uctmp=src[zz]; + if (uctmp>0) // terminierung + dest[zz+pp]=uctmp; + zz++; + } while(uctmp>0 && zz=20 bytes! + UCHAR tmp12[12]; + ULONG ultmp = 0; + + // a) Transaction ID, max 19 chars + // ab April 2017: TID muss über alle Automaten und über alle Zeiten eindeutig sein, + // sonst gibt SessionBase keine Antwort. + //uitmp=VKdata.TransID; sub_BufferNummEntry(ultmp); // einfache Version bis März 2017 + biox_ClearMem(buf, '0', 19); + biox_ClearMem(tmp12, 0, 12); + //VdKdata.TransID = com_totalSecSince1jan2017(); + //biox_ultoa(VKdata.TransID, tmp12); + biox_ultoa(transID, (char *)tmp12); + biox_MemCpPos(tmp12, buf, 1); + + qCritical() << "TransID 222" << hex << QByteArray((char *)buf, 20).toHex(':'); + + // Automaten-nr auch rein, sonst können versch. Automaten die gleiche Nummer haben! + biox_ClearMem(tmp12, 0, 12); + //ultmp=(ULONG) Conf.MachNr; //.MachineID; + ultmp=1000; //.MachineID; + biox_ultoa(ultmp, (char *)tmp12); + biox_MemCpPos(tmp12, buf, 11); + + qCritical() << "TransID 333" << hex << QByteArray((char *)buf, 20).toHex(':'); + + biox_ClearMem(tmp12, 0, 12); + //ultmp=(ULONG)Conf.CustomNr; //.CustID; + ultmp=100; //.CustID; + biox_ultoa(ultmp, (char *)tmp12); + biox_MemCpPos(tmp12, buf, 16); + + qCritical() << "TransID 444" << hex << QByteArray((char *)buf, 20).toHex(':'); + + buf[19]=0; +} + +void iuc_asynchpos_command_authorize(unsigned int vkPreis) { + UCHAR message[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; + UCHAR packetType = 0x00; + UINT uitemp = 0; + UCHAR command[] = "Authorize"; + UCHAR tag1Name[] = "Amount"; + UCHAR tag2Name[] = "Cash"; + UCHAR tag3Name[] = "Currency"; + UCHAR tag4Name[] = "DocNr"; + UCHAR tag5Name[] = "Time"; + UCHAR tag6Name[] = "Lang"; + //UCHAR tag1Value[10]; + UCHAR tag2Value[] = "0"; + UCHAR tag3Value[] = "978"; + UCHAR tag6Value[] = "lt"; + UINT vkPreis_ = vkPreis; + + + qCritical() << "START" << __func__; + + iuc_asynch_PRNrecieved = 0; + + //Constructing the message + iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); + //iuc_asynchpos_sub_initArray(tag1Value,10); + + uitemp = (UCHAR) biox_StrLen(command); + message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length + biox_CopyBlock(command,0,message,1,uitemp); //tag name + ++uitemp; + + //Amount + message[uitemp] = (UCHAR) biox_StrLen(tag1Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag1Name,0,message,uitemp, biox_StrLen(tag1Name));// tag name + uitemp += (1 + biox_StrLen(tag1Name)); + + std::string tag1Value = std::to_string(vkPreis_); + + message[uitemp] = (UCHAR) biox_StrLen((uint8_t *)tag1Value.c_str());//value length + ++uitemp; + biox_CopyBlock((uint8_t *)tag1Value.c_str(),0,message,uitemp, biox_StrLen((uint8_t *)tag1Value.c_str()));//value + uitemp += (/*1 + */biox_StrLen((uint8_t *)tag1Value.c_str())); + + //Cash + message[uitemp] = (UCHAR) biox_StrLen(tag2Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag2Name,0,message,uitemp, biox_StrLen(tag2Name));// tag name + uitemp += (1 + biox_StrLen(tag2Name)); + + message[uitemp] = (UCHAR) biox_StrLen(tag2Value);//value length + ++uitemp; + biox_CopyBlock(tag2Value,0,message,uitemp, biox_StrLen(tag2Value));//value + uitemp += (/*1 + */biox_StrLen(tag2Value)); + + //Currency + message[uitemp] = (UCHAR) biox_StrLen(tag3Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag3Name,0,message,uitemp, biox_StrLen(tag3Name));// tag name + uitemp += (1 + biox_StrLen(tag3Name)); + + message[uitemp] = (UCHAR) biox_StrLen(tag3Value);//value length + ++uitemp; + biox_CopyBlock(tag3Value,0,message,uitemp, biox_StrLen(tag3Value));//value + uitemp += (/*1 + */biox_StrLen(tag3Value)); + + //DocNr + message[uitemp] = (UCHAR) biox_StrLen(tag4Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag4Name,0,message,uitemp, biox_StrLen(tag4Name));// tag name + uitemp += (1 + biox_StrLen(tag4Name)); + + //biox_ltoa(asynchBill.docuNr,asynchBill.docNr); + //++asynchBill.docuNr; + + generate_UniqueTransNr(asynchBill.docNr); + + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.docNr);//value length + ++uitemp; + biox_CopyBlock(asynchBill.docNr,0,message,uitemp, biox_StrLen(asynchBill.docNr));//value + + uitemp += biox_StrLen(asynchBill.docNr)/* + 1*/; + + //Time + message[uitemp] = (UCHAR) biox_StrLen(tag5Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag5Name,0,message,uitemp, biox_StrLen(tag5Name));// tag name + uitemp += (1 + biox_StrLen(tag5Name)); + + iuc_asynchpos_sub_synchTime(); + message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length + ++uitemp; + biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value + + uitemp += biox_StrLen(asynchBill.time)/* + 1*/; + + //Language + message[uitemp] = (UCHAR) biox_StrLen(tag6Name);//data element, tag name length + ++uitemp; + biox_CopyBlock(tag6Name,0,message,uitemp, biox_StrLen(tag6Name));// tag name + uitemp += (1 + biox_StrLen(tag6Name)); + + message[uitemp] = (UCHAR) biox_StrLen(tag6Value);//value length + ++uitemp; + biox_CopyBlock(tag6Value,0,message,uitemp, biox_StrLen(tag6Value));//value + uitemp += biox_StrLen(tag6Value)/* + 1*/; + + iuc_asynchpos_send(packetType,message,uitemp,0x00); +} + int main() { -#if 1 +#if 0 MessageHelper msgHelp; - - - msgHelp.createLoginMessageChunksToSend(0x02); + // msgHelp.createLoginMessageChunksToSend(0x02); + msgHelp.createAuthorizeMessageChunksToSend(0x02); qCritical() << "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" << endl; - // return 0; // unsigned static char terminalID[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; // unsigned static char terminalAPAK[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; strncpy((char *)&terminalID[0], "T-TPS-SELF2002in", IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); strncpy((char *)&terminalAPAK[0], "8AC304380E0E476BA2558B75DB9E2516", IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); - iuc_asynchpos_command_Login(); + //iuc_asynchpos_command_Login(); + iuc_asynchpos_command_authorize(1000); + + qCritical() << "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"; return 0; // test aes @@ -829,7 +1057,6 @@ int main() { return 0; - CalcState cs; double cost; int durationInMinutes = 0; @@ -865,6 +1092,16 @@ int main() { } + /* + CalcState CALCULATE_LIBRARY_API compute_price_for_parking_ticket( + parking_tariff_t *tariff, + QDateTime &start_parking_time, + int netto_parking_time, + QDateTime &end_parking_time, // return value + struct price_t *price, // return value + bool prepaid = true); + */ + for (int minutes = 0; minutes < 1440; ++minutes) { QDateTime start = s.addSecs(minutes * 60); QDateTime effectiveStart = start;