瀏覽代碼

Z991239-4590 #comment 跨机激活移到卡机功能集

oilyang 2 年之前
父節點
當前提交
941b016c8c
共有 2 個文件被更改,包括 186 次插入96 次删除
  1. 145 90
      Module/mod_CardReadAdapter/CardReadAdapterFSM.cpp
  2. 41 6
      Module/mod_CardReadAdapter/CardReadAdapterFSM.h

+ 145 - 90
Module/mod_CardReadAdapter/CardReadAdapterFSM.cpp

@@ -411,15 +411,6 @@ unsigned int CCardReadAdapterFSM::s2_on_event(FSMEvent* pEvt)
 		GetEntityBase()->GetFunction()->PostThreadPoolTask(task);
 	}
 		break;
-	case USER_EVT_NOTIFY_PREONLINE:
-	{
-		pEvt->SetHandled();
-		NotifyPreonlineEvent* samice = dynamic_cast<NotifyPreonlineEvent*>(pEvt);
-		NotifyPreOnlineTask* task = new NotifyPreOnlineTask(this);
-		task->ctx = samice->ctx;
-		GetEntityBase()->GetFunction()->PostThreadPoolTask(task);
-	}
-		break;
 	case USER_EVT_QUERY_CARD_INFO_ON_STORE:
 	{
 		pEvt->SetHandled();
@@ -476,6 +467,15 @@ unsigned int CCardReadAdapterFSM::s3_on_event(FSMEvent* pEvt)
 	int ret = 0;
 	switch (pEvt->iEvt)
 	{
+	case USER_EVT_NOTIFY_PREONLINE:
+	{
+		pEvt->SetHandled();
+		NotifyPreonlineEvent* samice = dynamic_cast<NotifyPreonlineEvent*>(pEvt);
+		NotifyPreOnlineTask* task = new NotifyPreOnlineTask(this);
+		task->ctx = samice->ctx;
+		GetEntityBase()->GetFunction()->PostThreadPoolTask(task);
+	}
+	break;
 	case USER_EVT_READ_FINISHED:
 	{
 		pEvt->SetHandled();
@@ -2242,105 +2242,111 @@ int CCardReadAdapterFSM::BindSCI(SpReqAnsContext<CardReadAdapterService_BindSCI_
 int CCardReadAdapterFSM::PreOnlineOnStore(SpReqAnsContext<CardReadAdapterService_PreOnlineOnStore_Req, CardReadAdapterService_PreOnlineOnStore_Ans>::Pointer ctx)
 {
 	LOG_FUNCTION();
-	if (IsCardIssuerSessionOK())
+	//oilyang@20230525 to call heartbeat directly
+	if (!CheckHBSessionOrToConnect())
 	{
-		ErrorCodeEnum eErr = Error_Unexpect;
-		CardIssuerService_PreOnlineOnStore_Req req;
-		CardIssuerService_PreOnlineOnStore_Ans ans;
+		DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER)("While calling to PreOnlineOnStore, connect to HeartBeat failed.");
+		ctx->Answer(Error_DevNotAvailable);
+		return 0;
+	}
+	m_crossCtx = ctx;
+	ErrorCodeEnum eErr = Error_Unexpect;
+	CSimpleStringA errMsg(true);
+
+	m_ullCrossStart = GetTickCountRVC();
+
+	if (m_pHBClient != NULL)
+	{
+		HeartBeatService_CardActive_Req req;
+		HeartBeatService_CardActive_Ans ans;
+		req.type = 0;
 		req.account = ctx->Req.account;
-		req.businessData = ctx->Req.businessData;
+		req.term = ctx->Req.termNo;
+		req.data = ctx->Req.businessData;
 		req.slot = ctx->Req.slot;
-		req.termNo = ctx->Req.termNo;
-		req.reserved1.Copy(ctx->Req.reserved1);
-		req.reserved2.Copy(ctx->Req.reserved2);
-		req.reserved3.Copy(ctx->Req.reserved3);
-		req.reserved4.Copy(ctx->Req.reserved4);
-		CSimpleStringA inParam("");
-		if (!req.account.IsNullOrEmpty() && req.account.GetLength() > 10)
+
+		errMsg = CSimpleStringA::Format("<PreOnlineOnStore>, send CardActive, termNo:%s, slot:%d", req.term.GetData(), req.slot);
+		LogWarn(Severity_Low, Error_Unexpect, CardIssuer_UserErrorCode_PreOnline_Send_CardActive, errMsg.GetData());
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR040220327")("to call heartbeat CardActive");
+
+		eErr = m_pHBClient->CardActive(req, ans, 6000);
+		if (eErr == Error_Succeed)
 		{
-			inParam = CSimpleStringA::Format("account:%s****%s, bussinessDataLen:%d, slot:%d, termNo:%s",
-				req.account.SubString(0, 6).GetData(), req.account.SubString(req.account.GetLength() - 4, 4).GetData(), req.businessData.GetLength(), req.slot, req.termNo.GetData());
-		}
-		else {
-			inParam = CSimpleStringA::Format("accountLen:%d, bussinessDataLen:%d, slot:%d, termNo:%s",
-				req.account.GetLength(), req.businessData.GetLength(), req.slot, req.termNo.GetData());
+			m_bCardActiveNotify = false;
+			WaitCardActiveTask* pTask = new WaitCardActiveTask(this);
+			GetEntityBase()->GetFunction()->PostThreadPoolTask(pTask);
 		}
-		LogWarn(Severity_Low, Error_Unexpect, CardReadAdapter_UserErrorCode_PreOnline_Invoke, inParam.GetData());
-		eErr = m_pCardIssuer->PreOnlineOnStore(req, ans, 62000);//跨机CardIssuer的返回超时是60秒,这里选62秒
-		if (eErr == Error_Succeed)
+		else
 		{
-			ctx->Ans.cardPos = ans.cardPos;
-			ctx->Ans.findCard = ans.findCard;
-			ctx->Ans.result = ans.result;
-			ctx->Ans.reserved1.Copy(ans.reserved1);
-			ctx->Ans.reserved2.Copy(ans.reserved2);
-			ctx->Ans.reserved3.Copy(ans.reserved3);
-			ctx->Ans.reserved4.Copy(ans.reserved4);
-			CSimpleStringA outParam = CSimpleStringA::Format("cardPos:%d, findCard:%d, resultLen:%d",
-															ctx->Ans.cardPos, ctx->Ans.findCard, ctx->Ans.result.GetLength());
-			LogWarn(Severity_Low, Error_Unexpect, CardReadAdapter_UserErrorCode_PreOnline_Result, outParam.GetData());
-			ctx->Answer(eErr);
-		}else if (eErr == Error_TimeOut) {
-			DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_USER).setLogCode("QLR040220327").setResultCode("RTA2R01")("PreOnlineOnStore timeout(62s)");
-			DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)(CSimpleStringA::Format("PreOnlineOnStore, CardIssuer PreOnlineOnStore failed return:%d", eErr));
-			ctx->Answer(Error_TimeOut, CardReadAdapter_UserErrorCode_HBService_No_Return);
-		}
-		else if (eErr == Error_Duplication)
-			ctx->Answer(Error_DevNotAvailable, CardIssuer_UserErrorCode_DupCallPreOnline_WhileInWorking);
-		else if (eErr == Error_ReplyTimeOut)
-			ctx->Answer(Error_Unexpect, CardIssuer_UserErrorCode_CardStore_Reply_TooLong);
-		else if (eErr == Error_DevNotAvailable)
-			ctx->Answer(Error_DevNotAvailable, CardIssuer_UserErrorCode_CardActive_CardStore_OffLine);
-		else if (eErr == Error_Hardware)
-			ctx->Answer(Error_DevNotAvailable, CardIssuer_UserErrorCode_CardActive_CardIssuer_InFaultState);
-		else {
-			DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)(CSimpleStringA::Format("PreOnlineOnStore, CardIssuer PreOnlineOnStore failed return:%d", eErr));
-			ctx->Answer(eErr);
+			errMsg = CSimpleStringA::Format("CardActive Result(termNo:%s, slot:%d):%d(0x%x)", req.term.GetData(), req.slot, eErr, eErr);
+			LogWarn(Severity_Middle, Error_Unexpect, CardIssuer_UserErrorCode_PreOnline_Recv_CardActive, errMsg.GetData());
 		}
 	}
-	else
-	{
-		LogWarn(Severity_High, Error_Unexpect, CardReadAdapter_UserErrorCode_PreOnline_CardIssuer_Not_Ok, "Entity CardIssuer is not ok.");
-		ctx->Answer(Error_DevNotAvailable, CardReadAdapter_UserErrorCode_PreOnline_CardIssuer_Not_Ok);
-	}
-	return 0;
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER)("have send heartbeat CardActive");
+	return 1;//维持s3状态,直到收到返回或超时
 }
 int CCardReadAdapterFSM::NotifyPreonline(SpReqAnsContext<CardReadAdapterService_NotifyPreonline_Req, CardReadAdapterService_NotifyPreonline_Ans>::Pointer ctx)
 {
 	LOG_FUNCTION();
-	if (IsCardIssuerSessionOK())
+
+	UINT64 crossEnd = GetTickCountRVC();
+	//? ? ? 为什么是110s,重试?从生产实际来看,在25s到40s之间,大部分在30s左右,需要和前端(65s)一致,改成60s oilyang@20221019
+	//in 110 second 
+	if (m_crossCtx != NULL)
 	{
-		ErrorCodeEnum eErr = Error_Unexpect;
-		CardIssuerService_NotifyPreonline_Req req;
-		CardIssuerService_NotifyPreonline_Ans ans;
-		req.account = ctx->Req.account;
-		req.cardPos = ctx->Req.cardPos;
-		req.data = ctx->Req.data;
-		req.errCode = ctx->Req.errCode;
-		req.findCard = ctx->Req.findCard;
-		req.termNo = ctx->Req.termNo;
-		req.reserved1.Copy(ctx->Req.reserved1);
-		req.reserved2.Copy(ctx->Req.reserved2);
-		req.reserved3.Copy(ctx->Req.reserved3);
-		req.reserved4.Copy(ctx->Req.reserved4);
-		eErr = m_pCardIssuer->NotifyPreonline(req, ans, 100000);
-		if (eErr == Error_Succeed)
+		if ((crossEnd - m_ullCrossStart) < 60 * 1000)
 		{
-			ctx->Ans.reserved1.Copy(ans.reserved1);
-			ctx->Ans.reserved2.Copy(ans.reserved2);
-			ctx->Ans.reserved3.Copy(ans.reserved3);
-			ctx->Ans.reserved4.Copy(ans.reserved4);
+			m_bCardActiveNotify = true;
+			m_crossCtx->Ans.cardPos = ctx->Req.cardPos;
+			m_crossCtx->Ans.findCard = ctx->Req.findCard;
+			m_crossCtx->Ans.result = ctx->Req.data;
+			CSimpleStringA outParam = CSimpleStringA::Format("NotifyPreOnline, cardPos:%d, findCard:%d, errCode:%d", ctx->Req.cardPos, ctx->Req.findCard, ctx->Req.errCode);
+			LogWarn(Severity_Low, Error_Unexpect, CardIssuer_UserErrorCode_NotifyPreOnline_ParamInfo, outParam.GetData());
+			if (ctx->Req.errCode == Error_Duplication)//THE CardStore is issuing card
+			{
+				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setLogCode("QLR040220327").setResultCode("RTA230Q")("卡库正在使用中");
+				LogWarn(Severity_Middle, Error_Unexpect, CardIssuer_UserErrorCode_CardActive_CardStore_Issuing, "卡库正在使用中");
+				m_crossCtx->Answer(Error_DevNotAvailable, CardIssuer_UserErrorCode_DupCallPreOnline_WhileInWorking);
+			}
+			else if (ctx->Req.errCode == Error_TimeOut)//CardStore process cost too long!
+			{
+				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setLogCode("QLR040220327").setResultCode("RTA230W")("跨机时卡库处理耗时过长");
+				LogError(Severity_Middle, Error_Unexpect, CardIssuer_UserErrorCode_CardStore_Reply_TooLong, "跨机时卡库处理耗时过长");
+				m_crossCtx->Answer(Error_Unexpect, CardIssuer_UserErrorCode_CardStore_Reply_TooLong);
+			}
+			else if (ctx->Req.errCode == Error_NotExist)//heartbeat service can't find the dest terminal
+			{
+				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setLogCode("QLR040220327").setResultCode("RTA230Y")("跨机时卡库不在线");
+				LogWarn(Severity_Middle, Error_Unexpect, CardIssuer_UserErrorCode_CardActive_CardStore_OffLine, "跨机时卡库不在线");
+				m_crossCtx->Answer(Error_DevNotAvailable, CardIssuer_UserErrorCode_CardActive_CardStore_OffLine);
+			}
+			else if (ctx->Req.errCode == Error_DevNotAvailable)//CardStore maybe called by OTHER VTM
+			{
+				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setLogCode("QLR040220327").setResultCode("RTA2310")("卡库正在被其他VTM跨机调用");
+				LogWarn(Severity_Middle, Error_Unexpect, CardIssuer_UserErrorCode_CardActive_CardStore_CallByOther, "卡库正在被其他VTM跨机调用");
+				m_crossCtx->Answer(Error_DevNotAvailable, CardIssuer_UserErrorCode_CardActive_CardStore_CallByOther);
+			}
+			else if (ctx->Req.errCode == Error_Hardware)//CardStore's CardIssuer in fault state
+			{
+				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setLogCode("QLR040220327").setResultCode("RTA2311")("卡库卡机未成功打开");
+				LogWarn(Severity_Middle, Error_Unexpect, CardIssuer_UserErrorCode_CardActive_CardIssuer_InFaultState, "卡库卡机未成功打开");
+				m_crossCtx->Answer(Error_DevNotAvailable, CardIssuer_UserErrorCode_CardActive_CardIssuer_InFaultState);
+			}
+			else
+			{
+				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setLogCode("QLR040220327")("卡库异常:%d(0x%x)", ctx->Req.reserved1[0], ctx->Req.reserved1[0]);
+				m_crossCtx->Answer((ErrorCodeEnum)ctx->Req.errCode, MapErrorCodeWhileCallStore(ctx->Req.reserved1[0]));
+			}
 		}
 		else {
-			DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("NotifyPreonline, CardIssuer NotifyPreonline failed return:%d", eErr);
+			DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setLogCode("QLR040220327").setResultCode("RTA2312")("超时后,才收到卡库返回");
+			LogWarn(Severity_Middle, Error_Unexpect, CardIssuer_UserErrorCode_NotifyPreonline_Wait_TooLong, "CardStore return after timeout.");
 		}
-		ctx->Answer(eErr);
-	}
-	else
-	{
-		DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Entity CardIssuer is not ok.");
-		ctx->Answer(Error_Unexpect);
+		m_crossCtx = NULL;
 	}
+
+	ctx->Answer(Error_Succeed);
+
 	return 0;
 }
 int CCardReadAdapterFSM::QueryCardInfoOnStore(SpReqAnsContext<CardReadAdapterService_QueryCardInfoOnStore_Req, CardReadAdapterService_QueryCardInfoOnStore_Ans>::Pointer ctx)
