Parcourir la source

Z991239-5550 #comment feat: JS跨机激活接口实现

Signed-Off-By: commit-hook
刘文涛80174520 il y a 1 an
Parent
commit
95ef1ec649

+ 5 - 4
DevAdapter/include/CardAssist.cpp

@@ -470,16 +470,17 @@ bool CCardProcess::DetectIfICCard(CardReadType eType, DeviceBaseClass *pCardX, i
 		
 		if (eErr != Error_Succeed)
 		{
+			QueryLastErr(eType, errMsg);
+			errMsg = CSimpleStringA::Format("(CardIssuer)DetectIfICCard::ActiveContactlessICCard failed(%d):%s", eErr, errMsg.GetData());
 			if (eType == CARD_MACHINE_ISSUER_RF) {
+				LogWarn(Severity_Middle, Error_Unexpect, CardIssuer_UserErrorCode_ActiveContactlessICCard_Failed, errMsg.GetData());
 				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI("DevAdapter::ActiveContactlessICCard").setCostTime(l_endTime - l_beginTime).setResultCode("RTA23C6")("DetectIfICCard::ActiveContactlessICCard err=%s", SpStrError(eErr));
 			}
 			else {
+				LogWarn(Severity_Middle, Error_Unexpect, CardIssuerStore_UserErrorCode_ActiveContactlessICCard_Failed, errMsg.GetData());
 				DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI("DevAdapter::ActiveContactlessICCard").setCostTime(l_endTime - l_beginTime).setResultCode("RTA2WC6")("DetectIfICCard::ActiveContactlessICCard err=%s", SpStrError(eErr));
 			}
-			QueryLastErr(eType, errMsg);
-			errMsg = CSimpleStringA::Format("(CardIssuer)DetectIfICCard::ActiveContactlessICCard failed(%d):%s", eErr, errMsg.GetData());
-			LogWarn(Severity_Middle, Error_Unexpect, ContactlessCard_UserErrorCode_ActiveContactlessICCard_Failed, errMsg.GetData());
-			return false;
+			return false; 
 		}
 		else {
 			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::ActiveContactlessICCard").setCostTime(l_endTime - l_beginTime)("DetectIfICCard::ActiveContactlessICCard");

+ 875 - 7
Module/mod_cardissuerstore/CardIssuerFSM.cpp

@@ -198,13 +198,13 @@ unsigned int CCardIssuerFSM::s2_on_event(FSMEvent* pEvt)
 	}
 		break;
 	case USER_EVT_JS_ISSUE_FROM_BOX:
-		{
-			IssueFromBoxJSEvent* ifs = dynamic_cast<IssueFromBoxJSEvent*>(pEvt);
-			IssueFromBoxJSTask* mTask = new IssueFromBoxJSTask(this);
-			mTask->ctx = ifs->ctx;
-			GetEntityBase()->GetFunction()->PostThreadPoolTask(mTask);
-			pEvt->SetHandled();
-		}
+	{
+		IssueFromBoxJSEvent* ifs = dynamic_cast<IssueFromBoxJSEvent*>(pEvt);
+		IssueFromBoxJSTask* mTask = new IssueFromBoxJSTask(this);
+		mTask->ctx = ifs->ctx;
+		GetEntityBase()->GetFunction()->PostThreadPoolTask(mTask);
+		pEvt->SetHandled();
+	}
 		break;
 	case USER_EVT_JS_CAPTURE:
 	{
@@ -215,6 +215,15 @@ unsigned int CCardIssuerFSM::s2_on_event(FSMEvent* pEvt)
 		pEvt->SetHandled();
 	}
 		break;
+	case USER_EVT_JS_PREONLINE_CROSS:
+	{
+		PreOnlineCrossJSEvent* pjs = dynamic_cast<PreOnlineCrossJSEvent*>(pEvt);
+		PreOnlineCrossJSTask* task = new PreOnlineCrossJSTask(this);
+		task->ctx = pjs->ctx;
+		GetEntityBase()->GetFunction()->PostThreadPoolTask(task);
+		pEvt->SetHandled();
+	}
+		break;
 	case USER_EVT_ISSUE_EX:
 	{
 		IssueTask* task = new IssueTask(this);
@@ -1295,6 +1304,34 @@ unsigned int CCardIssuerFSM::s18_on_event(FSMEvent* pEvt)
 	}
 	return ret;
 }
