/*! see CMultiXSession::OnDataReplyReceived this reply is for a message or an ACK previously received from the POS terminal. */ void CMultiplexerClientFEClientSession::OnDataReplyReceived(CMultiXAppMsg &ReplyMsg,CMultiXAppMsg &OriginalMsg) { DebugPrint(2,"Data Reply Received\n"); CMultiplexerClientFELink *pLink = GetLink(); if(!pLink) // probably the link was disconnected before the reply was received { int Error = ErrLinkDisconnected; // TODO: Set an application specific error code ReplyMsg.Reply(Error); return; } if(ReplyMsg.AppDataSize() == 0) // an empty reply from the server application { if(ReplyMsg.Error() != 0) pLink->OnSessionSendFailed(OriginalMsg,ReplyMsg.Error()); else pLink->OnSessionSendCompleted(OriginalMsg); ReplyMsg.Reply(); // just reply to the received msg, in case the sender expects a reply return; } // forward the reply to the associated link CMultiXBuffer *Buf = Owner()->AllocateBuffer(ReplyMsg.AppData(),ReplyMsg.AppDataSize()); pLink->OnSessionReply(*Buf,OriginalMsg); Buf->ReturnBuffer(); ReplyMsg.Reply(0); }
//! see CMultiXSession::OnDataReplyReceived void CISO8583BackEndServerSession::OnDataReplyReceived(CMultiXAppMsg &ReplyMsg,CMultiXAppMsg &ForwardedMsg) { DebugPrint(3,"Data Reply Received\n"); /* We get here when we receive a response for a message we forwarded before. In this case we will forward the response back to the originator, we do not care for the content, we forward it back almost AS IS except for few fields that we need to restore because changed them before we forwarded the message, the fields are: MTI - Convert it to 1993 version. BMP 7 - Set Transmission time BMP 11 - restore sender STAN BMP 12 - Restore sender Date and Time Local BMP 32 - Restore senders Acquiring Institution Identification Code */ /* In order to restore old values, we need to restore the message we received originaly from the acquirer or from the pos terminal. this message is saved in the SaveContext() of the ForwardedMsg. */ CMultiXAppMsg *AcquirerMsg = (CMultiXAppMsg *)ForwardedMsg.SavedContext(); CISO8583Msg AcquirerISO; CISO8583Msg ReplyISO; AcquirerISO.FromISO((const byte_t *)AcquirerMsg->AppData(),AcquirerMsg->AppDataSize()); ReplyISO.FromISO((const byte_t *)ReplyMsg.AppData(),ReplyMsg.AppDataSize()); ReplyISO.SetTimes(time(NULL),true); ReplyISO.SetDateTimeLocal(AcquirerISO.DateTimeLocal()); ReplyISO.SetSTAN(AcquirerISO.STAN()); ReplyISO.SetAcquiringInstitutionIdentificationCode(AcquirerISO.AcquiringInstitutionIdentificationCode()); ReplyISO.ToISO(); AcquirerMsg->Reply(CISO8583Msg::VersionDependentMTI(CISO8583Msg::ISO8583_2_1993,ReplyMsg.MsgCode()), ReplyISO.ISOBuffer(), ReplyISO.ISOBufferSize(),0,0,0,0,0,ReplyMsg.Error()); delete AcquirerMsg; // WE MUST DELETE THE MESSAGE BECAUSE WE CALLED "Keep()" BEFORE WE FORWARDED IT. /* we reply the ReplyMsg for the case that the process that replied to us expects to receive a notification that we received the reply, if it does not wait for the reply, no reply is sent. */ ReplyMsg.Reply(); }
//! see CMultiXSession::OnDataReplyReceived void CISO8583AuthorizerServerSession::OnDataReplyReceived(CMultiXAppMsg &ReplyMsg,CMultiXAppMsg &ForwardedMsg) { DebugPrint(3,"Data Reply Received\n"); switch(CISO8583Msg::VersionIndependentMTI(ForwardedMsg.MsgCode())) // this will give us version independent MTI { case CISO8583Msg::MTIAuthorizationMessageRequest : case CISO8583Msg::MTIFinancialMessageRequest : { CMultiXAppMsg *AcquirerMsg = (CMultiXAppMsg *)ForwardedMsg.SavedContext(); if(ReplyMsg.AppDataSize() == 0) { AcquirerMsg->Reply(ReplyMsg.Error()); delete AcquirerMsg; break; } CISO8583Msg AcquirerISO; CISO8583Msg ReplyISO; AcquirerISO.FromISO((const byte_t *)AcquirerMsg->AppData(),AcquirerMsg->AppDataSize()); ReplyISO.FromISO((const byte_t *)ReplyMsg.AppData(),ReplyMsg.AppDataSize()); /* before we send the reply, we need to check if it is MTI 200 and if the response is positive, if so : 1. we debit the issuer account for the sales amount + commission. in this sample we derive the issuer account from the PAN. 2. we credit our own account for these amounts 3. we write transactions log. */ if(CISO8583Msg::VersionIndependentMTI(AcquirerMsg->MsgCode()) == CISO8583Msg::MTIFinancialMessageRequest) { if(CISO8583Utilities::ToInt64(ReplyISO.ActionCode()) == 0) { double Amount = (double)CISO8583Utilities::ToInt64(ReplyISO.TransactionAmount())/100; int IssuerAccount = PANToIssuerAccount(AcquirerISO.PAN()); int MerchantAccount = (int)CISO8583Utilities::ToInt64(AcquirerISO.CardAcceptorIdentificationCode().StringData()); if(!UpdateAuthorizedSale(IssuerAccount,MerchantAccount,AcquirerISO.PAN(),Amount)) { AcquirerMsg->Reply(CISO8583Msg::RequestRejected); // SendReversalToIssuer(ReplyISO); not implemented delete AcquirerMsg; return; } } } else if(CISO8583Msg::VersionIndependentMTI(AcquirerMsg->MsgCode()) == CISO8583Msg::MTIAuthorizationMessageRequest) { int IssuerAccount = PANToIssuerAccount(AcquirerISO.PAN()); double Amount = (double)CISO8583Utilities::ToInt64(AcquirerISO.TransactionAmount())/100; mysqlpp::Transaction Tran(Owner()->DBConn()); mysqlpp::Query Query = Owner()->DBConn().query(); transactions_log Log; Log.Time = TomysqlppDateTime(time(NULL)); Log.AccountNumber = IssuerAccount; Log.CardNumber = AcquirerISO.PAN(); Log.Action = 11; // Query Log.Amount = Amount; Log.NewBalance = 0; Query.insert(Log); Query.execute(); Tran.commit(); } /* We get here when we receive a response for a message we forwarded before. In this case we will forward the response back to the originator, we do not care for the content, we forward it back almost AS IS except for few fields that we need to restore because changed them before we forwarded the message, the fields are: BMP 7 - Set Transmission time BMP 11 - restore sender STAN BMP 12 - Restore sender Date and Time Local BMP 32 - Restore senders Acquiring Institution Identification Code */ /* In order to restore old values, we need to restore the message we received originaly from the acquirer or from the pos terminal. this message is saved in the SaveContext() of the ForwardedMsg. */ ReplyISO.SetTimes(time(NULL),true); ReplyISO.SetSTAN(AcquirerISO.STAN()); ReplyISO.SetDateTimeLocal(AcquirerISO.DateTimeLocal()); ReplyISO.SetAcquiringInstitutionIdentificationCode(AcquirerISO.AcquiringInstitutionIdentificationCode()); ReplyISO.ToISO(); AcquirerMsg->Reply(AcquirerMsg->MsgCode(), ReplyISO.ISOBuffer(), ReplyISO.ISOBufferSize(),0,0,0,0,0,ReplyMsg.Error()); delete AcquirerMsg; // WE MUST DELETE THE MESSAGE BECAUSE WE CALLED "Keep()" BEFORE WE FORWARDED IT. } break; } /* we reply the ReplyMsg for the case that the process that replied to us expects to receive a notification that we received the reply, if it does not wait for the reply, no reply is sent. */ ReplyMsg.Reply(); }
bool CMultiXProcess::OnAppMsg(CMultiXMsg &Msg) { if(!ReceiverEnabled() || !SenderEnabled()) return false; CMultiXAppMsg *OrgMsg = NULL; CMultiXSession *Session = NULL; CMultiXAppMsg *AppMsg = CreateNewAppMsg(&Msg); //if(m_MsgCount++ == 1) // m_LastPrintTime = Owner()->GetMilliClock(); m_LastMsgRecvMilliClock = Owner()->GetMilliClock(); AddToMsgQueue(m_pInQueue,AppMsg); if(!AppMsg->ResponseRequired()) { if(AppMsg->NotifyAny()) AppMsg->Reply(MultiXNoError); } if(AppMsg->IsResponse()) { OrgMsg = AppMsg->ReceiverMsgID().GetObject(); if(OrgMsg != NULL) { Session = Owner()->FindSession(OrgMsg->SessionID()); OrgMsg->m_bKeep = false; OrgMsg->ID().RemoveObject(); if(AppMsg->AppDataSize() || OrgMsg->ResponseRequired()) { if(Session) { if(AppMsg->IsCtrlMsgFromTpm()) Session->OnDataReplyFromTpmReceived(*AppMsg,*OrgMsg); else Session->OnDataReplyReceivedNV(*AppMsg,*OrgMsg); } else { if(AppMsg->IsCtrlMsgFromTpm()) OnDataReplyFromTpmReceived(*AppMsg,*OrgMsg); else OnDataReplyReceived(*AppMsg,*OrgMsg); } } else if(AppMsg->Error()) { if(OrgMsg->NotifyError()) { if(Session) { if(AppMsg->IsCtrlMsgFromTpm()) Session->OnSendMsgToTpmFailed(*OrgMsg); else Session->OnSendMsgFailedNV(*OrgMsg); } else { if(AppMsg->IsCtrlMsgFromTpm()) OnSendMsgToTpmFailed(*OrgMsg); else OnSendMsgFailed(*OrgMsg); } } } else { if(OrgMsg->NotifySuccess()) { if(Session) { if(AppMsg->IsCtrlMsgFromTpm()) Session->OnSendMsgToTpmCompleted(*OrgMsg); else Session->OnSendMsgCompletedNV(*OrgMsg); } else { if(AppMsg->IsCtrlMsgFromTpm()) OnSendMsgToTpmCompleted(*OrgMsg); else OnSendMsgCompleted(*OrgMsg); } } } } else // it is a response but the original does not exist { AppMsg->Reply(TpmErrUnableToForwardMsg); } } else { Session = Owner()->FindSession(AppMsg->SessionID(),true); if(Session) { if(AppMsg->IsCtrlMsgFromTpm()) Session->OnNewMsgFromTpm(*AppMsg); else Session->OnNewMsgNV(*AppMsg); } else { if(AppMsg->IsCtrlMsgFromTpm()) OnNewMsgFromTpm(*AppMsg); else OnNewMsg(*AppMsg); } if(AppMsg->ResponseRequired() && !(AppMsg->ReplySent() || AppMsg->m_bKeep)) Throw(); } if(!(AppMsg->ReplySent() || AppMsg->m_bKeep)) { if(AppMsg->ResponseRequired()) Throw(); else if(AppMsg->NotifyAny()) AppMsg->Reply(MultiXNoError); } if(OrgMsg && !OrgMsg->m_bKeep) delete OrgMsg; if(!AppMsg->m_bKeep) delete AppMsg; return true; }