@@ -2640,4 +2646,53 @@ int CCardReadAdapterFSM::QueryCIStatus(SpReqAnsContext<CardReadAdapterService_Qu
 		return 0;
 	}
 	return 0;
+}
+void CCardReadAdapterFSM::WaitCardActive()
+{
+	while (1)
+	{
+		if (m_bCardActiveNotify)
+			break;
+		UINT64 crossEnd = GetTickCountRVC();
+		if ((crossEnd - m_ullCrossStart) < 62 * 1000)
+			Sleep(1000);
+		else {
+			if (m_crossCtx != NULL)
+			{
+				FSMEvent* e = new FSMEvent(USER_EVT_PREONLINE_ON_STORE_FINISHED);
+				PostEventFIFO(e);
+
+				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setLogCode("QLR040220327").setResultCode("RTA230U")("跨机激活未收到返回,请确认卡库或服务是否正常");
+				m_crossCtx->Answer(Error_TimeOut, CardIssuer_UserErrorCode_CardActive_Service_NoReturn);
+				LogError(Severity_Middle, Error_Unexpect, CardIssuer_UserErrorCode_CardActive_Service_NoReturn, "CardActive havn't return in 60s");
+				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("oiltest record for SelfChecker test 1792 to kill CardIsser");
+				break;
+			}
+		}
+	}
+}
+bool CCardReadAdapterFSM::CheckHBSessionOrToConnect()
+{
+	if (m_pHBClient != NULL && !m_pHBClient->QuerySessionClosed())
+		return true;
+	else
+	{
+		ErrorCodeEnum eErr = Error_Unexpect;
+		m_pHBClient = new HeartBeatService_ClientBase(GetEntityBase());
+		if (m_pHBClient != NULL) {
+			eErr = m_pHBClient->Connect();
+			if (eErr != Error_Succeed)
+			{
+				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("connect to HeartBeat failed:%d(0x%x)", eErr, eErr);
+				return false;
+			}
+			else
+			{
+				DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("connect to HeartBeat suc.");
+				return true;
+			}
+		}
+		else
+			return false;
+	}
 }