+
+void CCardIssuerFSM::s19_on_entry()
+{
+	LOG_FUNCTION();
+	m_currentFSMState = 19;
+}
+
+void CCardIssuerFSM::s19_on_exit()
+{
+	LOG_FUNCTION();
+}
+
+unsigned int CCardIssuerFSM::s19_on_event(FSMEvent* pEvt)
+{
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("s19 evt (%d,%d)", pEvt->iEvt, pEvt->param1);
+	int ret = 0;
+	switch (pEvt->iEvt)
+	{
+	case USER_EVT_JS_PREONLINE_CROSS_FINISHED:
+		pEvt->SetHandled();
+		ret = pEvt->param1;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
 ErrorCodeEnum CCardIssuerFSM::OnInit()
 {
 	LOG_FUNCTION();
@@ -8780,6 +8817,40 @@ int CCardIssuerFSM::IssueFromBoxJS(SpReqAnsContext<CardIssuerStoreService_IssueF
 	return 0;
 }
 
+int CCardIssuerFSM::PreOnlineCrossJS(SpReqAnsContext<CardIssuerStoreService_PreOnlineCrossJS_Req, CardIssuerStoreService_PreOnlineCrossJS_Ans>::Pointer ctx)
+{
+	m_bCrossPreOnline = true;//设置联机状态
+	GetEntityBase()->GetFunction()->SetSysVar("CardStoreInUse", "Y");//设置卡槽使用状态为Y
+	bool bCtOK = false;//是否读到芯片
+	bool bContinue = false;//是否继续非接流程
+	bool bCaptureResult = true;//默认吞卡结果
+	m_csMagT2Track = "";//初始化赋值
+	m_csMagT3Track = "";
+	m_csMagAccout = "";
+	m_csMagRegion = "";
+	m_csMagCardSerial = "";
+	m_csMagCVC = "";
+	m_csMagExpireDate = "";
+	int ret = PreOnlineCrossJS_Contact(ctx, bCtOK, bContinue,bCaptureResult);
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("PreOnlineCrossJS_Contact bCtOK=%d,bContinue=%d,bCaptureResult=%d", (int)bCtOK, (int)bContinue, (int)bCaptureResult);
+	if (bContinue) {
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("PreOnlineCrossJS 用非接兜底");
+		ret = PreOnlineCrossJS_RF(ctx,bCaptureResult);
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("PreOnlineCrossJS_RF bCaptureResult=%d", (int)bCaptureResult);
+	}
+
+	if (bCaptureResult) {
+		ret = 0;//S2
+	}
+	else {
+		ret = 1;//S9
+		FSMSetIssueFlag(1);
+	}
+	GetEntityBase()->GetFunction()->SetSysVar("CardStoreInUse", "N");//设置卡槽使用状态为N
+	ClearCrossPreOnlineFlag();//清除联机状态
+	return ret;
+}
+
 DWORD CCardIssuerFSM::GetFsmStateErrCode()
 {
 	int state = GetFSMState();
@@ -8890,3 +8961,800 @@ int CCardIssuerFSM::PostOnlineJS_RF(SpReqAnsContext<CardIssuerStoreService_PostO
 	ctx->Answer(Error_Succeed);
 	return 0;
 }
+
+bool CCardIssuerFSM::AfterPreOnlineCrossJS(const int slot,CSimpleStringA cardNo)
+{
+	LOG_FUNCTION();
+	ErrorCodeEnum eErr = Error_Unexpect;
+	long l_beginTime, l_endTime;
+	CSimpleStringA errMsg(true);
+	bool ret = true;
+
+	l_beginTime = GetTickCountRVC();
+	eErr = m_hDevHelper->MoveCardToSlot(slot);
+	l_endTime = GetTickCountRVC();
+
+	if (eErr == Error_Succeed)
+	{
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::MoveCardToSlot").setCostTime(l_endTime - l_beginTime)("AfterPreOnlineCrossJS::MoveCardToSlot succ, slot:%d", slot);
+		LogWarn(Severity_Low, Error_Succeed, CardIssuerStore_UserErrorCode_MoveCardToSlot, "AfterPreOnlineOnStore MoveCardToSlot succ.");
+		m_cardPos = 1;
+		ret = true;
+	}
+	else
+	{
+		bool bTrans = true;
+		SetErrorAndLog(eErr, MEC_DEVAPI_CARDISSUER_MoveCardToSlot, "DevAdapter::MoveCardFromSlot", __FUNCTION__, false, l_endTime - l_beginTime, "", CSimpleStringA::Format("AfterPreOnlineCrossJS::MoveCardToSlot err, slot=%d", slot));
+
+		ToRegistCaptureCardInfo(cardNo);
+		m_captureReason = "9999";
+		eErr = MachineMoveCardBackNotHold();
+		if (eErr == Error_Succeed) {
+			m_cardPos = 2;
+			ret = true;
+			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("AfterPreOnlineCrossJS Capture succ.");
+		}
+		else {
+			m_cardPos = 3;
+			ret = false;
+			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("AfterPreOnlineCrossJS Capture fail.");
+		}
+	}
+	
+	return ret;
+}
+
+int CCardIssuerFSM::PreOnlineCrossJS_Contact(SpReqAnsContext<CardIssuerStoreService_PreOnlineCrossJS_Req, CardIssuerStoreService_PreOnlineCrossJS_Ans>::Pointer ctx, bool& bICOK, bool& bContinue, bool& CaptureResult)
+{
+	LOG_FUNCTION();
+	//oilyang@20220611 only return 0;if unexpected,process and return 0
+	m_findCard = m_cardPos = 0;
+	long l_beginTime, l_endTime;
+
+	CSimpleStringA reqCardno = MaskCardno(ctx->Req.account.GetData());
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("PreOnlineCrossJS_Contact, business data[%s], req.slot:%d, reqCardno:%s ", ctx->Req.businessData.GetData(), ctx->Req.slot, reqCardno.GetData());
+	CSimpleStringA csMagT2Track(""), csMagT3Track(""), csMagAccout(""), csMagRegion(""), csMagCardSerial(""), csMagCVC(""), csMagExpireDate("");
+	
+	//读磁
+	int slot = ctx->Req.slot;
+	DWORD dwTmpUserErrCode = 0;
+	CSimpleStringA errMsg("");
+
+	if (!IsValidSlotNum(slot))
+	{
+		errMsg = CSimpleStringA::Format("PreOnlineCrossJS_Contact, web give a invalid slot num(%d)", slot);
+		LogWarn(Severity_Middle, Error_Unexpect, CardIssuerStore_UserErrorCode_Dev_SlotInvalid, errMsg.GetData());
+		DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("invalid slot:%d", slot);
+		m_findCard = 1;
+		ctx->Ans.findCard = 1;
+		ctx->Ans.cardPos = 0;
+		ctx->Answer(Error_Unexpect, CardIssuerStore_UserErrorCode_Dev_SlotInvalid);
+		return 0;//此情况下后续不再非接流程
+	}
+	if (!IsSlotHasCard(slot))
+	{
+		errMsg = CSimpleStringA::Format("PreOnlineCrossJS_Contact, the slot(%d) has no card.", slot);
+		LogWarn(Severity_Middle, Error_Unexpect, CardIssuerStore_UserErrorCode_Dev_SlotHasNoCard, errMsg.GetData());
+		DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("the slot(%d) has no card", slot);
+		m_findCard = 2;
+		ctx->Ans.findCard = 2;
+		ctx->Ans.cardPos = 0;
+		ctx->Answer(Error_Unexpect, CardIssuerStore_UserErrorCode_Dev_SlotHasNoCard);
+		return 0;//此情况下后续不再非接流程
+	}
+
+	ErrorCodeEnum eErr = Error_Unexpect;
+	l_beginTime = GetTickCountRVC();
+	eErr = m_hDevHelper->MoveCardFromSlot(slot);
+	l_endTime = GetTickCountRVC();
+
+	if (eErr != Error_Succeed)
+	{
+		SetErrorAndLog(eErr, MEC_DEVAPI_CARDISSUER_MoveCardFromSlot, "DevAdapter::MoveCardFromSlot", __FUNCTION__, false, l_endTime - l_beginTime, "QLR040222052", CSimpleStringA::Format("PreOnlineCrossJS_Contact::MoveCardFromSlot err, slot=%d", slot));
+		m_findCard = 4;
+		ctx->Ans.findCard = 4; 
+		ctx->Ans.cardPos = 0;
+		ctx->Answer(Error_Unexpect, GetAlarmDEC());
+		return 0;//此情况下后续不再非接流程
+	}
+	else {
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::MoveCardFromSlot").setCostTime(l_endTime - l_beginTime)("PreOnlineCrossJS_Contact::MoveCardFromSlot succ, slot=%d",slot);
+	}
+	LogWarn(Severity_Low, Error_Succeed, CardIssuerStore_UserErrorCode_MoveCardFromSlot, CSimpleStringA::Format("PreOnlineCrossJS_Contact MoveCardFromSlot succ, slot=%d",slot));
+
+	CardNo card;
+	ZeroMemory(card.account, sizeof(card.account));
+	ZeroMemory(card.track2, sizeof(card.track2));
+	ZeroMemory(card.track3, sizeof(card.track3));
+
+	l_beginTime = GetTickCountRVC();
+	eErr = m_hDevHelper->ReadAccount(card);//读卡(三种方式都要求厂商尝试)
+	l_endTime = GetTickCountRVC();
+
+	LogWarn(Severity_Low, Error_Unexpect, CardIssuerStore_UserErrorCode_ReadAccount_Cost_Time, CSimpleStringA::Format("{\"cost\":%d}", l_endTime - l_beginTime));
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("ReadAccount t2Size:%d(%d),t3Size:%d(%d), req account len:%d, read account len:%d",
+		card.dwTrack2Size, strlen(card.track2), card.dwTrack3Size, strlen(card.track3), ctx->Req.account.GetLength(), strlen(card.account));
+
+	if (eErr != Error_Succeed)
+	{
+		SetErrorAndLog(eErr, MEC_DEVAPI_CARDISSUER_ReadAccount, "DevAdapter::ReadAccount", __FUNCTION__, false, l_endTime - l_beginTime, "QLR040222052", CSimpleStringA::Format("PreOnlineCrossJS_Contact::ReadAccount err, slot=%d", slot));
+		CaptureResult = AfterPreOnlineCrossJS(slot, "");//执行移回操作
+		m_findCard = 4;
+		ctx->Ans.findCard = 4;
+		ctx->Ans.cardPos = m_cardPos;
+		ctx->Answer(Error_Unexpect, GetAlarmDEC());
+		return 0;//此情况下后续不再非接流程
+	}
+	else {
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::ReadAccount").setCostTime(l_endTime - l_beginTime)("PreOnlineCrossJS_Contact::ReadAccount succ, slot=%d", slot);
+	}
+
+	m_currCardNo = card.account;//读出的卡号
+	CSimpleStringA reqCardmask = MaskCardno(ctx->Req.account.GetData());
+	CSimpleStringA readCardmask = MaskCardno(card.account);
+
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact::ReadAccount>, req.account:%s, card.account:%s", reqCardmask.GetData(),readCardmask.GetData());
+	LogWarn(Severity_Low, Error_Succeed, CardIssuerStore_UserErrorCode_CardBin, CSimpleStringA::Format("cardBin:%s", readCardmask.GetData()));
+
+	if (ctx->Req.account.GetLength() > 0 && ctx->Req.account.Compare(card.account) != 0)
+	{
+		CaptureResult = AfterPreOnlineCrossJS(slot, m_currCardNo);//执行移回操作
+		m_findCard = 3;
+		ctx->Ans.findCard = 3;
+		ctx->Ans.cardPos = m_cardPos;
+		ctx->Answer(Error_Succeed);
+		return 0;//此情况下后续不再非接流程
+	}
+	if (card.dwTrack2Size > 0 && card.dwTrack2Size < 41)
+	{
+		if (card.track2[card.dwTrack2Size - 1] == 'F') {
+			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact>, track2 data has F in the end.");
+			card.track2[card.dwTrack2Size - 1] = '\0';
+		}
+		csMagT2Track = card.track2;
+		m_csMagT2Track = csMagT2Track;
+	}
+	if (card.dwTrack3Size > 0 && card.dwTrack3Size < 108)
+	{
+		if (card.track3[card.dwTrack3Size - 1] == 'F')
+		{
+			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact>, track3 data has F in the end.");
+			card.track3[card.dwTrack3Size - 1] = '\0';
+		}
+		csMagT3Track = card.track3;
+		m_csMagT3Track = csMagT3Track;
+	}
+	//oilyang@20180516 add for kaku
+	char* pTmpMag2 = new char[128];
+	ZeroMemory(pTmpMag2, 128);
+	Track2Data track2Data;
+	bool bT2OK, bT3OK;
+	bT2OK = bT3OK = false;
+	if (card.dwTrack2Size > 8 && strlen(card.track2) > 8)
+		bT2OK = true;
+	if (card.dwTrack3Size > 8 && strlen(card.track3) > 8)
+		bT3OK = true;
+	DecodeTracksData((const char*)csMagT2Track, card.dwTrack2Size, (const char*)csMagT3Track, card.dwTrack3Size, pTmpMag2, bT2OK, bT3OK);
+	if ((SplitTrack2(pTmpMag2, track2Data) == 0))
+	{
+		csMagAccout = track2Data.t2Account;
+		m_csMagAccout = csMagAccout;
+		csMagRegion = track2Data.t2Region;
+		m_csMagRegion = csMagRegion;
+		csMagCardSerial = track2Data.t2CardSerial;
+		m_csMagCardSerial = csMagCardSerial;
+		csMagCVC = track2Data.t2CVC;
+		m_csMagCVC = csMagCVC;
+		csMagExpireDate = track2Data.t2ExpireDate;
+		m_csMagExpireDate = csMagExpireDate;
+	}
+	else {
+		LogWarn(Severity_Low, Error_Succeed, CardIssuerStore_UserErrorCode_Split_MagTrack2_Failed, CSimpleStringA::Format("<PreOnlineCrossJS_Contact> SplitTrack2 fail,Mag pTrack2.len:%d", strlen(pTmpMag2)));//记录解析错误的磁条数据长度
+	}
+	delete[]pTmpMag2;
+
+
+	m_pCardProcess->DataInit();
+	//数据已读出,开始pmoc流程
+	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_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact>, the front BusinessData have not provide aid data.");
+		int icRetryTimes = 0;
+		while (1)
+		{
+			l_beginTime = GetTickCountRVC();
+			retDetectAndRead = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_ISSUER_STORE, m_hDevHelper, m_aidList, activeCardType, false);
+			l_endTime = GetTickCountRVC();
+			if (retDetectAndRead == -1)//only retry for active ic card failed!
+				icRetryTimes++;
+			else
+				break;
+			Sleep(500);
+			if (icRetryTimes >= m_ICRetryTimes)
+				break;
+		}
+	}
+	else {
+		char* pAIDTmp = new char[64];
+		memset(pAIDTmp, 0, 64);
+		HexBuf2StrBuf(aidFromBus.value, &pAIDTmp, aidFromBus.lenth);
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact>, the aid from business is[%s],len:%d .", pAIDTmp, strlen(pAIDTmp));
+		CAutoArray<CSimpleString> preAIDs;
+		preAIDs.Init(1);
+		preAIDs[0] = (CSimpleStringA)pAIDTmp;
+		int icRetryTimes = 0;
+		while (1)
+		{
+			l_beginTime = GetTickCountRVC();
+			retDetectAndRead = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_ISSUER_STORE, m_hDevHelper, preAIDs, activeCardType, false);
+			l_endTime = GetTickCountRVC();
+			if (retDetectAndRead == -1)//only retry for active ic card failed!
+				icRetryTimes++;
+			else
+				break;
+			Sleep(500);
+			if (icRetryTimes >= m_ICRetryTimes)
+				break;
+		}
+		if (pAIDTmp != NULL)
+			delete[]pAIDTmp;
+	}
+
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact>, After invoke DetectAndReadICData, retDetectAndRead:%d, activeCardType:%d", retDetectAndRead, activeCardType);
+	
+	if (retDetectAndRead < 0)
+	{
+		if (IfUseRf()) {
+			bContinue = true; //继续后面的非接流程
+			if (retDetectAndRead == -1) {
+				SetErrorAndLog(Error_Unexpect, CardIssuerStore_UserErrorCode_ActiveICCard_Failed, "PreOnlineCrossJS_Contact::DetectIfICCard", __FUNCTION__, false, l_endTime - l_beginTime, "QLR040222052", CSimpleStringA::Format("PreOnlineCrossJS_Contact::DetectAndReadICData(-1) err, slot:%d", slot));
+			}
+			else if (retDetectAndRead == -2) {
+				SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_CARDISSUER_ICCommand, "DevAdapter::ICCommand", __FUNCTION__, false, l_endTime - l_beginTime, "QLR040222052", CSimpleStringA::Format("PreOnlineCrossJS_Contact::DetectAndReadICData(-2) err, slot:%d", slot));
+			}
+			else if (retDetectAndRead == -3) {
+				SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_CARDISSUER_ICCommand, "DevAdapter::ICCommand", __FUNCTION__, false, l_endTime - l_beginTime, "QLR040222052", CSimpleStringA::Format("PreOnlineCrossJS_Contact::DetectAndReadICData(-3) err, slot:%d", slot));
+			}
+		}
+		else {
+			CaptureResult = AfterPreOnlineCrossJS(slot, m_currCardNo);//执行移回操作
+			m_findCard = 4;
+			ctx->Ans.findCard = 4;
+			ctx->Ans.cardPos = m_cardPos;
+			if (retDetectAndRead == -1) {
+				SetErrorAndLog(Error_Unexpect, CardIssuerStore_UserErrorCode_ActiveICCard_Failed, "PreOnlineCrossJS_Contact::DetectIfICCard", __FUNCTION__, IsInBusiness(), l_endTime - l_beginTime, "QLR040222052", CSimpleStringA::Format("PreOnlineCrossJS_Contact::DetectAndReadICData(-1) err, slot:%d", slot));
+				ctx->Answer(Error_Unexpect, CardIssuerStore_UserErrorCode_ActiveICCard_Failed);
+			}
+			else if (retDetectAndRead == -2) {
+				SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_CARDISSUER_ICCommand, "DevAdapter::ICCommand", __FUNCTION__, IsInBusiness(), l_endTime - l_beginTime, "QLR040222052", CSimpleStringA::Format("PreOnlineCrossJS_Contact::DetectAndReadICData(-2) err, slot:%d", slot));
+				ctx->Answer(Error_Unexpect, GetAlarmDEC());
+			}
+			else if (retDetectAndRead == -3) {
+				SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_CARDISSUER_ICCommand, "DevAdapter::ICCommand", __FUNCTION__, IsInBusiness(), l_endTime - l_beginTime, "QLR040222052", CSimpleStringA::Format("PreOnlineCrossJS_Contact::DetectAndReadICData(-3) err, slot:%d", slot));
+				ctx->Answer(Error_Unexpect, GetAlarmDEC());
+			}
+		}
+		bICOK = false;
+		return 0;//上电读卡失败
+	}
+
+	m_pCardProcess->TermRiskManage();
+	CSimpleStringA taaResult;
+	BYTE bt9f27 = 0;
+	int retTAA = m_pCardProcess->TermActionAnalyze(CARD_MACHINE_ISSUER_STORE, m_hDevHelper, taaResult, true, m_bCDA, bt9f27);
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact>, TermActionAnalyze, retTAA:%d, taaResult:%s", retTAA, taaResult.GetData());
+	switch (retTAA)
+	{//to be added oiltmp 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)
+	{
+		if (IfUseRf()) {
+			bContinue = true; //继续后面的非接流程
+		}
+		else {
+			CaptureResult = AfterPreOnlineCrossJS(slot, m_currCardNo);//执行移回操作
+			m_findCard = 0;
+			ctx->Ans.findCard = 0;
+			ctx->Ans.cardPos = m_cardPos;
+			ctx->Answer(Error_Succeed);
+		}
+		return 0;
+	}
+
+	string tmpResult, actionType, result = "", baseICData = "";
+	tmpResult = ctx->Ans.result;
+	char* pSomeICData = new char[ONE_K];
+	ZeroMemory(pSomeICData, ONE_K);
+	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));
+	_itoa(lenRet, arqcLen, 10);
+	ICData appExpiryDate(false, 0x5f, 0x24);
+	if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC, appExpiryDate, false, 0) == -1)
+	{
+		DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact>, can't find expire date");
+		if (IfUseRf()) {
+			bContinue = true; //继续后面的非接流程
+		}
+		else {
+			CaptureResult = AfterPreOnlineCrossJS(slot, m_currCardNo);//执行移回操作
+			m_findCard = 0;
+			ctx->Ans.findCard = 0;
+			ctx->Ans.cardPos = m_cardPos;
+			ctx->Answer(Error_Succeed);
+		}		
+		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)("<PreOnlineCrossJS_Contact>, 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_WARN, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact>, ic no track2 data");
+		l_beginTime = GetTickCountRVC();
+		eErr = m_hDevHelper->ReleaseIC();
+		l_endTime = GetTickCountRVC();
+		if (eErr != Error_Succeed) {
+			SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_CARDISSUER_ReleaseIC, "DevAdapter::ReleaseIC", __FUNCTION__, false, l_endTime - l_beginTime, "", "PreOnlineCrossJS_Contact::ReleaseIC err");
+		}
+		else {
+			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::ReleaseIC").setCostTime(l_endTime - l_beginTime)("PreOnlineCrossJS_Contact::ReleaseIC");
+		}
+	}
+	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_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact>, ic.track2, split pos:%d", pos);
+
+		char* ddd = new char[40];
+		memset(ddd, 0, 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;
+		}
+		else {
+			LogWarn(Severity_Low, Error_Succeed, CardIssuerStore_UserErrorCode_Split_ICTrack2_Failed, CSimpleStringA::Format("<PreOnlineCrossJS_Contact> SplitTrack2 fail,ic pTrack2.len:%d", strlen(icTrack2Data)));
+		}
+		if (_strnicmp(track2Data.t2Account, ddd, strlen(ddd)))
+		{
+			t2ICCVC = "";
+			t2ICTrack2 = pICTrack2;
+			t2ICAccount = (char*)ddd;
+			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("count:%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) {
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact>, actionType:%s", actionType.c_str());
+		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 + "|MAGT2," + (const char*)csMagT2Track
+		+ "|MAGT3," + (const char*)csMagT3Track + "|MAGACCOUNT," + (const char*)csMagAccout + "|MAGREGION," + (const char*)csMagRegion
+		+ "|MAGCARDSERIAL," + (const char*)csMagCardSerial + "|MAGCVC," + (const char*)csMagCVC + "|MAGEXPIREDATAE," + (const char*)csMagExpireDate;
+	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;
+	m_currCardNo = t2ICAccount.c_str();
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_Contact>, data to host(less)[%s],baseICData length:%d", txtresult.c_str(), baseICData.length());
+
+	if (pCID != NULL)
+		delete[]pCID;
+	if (pIssueBankLen != NULL)
+		delete[]pIssueBankLen;
+	if (pExpireDate != NULL)
+		delete[]pExpireDate;
+
+	if (m_pDataToARQC != NULL)
+	{
+		delete[]m_pDataToARQC;
+		m_pDataToARQC = NULL;
+	}
+
+	
+	bICOK = true;
+	bContinue = false;
+	CaptureResult = AfterPreOnlineCrossJS(slot, m_currCardNo);//执行移回操作
+	m_findCard = 0;
+	ctx->Ans.findCard = 0;
+	ctx->Ans.cardPos = m_cardPos;
+	ctx->Answer(Error_Succeed);
+
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR040222052")();
+	return 0;//不再继续后面的非接流程
+}
+
+int CCardIssuerFSM::PreOnlineCrossJS_RF(SpReqAnsContext<CardIssuerStoreService_PreOnlineCrossJS_Req, CardIssuerStoreService_PreOnlineCrossJS_Ans>::Pointer ctx, bool& CaptureResult)
+{
+	LOG_FUNCTION();
+	long l_beginTime, l_endTime;
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("(PreOnlineCrossJS_RF) use CardIssuerStore rf");
+	l_beginTime = GetTickCountRVC();
+	ErrorCodeEnum eErr = m_hDevHelper->MoveCard(CI_MOVECARD_RF_POSITION);
+	l_endTime = GetTickCountRVC();
+	if (eErr == Error_Succeed) {
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("DevAdapter::MoveCard").setCostTime(l_endTime - l_beginTime)("PreOnlineCrossJS_RF::MoveCard, (CI_MOVECARD_RF_POSITION)");
+	}
+	else {
+		SetErrorAndLog(eErr, MEC_DEVAPI_CARDISSUER_MoveCard, "DevAdapter::MoveCard", __FUNCTION__, false, l_endTime - l_beginTime, "QLR040222052", "PreOnlineCrossJS_RF::MoveCard err");
+	}
+	m_findCard = m_cardPos = 0;//just for RVC.CardStore
+
+	CSimpleStringA reqCardno = MaskCardno(ctx->Req.account.GetData());
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("PreOnlineCrossJS_RF, business data[%s], req.slot:%d, reqCardno:%s ", ctx->Req.businessData.GetData(), ctx->Req.slot, reqCardno.GetData());
+	CSimpleStringA csMagT2Track(""), csMagT3Track(""), csMagAccout(""), csMagRegion(""), csMagCardSerial(""), csMagCVC(""), csMagExpireDate("");
+	csMagT2Track = m_csMagT2Track;//从PreOnline_Contact得到的重新赋值
+	csMagT3Track = m_csMagT3Track;
+	csMagAccout = m_csMagAccout;
+	csMagRegion = m_csMagRegion;
+	csMagCardSerial = m_csMagCardSerial;
+	csMagCVC = m_csMagCVC;
+	csMagExpireDate = m_csMagExpireDate;
+
+	int slot = ctx->Req.slot;//请求的卡槽位
+
+	m_pCardProcess->DataInit();
+	//数据已读出,开始pmoc流程
+	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_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_RF>, the front BusinessData have not provide aid data.");
+		int icRetryTimes = 0;
+		while (1)
+		{
+			l_beginTime = GetTickCountRVC();
+			retDetectAndRead = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_ISSUER_STORE_RF, m_hDevHelper, m_aidList, activeCardType, false);
+			l_endTime = GetTickCountRVC();
+			if (retDetectAndRead == -1)//only retry for active ic card failed!
+				icRetryTimes++;
+			else
+				break;
+			Sleep(500);
+			if (icRetryTimes >= m_ICRetryTimes)
+				break;
+		}
+	}
+	else {
+		char* pAIDTmp = new char[64];
+		memset(pAIDTmp, 0, 64);
+		HexBuf2StrBuf(aidFromBus.value, &pAIDTmp, aidFromBus.lenth);
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_RF>, the aid from business is[%s],len:%d .", pAIDTmp, strlen(pAIDTmp));
+		CAutoArray<CSimpleString> preAIDs;
+		preAIDs.Init(1);
+		preAIDs[0] = (CSimpleStringA)pAIDTmp;
+		int icRetryTimes = 0;
+		while (1)
+		{
+			l_beginTime = GetTickCountRVC();
+			retDetectAndRead = m_pCardProcess->DetectAndReadICData(CARD_MACHINE_ISSUER_STORE_RF, m_hDevHelper, preAIDs, activeCardType, false);
+			l_endTime = GetTickCountRVC();
+			if (retDetectAndRead == -1)//only retry for active ic card failed!
+				icRetryTimes++;
+			else
+				break;
+			Sleep(500);
+			if (icRetryTimes >= m_ICRetryTimes)
+				break;
+		}
+		if (pAIDTmp != NULL)
+			delete[]pAIDTmp;
+	}
+
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_RF>, After invoke DetectAndReadICData, retDetectAndRead:%d, activeCardType:%d", retDetectAndRead, activeCardType);
+
+	if (retDetectAndRead < 0)
+	{
+		CaptureResult = AfterPreOnlineCrossJS(slot, m_currCardNo);//执行移回操作
+		m_findCard = 4;
+		ctx->Ans.findCard = 4;
+		ctx->Ans.cardPos = m_cardPos;
+
+		if (retDetectAndRead == -1) {		
+			SetErrorAndLog(Error_Unexpect, CardIssuerStore_UserErrorCode_ActiveContactlessICCard_Failed, "PreOnlineCrossJS_RF::DetectIfICCard", __FUNCTION__, IsInBusiness(), l_endTime - l_beginTime, "QLR040222052", CSimpleStringA::Format("PreOnlineCrossJS_RF::DetectAndReadICData(-1) err, slot:%d", slot));
+			ctx->Answer(Error_Unexpect, CardIssuerStore_UserErrorCode_ActiveContactlessICCard_Failed);		
+		}
+		else if (retDetectAndRead == -2) {
+			SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_CARDISSUER_RFTypeABCommand, "DevAdapter::RFTypeABCommand", __FUNCTION__, IsInBusiness(), l_endTime - l_beginTime, "QLR040222052", CSimpleStringA::Format("PreOnlineCrossJS_RF::DetectAndReadICData(-2) err, slot:%d", slot));
+			ctx->Answer(Error_Unexpect, GetAlarmDEC());
+		}
+		else if (retDetectAndRead == -3) {
+			SetErrorAndLog(Error_Unexpect, MEC_DEVAPI_CARDISSUER_RFTypeABCommand, "DevAdapter::RFTypeABCommand", __FUNCTION__, IsInBusiness(), l_endTime - l_beginTime, "QLR040222052", CSimpleStringA::Format("PreOnlineCrossJS_RF::DetectAndReadICData(-3) err, slot:%d", slot));
+			ctx->Answer(Error_Unexpect, GetAlarmDEC());
+		}
+		return 0;//上电读卡失败
+	}
+
+	m_pCardProcess->TermRiskManage();
+	CSimpleStringA taaResult;
+	BYTE bt9f27 = 0;
+	int retTAA = m_pCardProcess->TermActionAnalyze(CARD_MACHINE_ISSUER_STORE_RF, m_hDevHelper, taaResult, true, m_bCDA, bt9f27);
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_RF>, TermActionAnalyze, retTAA:%d, taaResult:%s", retTAA, taaResult.GetData());
+	switch (retTAA)
+	{//to be added oiltmp 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)
+	{
+		CaptureResult = AfterPreOnlineCrossJS(slot, m_currCardNo);//执行移回操作
+		m_findCard = 0;
+		ctx->Ans.findCard = 0;
+		ctx->Ans.cardPos = m_cardPos;
+		ctx->Answer(Error_Succeed);
+		return 0;
+	}
+
+	string tmpResult, actionType, result = "", baseICData = "";
+	tmpResult = ctx->Ans.result;
+	char* pSomeICData = new char[ONE_K];
+	ZeroMemory(pSomeICData, ONE_K);
+	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));
+	_itoa(lenRet, arqcLen, 10);
+	ICData appExpiryDate(false, 0x5f, 0x24);
+	if (m_pCardProcess->FindTagValue(TAG_VECTOR_IC, appExpiryDate, false, 0) == -1)
+	{
+		DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_RF>, can't find expire date");
+		CaptureResult = AfterPreOnlineCrossJS(slot, m_currCardNo);//执行移回操作
+		m_findCard = 0;
+		ctx->Ans.findCard = 0;
+		ctx->Ans.cardPos = m_cardPos;
+		ctx->Answer(Error_Succeed);
+		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);
+
+	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)("<PreOnlineCrossJS_RF>, 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_WARN, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_RF>, ic no track2 data");
+	}
+	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_INFO, LOG_TYPE_SYSTEM)(CSimpleStringA::Format("<PreOnlineCrossJS_RF>, ic.track2, split pos:%d", pos));
+
+		char* ddd = new char[40];
+		memset(ddd, 0, 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;
+		}
+		else{
+			LogWarn(Severity_Low, Error_Succeed, CardIssuerStore_UserErrorCode_Split_ICTrack2_Failed, CSimpleStringA::Format("<PreOnlineCrossJS_RF> SplitTrack2 fail,ic pTrack2.len:%d", strlen(icTrack2Data)));
+		}
+		if (_strnicmp(track2Data.t2Account, ddd, strlen(ddd)))
+		{
+			t2ICCVC = "";
+			t2ICTrack2 = pICTrack2;
+			t2ICAccount = (char*)ddd;
+			DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("count:%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) {
+		DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnline>, actionType:%s", actionType.c_str());
+		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 + "|MAGT2," + (const char*)csMagT2Track
+		+ "|MAGT3," + (const char*)csMagT3Track + "|MAGACCOUNT," + (const char*)csMagAccout + "|MAGREGION," + (const char*)csMagRegion
+		+ "|MAGCARDSERIAL," + (const char*)csMagCardSerial + "|MAGCVC," + (const char*)csMagCVC + "|MAGEXPIREDATAE," + (const char*)csMagExpireDate;
+	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;
+	m_currCardNo = t2ICAccount.c_str();
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("<PreOnlineCrossJS_RF>, data to host(less)[%s],baseICData length:%d", txtresult.c_str(), baseICData.length());
+
+	if (pCID != NULL)
+		delete[]pCID;
+	if (pIssueBankLen != NULL)
+		delete[]pIssueBankLen;
+	if (pExpireDate != NULL)
+		delete[]pExpireDate;
+
+	if (m_pDataToARQC != NULL)
+	{
+		delete[]m_pDataToARQC;
+		m_pDataToARQC = NULL;
+	}
+	LogWarn(Severity_Low, Error_Succeed, CardIssuerStore_UserErrorCode_ReadByRF, "PreOnlineCrossJS_RF ok");
+
+	CaptureResult = AfterPreOnlineCrossJS(slot, m_currCardNo);//执行移回操作
+	m_findCard = 0;
+	ctx->Ans.findCard = 0;
+	ctx->Ans.cardPos = m_cardPos;
+	ctx->Answer(Error_Succeed);
+
+	DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode("QLR040222052")();
+	return 0;
+}
+

+ 47 - 3
Module/mod_cardissuerstore/CardIssuerFSM.h

@@ -80,7 +80,9 @@ enum EvtType
 	USER_EVT_JS_POSTONLINE,
 	USER_EVT_JS_POSTONLINE_FINISHED,
 	USER_EVT_JS_ISSUE_FROM_BOX,
-	USER_EVT_JS_ISSUE_FROM_BOX_FINISHED
+	USER_EVT_JS_ISSUE_FROM_BOX_FINISHED,
+	USER_EVT_JS_PREONLINE_CROSS,
+	USER_EVT_JS_PREONLINE_CROSS_FINISHED
 };
 enum SAMICCommandType
 {
@@ -931,6 +933,22 @@ public:
 	}
 };
 
