ucDate1[0] = 0x20; } else { ucDate1[0] = 0x19; } memcpy(ucDate1+1,ucEffectDate,3); if (ucTransDate[0] < 0x50) { ucDate2[0] = 0x20; } else { ucDate2[0] = 0x19; } memcpy(ucDate2+1,ucTransDate,3); if (memcmp(ucDate1,ucDate2,4) > 0) { SetBitOfEntityValue(TAG_TVR,TVR_APP_NOT_EFFECT); } return ICC_SUCCESS; }
//应用失效日期检查
int CICParam::VerifyExpiredDate() { INT nLen; BYTE ucExpDate[3],ucTransDate[3],ucDate1[4],ucDate2[4]; if ((ICC_SUCCESS
GetEntityValue(TAG_APPLICATION_EXPIRATION_DATE,&nLen,ucExpDate)) || (ICC_SUCCESS
GetEntityValue(TAG_TRANSACTION_DATE,&nLen,ucTransDate))) return ICC_ERR_TLVDATA; if ((!Formater.VerifyYYMMDD(ucExpDate)) || (!Formater.VerifyYYMMDD(ucTransDate))) return ICC_ERR_TLVDATA; if(ucExpDate[0] < 0x50) { ucDate1[0] = 0x20; } else { ucDate1[0] = 0x19; } memcpy(ucDate1+1,ucExpDate,3);
!= !=
if (ucTransDate[0] < 0x50) { ucDate2[0] = 0x20; } else { ucDate2[0] = 0x19; } memcpy(ucDate2+1,ucTransDate,3); if (memcmp(ucDate1, ucDate2, 4) < 0) { SetBitOfEntityValue(TAG_TVR,TVR_APP_EXPIRED); } return ICC_SUCCESS; }
//获取交易金额
BOOL CICParam::GetTransAmount(__int64 *pAmount) { __int64 nAmount = 0; TLVDATA tlvData; if (ICC_SUCCESS == GetEntityValue(TAG_AMOUNT_AUTHORISED_NUMERIC,&tlvData)) nAmount += Formater.BCDToINT64(tlvData.pValue,tlvData.nLength); else return FALSE; if (ICC_SUCCESS == GetEntityValue(TAG_AMOUNT_OTHER_NUMERIC,&tlvData)) nAmount += Formater.BCDToINT64(tlvData.pValue,tlvData.nLength); else return FALSE; *pAmount = nAmount; return TRUE; }
//最低限额检查
void CICParam::CheckFloorLimit(__int64 nAmount) { __int64 nLogAmount,nTotalAmount; nTotalAmount = nAmount; //如果终端包含一个交易日志,终端就检查同一张卡片先前的交易金额加上现在的交易金额是否超过了最低限额 //终端风险管理的交易日志对于终端来说是必备支持的,如果支持,如何得到这个日志呢。 nLogAmount = 0; nTotalAmount += nLogAmount; if (nTotalAmount >= m_TerminalParams.nTerminalFloorLimit)
{ SetBitOfEntityValue(TAG_TVR,TVR_TEFL); } }
//随机交易选择
void CICParam::SelectRandomTrans(__int64 nCurAmt) { __int64 uRand=0, uPercent=0; srand( (unsigned int)time(NULL) ); //终端产生位于1-99之间的一个随机数 uRand = rand()0; if ( 0==uRand ) uRand = 1; if (nCurAmt < m_TerminalParams.ulBRSThresholdValue) { //任何交易金额小于偏置随机选择阈值的交易需要进行随机选择,而不管交易的金额具体为多少 //随机数小于或等于随机选择的目标百分数,该交易就会被选中 if (uRand <= m_TerminalParams.ucRsTargetPercent) { SetBitOfEntityValue(TAG_TVR,TVR_TSRFOP); } } else if (nCurAmt < m_TerminalParams.nTerminalFloorLimit) { //任何交易金额大于偏置随机选择阈值而小于最低限额的交易需要进行偏置随机选择 //插值因子=(授权金额-阈值)/(最低限额-阈值) //交易目标百分比=((最大目标百分比-目标百分比)×插值因子)+目标百分比 uPercent = (m_TerminalParams.ucBRSMaxTargetPercent-m_TerminalParams.ucRsTargetPercent) *(nCurAmt-m_TerminalParams.ulBRSThresholdValue)/(m_TerminalParams.nTerminalFloorLimit-m_TerminalParams.ulBRSThresholdValue) +m_TerminalParams.ucRsTargetPercent; if (uRand <= uPercent) { //随机数小于或等于交易目标百分数,交易就被选中 SetBitOfEntityValue(TAG_TVR,TVR_TSRFOP); } } else { SetBitOfEntityValue(TAG_TVR,TVR_TEFL); } }
//设置交易授权响应码
int CICParam::SetARC(char *ucARC) { if (ICC_SUCCESS <= SetEntity(TAG_AUTHORISATION_RESPONSE_CODE,2,(BYTE*)ucARC)) return ICC_SUCCESS; else return ICC_ERR_TLVDATA; }
//获取所有有效的CVM条目
//每个有效的CVM条目由2字节构成,第一字节为CVMCODE,第二字节为CVM condition code //ucCVMEntry即条目的集合,调用者分配最大占用内存为512BYTE足以 //pCVMNUM为有效条目的数目
int CICParam::GetCVMEntry(BYTE *ucCVMEntry,int *pCVMNum) { TLVDATA tlvCVMList; ULONG ulMoneyX,ulMoneyY; BYTE ucCVMCode,ucCondition,ucCVMR[3]; int nCVMIndex; USHORT usOffsetOfCVMList; memcpy(ucCVMR,\ SetEntity(TAG_CVM_RESULTS,3,ucCVMR); if (!CheckBitOfEntityValue(TAG_AIP,AIP_CARDHOLDER_VERIFY)) return ICC_ERR_NOTSUPPORT; if (ICC_SUCCESS != GetEntityValue(TAG_CVM_LIST,&tlvCVMList)) { SetBitOfEntityValue(TAG_TVR,TVR_ICCDM); return ICC_ERR_TLVDATA; } if (tlvCVMList.nLength <= 8) { SetBitOfEntityValue(TAG_TVR,TVR_ICCDM); return ICC_ERR_TLVDATA; } ulMoneyX = Formater.BinaryToLong(tlvCVMList.pValue,4); ulMoneyY = Formater.BinaryToLong(tlvCVMList.pValue+4,4); usOffsetOfCVMList = 8; SetBitOfEntityValue(TAG_TSI,TSI_CARDHOLDERVERIFY_PERFORMED); nCVMIndex = 0; while(usOffsetOfCVMList + 2 <= tlvCVMList.nLength) { ucCVMCode = tlvCVMList.pValue[usOffsetOfCVMList++]; ucCondition = tlvCVMList.pValue[usOffsetOfCVMList++];
if (VerifyCVMCondition(ucCVMCode,ucCondition,ulMoneyX,ulMoneyY)) { strLog.Format(\Code = 0xX,CVM Condition Code = 0xX\\r\\n\ Log.WTrace(strLog); ucCVMEntry[nCVMIndex*2 + 0] = ucCVMCode; ucCVMEntry[nCVMIndex*2 + 1] = ucCondition; nCVMIndex++; } //终端检查 CVM 代码 bit7 位。如果为 1,则继续处理下一个 CVM 条目; if ((ucCVMCode & 0x40) == 0) { //此CVM失败,则持卡人验证失败(文档中“CVM列表例子”和表A1的描述有冲突,这里引用表A1的) break; } } *pCVMNum = nCVMIndex; if (nCVMIndex != 0) { return ICC_SUCCESS; } //有另种情况下需设置“持卡人验证不成功” //1、CVM条件不满足 //2、没有CVM条目需要处理 //在TVR中置“持卡人验证不成功”位为‘1’ SetBitOfEntityValue(TAG_TVR,TVR_CVF); return ICC_ERR_CMDFAILED; }
//验证持卡人验证条件是否符合 /*
如果下面这些条件都成立, 则执行该CVM:
——“CVM 条件代码”是终端可理解的;
——条件要求的卡片数据存在。例如 CVM 条件中包含金额检查时“应用货币代码”存在; ——“CVM 条件代码”规定的条件满足。例如如果“CVM 条件代码”为“终端支持该 CVM”,则“终
端性能”中应指示支持 CVM 处理。如果条件包括金额判断则“交易货币代码”应与“应用货币
代码”相同。
如果上面有一个条件不满足,终端根据“持卡人验证方法代码”决定是否继续下一个CVM处 理。