+ 41 - 6
Module/mod_CardReadAdapter/CardReadAdapterFSM.h

@@ -779,7 +779,7 @@ public:
 
 		END_FSM_RULE()
 
-		CCardReadAdapterFSM() : m_pCardIssuer(NULL), m_pContactless(NULL), m_pCardSwiper(NULL){}
+		CCardReadAdapterFSM() : m_pCardIssuer(NULL), m_pContactless(NULL), m_pCardSwiper(NULL), m_pHBClient(NULL){}
 	~CCardReadAdapterFSM(){}
 	virtual ErrorCodeEnum OnInit();
 	virtual ErrorCodeEnum OnExit();
@@ -877,6 +877,7 @@ public:
 	}
 	MachineType GetMachineType() {return m_eMachineType;}
 	int QueryCIStatus(SpReqAnsContext<CardReadAdapterService_QueryCIStatus_Req, CardReadAdapterService_QueryCIStatus_Ans>::Pointer ctx);
+	void WaitCardActive();
 protected:
 	//LPIDCCARDDATA* lppCardData;
 	int m_iInsertTries;
@@ -887,6 +888,7 @@ private:
 	CardIssuerService_ClientBase *m_pCardIssuer;
 	ContactlessCardService_ClientBase *m_pContactless;
 	CardSwiperService_ClientBase *m_pCardSwiper;