+class PreOnlineCrossJSEvent : public FSMEvent
+{
+public:
+	PreOnlineCrossJSEvent() : FSMEvent(USER_EVT_JS_PREONLINE_CROSS) {}
+	~PreOnlineCrossJSEvent() {}
+	SpReqAnsContext<CardIssuerStoreService_PreOnlineCrossJS_Req, CardIssuerStoreService_PreOnlineCrossJS_Ans>::Pointer ctx;
+	virtual void OnUnhandled()
+	{
+		if (ctx != NULL)
+		{
+			DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Operate unhandled");
+			ctx->Answer(Error_Unexpect, CardIssuerStore_UserErrorCode_EntityInStateCannotProcess);
+		}
+	}
+};
+
 struct AddCardInfo
 {
 	int slot;
@@ -942,7 +960,7 @@ struct AddCardInfo
 class CCardIssuerFSM : public CCommDevFSM<CCardIssuerFSM, CardIssuerClass>
 {
 public:
-	enum {s0,s1,s2,s4,s5,s6,s7,s8,s9,s10,s11,s14,s17,s18};
+	enum {s0,s1,s2,s4,s5,s6,s7,s8,s9,s10,s11,s14,s17,s18,s19};
 	BEGIN_FSM_STATE(CCardIssuerFSM)
 		FSM_STATE_ENTRY(s0,"Init",s0_on_entry,s0_on_exit,s0_on_event)
 		FSM_STATE_ENTRY(s1,"Initializing",s1_on_entry,s1_on_exit,s1_on_event)
@@ -958,6 +976,7 @@ public:
 		FSM_STATE_ENTRY(s14, "SAMIC", s14_on_entry, s14_on_exit, s14_on_event)
 		FSM_STATE_ENTRY(s17, "OperateCardStore", s17_on_entry, s17_on_exit, s17_on_event)
 		FSM_STATE_ENTRY(s18, "PrintCardIm", s18_on_entry, s18_on_exit, s18_on_event)
+		FSM_STATE_ENTRY(s19, "PreonlineCross", s19_on_entry, s19_on_exit, s19_on_event)
 		END_FSM_STATE()
 
 	BEGIN_FSM_RULE(CCardIssuerFSM,s0)
@@ -977,6 +996,7 @@ public:
 		FSM_RULE_ENTRY(s2, s10, USER_EVT_JS_ISSUE_FROM_SLOT, 0)//JS 领卡发卡
 		FSM_RULE_ENTRY(s2, s8,  USER_EVT_JS_CAPTURE, 0)//JS 吞卡
 		FSM_RULE_ENTRY(s2, s10,	USER_EVT_JS_ISSUE_FROM_BOX, 0)//JS 卡箱发卡
+		FSM_RULE_ENTRY(s2, s19, USER_EVT_JS_PREONLINE_CROSS, 0)//JS 跨机激活
 		FSM_RULE_ENTRY(s4,s5,USER_EVT_READ,0)
 		FSM_RULE_ENTRY(s4,s6,USER_EVT_EJECT,0)
 		FSM_RULE_ENTRY(s4, s6, USER_EVT_JS_EJECT, 0)//JS 吐卡
@@ -1054,7 +1074,8 @@ public:
 		FSM_RULE_ENTRY(s17, s9, USER_EVT_JS_READ_BATCHCARDINFO_IN_RANGE_FINISHED, 1)//JS 
 		FSM_RULE_ENTRY(s18, s4, USER_EVT_PRINT_CARD_IM_FINISHED, 0)
 		FSM_RULE_ENTRY_ANY(s18, s4, USER_EVT_JS_PRINT_CARD_FINISHED)//JS
-		
+		FSM_RULE_ENTRY(s19, s2, USER_EVT_JS_PREONLINE_CROSS_FINISHED, 0)//JS
+		FSM_RULE_ENTRY(s19, s9, USER_EVT_JS_PREONLINE_CROSS_FINISHED, 1)//JS 吞卡失败
 	END_FSM_RULE()
 
 	CCardIssuerFSM() : m_bCancelAccept(false),m_bWaitingAccept(false),
@@ -1126,6 +1147,9 @@ public:
 	void s18_on_entry();
 	void s18_on_exit();
 	unsigned int s18_on_event(FSMEvent* event);
+	void s19_on_entry();
+	void s19_on_exit();
+	unsigned int s19_on_event(FSMEvent* event);
 	
 	void Load();
 	ErrorCodeEnum OpenDevice(BYTE btOpenType, const char *pDevSN);
@@ -1363,6 +1387,8 @@ public:
 	int PostOnlineJS(SpReqAnsContext<CardIssuerStoreService_PostOnlineJS_Req, CardIssuerStoreService_PostOnlineJS_Ans>::Pointer ctx);
 
 	int IssueFromBoxJS(SpReqAnsContext<CardIssuerStoreService_IssueFromBoxJS_Req, CardIssuerStoreService_IssueFromBoxJS_Ans>::Pointer ctx);
+
+	int PreOnlineCrossJS(SpReqAnsContext<CardIssuerStoreService_PreOnlineCrossJS_Req, CardIssuerStoreService_PreOnlineCrossJS_Ans>::Pointer ctx);
 #pragma endregion JS接口具体实现方法
 
 #pragma region JS新增接口
@@ -1370,6 +1396,10 @@ public:
 	CSimpleStringA MaskCardno(const char* cardno);
 	int PostOnlineJS_Contact(SpReqAnsContext<CardIssuerStoreService_PostOnlineJS_Req, CardIssuerStoreService_PostOnlineJS_Ans>::Pointer ctx, bool& bICOK);
 	int PostOnlineJS_RF(SpReqAnsContext<CardIssuerStoreService_PostOnlineJS_Req, CardIssuerStoreService_PostOnlineJS_Ans>::Pointer ctx);
+
+	bool AfterPreOnlineCrossJS(const int slot, CSimpleStringA cardNo);
+	int PreOnlineCrossJS_Contact(SpReqAnsContext<CardIssuerStoreService_PreOnlineCrossJS_Req, CardIssuerStoreService_PreOnlineCrossJS_Ans>::Pointer ctx, bool& bICOK, bool& bContinue, bool& CaptureResult);
+	int PreOnlineCrossJS_RF(SpReqAnsContext<CardIssuerStoreService_PreOnlineCrossJS_Req, CardIssuerStoreService_PreOnlineCrossJS_Ans>::Pointer ctx, bool& CaptureResult);
 #pragma endregion JS新增接口
 
 };
@@ -1743,6 +1773,20 @@ struct IssueFromBoxJSTask : public ITaskSp
 		fsm->PostEventFIFO(e);
 	}
 };
