Procházet zdrojové kódy

Revert "Revert "#IQRV #comment [CW] 恒银代码_2023-05-24_cw""

This reverts commit e96fa222a07fb8acd22008f5a0a1324e08fbf75c.
gifur před 2 roky
rodič
revize
4ee622b5e4

+ 98 - 0
DevAdapter/cw/idcer.1.1/idcertconn.cpp

@@ -372,6 +372,7 @@ bool IDCertConn::load_so(const char* sPathName)
     GetIDCardType = (mGetIDCardType)dlsym(hlibID81, "GetIDCardType");
     GetIDInfoForeign = (mGetIDInfoForeign)dlsym(hlibID81, "GetIDInfoForeign");
     GetIDInfoGAT = (mGetIDInfoGAT)dlsym(hlibID81, "GetIDInfoGAT");
+    GetIDInfoRawData = (mGetIDInfoRawData)dlsym(hlibID81, "GetIDInfoRawData");
     return true;
 }
 
@@ -548,6 +549,103 @@ int IDCertConn::GetID2InfoAll(
     return iRt;
 }
 
+//二代证、港澳台居住证、外国人全部支持的接口
+int IDCertConn::GetID2InfoAllHead(
+    char* lpHeadDir,     // 头像保存文件路径
+    int& iIDType        // 证件类型
+    )
+{
+    if (!m_bOpened) return -2;
+    int iRt = CWERR_IDCARD_SUCCESS;
+    char strHeadDir[MAX_PATH]={0};
+    if(lpHeadDir != NULL && strlen(lpHeadDir) > 0)
+    {
+        strcpy(strHeadDir,lpHeadDir);
+    }
+    else
+    {
+        strcpy(strHeadDir,"C:");
+    }
+    do
+    {
+        int nDirLen = strlen(strHeadDir);
+        if(strHeadDir[nDirLen - 1] == '\\')
+        {
+            strHeadDir[nDirLen - 1] = 0x00;
+        }
+        else
+        {
+            break;
+        }
+    } while (1);
+//    IDInfoEx infEX = Null_IDinfoEx;
+    IDInfoEx infEX = Null_IDinfo;
+    IDInfoForeign infForeign = Null_IDinfoForeign;
+    IDInfoGAT infGAT = Null_IDinfoGAT;
+    if(0 != iIDType && 1 != iIDType && 2 != iIDType)
+    {
+        iRt = GetIDCardType(mDeviceID, &iIDType);
+        if(iRt != CWERR_IDCARD_SUCCESS) return iRt;
+    }
+    switch(iIDType)
+    {
+    case 0://二代身份证
+        {
+            iRt = GetID2InfoEx(mDeviceID, &infEX, strHeadDir);
+            if(iRt == CWERR_IDCARD_SUCCESS)
+            {
+
+            }
+            break;
+        }
+    case 1://外国人
+        {
+            iRt = GetIDInfoForeign(mDeviceID, &infForeign, strHeadDir);
+            if(iRt == CWERR_IDCARD_SUCCESS)
+            {
+
+            }
+            break;
+        }
+    case 2://港澳台居住证
+        {
+            iRt = GetIDInfoGAT(mDeviceID, &infGAT, strHeadDir);
+            if(iRt == CWERR_IDCARD_SUCCESS)
+            {
+
+            }
+            break;
+        }
+    default:break;
+    }
+    return iRt;
+}
+
+int IDCertConn::ReadIDInfoRawData(char*ppData, int& len)
+{
+    int iRt = GetIDInfoRawData(mDeviceID, ppData, &len);
+    return iRt;
+}
+
+//int IDCertConn::getCardInfo(CardInfo *Info)
+//{
+//    if(nullptr == GetCardInfo)
+//    {
+//        return -1;
+//    }
+//    return GetCardInfo(mDeviceID, Info);
+//}
+
+//int IDCertConn::parseCardInfo(void *Card)
+//{
+//    if(nullptr == ParseCardInfo)
+//    {
+//        return -1;
+//    }
+//    return ParseCardInfo(mDeviceID, Card);
+//}
+
+
 /******************************************************************************
  * FUNCTION: gbk2utf8
  * DESCRIPTION: 实现由gbk编码到utf8编码的转换

+ 14 - 0
DevAdapter/cw/idcer.1.1/idcertconn.h

@@ -67,6 +67,17 @@ public:
         int& iIDType         // 证件类型
     );
 
+    //二代证、港澳台居住证、外国人全部支持的接口
+    int GetID2InfoAllHead(
+        char* lpHeadDir,    // 头像保存文件路径
+        int& iIDType        // 证件类型
+    );
+
+    int ReadIDInfoRawData(char*ppData, int& len);
+
+    int getCardInfo(CardInfo* Info);
+    int parseCardInfo(void *Card);
+
     int DoScan(string  lpFrontFile, string lpRearFile);
     int CheckFormat(string lpFile);
     int GetStatus(int &nCardSt);
@@ -110,6 +121,9 @@ private:
     mGetIDCardType              GetIDCardType       ;
     mGetIDInfoForeign           GetIDInfoForeign	;
     mGetIDInfoGAT               GetIDInfoGAT	    ;
+    mGetIDInfoRawData           GetIDInfoRawData    ;
+//    mGetCardInfo                GetCardInfo         ;
+//    mParseCardInfo              ParseCardInfo       ;
 
 private:
     bool        m_bOpened;

+ 252 - 1
DevAdapter/cw/idcer.1.1/idcertimpl.cpp

@@ -114,7 +114,7 @@ ErrorCodeEnum IDCertImpl::GetDevCategory(DevCategoryInfo &devCategory)
 //        LOG4VTM(INFO, "GetDevCategory getFWVersion error");
 //        devCategory.eState = DEVICE_STATUS_CONNECTING;
     }
-    sprintf(devCategory.szModel , "FWID=%s#STYLE=IG#FUNCTION=ITF", sFile);
+    sprintf(devCategory.szModel , "FWID=%s#STYLE=IG#FUNCTION=ITF#CODE=UCS2", sFile);
     return Error_Succeed;
 }
 
@@ -511,6 +511,257 @@ ErrorCodeEnum IDCertImpl::IDCerGetDataEx(IDCerInfoEx &idCerInfoEx)
     return Error_Succeed;
 }
 
+ErrorCodeEnum IDCertImpl::IDCerGetDataEx2(IDCerInfoEx2 &idCerInfoEx2)
+{
+    LOG4VTM_FUNCTION();
+    if (!m_bOpen)
+        return HandleDevError(DEV_NOT_OPEN, __FUNCTION__);
+    memset(&idCerInfoEx2,0,sizeof(IDCerInfoEx2));
+    int iRt = Error_Succeed;
+    char strName[256]={0};
+    char strHeadPath[256] = {0};
+    sprintf(strHeadPath, 	"%s/zp.bmp", m_sLibPath);
+    char* pData = new char[4096];
+    memset(pData, 0, 4096);
+    int ppLen = 4096;
+    int iRetryCount = 0;
+    do
+    {
+        if (0 < iRetryCount)
+            LOG4VTM(WARN, "ReadIDInfoRawData need retry");
+        LOG4VTM(INFO, "ReadIDInfoRawData begin");
+        iRt = m_id81Dev->ReadIDInfoRawData(pData, ppLen);
+        LOG4VTM(INFO, "ReadIDInfoRawData end");
+        if (CWERR_IDCARD_SUCCESS == iRt)
+            break;
+        Sleep(100);
+        ++iRetryCount;
+    } while (iRetryCount < 2);
+
+    if (CWERR_IDCARD_SUCCESS == iRt)
+    {
+        char* pRawData = new char[2048];
+        memset(pRawData, 0, 2048);
+        size_t offset = 6;
+        WORD wRawLen = MAKEWORD(pData[1], pData[0]);
+        memcpy(pRawData, pData + offset, wRawLen);
+        offset += wRawLen;
+        m_iCardType = GetCardType(pRawData);
+        if (0 == m_iCardType || 2 == m_iCardType)
+        {
+            ExchangeNormalAndGAT(pRawData, idCerInfoEx2, 0 == m_iCardType);
+        }
+        else
+        {
+            ExchangeForeign(pRawData, idCerInfoEx2);
+        }
+        delete[] pRawData; pRawData = nullptr;
+    }
+    iRt = m_id81Dev->GetID2InfoAllHead(strHeadPath,
+                                   m_iCardType);
+    memcmp(idCerInfoEx2.photoPath.data, strHeadPath, strlen(strHeadPath));
+    idCerInfoEx2.photoPath.dwSize = strlen(idCerInfoEx2.photoPath.data);
+
+    delete[] pData;
+    pData = nullptr;
+    LOG4VTM(INFO, "IDCerGetDataEx2<<<<<");
+    sprintf(strName, "IDCerGetData name=%d addr=%d", idCerInfoEx2.name.dwSize, idCerInfoEx2.address.dwSize);
+    LOG4VTM(INFO, strName);
+    return Error_Succeed;
+}
+
+void IDCertImpl::ExchangeNormalAndGAT(const char* lpSrcStr, IDCerInfoEx2& idCerInfoEx2, bool needTypeNull)
+{
+    int uDataOffset = 0;
+    // 姓名 30 bytes
+    memcpy(idCerInfoEx2.name.data, lpSrcStr + uDataOffset, 30);
+    idCerInfoEx2.name.dwSize = 30;
+    uDataOffset += 30;
+
+    // 性别 2 bytes
+    // 符合 GB/T 2261.1 的规定
+    // 第一字节:0--未知的性别; 1--男性; 2--女性; 9--未说明的性别。
+    //           5--女性改(变)为男性;    6--男性改(变)为女性
+    // 第二字节:00
+    memcpy(idCerInfoEx2.sex.data, lpSrcStr + uDataOffset, 2);
+    idCerInfoEx2.sex.dwSize = 2;
+    uDataOffset += 2;
+
+    // 民族 4 bytes
+    // 符合 GB/T 3304 的规定
+    memcpy(idCerInfoEx2.nation.data, lpSrcStr + uDataOffset, 4);
+    idCerInfoEx2.nation.dwSize = 4;
+    uDataOffset += 4;
+
+    // 出生日期 16 bytes 年月日:CCYYMMDD
+    memcpy(idCerInfoEx2.birthday.data, lpSrcStr + uDataOffset, 16);
+    idCerInfoEx2.birthday.dwSize = 16;
+    uDataOffset += 16;
+
+    // 住址 70 bytes
+    memcpy(idCerInfoEx2.address.data, lpSrcStr + uDataOffset, 70);
+    idCerInfoEx2.address.dwSize = 70;
+    uDataOffset += 70;
+
+    // 公民身份号码 36 bytes 符合 GB/T11643 的规定
+    memcpy(idCerInfoEx2.idno.data, lpSrcStr + uDataOffset, 36);
+    idCerInfoEx2.idno.dwSize = 36;
+    uDataOffset += 36;
+
+    // 签发机关 30 bytes
+    memcpy(idCerInfoEx2.department.data, lpSrcStr + uDataOffset, 30);
+    idCerInfoEx2.department.dwSize = 30;
+    uDataOffset += 30;
+
+    // 有效期起始日期 16 bytes 年月日:CCYYMMDD
+    memcpy(idCerInfoEx2.startDate.data, lpSrcStr + uDataOffset, 16);
+    idCerInfoEx2.startDate.dwSize = 16;
+    uDataOffset += 16;
+
+    // 有效期截止日期 16 bytes 年月日:CCYYMMDD
+    // 有效期为长期的存储表示为“长期”
+    memcpy(idCerInfoEx2.endDate.data, lpSrcStr + uDataOffset, 16);
+    idCerInfoEx2.endDate.dwSize = 16;
+    uDataOffset += 16;
+
+    // 通行证号码 18 bytes
+    // 台湾居民来往大陆通行证证件号码,如:“12345678”
+    // 港澳居民来往内地通行证证件号码,如:“H12345678”、“M12345678”
+    memcpy(idCerInfoEx2.txzCode.data, lpSrcStr + uDataOffset, 18);
+    idCerInfoEx2.txzCode.dwSize = 18;
+    uDataOffset += 18;
+
+    // 签发次数 4 bytes
+    // 港澳台居民居住证的签发次数,首次签发为“01”。
+    memcpy(idCerInfoEx2.issuedSN.data, lpSrcStr + uDataOffset, 4);
+    idCerInfoEx2.issuedSN.dwSize = 4;
+    uDataOffset += 4;
+
+    // 预留区 6 bytes
+    uDataOffset += 6;
+
+    // 证件类型标识 2 bytes
+    memcpy(idCerInfoEx2.idType.data, lpSrcStr + uDataOffset, 2);
+    idCerInfoEx2.idType.dwSize = 2;
+    if (needTypeNull)
+    {
+        memset(idCerInfoEx2.idType.data, 0x00, 2);
+        idCerInfoEx2.idType.dwSize = 0;
+    }
+    uDataOffset += 2;
+
+    // 预留区 6 bytes
+    uDataOffset += 6;
+}
+
+void IDCertImpl::ExchangeForeign(const char* lpSrcStr, IDCerInfoEx2& idCerInfoEx2)
+{
+    int uDataOffset = 0;
+    // 英文姓名 120 bytes
+    memcpy(idCerInfoEx2.englishName.data, lpSrcStr + uDataOffset, 120);
+    idCerInfoEx2.englishName.dwSize = 120;
+    uDataOffset += 120;
+
+    // 性别 2 bytes
+    // 符合 GB/T 2261.1 的规定
+    // 第一字节:0--未知的性别; 1--男性; 2--女性; 9--未说明的性别。
+    //           5--女性改(变)为男性;    6--男性改(变)为女性
+    // 第二字节:00
+    memcpy(idCerInfoEx2.sex.data, lpSrcStr + uDataOffset, 2);
+    idCerInfoEx2.sex.dwSize = 2;
+    uDataOffset += 2;
+
+    // 永久居留证号码 30 bytes
+    memcpy(idCerInfoEx2.idno.data, lpSrcStr + uDataOffset, 30);
+    idCerInfoEx2.idno.dwSize = 30;
+    uDataOffset += 30;
+
+    // 国籍或所在地区代码 6 bytes
+    // 符合 GB/T 2659-2000 的规定
+    memcpy(idCerInfoEx2.nationality.data, lpSrcStr + uDataOffset, 6);
+    idCerInfoEx2.nationality.dwSize = 6;
+    uDataOffset += 6;
+
+    // 中文姓名 30 bytes
+    memcpy(idCerInfoEx2.name.data, lpSrcStr + uDataOffset, 30);
+    idCerInfoEx2.name.dwSize = 30;
+    uDataOffset += 30;
+
+    // 证件签发日期 16 bytes
+    memcpy(idCerInfoEx2.startDate.data, lpSrcStr + uDataOffset, 16);
+    idCerInfoEx2.startDate.dwSize = 16;
+    uDataOffset += 16;
+
+    // 证件终止日期 16 bytes
+    memcpy(idCerInfoEx2.endDate.data, lpSrcStr + uDataOffset, 16);
+    idCerInfoEx2.endDate.dwSize = 16;
+    uDataOffset += 16;
+
+    // 出生日期 16 bytes
+    memcpy(idCerInfoEx2.birthday.data, lpSrcStr + uDataOffset, 16);
+    idCerInfoEx2.birthday.dwSize = 16;
+    uDataOffset += 16;
+
+    // 证件版本号 4 bytes
+    memcpy(idCerInfoEx2.idVersion.data, lpSrcStr + uDataOffset, 4);
+    idCerInfoEx2.idVersion.dwSize = 4;
+    uDataOffset += 4;
+
+    // 当次申请受理机关代码 8 bytes
+    memcpy(idCerInfoEx2.department.data, lpSrcStr + uDataOffset, 8);
+    idCerInfoEx2.department.dwSize = 8;
+    uDataOffset += 8;
+
+    // 证件类型标识 2 bytes
+    memcpy(idCerInfoEx2.idType.data, lpSrcStr + uDataOffset, 2);
+    idCerInfoEx2.idType.dwSize = 2;
+    uDataOffset += 2;
+
+    // 预留项 6 bytes
+    uDataOffset += 6;
+}
+
+int IDCertImpl::GetCardType(char* lpSrcStr)
+{
+    //0:二代身份证  1:外国人永久居留证 2:港澳台居民居住证
+    int iType = 0;
+    int uDataOffset = 0;
+    int uPartLen = 1;
+    char cDataTmp[128] = {0x00};
+    int cDataTmpLen = 0;
+
+    // 首先需要识别证件类型,返回的总数据为256字节
+    // 其中 249-250 这两个字节是证件类型标识
+    // 正常二代证这个字段可能为空
+    // "I" 表示 外国人永久居留证
+    // "J" 表示 港澳台居民居住证
+//    memcpy(cDataTmp,lpSrcStr,sizeof(lpSrcStr));
+    cDataTmpLen = strlen(lpSrcStr);
+    if (0 < cDataTmpLen)
+    {
+        switch (lpSrcStr[248])
+        {
+        case 'I':
+            // 外国人永久居留身份证
+            iType = 1;
+            break;
+        case 'J':
+            // 港澳台居民居住证
+            iType = 2;
+            break;
+        case ' ':
+            iType = 0;
+            break;
+        default:
+            break;
+        }
+        LOG4VTM(INFO, iType);
+    }
+    sprintf(cDataTmp, "IDCerGetData 248=%c 249=%c 250=%c", lpSrcStr[248],lpSrcStr[249], lpSrcStr[250]);
+    LOG4VTM(INFO, cDataTmp);
+    return iType;
+}
+
 //	强制弹出身份证等证件
 //	Force ID Card to eject。
 //

+ 6 - 0
DevAdapter/cw/idcer.1.1/idcertimpl.h

@@ -26,9 +26,15 @@ public:
     ErrorCodeEnum IDCerAuthenticate();
     ErrorCodeEnum IDCerGetData(IDCerInfo &idCerInfo);
     ErrorCodeEnum IDCerGetDataEx(IDCerInfoEx &idCerInfoEx);
+    ErrorCodeEnum IDCerGetDataEx2(IDCerInfoEx2 &idCerInfoEx2);
     ErrorCodeEnum ForceIDEject();
     ErrorCodeEnum ScanIDAndSaveImage();
     ErrorCodeEnum QueryCardPos(int &pos);
+
+    int GetCardType(char* lpSrcStr);
+    void ExchangeForeign(const char* lpSrcStr, IDCerInfoEx2& idCerInfoEx2);
+    void ExchangeNormalAndGAT(const char* lpSrcStr, IDCerInfoEx2& idCerInfoEx2, bool needTypeNull);
+
 public:
     void CancelWaitMediaInsert();
     SMutex          m_MutexLock;

+ 22 - 0
DevAdapter/cw/idcer.1.1/libID81_SO.h

@@ -154,6 +154,22 @@ typedef struct
     int iStatusScanSensorHaveCard;
 }DEVSTATUS;
 
+typedef struct CardInfo
+{
+    int StructSize;              //结构体长度,匹配版本
+    unsigned int   CardType;     //证卡的类型 0:身份证 1:外国人居住证 2:港澳台居住证
+    unsigned char* CardData;     //证卡信息
+    unsigned int   CardDataLen;  //证卡信息长度
+    CardInfo()
+    {
+        StructSize = 0;
+        CardType = 0;
+        CardData = nullptr;
+        CardDataLen = 0;
+    }
+} *PCardInfo;
+
+
 /**********************************************************************************************************************
 * 返回值宏定义
 **********************************************************************************************************************/
@@ -247,6 +263,12 @@ typedef int (*mGetIDInfoGAT)(unsigned DeviceID, IDInfoGAT *IDCard, char *HeadIma
 typedef int (*mGetIDCardType)(unsigned DeviceID,int* iCardType);
 typedef int (*mGetAllTypeIdInfo)(unsigned DeviceID,int iCardType,void* idinfo,char* ImageName);
 
+typedef int (*mGetIDInfoRawData)(unsigned DeviceID, char* DataBuffer, int* iCardType);
+
+////以下这两个接口替代了第3条所有接口
+//typedef int (*mGetCardInfo)(unsigned DeviceID, CardInfo* Info);
+//typedef int (*mParseCardInfo)(unsigned DeviceID, void *Card);
+
 //获取最近一次的错误码
 typedef int (*mGetLastErrorCode)();