+	HeartBeatService_ClientBase* m_pHBClient;
 	BusinessContext m_busCtx;
 	SpReqAnsContext<CardReadAdapterService_Read_Req, CardReadAdapterService_Read_Ans>::Pointer m_readCtx;
 
@@ -905,7 +907,8 @@ private:
 	HMODULE m_hVerdorDll;
 	//GUIConsoleService_ClientBase *m_pGUIConsoleClient;
 	bool m_devInit, m_bCancelAccept, m_bWaitingAccept, m_bWaitAccepteMore
-		, m_bCDA, m_bIssuingExit, m_bCardIssued, m_bCaptureCfgFlag, m_bHasHopper[3], m_bBTConncting;
+		, m_bCDA, m_bIssuingExit, m_bCardIssued, m_bCaptureCfgFlag, m_bHasHopper[3], m_bBTConncting
+		, m_bCardActiveNotify;
 	ErrorCodeEnum m_testResult;
 	//m_CardInit,m_CardRemains,m_CardIssued,m_CardMixed,m_CardPercent
 	int m_CardCaptured, m_issueStatusFromFile, m_issueStatus, m_port, m_baudRate, m_currentHopper, m_scanSlot;
@@ -924,11 +927,36 @@ private:
 	char m_AuthCode[2];
 	bool m_bBTConnected;
 	map<int, CtxInfo> m_mapCtx;