+//跨机激活
+struct PreOnlineCrossJSTask : public ITaskSp
+{
+	CCardIssuerFSM* fsm;
+	SpReqAnsContext<CardIssuerStoreService_PreOnlineCrossJS_Req, CardIssuerStoreService_PreOnlineCrossJS_Ans>::Pointer ctx;
+	PreOnlineCrossJSTask(CCardIssuerFSM* f) : fsm(f) {}
+	void Process()
+	{
+		FSMEvent* e = new FSMEvent(USER_EVT_JS_PREONLINE_CROSS_FINISHED);
+		e->param1 = fsm->PreOnlineCrossJS(ctx);
+		
+		fsm->PostEventFIFO(e);
+	}
+};
 
 
 

+ 2 - 0
Module/mod_cardissuerstore/CardIssuerStore_UserErrorCode.h

@@ -213,6 +213,8 @@
 
 #define CardIssuerStore_UserErrorCode_EnterMainPage_SetFlag		0x22000300 //卡库进入首页设置运行时标志位
 #define CardIssuerStore_UserErrorCode_CopyRuncfg				0x22000301 //卡库拷贝旧运行时文件
+#define CardIssuerStore_UserErrorCode_Split_MagTrack2_Failed		0x22000302 //磁条磁道2解析失败
+#define CardIssuerStore_UserErrorCode_Split_ICTrack2_Failed		0x22000303 //IC磁道2解析失败
 
 //卡库流程状态报错
 #define CardIssuerStore_UserErrorCode_PROCESS_IDLE				0x22000402		//当前处于卡机无卡空闲状态,无法处理此请求

