#include "stdafx.h" #include "ContactlessFSM.h" #include "EventCode.h" #include "ContactlessCard_msg_g.h" #include "ContactlessCard_UserErrorCode.h" #include "CommDevEntityErrorCode.h" #include #include "publicFunExport.h" #ifdef RVC_OS_WIN #else #include #endif //RVC_OS_WIN const int GET_DEV_STATUS_COUNT = 1; const int MAX_RESET_TIMES_PERIOD = 1000;//oiltest configure to ini file? const int MAX_RESET_TIMEROUT = 5000; const int WAIT_TRY_NUM = 120; const int WAIT_INTERVAL = 500; const int ACCEPT_TRY_INTERVAL = 500; const int ACCEPT_TRY_NUM = 110; // 500*110=55 seconds //const int READ_TRY_NUM = 1;//oiltest const int INIT_TRY_NUM = 1; class CContactlessCardEntity; void CContactlessCardFSM::s0_on_entry() { LOG_FUNCTION(); m_currentFSMState = 0; SetDevState(DEVICE_STATUS_NOT_READY); FSMEvent *e = new FSMEvent(USER_EVT_INIT); PostEventFIFO(e); } void CContactlessCardFSM::s0_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s0_on_event(FSMEvent* e) { LOG_FUNCTION(); if (e->iEvt == USER_EVT_INIT) { InitTask* task = new InitTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(task); e->SetHandled(); return 0; }else if (e->iEvt == USER_EVT_QUIT) { e->SetHandled(); return 0; } return 0; } void CContactlessCardFSM::s1_on_entry() { LOG_FUNCTION(); m_currentFSMState = 1; } void CContactlessCardFSM::s1_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s1_on_event(FSMEvent* event) { LOG_FUNCTION(); if (event->iEvt == USER_EVT_INITFINISHED) { event->SetHandled(); int err = event->param1; if (err == 0) { return 0; } else { return 1; } }else if (event->iEvt == USER_EVT_QUIT) { event->SetHandled(); return 0; } return 0; } //Idle void CContactlessCardFSM::s2_on_entry() { LOG_FUNCTION(); m_currentFSMState = 2; SetDevState(DEVICE_STATUS_NORMAL); m_resetTimes = 0; m_testResult = Error_Succeed; } void CContactlessCardFSM::s2_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s2_on_event(FSMEvent* pEvt) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("s2 evt(%d)",pEvt->iEvt); int ret = 0; switch(pEvt->iEvt) { case USER_EVT_JS_READ: { ReadJSEvent* rje = dynamic_cast(pEvt); m_bCancelRead = false; m_bPageExit = false; ReadJSTask* task = new ReadJSTask(this); task->ctx = rje->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); } break; case USER_EVT_JS_EJECT: { EjectJSEvent* eje = dynamic_cast(pEvt); m_bPageExit = false; EjectJSTask* task = new EjectJSTask(this); task->ctx = eje->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); } break; case USER_EVT_JS_POSTONLINE: { PostOnlineJSEvent* pje = dynamic_cast(pEvt); m_bCancelRead = false; m_bPageExit = false; PostOnlineJSTask* task = new PostOnlineJSTask(this); task->ctx = pje->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); } break; case USER_EVT_JS_READ_CANCEL: { m_bCancelRead = true; pEvt->SetHandled(); } break; case USER_EVT_ACCEPT: { CardAcceptEvent *cae = dynamic_cast(pEvt); m_bCancelAccept = false; AcceptTask* task = new AcceptTask(this); task->ctx = cae->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); } break; case USER_EVT_QUERY_CARD_INFO: { pEvt->SetHandled(); QueryCardInfoEvent *pQCIE = dynamic_cast(pEvt); QueryCardInfoTask* task = new QueryCardInfoTask(this); task->ctx = pQCIE->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_EJECT: { CardEjectEvent *cee; if (pEvt->iEvt == USER_EVT_EJECT) cee = dynamic_cast(pEvt); EjectTask *task= new EjectTask(this); if (pEvt->iEvt == USER_EVT_EJECT) task->ctx = cee->ctx; else task->ctx = NULL; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); return 0; } case USER_EVT_EXIT: m_bExit = true; pEvt->SetHandled(); break; case USER_EVT_QUIT: pEvt->SetHandled(); break; default: break; } return ret; } //accepting void CContactlessCardFSM::s3_on_entry() { LOG_FUNCTION(); m_currentFSMState = 3; } void CContactlessCardFSM::s3_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s3_on_event(FSMEvent* pEvt) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("s3 evt (%d,%d)",pEvt->iEvt,pEvt->param1); int ret = 0; switch(pEvt->iEvt) { case USER_EVT_ACCEPTFINISHED: { pEvt->SetHandled(); switch(pEvt->param1) { case 0: case 1: case 2: case 3: case 4: ret = pEvt->param1; break; default: ret = 1; break; } } break; case USER_EVT_ACCEPT_CANCEL: m_bCancelAccept = true; pEvt->SetHandled(); ret = 3; break; case USER_EVT_QUERY_CARD_INFO: { pEvt->SetHandled(); QueryCardInfoEvent *pQCIE = dynamic_cast(pEvt); QueryCardInfoTask* task = new QueryCardInfoTask(this); task->ctx = pQCIE->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_EXIT: m_bExit = true; pEvt->SetHandled(); break; case USER_EVT_QUIT: pEvt->SetHandled(); break; default: break; } return ret; } //Hold void CContactlessCardFSM::s4_on_entry() { LOG_FUNCTION(); m_currentFSMState = 4; } void CContactlessCardFSM::s4_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s4_on_event(FSMEvent* pEvt) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("s4 evt(%d,%d)",pEvt->iEvt,pEvt->param1); switch(pEvt->iEvt){ case USER_EVT_ACCEPT: { CardAcceptEvent *cae = dynamic_cast(pEvt); m_bCancelAccept = false; AcceptTask* task = new AcceptTask(this); task->ctx = cae->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); } break; case USER_EVT_PREONLINE: { PreOnlineEvent* poe = dynamic_cast(pEvt); PreOnlineTask* task = new PreOnlineTask(this); task->ctx = poe->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); return 0; } case USER_EVT_POSTONLINE: { PostOnlineEvent* poe = dynamic_cast(pEvt); PostOnlineTask* task = new PostOnlineTask(this); task->ctx = poe->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); return 0; } case USER_EVT_EXIT: case USER_EVT_EJECT: { pEvt->SetHandled(); CardEjectEvent *cee; if (pEvt->iEvt == USER_EVT_EJECT) cee = dynamic_cast(pEvt); EjectTask *task= new EjectTask(this); if (pEvt->iEvt == USER_EVT_EJECT) task->ctx = cee->ctx; else task->ctx = NULL; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_QUERY_CARD_INFO: { pEvt->SetHandled(); QueryCardInfoEvent *pQCIE = dynamic_cast(pEvt); QueryCardInfoTask* task = new QueryCardInfoTask(this); task->ctx = pQCIE->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_QUERY_CARD_INFO_FINISHED: { pEvt->SetHandled(); if (pEvt->param1 == 0) return 0; else return 1; } case USER_EVT_QUIT: { pEvt->SetHandled(); return 0; } case USER_EVT_ACCEPT_CANCEL: m_bCancelAccept = true; pEvt->SetHandled(); default: break; } return 0; } //Reading void CContactlessCardFSM::s5_on_entry() { LOG_FUNCTION(); m_currentFSMState = 5; } void CContactlessCardFSM::s5_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s5_on_event(FSMEvent* pEvt) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("s5 event(%d)",pEvt->iEvt); switch(pEvt->iEvt) { case USER_EVT_EXIT: { EjectTask *task= new EjectTask(this); task->ctx = NULL; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); pEvt->SetHandled(); return 0; } break; case USER_EVT_QUIT: { pEvt->SetHandled(); return 0; } default: break; } return 0; } //Ejecting void CContactlessCardFSM::s6_on_entry() { LOG_FUNCTION(); m_currentFSMState = 6; } void CContactlessCardFSM::s6_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s6_on_event(FSMEvent* pEvt) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("s6 evt(%d,%d)",pEvt->iEvt,pEvt->param1); int ret = 0; switch(pEvt->iEvt) { case USER_EVT_EJECTFINISHED: pEvt->SetHandled(); ret = pEvt->param1; break; case USER_EVT_QUIT: case USER_EVT_EXIT: pEvt->SetHandled(); break; default: break; } return ret; } void CContactlessCardFSM::s7_on_entry() { LOG_FUNCTION(); m_currentFSMState = 7; WaitFetchingTask* task = new WaitFetchingTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(task); } void CContactlessCardFSM::s7_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s7_on_event(FSMEvent* pEvt) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("s7 evt(%d)",pEvt->iEvt); switch(pEvt->iEvt) { case USER_EVT_WAITFINISHED: { pEvt->SetHandled(); if (pEvt->param1 == 0) { FetchCard evt; evt.status = 0; SpSendBroadcast(m_pEntity->GetFunction(),SP_MSG_OF(FetchCard),SP_MSG_SIG_OF(FetchCard),evt); LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_OP,"ContactlessCard op."); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("客户取走卡片msg发送"); return 0; } else if (pEvt->param1 == 1) { //FetchCard evt; //evt.status = 1; //SpSendBroadcast(m_pEntity->GetFunction(),SP_MSG_OF(FetchCard),SP_MSG_SIG_OF(FetchCard),evt); //Dbg("取卡时设备故障"); //return 1; } else { FetchCard evt; evt.status = 2; SpSendBroadcast(m_pEntity->GetFunction(),SP_MSG_OF(FetchCard),SP_MSG_SIG_OF(FetchCard),evt); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("客户未取卡超时msg发送"); LogWarn(Severity_Middle, Error_NotInit, ContactlessCard_UserErrorCode_FORGET_FETCH, "Customer forget fetch card."); return 2; } } case USER_EVT_QUERY_CARD_INFO: { pEvt->SetHandled(); QueryCardInfoEvent *pQCIE = dynamic_cast(pEvt); QueryCardInfoTask* task = new QueryCardInfoTask(this); task->ctx = pQCIE->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_QUIT: { pEvt->SetHandled(); return 0; } default: break; } return 0; } //capture void CContactlessCardFSM::s8_on_entry() { LOG_FUNCTION(); m_currentFSMState = 8; } void CContactlessCardFSM::s8_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s8_on_event(FSMEvent* pEvt) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("s8 evt(%d)",pEvt->iEvt); if (pEvt->iEvt == USER_EVT_CAPTUREFINISHED){ pEvt->SetHandled(); int err = pEvt->param1; if (err == 0) return 0; else return 1; }else if (pEvt->iEvt == USER_EVT_QUIT) { pEvt->SetHandled(); return 0; } return 0; } void CContactlessCardFSM::s9_on_entry() { LOG_FUNCTION(); m_currentFSMState = 9; SetDevState(DEVICE_STATUS_FAULT); if (m_bNeedReset) { FSMEvent* e = new FSMEvent(USER_EVT_RESET); PostEventFIFO(e); } else { m_testResult = Error_InvalidState; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("device is fault, wait for restart entity"); } } void CContactlessCardFSM::s9_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s9_on_event(FSMEvent* pEvt) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("s9 evt(%d)(%d)",pEvt->iEvt, pEvt->param1); switch(pEvt->iEvt) { case USER_EVT_RESET: { pEvt->SetHandled(); m_resetTimes++; if (m_resetTimes > MAX_RESET_TIMES_PERIOD) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("restart tried %d times,give up",m_resetTimes); m_testResult = Error_InvalidState; LogWarn(Severity_Middle,Error_Unexpect, ContactlessCard_UserErrorCode_Reset_Failed,"reset failed more times"); return 0; } ResetDeviceEvent* rde = dynamic_cast(pEvt); ResetTask* task = new ResetTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } break; case USER_EVT_RESETFINISHED: { ResetFinishedEvent *rfe = dynamic_cast(pEvt); return rfe->param1; } case USER_EVT_QUERY_CARD_INFO: { pEvt->SetHandled(); QueryCardInfoEvent *pQCIE = dynamic_cast(pEvt); QueryCardInfoTask* task = new QueryCardInfoTask(this); task->ctx = pQCIE->ctx; GetEntityBase()->GetFunction()->PostThreadPoolTask(task); return 0; } case USER_EVT_QUIT: pEvt->SetHandled(); return 0; case USER_EVT_ACCEPT_CANCEL: m_bCancelAccept = true; pEvt->SetHandled(); break; default: break; } return 0; } void CContactlessCardFSM::s10_on_entry() { LOG_FUNCTION(); m_currentFSMState = 10; } void CContactlessCardFSM::s10_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s10_on_event(FSMEvent* pEvt) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("s10 event(%d)", pEvt->iEvt); int ret = 0; switch (pEvt->iEvt) { case USER_EVT_JS_READ_FINISHED: { pEvt->SetHandled(); ret = 0; } break; case USER_EVT_JS_POSTONLINEFINISHED: { pEvt->SetHandled(); ret = 0; } break; case USER_EVT_JS_READ_CANCEL: { m_bCancelRead = true; pEvt->SetHandled(); ret = 0; } break; case EVT_MAINPAGE_DISPLAY: { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("S10 receive exit to main page"); m_bPageExit = true; pEvt->SetHandled(); ret = 0; } break; default: break; } return ret; } void CContactlessCardFSM::s11_on_entry() { LOG_FUNCTION(); m_currentFSMState = 11; } void CContactlessCardFSM::s11_on_exit() { LOG_FUNCTION(); } unsigned int CContactlessCardFSM::s11_on_event(FSMEvent* pEvt) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("s11 event(%d)", pEvt->iEvt); int ret = 0; switch (pEvt->iEvt) { case USER_EVT_JS_EJECTFINISHED: { pEvt->SetHandled(); ret = pEvt->param1; } break; case EVT_MAINPAGE_DISPLAY: { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("S11 receive exit to main page"); m_bPageExit = true; pEvt->SetHandled(); ret = 0; } break; default: break; } return ret; } ErrorCodeEnum CContactlessCardFSM::OnInit() { LOG_FUNCTION(); AddStateHooker(this); auto pEntity = GET_DEV_ENTITY_BASE_POINTER(); pEntity->InitializeVendorLogSwitch(); FulfillAdapterInfoFrom(pEntity->vendorLibInfo); m_pCardProcess = new CCardProcess(); if (m_pCardProcess == NULL)//almost no use... { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J19")("create card process failed."); return Error_Resource; } CSystemStaticInfo sysInfo; m_csMachineType = ""; GetEntityBase()->GetFunction()->GetSystemStaticInfo(sysInfo); m_csMachineType = sysInfo.strMachineType; m_bOpening = true; ErrorCodeEnum errCode = Load(); if (errCode != Error_Succeed) { //DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Load failed(%d).",errCode); SetDevInitFlag(false);//打开失败 } devStatus.eMediaPos = CI_MEDIA_NOTPRESENT; m_bOpening = false; return Error_Succeed; } ErrorCodeEnum CContactlessCardFSM::OnExit() { LOG_FUNCTION(); ErrorCodeEnum eExit; long l_beginTime, l_endTime; if (m_hDevHelper != nullptr) { l_beginTime = SP::Module::Comm::RVCGetTickCount(); eExit = m_hDevHelper->GetDevStatus(devStatus); l_endTime = SP::Module::Comm::RVCGetTickCount(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("OnExit::GetDevStatus eMedia:%d, eErr:%d", devStatus.eMediaPos, eExit); if (eExit == Error_Succeed) { if (devStatus.eMediaPos == CI_MEDIA_PRESENT){ } } l_beginTime = SP::Module::Comm::RVCGetTickCount(); eExit = m_hDevHelper->DevClose(); l_endTime = SP::Module::Comm::RVCGetTickCount(); if (eExit == Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::DevClose").setCostTime(l_endTime - l_beginTime)("读卡器关闭成功"); } else{ SetErrorAndLog(eExit, MEC_DEVAPI_RF_DevClose, "DevAdapter::DevClose", __FUNCTION__, false, l_endTime - l_beginTime, "", "读卡器关闭失败"); } } FSMImpl::OnExit(); return Error_Succeed; } ErrorCodeEnum CContactlessCardFSM::Load() { LOG_FUNCTION(); ErrorCodeEnum hr; long l_beginTime, l_endTime; int initTries = 0; ErrorCodeEnum eErrDev = Error_Unexpect; CSimpleString errMsg(true); CSmartPointer spEntityFunction = GetEntityBase()->GetFunction(); CSmartPointer spConfig; CSimpleStringA csBinPath,csBackslash("\\"); ErrorCodeEnum eErrPath = GetEntityBase()->GetFunction()->GetPath("Bin", csBinPath); if (eErrPath != Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Load, GetBasePath failed (%d).",eErrPath); return Error_Param; } LogWarn(Severity_Low, Error_Unexpect, ContactlessCard_UserErrorCode_RootInfo, m_adapterInfo.adapterFilePath.GetData()); if (Error_Succeed != LoadUpAdapterLibrary()) { errMsg = "非接读卡器加载厂商适配器失败!请检查root.ini配置是否正确。"; LogWarn(Severity_Middle, Error_Unexpect, ContactlessCard_UserErrorCode_DllLoadFailed, errMsg.GetData()); return Error_DevLoadFileFailed; } do{ l_beginTime = SP::Module::Comm::RVCGetTickCount(); hr = m_hDevHelper->DevOpen(m_adapterInfo.GetPortInt(), m_adapterInfo.GetBaudrateInt()); l_endTime = SP::Module::Comm::RVCGetTickCount(); if (hr == Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::DevOpen").setCostTime(l_endTime - l_beginTime)("ContactlessCard DevOpen succ , dwPort:%d, dwBaudRate:%d", m_adapterInfo.GetPortInt(), m_adapterInfo.GetBaudrateInt()); SetDevInitFlag(); ZeroMemory(m_devCatInfo.szModel, sizeof(m_devCatInfo.szModel)); ZeroMemory(m_devCatInfo.szType, sizeof(m_devCatInfo.szType)); ZeroMemory(m_devCatInfo.szVendor, sizeof(m_devCatInfo.szVendor)); l_beginTime = SP::Module::Comm::RVCGetTickCount(); eErrDev = m_hDevHelper->GetDevCategory(m_devCatInfo); l_endTime = SP::Module::Comm::RVCGetTickCount(); if(eErrDev == Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::GetDevCategory").setCostTime(l_endTime - l_beginTime)("OpenDevice::GetDevCategory"); m_adapterInfo.FulfillCategoryInfo(m_devCatInfo); } else { SetErrorAndLog(eErrDev, MEC_DEVAPI_RF_GetDevCategory, "DevAdapter::GetDevCategory", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); return Error_DevCommFailed; } if (!LoadCMBPrint(csBinPath)) { errMsg = CSimpleStringA::Format("Contactless 启动失败:Load CMBPrint failed."); LogWarn(Severity_Middle, Error_Unexpect, ContactlessCard_UserErrorCode_DllLoadFailed, errMsg.GetData()); return Error_DevLoadFileFailed; } initTries = 0; break; } else { //DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("ContactlessCard DevOpen failed ,重试:%d, dwPort:%d, dwBaudRate:%d", initTries, m_adapterInfo.GetPortInt(), m_adapterInfo.GetBaudrateInt()); CSimpleStringA errmsg = CSimpleStringA::Format("ContactlessCard DevOpen failed ,重试:%d, dwPort:%d, dwBaudRate:%d", initTries, m_adapterInfo.GetPortInt(), m_adapterInfo.GetBaudrateInt()); SetErrorAndLog(hr, MEC_DEVAPI_RF_DevOpen, "DevAdapter::DevOpen", __FUNCTION__, false, l_endTime - l_beginTime, "", errmsg.GetData()); //DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("ContactlessCard 启动失败:DevOpen failed.重试:%d", initTries); initTries++; } } while (initTries < INIT_TRY_NUM); if (initTries != 0) { if (m_bOpened) { m_hDevHelper->DevClose(); SetDevInitFlag(false); } errMsg = CSimpleStringA::Format("非接读卡器启动失败,have tried %d times!!!", initTries); LogWarn(Severity_Middle, Error_Unexpect, ContactlessCard_UserErrorCode_DevOpen_Failed, errMsg.GetData()); return Error_DevCommFailed; } else { m_devInit = true; LogWarn(Severity_Low, Error_Unexpect, ContactlessCard_UserErrorCode_DevOpen_Success, "非接读卡器打开成功"); return Error_Succeed; } } int CContactlessCardFSM::Initial() { if (!m_bOpened) { m_bNeedReset = false; return 1;//故障模式 } return 0; } bool CContactlessCardFSM::GetDevStatus(bool bPrint) { int getDevInfoCount = 0; long l_beginTime, l_endTime; ErrorCodeEnum eErr; do{ l_beginTime = SP::Module::Comm::RVCGetTickCount(); eErr = m_hDevHelper->GetDevStatus(devStatus); l_endTime = SP::Module::Comm::RVCGetTickCount(); //if (bPrint) // DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("GetDevStatus eMedia:%d, eErr:%d", devStatus.eMediaPos, eErr); if (Error_Succeed == eErr) { if (bPrint) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::GetDevStatus").setCostTime(l_endTime - l_beginTime)("GetDevStatus eMedia:%d", devStatus.eMediaPos); } return true; } else { //DevErrorInfo devErrInfo; //m_hDevHelper->GetLastErr(devErrInfo); //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("GetDevStatus, errMsg:%s",devErrInfo.szErrMsg); if (bPrint) { SetErrorAndLog(eErr, MEC_DEVAPI_RF_GetDevStatus, "DevAdapter::GetDevStatus", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); } getDevInfoCount++; Sleep(3000); } } while (getDevInfoCount < GET_DEV_STATUS_COUNT); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("get devstatus to reset"); eErr = m_hDevHelper->Reset(); Sleep(MAX_RESET_TIMEROUT); if (eErr == Error_Succeed) { eErr = m_hDevHelper->GetDevStatus(devStatus); if (eErr == Error_Succeed && devStatus.eMediaPos == CI_MEDIA_PRESENT) { } } return false; } int CContactlessCardFSM::Reset() { LOG_FUNCTION(); ErrorCodeEnum eErr; long l_beginTime, l_endTime; l_beginTime = SP::Module::Comm::RVCGetTickCount(); eErr = m_hDevHelper->Reset(); l_endTime = SP::Module::Comm::RVCGetTickCount(); if (eErr == Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::Reset").setCostTime(l_endTime - l_beginTime)("Reset succ"); l_beginTime = SP::Module::Comm::RVCGetTickCount(); eErr = m_hDevHelper->GetDevStatus(devStatus); l_endTime = SP::Module::Comm::RVCGetTickCount(); if (Error_Succeed == eErr) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::GetDevStatus").setCostTime(l_endTime - l_beginTime)("Reset::GetDevStatus,eMedia:%d", devStatus.eMediaPos); return 0; } else{ SetErrorAndLog(eErr, MEC_DEVAPI_RF_GetDevStatus, "DevAdapter::GetDevStatus", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); return 2; } } else { SetErrorAndLog(eErr, MEC_DEVAPI_RF_Reset, "DevAdapter::Reset", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); return 1; } } int CContactlessCardFSM::InternalAcceptCard() { LOG_FUNCTION(); int acceptTries = 0, err = 0; m_bWaitingAccept = true; DWORD64 dwStart = SP::Module::Comm::RVCGetTickCount(); DWORD64 dwEnd = dwStart; do { if (m_bExit) { m_bCancelAccept = true; break; } if (m_bCancelAccept) { err = 3; goto Err; } if (m_bWaitAccepteMore) { acceptTries = 0; m_bWaitAccepteMore = false; dwEnd = dwStart = SP::Module::Comm::RVCGetTickCount(); } if (GetDevStatus(false)) { if (devStatus.eMediaPos == CI_MEDIA_RF) { LogEvent(Severity_Middle, LOG_EVT_CONTACTLESS_CARD_OP, "Contactless card op."); acceptTries = 0; goto Err; } else { acceptTries++; Sleep(ACCEPT_TRY_INTERVAL); } } else { err = 1; goto Err; } dwEnd = SP::Module::Comm::RVCGetTickCount(); } while (dwEnd - dwStart <= 55 * 1000); err = 2; Err: m_bExit = false; m_bWaitingAccept = false; if (m_bCancelAccept && err != 1) { if (GetDevStatus()) { if (devStatus.eMediaPos == CI_MEDIA_PRESENT) { err = 4; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("cancel eject......"); } } else err = 2; } return err; } int FindHexCharPosition(LPBYTE data, BYTE hexChar, int len) { int notExist = -1,ret = 1,pos = 0; for (; pos < len; ++pos) { BYTE high = (*(data+pos))&0xf0; BYTE low = (*(data+pos))&0x0f; if ((high>>4) != hexChar) ret++; else return ret; if (low != hexChar) ret++; else return ret; } ret = notExist; return ret; } int CContactlessCardFSM::AcceptCard(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); long l_beginTime, l_endTime; ctx->Ans.ICType = 0; m_pCardProcess->DataInit(); LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_ON,"ContactCard green on"); m_bWaitAccepteMore = false; int rc = InternalAcceptCard(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("InternalAcceptCard ret:%d", rc); LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_OFF,"ContactCard green off"); if (rc == 0) { if (ctx != NULL) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("insert error_succeed"); //FetchCard evt; //evt.status = 3;//oilyang@20181210 用于通知卡机取消插卡 //SpSendBroadcast(m_pEntity->GetFunction(), SP_MSG_OF(FetchCard), SP_MSG_SIG_OF(FetchCard), evt); ctx->Ans.ICData = ""; int activeCardType; //int retICData = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_RFIC, m_hDevHelper, "A000000333", activeCardType); //oilyang@20201014 add emv card support int retDetectAndRead = -1; if (!ctx->Req.aid.IsNullOrEmpty()) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("front business provide aid:[%s]",(const char*)ctx->Req.aid); CAutoArray aidReq; aidReq.Init(1); aidReq[0] = ctx->Req.aid; l_beginTime = SP::Module::Comm::RVCGetTickCount(); retDetectAndRead = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_RFIC, m_hDevHelper, aidReq, activeCardType); l_endTime = SP::Module::Comm::RVCGetTickCount(); } else { l_beginTime = SP::Module::Comm::RVCGetTickCount(); retDetectAndRead = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_RFIC, m_hDevHelper, m_aidList, activeCardType); l_endTime = SP::Module::Comm::RVCGetTickCount(); } if (retDetectAndRead < 0) { // -1和-2是上电或APDU交互失败,功能集循环调用 if (retDetectAndRead == -1){ if (!ctx->Req.reserved1.IsNullOrEmpty() && ctx->Req.reserved1.Compare("P") == 0) { SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_RF_ActiveContactlessICCard, "DevAdapter::ActiveContactlessICCard", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); } ctx->Answer(Error_Interact, GetAlarmDEC()); } else if (retDetectAndRead == -2){ if (!ctx->Req.reserved1.IsNullOrEmpty() && ctx->Req.reserved1.Compare("P") == 0) { SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_RF_RFTypeABCommand, "DevAdapter::RFTypeABCommand", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); } ctx->Answer(Error_Interact, GetAlarmDEC()); }else if (retDetectAndRead == -3){ if (!ctx->Req.reserved1.IsNullOrEmpty() && ctx->Req.reserved1.Compare("P") == 0) { SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_RF_RFTypeABCommand, "DevAdapter::RFTypeABCommand", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); } ctx->Answer(Error_Interact, GetAlarmDEC()); } return 2; } ctx->Ans.t2Account = ctx->Ans.ICData = ""; ICData track2(false,0x57,0x00); ErrorCodeEnum eErr = Error_Unexpect; string t2ICAccount(""),t2ICCardSerial(""),t2ICCVC(""),t2ICTrack2(""),cardType; if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC,track2,false,0) == -1) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("no track2 data in ic"); l_beginTime = SP::Module::Comm::RVCGetTickCount(); eErr = m_hDevHelper->HaltCard(); l_endTime = SP::Module::Comm::RVCGetTickCount(); if(Error_Succeed != eErr){ if (!ctx->Req.reserved1.IsNullOrEmpty() && ctx->Req.reserved1.Compare("P") == 0) { SetErrorAndLog(eErr, MEC_DEVAPI_RF_HaltCard, "DevAdapter::HaltCard", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); } } ctx->Answer(Error_Interact);//can't find track2,retry 20150128 } else { int pos = FindHexCharPosition(track2.value, 0x0d, track2.lenth); char *pICTrack2 = new char[128]; ZeroMemory(pICTrack2, 128); HexBuf2StrBuf(track2.value, &pICTrack2, track2.lenth); pICTrack2[37] = '\0'; char *ddd = new char[128]; memset(ddd, 0, 128); memcpy(ddd, pICTrack2, pos - 1); t2ICTrack2 = pICTrack2; t2ICAccount = (char*)ddd;//oiltest LogWarn(Severity_Low, Error_Succeed, ContactlessCard_UserErrorCode_ReadAccount, CSimpleStringA::Format("split pos:%d, card acount:%s,%s" , pos, t2ICAccount.substr(0, 6).c_str(), t2ICAccount.substr(t2ICAccount.length() - 4, 4).c_str())); ctx->Ans.ICData = ctx->Ans.t2Account = t2ICAccount.c_str(); ctx->Ans.ICType = 4; ctx->Ans.status = 0; delete[]ddd; delete[]pICTrack2; //m_hDevHelper->DeactContactlessICCard(); } ctx->Answer(Error_Succeed); } } else if(rc == 2) { if (ctx != NULL) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("AcceptCard, insert timeout"); ctx->Answer(Error_TimeOut); } } else if(rc == 3 || rc == 4) { if (ctx != NULL) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("AcceptCard, insert cancel"); ctx->Answer(Error_Cancel); } }else { //oilyang@20221212 //actully,we reach here only when calling GetDevStatus failed //we have ContactlessCard AND 卡机,no need to throw Error_Unexpect here if (ctx != NULL) ctx->Answer(Error_DevNotAvailable); } return rc; } static CSimpleStringA GetStrData(TrackInfo trackInfo) { //LOG_FUNCTION(); CSimpleStringA strRet; switch (trackInfo.eStatus) { case CI_DATA_OK: strRet = (char*)trackInfo.data; break; case CI_DATA_INVALID: strRet = "无效数据"; break; //case CI_DATA_MISSING: default: strRet = "数据丢失"; } return strRet; } int CContactlessCardFSM::SplitTrack2(CSimpleStringA pTrack2,Track2Data &decodeData) { LOG_FUNCTION(); int dataLen = strlen(pTrack2); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)(", pTrack2.len:%d", dataLen); if (pTrack2.GetLength() == 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J1A")(", pTrack2.len=0"); return -1; } switch(dataLen) { case 28: decodeData.t2Region = CSimpleString(pTrack2,4); decodeData.t2Account = pTrack2.SubString(4,8); decodeData.t2CardSerial = pTrack2.SubString(14,8);//oilyang for 8 onecard decodeData.t2CVC = pTrack2.SubString(22,6); decodeData.t2ExpireDate = ""; break; case 31: decodeData.t2Account = CSimpleString(pTrack2,16); decodeData.t2CardSerial = pTrack2.SubString(16,1); decodeData.t2CVC = pTrack2.SubString(17,6); decodeData.t2Region = pTrack2.SubString(23,4); decodeData.t2ExpireDate = pTrack2.SubString(27,4); break; case 25://AE Card decodeData.t2Account = CSimpleString(pTrack2, 15); decodeData.t2CardSerial = pTrack2.SubString(15, 1); decodeData.t2CVC = pTrack2.SubString(16, 5); decodeData.t2ExpireDate = pTrack2.SubString(21, 4); decodeData.t2Region = ""; break; case 38: DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)(", pTrack2.len=38 Not implemented "); break; default: DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)(", pTrack2.len=%d Not implemented ", dataLen); return -1; } decodeData.status = 0; return 0; } int CContactlessCardFSM::PreOnline(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); long l_beginTime, l_endTime; m_pCardProcess->DataInit(); m_pCardProcess->SplitBusinessData(ctx->Req.businessData,ctx->Req.businessData.GetLength()); m_pCardProcess->SplitBusinessData("DF690101",strlen("DF690101")); int activeCardType; //oilyang@20201014 add emv card support int retDetectAndRead = -1; ICData aidFromBus(false, 0x4f, 0x00); if (m_pCardProcess->FindTagValue(TAG_VECTOR_BUS, aidFromBus, false, 0) == -1) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("the front BusinessData han't provide aid data."); retDetectAndRead = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_RFIC, m_hDevHelper, m_aidList, activeCardType); } else { char* pAIDTmp = new char[64]; memset(pAIDTmp, 0, 64); HexBuf2StrBuf(aidFromBus.value, &pAIDTmp, aidFromBus.lenth); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)(", the aid is[%s],len:%d .", pAIDTmp, strlen(pAIDTmp)); CAutoArray preAIDs; preAIDs.Init(1); preAIDs[0] = (CSimpleStringA)pAIDTmp; l_beginTime = SP::Module::Comm::RVCGetTickCount(); retDetectAndRead = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_RFIC, m_hDevHelper, preAIDs, activeCardType); l_endTime = SP::Module::Comm::RVCGetTickCount(); if (pAIDTmp != NULL) delete[]pAIDTmp; } if (retDetectAndRead < 0) { // -1和-2是上电或APDU交互失败,功能集循环调用 if (retDetectAndRead == -1){ if (!ctx->Req.reserved1.IsNullOrEmpty() && ctx->Req.reserved1.Compare("P") == 0) { SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_RF_ActiveContactlessICCard, "DevAdapter::ActiveContactlessICCard", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); } ctx->Answer(Error_Interact, GetAlarmDEC()); } else if (retDetectAndRead == -2){ if (!ctx->Req.reserved1.IsNullOrEmpty() && ctx->Req.reserved1.Compare("P") == 0) { SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_RF_RFTypeABCommand, "DevAdapter::RFTypeABCommand", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); } ctx->Answer(Error_Interact, GetAlarmDEC()); }else if (retDetectAndRead == -3){ if (!ctx->Req.reserved1.IsNullOrEmpty() && ctx->Req.reserved1.Compare("P") == 0) { SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_RF_RFTypeABCommand, "DevAdapter::RFTypeABCommand", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); } ctx->Answer(Error_Interact, GetAlarmDEC()); } return 0; } //if (m_cardType == CI_CARDTYPE_IC) //{ // ProcessRestrict(); // CardholderVerify(); m_pCardProcess->TermRiskManage(); CSimpleStringA taaResult; BYTE bt9f27 = 0; int retTAA = m_pCardProcess->TermActionAnalyze(CARD_MACHINE_RFIC,m_hDevHelper,taaResult,true,m_bCDA,bt9f27); if (retTAA != 0) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)(", TermActionAnalyze , retTAA:%d, taaResult:%s", retTAA, taaResult.GetData()); } switch(retTAA) {//to be added oiltest 20140929 case -1: //some data may be wrong break; case 1: //terminal trans break; case 2: //to do trans end "TransEnd" break; default: break; } ctx->Ans.result = taaResult; if (ctx->Ans.result.GetLength() == 0) { ctx->Answer(Error_Succeed); return 0; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)(", term action analyze result[%s]",(const char*)ctx->Ans.result); string tmpResult, actionType, result = "", baseICData = ""; tmpResult = ctx->Ans.result; char *pSomeICData = new char[1024]; ZeroMemory(pSomeICData, 1024); int lenRet = m_pCardProcess->ConstructARQCData(tmpResult.substr(6, 4).c_str(), m_pDataToARQC, pSomeICData); baseICData = pSomeICData; if (pSomeICData != NULL) delete[]pSomeICData; char arqcLen[8]; ZeroMemory(arqcLen,sizeof(arqcLen)); //TODO: CrossPlaform [Gifur@2025729] #ifdef RVC_OS_WIN itoa(lenRet, arqcLen, 10); #else sprintf(arqcLen, "%d", lenRet); #endif // RVC_OS_WIN ICData appExpiryDate(false,0x5f,0x24); if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC,appExpiryDate,false,0) == -1) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J1B")("can't find expire date"); return 0; } char *pExpireDate = new char[12]; ZeroMemory(pExpireDate,12); HexBuf2StrBuf(appExpiryDate.value,&pExpireDate,appExpiryDate.lenth); ICData track2(false,0x57,0x00),ICCardSerial(false,0x5f,0x34); ErrorCodeEnum eErr = Error_Unexpect; string t2ICAccount(""),t2ICCardSerial(""),t2ICCVC(""),t2ICTrack2(""),cardType("0"); char *pICCardSerial = new char[4]; ZeroMemory(pICCardSerial,4); if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC,ICCardSerial,false) == -1) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J1B")("can't find card serial."); } else { HexBuf2StrBuf(ICCardSerial.value,&pICCardSerial,ICCardSerial.lenth); } if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC,track2,false,0) == -1) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("no track2 data in ic"); } else { int pos = FindHexCharPosition(track2.value,0x0d,track2.lenth); char *pICTrack2 = new char[128]; ZeroMemory(pICTrack2,128); HexBuf2StrBuf(track2.value,&pICTrack2,track2.lenth); pICTrack2[37] = '\0'; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)(", split pos:%d", pos); char *ddd = new char[40]; ZeroMemory(ddd,40); memcpy(ddd,pICTrack2,pos-1); char icTrack2Data[128]; ZeroMemory(icTrack2Data,sizeof(icTrack2Data)); Track2Data track2Data; track2Data.status = 0; track2Data.t2Account = ""; cmdDecodeMag2(pICTrack2,icTrack2Data); if (SplitTrack2(icTrack2Data,track2Data) == 0) { t2ICAccount = track2Data.t2Account; //t2ICCardSerial = track2Data.t2CardSerial; t2ICCVC = track2Data.t2CVC; t2ICTrack2 = pICTrack2; } //} if (strnicmp(track2Data.t2Account,ddd,strlen(ddd))) { t2ICCVC = ""; t2ICTrack2 = pICTrack2; t2ICAccount = (char*)ddd; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("contactless card countcount:%s,%s", t2ICAccount.substr(0, 6).c_str(), t2ICAccount.substr(t2ICAccount.length() - 4, 4).c_str()); } t2ICCardSerial = pICCardSerial; delete []ddd; delete []pICTrack2; } //80 1e 80 0008 328ab54bfc986b85 07010103a0b000010a010000000000754048769000 if (m_pCardProcess->GetP1() == 0x1) { actionType = "ARQC"; } else { actionType = ""; } //【55域】 // 基本域: // 9F26 8b 应用密文AC // 9F27 1b 密文信息数据 // 9F10 max.32b 发卡行应用数据IAD // 9F37 4b 不可预知数 // 9F36 2b 应用交易计数器ATC // 95 5b 终端验证结果TVR // 9A 3cn 交易日期(6位有效数字,YYMMDD) // 9C 1cn 交易类型(2位有效数字) // 9F02 6cn 授权金额(12位有效数字) // 5F2A 2cn 交易货币代码(3位有效数字) // 82 2b 应用交互特征AIP // 9F1A 2cn 终端国家代码(3位有效数字) // 9F03 6cn 其他金额(12位有效数字) // 9F33 3b 终端性能 "E0C900" // 可选域: //添加9F26,9F27,9F10,9F33的数据 char *pCID = new char[4]; ZeroMemory(pCID, 4); HexBuf2StrBuf(&bt9f27, &pCID, 1); char *pIssueBankLen = new char[4]; ZeroMemory(pIssueBankLen, 4); int len9f10 = tmpResult.length() - 26 - 4; int lenHigh, lenLow; len9f10 = len9f10 / 2; lenHigh = len9f10 / 16; lenLow = len9f10 % 16; BYTE bt9f10; bt9f10 = (lenHigh << 4) + lenLow; HexBuf2StrBuf(&bt9f10, &pIssueBankLen, 1); baseICData += "9F2608" + tmpResult.substr(10, 16) + "9F2701" + pCID + "9F10" + pIssueBankLen + tmpResult.substr(26, tmpResult.length() - 26 - 4) + "9F3303" + "E0C900"; result = "ACTION," + actionType + "|" + "ATCCODE," + tmpResult.substr(6, 4) + "|" + "ARQCCODE," + tmpResult.substr(10, 16) + "|" + "MAC," + tmpResult.substr(26, tmpResult.length() - 26 - 4) + "|" + "ARQCSIZE," + string(arqcLen) + "|" + "ARQCDATA," + m_pDataToARQC + "|EXPIREDATE," + pExpireDate + "|T2ACCOUNT," + t2ICAccount + "|T2CARDSERIAL," + t2ICCardSerial + "|T2CVC," + t2ICCVC + "|T2TRACK2," + t2ICTrack2 + "|CARDCAT," + cardType + "|ICTAGS," + baseICData; ctx->Ans.result = result.c_str(); string txtresult = ""; txtresult = "ACTION," + actionType + "|" + "ATCCODE," + tmpResult.substr(6, 4) + "|" + "ARQCCODE," + tmpResult.substr(10, 16) + "|" + "MAC," + tmpResult.substr(26, tmpResult.length() - 26 - 4) + "|" + "ARQCSIZE," + string(arqcLen) + "|" + "ARQCDATA," + m_pDataToARQC + "|T2ACCOUNT(F6)," + t2ICAccount.substr(0, 6) + "|T2ACCOUNT(L4)," + t2ICAccount.substr(t2ICAccount.length() - 4, 4) + "|T2CARDSERIAL(len)," + t2ICCardSerial + "|CARDCAT," + cardType; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("data to host(less)[%s],baseICData length:%d", txtresult.c_str(), baseICData.length()); if (m_pDataToARQC != NULL) { delete []m_pDataToARQC; m_pDataToARQC = NULL; } ctx->Answer(Error_Succeed); return 0; } int CContactlessCardFSM::PostOnline(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("post online data[%s]",(LPCTSTR)ctx->Req.data); m_pCardProcess->SplitOnlineReplyData(ctx->Req.data,strlen(ctx->Req.data)); int issBnkAuth = m_pCardProcess->IssueBankAuth(CARD_MACHINE_RFIC,m_hDevHelper); CSimpleStringA csTransEnd; if (issBnkAuth == 0) { int transEnd = m_pCardProcess->TransEnd(CARD_MACHINE_RFIC,m_hDevHelper,m_bCDA); if (transEnd == 0) csTransEnd = "TRANSEND,0"; else if (transEnd == 1) csTransEnd = "TRANSEND,1"; } else csTransEnd = "TRANSEND,1"; ctx->Ans.result = csTransEnd; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("PostOnline, issBnkAuth:%d, csTransEnd:%s", issBnkAuth, csTransEnd.GetData()); ctx->Answer(Error_Succeed); return 0; } int CContactlessCardFSM::EjectCard(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); m_pCardProcess->DataInit(); int ret = 0; DWORD dwStart = SP::Module::Comm::RVCGetTickCount(); DWORD dwEnd = dwStart; while(1) { if (m_bExit) { ret = 2; break; } dwEnd = SP::Module::Comm::RVCGetTickCount(); if ((dwEnd-dwStart) > 58*1000) { ret = 2; break; } ErrorCodeEnum eErr = m_hDevHelper->GetDevStatus(devStatus); if (eErr == Error_Succeed) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("EjectCard, devStatus.eMedia %d",devStatus.eMediaPos); if (devStatus.eMediaPos == CI_MEDIA_RF || devStatus.eMediaPos == CI_MEDIA_NOTPRESENT) { if (devStatus.eMediaPos == CI_MEDIA_NOTPRESENT) ret = 0; else if (devStatus.eMediaPos == CI_MEDIA_RF) ret = 1; break; } } Sleep(100); } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("eject, ret:%d",ret); if (ctx != NULL) ctx->Answer(Error_Succeed); return ret; } int CContactlessCardFSM::WaitFetchingCard() { LOG_FUNCTION(); int waitTries = 0; LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_ON,"ContactCard(fetch) warning on"); do { if (GetDevStatus(false)){ if (devStatus.eMediaPos == CI_MEDIA_RF){ Sleep(WAIT_INTERVAL); waitTries++; } else if (devStatus.eMediaPos == CI_MEDIA_NOTPRESENT){ waitTries = 0; LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_OFF,"ContactCard(fetch) warning off"); return 0; } }else { LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_OFF,"ContactCard(fetch) warning off"); return 1; } }while (waitTries < WAIT_TRY_NUM); LogEvent(Severity_Middle,LOG_EVT_CONTACTLESS_CARD_GREEN_OFF,"ContactCard(fetch) warning off"); return 2; } int CContactlessCardFSM::QueryCardInfo(SpReqAnsContext::Pointer ctx) { RFICReaderStatus devStatus; long l_beginTime, l_endTime; l_beginTime = SP::Module::Comm::RVCGetTickCount(); ErrorCodeEnum eErr = m_hDevHelper->GetDevStatus(devStatus); l_endTime = SP::Module::Comm::RVCGetTickCount(); if (eErr != Error_Succeed) { SetErrorAndLog(eErr, MEC_DEVAPI_RF_GetDevStatus, "DevAdapter::GetDevStatus", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); ctx->Answer(Error_Unexpect); return 1; } int ret = 0; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::GetDevStatus").setCostTime(l_endTime - l_beginTime)("QueryCardInfo, eMedia pos:%d",devStatus.eMediaPos); switch(devStatus.eMediaPos) { //case CI_MEDIA_IC: // ret = 2; // break; //case CI_MEDIA_NOT_IC: // ret = 3; // break; case CI_MEDIA_RF: ret = 4; break; case CI_MEDIA_NOTPRESENT: default: ret = 0; break; } ctx->Ans.position = ret; ctx->Answer(Error_Succeed); return ret; } bool CContactlessCardFSM::LoadCMBPrint(CSimpleStringA csBinPath) { if (cmdDecodeEx == NULL) { CSimpleStringA csCMBPrint(""); //TODO: CrossPlaform [Gifur@2025730] #ifdef RVC_OS_WIN csCMBPrint = "CMBPrint.dll"; csCMBPrint = csBinPath + SPLIT_SLASH_STR + csCMBPrint; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("cmbpath %s", (const char*)csCMBPrint); HMODULE hr = LoadLibraryA(csCMBPrint); if (hr == NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J18")("Load CMBPrint failed(%d).", hr); return false; } if ((cmdDecodeMag2 = (lpCMBdecodeMag2)GetProcAddress(hr, "CMBdecodeMag2")) == NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J18")("Get Mag2 address failed."); return false; } if ((cmdDecodeEx = (lpCMBdecodeEx)GetProcAddress(hr, "CMBdecodeEx")) == NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J18")("Get Mag23Ex address failed."); cmdDecodeMag2 = NULL; return false; } #else csCMBPrint = "libCMBPrint.so"; csCMBPrint = csBinPath + "/" + csCMBPrint; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("cmbpath %s", (const char*)csCMBPrint); void* hr = NULL; hr = dlopen(csCMBPrint, RTLD_LAZY); if (hr == NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J18")("Load CMBPrint failed(%s).", dlerror()); return false; } //pfunc_unpack = (PF_unpack)dlsym(hLib, "_Z6unpackPcS_i"); if ((cmdDecodeMag2 = (lpCMBdecodeMag2)dlsym(hr, "CMBdecodeMag2")) == NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J18")("Get Mag2 address failed."); return false; } if ((cmdDecodeEx = (lpCMBdecodeEx)dlsym(hr, "CMBdecodeEx")) == NULL) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J18")("Get Mag23Ex address failed."); cmdDecodeMag2 = NULL; return false; } #endif DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Load %s succ.", (const char*)csCMBPrint); } return true; } void CContactlessCardFSM::GetCardProcessLastErr(ErrorCodeEnum& eErrCode, CSimpleStringA& ApiName, CSimpleStringA& alarmMsg, CSimpleStringA& csErrMsgWithReturnCode) { if (m_pCardProcess == NULL) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("GetCardProcessLastErr m_pCardProcess is null"); eErrCode = Error_Null; ApiName = ""; alarmMsg = ""; csErrMsgWithReturnCode = ""; return; } ErrorCodeEnum lastErrCode = Error_Succeed; CSimpleStringA lastErrMsg = ""; CSimpleStringA lastApiName = ""; m_pCardProcess->getCardAssistLastErr(lastErrCode, lastErrMsg, lastApiName); const CSimpleStringA alarmMsgStr = CSimpleStringA::Format("{\"Function\":\"%s\", \"DevApi\":\"%s\", \"ReturnCode\":\"%s\", \"Msg\":\"%s\", \"Context\":\"%s\"}" , __FUNCTION__, lastApiName.GetData(), SpStrError(lastErrCode), lastErrMsg.GetData(), ""); std::map msgInfo; msgInfo["ReturnCode"] = SpStrError(lastErrCode); msgInfo["ErrMsg"] = lastErrMsg.GetData(); msgInfo["Context"] = ""; std::pair strResult; strResult = generateJsonStr(msgInfo); CSimpleStringA csErrMsgWithReturnCodeStr = strResult.second.c_str(); eErrCode = lastErrCode; ApiName = lastApiName; alarmMsg = alarmMsgStr.GetData(); csErrMsgWithReturnCode = csErrMsgWithReturnCodeStr.GetData(); } DWORD CContactlessCardFSM::GetFsmStateErrCode() { int state = GetFSMState(); switch (state) { case 2: return ContactlessCard_UserErrorCode_PROCESS_IDLE; case 4: return ContactlessCard_UserErrorCode_PROCESS_HOLD; case 5: return ContactlessCard_UserErrorCode_PROCESS_READ; case 6: return ContactlessCard_UserErrorCode_PROCESS_EJECT; case 7: return ContactlessCard_UserErrorCode_PROCESS_WAIT_FETCH; case 8: return ContactlessCard_UserErrorCode_PROCESS_CAPTURE; case 9: return ContactlessCard_UserErrorCode_PROCESS_FAULT; case 10: return ContactlessCard_UserErrorCode_PROCESS_READ_JS; case 11: return ContactlessCard_UserErrorCode_PROCESS_EJECT_JS; default: return ContactlessCard_UserErrorCode_EntityInStateCannotProcess; } } void CContactlessCardFSM::QueryHasCardJS(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); int ret = 0; if (m_hDevHelper == nullptr) { ctx->Answer(Error_Unexpect, ContactlessCard_UserErrorCode_DevOpen_Failed); } else { RFICReaderStatus devStatus; long l_beginTime, l_endTime; l_beginTime = SP::Module::Comm::RVCGetTickCount(); ErrorCodeEnum eErr = m_hDevHelper->GetDevStatus(devStatus); l_endTime = SP::Module::Comm::RVCGetTickCount(); if (Error_Succeed == eErr) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::GetDevStatus").setCostTime(l_endTime - l_beginTime)("QueryInternalHasCardJS::GetDevStatus, eMedia pos:%d", devStatus.eMediaPos); //switch (devStatus.eMediaPos) //{ //case CI_MEDIA_RF: // ret = 6; // break; //case CI_MEDIA_NOTPRESENT: // ret = 0; // break; //case CI_MEDIA_IDCARD: // ret = 7; // break; //default: // ret = 0; // break; //} ctx->Ans.position = (int)devStatus.eMediaPos; ctx->Answer(Error_Succeed); } else { DWORD dwTmpUserErrCode = SetErrorAndLog(eErr, MEC_DEVAPI_RF_GetDevStatus, "DevAdapter::GetDevStatus", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); ctx->Answer(Error_Unexpect, dwTmpUserErrCode); } } } int CContactlessCardFSM::EjectJS(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("吐卡开始"); m_pCardProcess->DataInit(); int ret = 0; int getDevInfoCount = 0; DWORD dwStart = SP::Module::Comm::RVCGetTickCount(); DWORD dwEnd = dwStart; LogEvent(Severity_Middle, LOG_EVT_CONTACTLESS_CARD_GREEN_ON, "ContactCard(fetch) warning on"); while (true) { dwEnd = SP::Module::Comm::RVCGetTickCount(); if ((dwEnd - dwStart) > 58 * 1000) { ret = 1;//超时 break; } if (m_bPageExit) { ret = 2; break;//退到首页 } ErrorCodeEnum eErr = m_hDevHelper->GetDevStatus(devStatus); if (eErr == Error_Succeed) { if (devStatus.eMediaPos == CI_MEDIA_RF || devStatus.eMediaPos == CI_MEDIA_NOTPRESENT) { if (devStatus.eMediaPos == CI_MEDIA_NOTPRESENT){ DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("EjectCard, devStatus.eMedia %d", devStatus.eMediaPos); ret = 0;//取走 break; } else if (devStatus.eMediaPos == CI_MEDIA_RF) { } } } else { //getDevInfoCount++; //if (getDevInfoCount % 10 == 0) { // DevErrorInfo devErrInfo; // m_hDevHelper->GetLastErr(devErrInfo); // DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("GetDevStatus, errMsg:%s", devErrInfo.szErrMsg); //} } Sleep(WAIT_INTERVAL); } LogEvent(Severity_Middle, LOG_EVT_CONTACTLESS_CARD_GREEN_OFF, "ContactCard(fetch) warning off"); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("eject return.ret=%d",ret); if (ctx != NULL) { if (ret == 0) { ctx->Answer(Error_Succeed); } else if(ret == 1 || ret == 2){ ctx->Answer(Error_Exception, ContactlessCard_UserErrorCode_Forget_Fectch_Card); } } return ret; } int CContactlessCardFSM::ReadJS(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("读卡开始"); int ret = InternalAcceptCardJS(); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("InternalAcceptCardJS ret:%d", ret); if (ret == 0) { //寻卡成功,开始联机读卡 ret = PreOnlineJS(ctx); } else if (ret == 1) { //非IC卡 ctx->Answer(Error_Exception, ContactlessCard_UserErrorCode_Read_Not_IC); } else if (ret == 2) { //寻卡超时 ctx->Answer(Error_Exception, ContactlessCard_UserErrorCode_Read_TimeOut); } else if (ret == 3 || ret == 4){ //读卡取消 ctx->Answer(Error_Exception, ContactlessCard_UserErrorCode_Read_Cancel); } return 0; } int CContactlessCardFSM::PostOnlineJS(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("(PostOnlineJS) 联机后IC接触处理"); m_pCardProcess->DataInit(); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("postOnLine data[%s]", ctx->Req.data.GetData()); m_pCardProcess->SplitOnlineReplyData(ctx->Req.data, strlen(ctx->Req.data)); int issBnkAuth = m_pCardProcess->IssueBankAuth(CARD_MACHINE_RFIC, m_hDevHelper); CSimpleStringA csTransEnd; if (issBnkAuth == 0) { int transEnd = m_pCardProcess->TransEnd(CARD_MACHINE_RFIC, m_hDevHelper, m_bCDA); if (transEnd == 0) { csTransEnd = "TRANSEND,0"; } else if (transEnd == 1) { csTransEnd = "TRANSEND,1"; } } else { csTransEnd = "TRANSEND,1"; } ctx->Ans.result = csTransEnd; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)(", issBnkAuth:%d, csTransEnd:%s", issBnkAuth, csTransEnd.GetData()); ctx->Answer(Error_Succeed); return 0; } int CContactlessCardFSM::InternalAcceptCardJS() { LOG_FUNCTION(); int err = 0; long l_beginTime, l_endTime; DWORD64 dwStart = SP::Module::Comm::RVCGetTickCount(); DWORD64 dwEnd = dwStart; ErrorCodeEnum eErr = Error_Succeed; LogEvent(Severity_Middle, LOG_EVT_CONTACTLESS_CARD_GREEN_ON, "ContactCard green on"); int timeOutResult = 0; do { if (m_bCancelRead) { err = 3;//取消读卡 break; } if (m_bPageExit) { err = 4;//退到首页,取消读卡 break; } l_beginTime = SP::Module::Comm::RVCGetTickCount(); eErr = m_hDevHelper->GetDevStatus(devStatus); l_endTime = SP::Module::Comm::RVCGetTickCount(); if (eErr == Error_Succeed) { if (devStatus.eMediaPos == CI_MEDIA_RF) { LogEvent(Severity_Middle, LOG_EVT_CONTACTLESS_CARD_OP, "Contactless card op."); int activeCardType; l_beginTime = SP::Module::Comm::RVCGetTickCount(); bool bIC = m_pCardProcess->DetectIfICCard(CARD_MACHINE_RFIC, m_hDevHelper, activeCardType); l_endTime = SP::Module::Comm::RVCGetTickCount(); if (bIC) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("InternalAcceptCardJS::DetectIfICCard activeCardType=%d", activeCardType); if (activeCardType == 'A' || activeCardType == 'B' || activeCardType == 'M') { err = 0;//探测到IC卡 } else { err = 1;//非IC卡 } break; } else { //探测失败,继续循环 err = 2; timeOutResult = 1; Sleep(ACCEPT_TRY_INTERVAL); } } else { //无卡,继续循环 err = 2; timeOutResult = 3; Sleep(ACCEPT_TRY_INTERVAL); } } else { //查询卡机状态失败,继续循环 err = 2; timeOutResult = 2; Sleep(ACCEPT_TRY_INTERVAL); } dwEnd = SP::Module::Comm::RVCGetTickCount(); } while (dwEnd - dwStart <= 55 * 1000); //超时报错 if (err == 2) { if (timeOutResult == 1) { SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_RF_ActiveContactlessICCard, "DevAdapter::ActiveContactlessICCard", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); } else if (timeOutResult == 2) { SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_RF_GetDevStatus, "DevAdapter::GetDevStatus", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("InternalAcceptCardJS No IC card found "); } } LogEvent(Severity_Middle, LOG_EVT_CONTACTLESS_CARD_GREEN_OFF, CSimpleStringA::Format("ContactCard green off,err=%d", err).GetData()); return err; } int CContactlessCardFSM::PreOnlineJS(SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); long l_beginTime, l_endTime; m_pCardProcess->DataInit(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)(", aid[%s], bus data[%s]", ctx->Req.aid.GetData(),ctx->Req.businessData.GetData()); m_pCardProcess->SplitBusinessData(ctx->Req.businessData, ctx->Req.businessData.GetLength()); m_pCardProcess->SplitBusinessData("DF690101", strlen("DF690101")); int activeCardType; //oilyang@20201014 add emv card support int retDetectAndRead = -1; ICData aidFromBus(false, 0x4f, 0x00); if (m_pCardProcess->FindTagValue(TAG_VECTOR_BUS, aidFromBus, false, 0) == -1) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("the front BusinessData han't provide aid data."); retDetectAndRead = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_RFIC, m_hDevHelper, m_aidList, activeCardType); } else { char* pAIDTmp = new char[64]; memset(pAIDTmp, 0, 64); HexBuf2StrBuf(aidFromBus.value, &pAIDTmp, aidFromBus.lenth); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)(", the aid is[%s],len:%d .", pAIDTmp, strlen(pAIDTmp)); CAutoArray preAIDs; preAIDs.Init(1); preAIDs[0] = (CSimpleStringA)pAIDTmp; l_beginTime = SP::Module::Comm::RVCGetTickCount(); retDetectAndRead = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_RFIC, m_hDevHelper, preAIDs, activeCardType); l_endTime = SP::Module::Comm::RVCGetTickCount(); if (pAIDTmp != NULL) { delete[]pAIDTmp; } } if (retDetectAndRead < 0) { ctx->Ans.icState = 0;//调用失败 if (retDetectAndRead == -1) { DWORD dwTmpUserErrCode = SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_RF_ActiveContactlessICCard, "DevAdapter::ActiveContactlessICCard", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); ctx->Answer(Error_Exception, dwTmpUserErrCode); } else if (retDetectAndRead == -2) { DWORD dwTmpUserErrCode = SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_RF_RFTypeABCommand, "DevAdapter::RFTypeABCommand", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); ctx->Answer(Error_Exception, dwTmpUserErrCode); } else if (retDetectAndRead == -3) { DWORD dwTmpUserErrCode = SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_RF_RFTypeABCommand, "DevAdapter::RFTypeABCommand", __FUNCTION__, false, l_endTime - l_beginTime, "", ""); ctx->Answer(Error_Exception, dwTmpUserErrCode); } return -1; } m_pCardProcess->TermRiskManage(); CSimpleStringA taaResult; BYTE bt9f27 = 0; int retTAA = m_pCardProcess->TermActionAnalyze(CARD_MACHINE_RFIC, m_hDevHelper, taaResult, true, m_bCDA, bt9f27); if (retTAA != 0) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)(",TermActionAnalyze retTAA:%d, taaResult:%s", retTAA, taaResult.GetData()); } switch (retTAA) {//to be added oiltest 20140929 case -1: //some data may be wrong break; case 1: //terminal trans break; case 2: //to do trans end "TransEnd" break; default: break; } ctx->Ans.result = taaResult; if (ctx->Ans.result.GetLength() == 0) { ctx->Ans.icState = 0; ctx->Answer(Error_Succeed); return 0; } string tmpResult, actionType, result = "", baseICData = ""; tmpResult = ctx->Ans.result; char* pSomeICData = new char[1024]; ZeroMemory(pSomeICData, 1024); int lenRet = m_pCardProcess->ConstructARQCData(tmpResult.substr(6, 4).c_str(), m_pDataToARQC, pSomeICData); baseICData = pSomeICData; if (pSomeICData != NULL) { delete[]pSomeICData; } char arqcLen[8]; ZeroMemory(arqcLen, sizeof(arqcLen)); //TODO: CrossPlaform [Gifur@2025729] #ifdef RVC_OS_WIN itoa(lenRet, arqcLen, 10); #else sprintf(arqcLen, "%d", lenRet); #endif // RVC_OS_WIN ICData track2(false, 0x57, 0x00), ICCardSerial(false, 0x5f, 0x34), appExpiryDate(false, 0x5f, 0x24); string t2ICAccount(""), t2ICCardSerial(""), t2ICCVC(""), t2ICTrack2(""), cardType("0"),t2ICExpireDate(""); char* pExpireDate = new char[12];//获取ic有效期 ZeroMemory(pExpireDate, 12); if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC, appExpiryDate, false, 0) == -1) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J1B")("can't find expire date"); } else { HexBuf2StrBuf(appExpiryDate.value, &pExpireDate, appExpiryDate.lenth); t2ICExpireDate = pExpireDate; } delete[] pExpireDate; char* pICCardSerial = new char[4];//获取ic序号 ZeroMemory(pICCardSerial, 4); if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC, ICCardSerial, false) == -1) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA2J1B")("can't find card serial."); } else { HexBuf2StrBuf(ICCardSerial.value, &pICCardSerial, ICCardSerial.lenth); t2ICCardSerial = pICCardSerial; } delete[] pICCardSerial; char* pICTrack2 = new char[128];//获取等效磁条2 ZeroMemory(pICTrack2, 128); if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC, track2, false, 0) == -1) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("no track2 data in ic"); } else { HexBuf2StrBuf(track2.value, &pICTrack2, track2.lenth); t2ICTrack2 = pICTrack2; int pos = FindHexCharPosition(track2.value, 0x0d, track2.lenth); pICTrack2[37] = '\0'; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)(", split pos:%d", pos); char* ddd = new char[40]; ZeroMemory(ddd, 40); memcpy(ddd, pICTrack2, pos - 1); char icTrack2Data[128]; ZeroMemory(icTrack2Data, sizeof(icTrack2Data)); Track2Data track2Data; track2Data.status = 0; track2Data.t2Account = ""; cmdDecodeMag2(pICTrack2, icTrack2Data); if (SplitTrack2(icTrack2Data, track2Data) == 0) { t2ICAccount = track2Data.t2Account; //t2ICCardSerial = track2Data.t2CardSerial; t2ICCVC = track2Data.t2CVC; } if (strnicmp(track2Data.t2Account, ddd, strlen(ddd))) { t2ICCVC = ""; t2ICAccount = (char*)ddd; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("contactless card countcount:%s,%s", t2ICAccount.substr(0, 6).c_str(), t2ICAccount.substr(t2ICAccount.length() - 4, 4).c_str()); } delete[]ddd; LogWarn(Severity_Low, Error_Succeed, ContactlessCard_UserErrorCode_ReadAccount, CSimpleStringA::Format("split pos:%d, card acount:%s,%s" , pos, t2ICAccount.substr(0, 6).c_str(), t2ICAccount.substr(t2ICAccount.length() - 4, 4).c_str()));//读到的卡号 } delete[]pICTrack2; //80 1e 80 0008 328ab54bfc986b85 07010103a0b000010a010000000000754048769000 if (m_pCardProcess->GetP1() == 0x1) { actionType = "ARQC"; } else { actionType = ""; } //【55域】 // 基本域: // 9F26 8b 应用密文AC // 9F27 1b 密文信息数据 // 9F10 max.32b 发卡行应用数据IAD // 9F37 4b 不可预知数 // 9F36 2b 应用交易计数器ATC // 95 5b 终端验证结果TVR // 9A 3cn 交易日期(6位有效数字,YYMMDD) // 9C 1cn 交易类型(2位有效数字) // 9F02 6cn 授权金额(12位有效数字) // 5F2A 2cn 交易货币代码(3位有效数字) // 82 2b 应用交互特征AIP // 9F1A 2cn 终端国家代码(3位有效数字) // 9F03 6cn 其他金额(12位有效数字) // 9F33 3b 终端性能 "E0C900" // 可选域: //添加9F26,9F27,9F10,9F33的数据 char* pCID = new char[4]; ZeroMemory(pCID, 4); HexBuf2StrBuf(&bt9f27, &pCID, 1); char* pIssueBankLen = new char[4]; ZeroMemory(pIssueBankLen, 4); int len9f10 = tmpResult.length() - 26 - 4; int lenHigh, lenLow; len9f10 = len9f10 / 2; lenHigh = len9f10 / 16; lenLow = len9f10 % 16; BYTE bt9f10; bt9f10 = (lenHigh << 4) + lenLow; HexBuf2StrBuf(&bt9f10, &pIssueBankLen, 1); baseICData += "9F2608" + tmpResult.substr(10, 16) + "9F2701" + pCID + "9F10" + pIssueBankLen + tmpResult.substr(26, tmpResult.length() - 26 - 4) + "9F3303" + "E0C900"; //result = "ACTION," + actionType + "|" + "ATCCODE," + tmpResult.substr(6, 4) + "|" + "ARQCCODE," + tmpResult.substr(10, 16) + "|" // + "MAC," + tmpResult.substr(26, tmpResult.length() - 26 - 4) + "|" + "ARQCSIZE," + string(arqcLen) + "|" // + "ARQCDATA," + m_pDataToARQC + "|EXPIREDATE," + pExpireDate + "|T2ACCOUNT," + t2ICAccount + "|T2CARDSERIAL," + t2ICCardSerial // + "|T2CVC," + t2ICCVC + "|T2TRACK2," + t2ICTrack2 + "|CARDCAT," + cardType + "|ICTAGS," + baseICData; //json格式返回 std::map msgInfo; msgInfo["ACTION"] = actionType.c_str(); msgInfo["ATC_CODE"] = tmpResult.substr(6, 4).c_str(); msgInfo["ARQC_CODE"] = tmpResult.substr(10, 16).c_str(); msgInfo["MAC"] = tmpResult.substr(26, tmpResult.length() - 26 - 4).c_str(); CSimpleStringA arqcLenStr = arqcLen; msgInfo["ARQC_SIZE"] = arqcLenStr.GetData(); CSimpleStringA arqcData = m_pDataToARQC; msgInfo["ARQC_DATA"] = arqcData.GetData(); msgInfo["T2TRACK2_DATA"] = t2ICTrack2.c_str(); msgInfo["EXPIRE_DATE"] = t2ICExpireDate.c_str(); msgInfo["T2CARD_SERIAL"] = t2ICCardSerial.c_str(); msgInfo["CARD_CAT"] = cardType.c_str(); msgInfo["IC_TAGS"] = baseICData.c_str(); std::pair strResult; strResult = generateJsonStr(msgInfo); result = strResult.second.c_str(); ctx->Ans.result = result.c_str(); ctx->Ans.icState = 1; //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("data to host result=%s,len=%d", result.c_str(),result.length()); string txtresult = "ACTION," + actionType + "|" + "ATCCODE," + tmpResult.substr(6, 4) + "|" + "ARQCCODE," + tmpResult.substr(10, 16) + "|" + "MAC," + tmpResult.substr(26, tmpResult.length() - 26 - 4) + "|" + "ARQCSIZE," + string(arqcLen) + "|ARQCDATA, " + m_pDataToARQC + "|" + "T2TRACK2(len)," + CSimpleStringA::Format("%d", t2ICTrack2.length()).GetData() + "|" + "EXPIREDATE(len)," + CSimpleStringA::Format("%d", t2ICExpireDate.length()).GetData() + "|" + "T2CARDSERIAL(len), " + CSimpleStringA::Format("%d", t2ICCardSerial.length()).GetData() + "|" + "CARDCAT, " + cardType + "|" + "ICTAGS, " + CSimpleStringA::Format("%d", baseICData.length()).GetData(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("data to host(less)[%s]", txtresult.c_str()); if (pCID != NULL) delete[]pCID; if (pIssueBankLen != NULL) delete[]pIssueBankLen; if (m_pDataToARQC != NULL) { delete[]m_pDataToARQC; m_pDataToARQC = NULL; } ctx->Answer(Error_Succeed); return 0; } void CContactlessCardFSM::OnStateTrans(int iSrcState, int iDstState) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("trans from %s to %s", GetStateName(iSrcState), GetStateName(iDstState)); }