+	SpReqAnsContext<CardReadAdapterService_PreOnlineOnStore_Req, CardReadAdapterService_PreOnlineOnStore_Ans>::Pointer m_crossCtx;
+	ULONGLONG m_ullCrossStart;
 
 	bool IsCardIssuerSessionOK();
 	bool IsContactlessCardSessionOK();
 	bool IsCardSwiperSessionOK();
 	bool IsTheEntity(int module,ModuleType eModule);
+	bool CheckHBSessionOrToConnect();
+	//oilyang@20230614 跨及时因为卡片的实际交易发生在卡库,需要在发起端对返回的UserErrorCode做二次映射,方便客户理解提示信息
+	DWORD MapErrorCodeWhileCallStore(DWORD eErrCode)
+	{
+		//eErrCode defined on CardIssuer_UserErrorCode.h
+		switch (eErrCode)
+		{
+		case 0x20300240:
+			return 0x203002E0;
+		case 0x20300242:
+			return 0x203002E1;
+		case 0x20300243:
+			return 0x203002E2;
+		case 0x20300244:
+			return 0x203002E3;
+		case 0x20300246:
+			return 0x203002E4;
+		case 0x2030000D:
+			return 0x203002E5;
+		default:
+			return eErrCode;
+		}
+	}
 };
 struct InitTask : public ITaskSp
 {
@@ -1283,9 +1311,7 @@ struct PreOnlineOnStoreTask : public ITaskSp
 	PreOnlineOnStoreTask(CCardReadAdapterFSM* f) : fsm(f) {}
 	void Process()
 	{
-		FSMEvent *e = new FSMEvent(USER_EVT_PREONLINE_ON_STORE_FINISHED);
-		e->param1 = fsm->PreOnlineOnStore(ctx);
-		fsm->PostEventFIFO(e);
+		fsm->PreOnlineOnStore(ctx);
 	}
 };
 struct GetAddCardInfoTask : public ITaskSp
@@ -1307,7 +1333,7 @@ struct NotifyPreOnlineTask : public ITaskSp
 	NotifyPreOnlineTask(CCardReadAdapterFSM* f) : fsm(f) {}
 	void Process()
 	{
-		FSMEvent *e = new FSMEvent(USER_EVT_NOTIFY_PREONLINE_FINISHED);
+		FSMEvent* e = new FSMEvent(USER_EVT_PREONLINE_ON_STORE_FINISHED);
 		e->param1 = fsm->NotifyPreonline(ctx);
 		fsm->PostEventFIFO(e);
 	}
@@ -1384,4 +1410,13 @@ struct Test2Task : public ITaskSp
 		fsm->PostEventFIFO(e);
 	}
 };
+struct WaitCardActiveTask : public ITaskSp
+{
+	CCardReadAdapterFSM* fsm;
+	WaitCardActiveTask(CCardReadAdapterFSM* f) : fsm(f) {}
+	void Process()
+	{
+		fsm->WaitCardActive();
+	}
+};
 #endif //__CARDREAD_ADAPTER_FSM_H