+ 1 - 1
Module/mod_cardissuerstore/mod_cardissuer.cpp

@@ -275,7 +275,7 @@ void CardIssuerStoreServerSession::Handle_PreOnlineCrossJS(SpReqAnsContext<CardI
 	LOG_FUNCTION();
 	DbgToBeidou(ctx->link, __FUNCTION__)();
 	DbgWithLink(LOG_LEVEL_INFO, ctx->link.checkEmpty() ? LOG_TYPE_SYSTEM : LOG_TYPE_USER).setAPI(__FUNCTION__)("Invoke PreOnlineCrossJS");
-	//m_pEntity->IssueFromBoxJS(ctx);
+	m_pEntity->PreOnlineCrossJS(ctx);
 }
 
 #pragma endregion JS接口实现

+ 25 - 0
Module/mod_cardissuerstore/mod_cardissuer.h

@@ -562,6 +562,31 @@ public:
 		}
 	}
 
+	void PreOnlineCrossJS(SpReqAnsContext<CardIssuerStoreService_PreOnlineCrossJS_Req, CardIssuerStoreService_PreOnlineCrossJS_Ans>::Pointer ctx)
+	{
+		LOG_FUNCTION();
+		if (!m_fsm.GetDevInitFlag()) {
+			ctx->Answer(Error_DevNotAvailable, CardIssuerStore_UserErrorCode_DevOpen_Failed);
+		}
+		else if (_stricmp(m_fsm.GetCurrStateName(), "Failed") == 0) {
+			ctx->Answer(Error_DevNotAvailable, CardIssuerStore_UserErrorCode_EntityInFailState);
+			return;
+		}
+		else if (_stricmp(m_fsm.GetCurrStateName(), "Idle") != 0 || m_fsm.CheckIsCrossPreOnline()) {
+			//不符合请求调用,告知具体错误流程
+			DWORD errCode = m_fsm.GetFsmStateErrCode();
+			int state = m_fsm.GetFSMState();
+			DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("PreOnlineCrossJS req is unhandled ,CurrState=%d", state);
+			ctx->Answer(Error_InvalidState, CardIssuerStore_UserErrorCode_CardActive_CardStore_Issuing);
+			return;
+		}
+		else {
+			PreOnlineCrossJSEvent* pEvt = new PreOnlineCrossJSEvent();
+			pEvt->ctx = ctx;
+			m_fsm.PostEventFIFO(pEvt);
+		}
+	}
+
 	virtual void OnSysVarEvent(const char* pszKey, const char* pszValue, const char* pszOldValue, const char* pszEntityName);
 	virtual bool IsService()const{return true;}
 	virtual bool IsMultiThread()const{return true;}