身份证读卡器标准接口使用

原创 2017年09月21日 14:13:50
#ifndef __READ_CARD_INFO_H
#define __READ_CARD_INFO_H
#include <string>

class CardInfo
{
public:
	std::wstring name;
	std::wstring sex;
	std::wstring national;
	std::wstring birthData;
	std::wstring residenceAddress;
	std::wstring identityCardNo;
	std::wstring organIssue;
	std::wstring validStartDay;
	std::wstring validEndDay;
};
class ReadCardInfo 
{
public:
	ReadCardInfo();
	~ReadCardInfo();

	std::wstring GetNationName(int number);

	bool ReadCard(CardInfo &info);
private:
	void InitNationName();
	void GetCardInfo(unsigned char *Msg, int MsgLen);
	void WltChangeToBmpFile(unsigned char* pphotoMsg, int len);

public:
	bool m_bExit;
	bool m_bReadCardSucc;
	CardInfo m_cardInfo;

private:
	int m_commPort;
	bool m_bClosePort;
	std::wstring m_nationNameVec[100];
};
#endif


#include "stdafx.h"
#include "ReadCardInfo.h"
#include "log.h"
#include "sdtapi.h"
#include "WltRS.h"

ReadCardInfo::ReadCardInfo() 
{

	m_bExit = false;
	m_bClosePort = true;
	m_commPort = 1001; // usb口1001

	InitNationName();
}

ReadCardInfo::~ReadCardInfo()
{
	m_bExit = true;
}

bool ReadCardInfo::ReadCard(CardInfo &info)
{
	int ret = -1;
	if (m_bClosePort)
	{
		ret = SDT_OpenPort(m_commPort);
		if (ret == 0x90) //打开成功
		{
			m_bClosePort = false;
		}
	}

	int iIfOpen = 0; //是否需要打开端口 
	unsigned char pucManaInfo[4] = { 0 }; //证件芯片管理号
	ret = SDT_StartFindIDCard(m_commPort, pucManaInfo, iIfOpen);
	if (ret != 0x9f) 
	{
		m_bReadCardSucc = false;
		return false;
	}

	unsigned char pucManaMsg[8] = { 0 };  //证件序列号
	ret = SDT_SelectIDCard(m_commPort, pucManaMsg, iIfOpen);
	if (ret != 0x90) 
	{
		m_bReadCardSucc = false;
		WLog(LOG_DEBUG, "SDT_SelectIDCard ret[%x]", ret);
		return false;
	}

	unsigned char pucCHMsg[256] = { 0 }; //文字信息最长256字节  
	unsigned char pucPHMsg[1024] = { 0 }; //相片信息最长1024字节  
	unsigned char pucFPMsg[1024] = { 0 }; //指纹信息最长1024字节  
	unsigned int uiCHMsgLen, uiPHMsgLen, uiFPMsgLen;

	ret = SDT_ReadBaseMsg(m_commPort, pucCHMsg, &uiCHMsgLen, pucPHMsg, &uiPHMsgLen, iIfOpen);
	if (ret != 0x90)
	{
		m_bReadCardSucc = false;
		WLog(LOG_DEBUG, "SDT_ReadBaseMsg ret[%x]", ret);
		return false;
	}
	GetCardInfo(pucCHMsg, uiCHMsgLen);
	WltChangeToBmpFile(pucPHMsg, uiPHMsgLen);
	info = m_cardInfo;
	return true;
}

void ReadCardInfo::InitNationName()
{
	//初始化民族信息字典
	m_nationNameVec[1] = L"汉";
	m_nationNameVec[2] = L"蒙古";
	m_nationNameVec[3] = L"回";
	m_nationNameVec[4] = L"藏";
	m_nationNameVec[5] = L"维吾尔";
	m_nationNameVec[6] = L"苗族";
	m_nationNameVec[7] = L"彝";
	m_nationNameVec[8] = L"壮";
	m_nationNameVec[9] = L"布依";
	m_nationNameVec[10] = L"朝鲜";
	m_nationNameVec[11] = L"满";
	m_nationNameVec[12] = L"侗";
	m_nationNameVec[13] = L"瑶";
	m_nationNameVec[14] = L"白";
	m_nationNameVec[15] = L"土家";
	m_nationNameVec[16] = L"哈尼";
	m_nationNameVec[17] = L"哈萨克";
	m_nationNameVec[18] = L"傣";
	m_nationNameVec[19] = L"黎";
	m_nationNameVec[20] = L"傈僳";
	m_nationNameVec[21] = L"佤";
	m_nationNameVec[22] = L"畲";
	m_nationNameVec[23] = L"高山";
	m_nationNameVec[24] = L"拉祜";
	m_nationNameVec[25] = L"水";
	m_nationNameVec[26] = L"东乡";
	m_nationNameVec[27] = L"纳西";
	m_nationNameVec[28] = L"景颇";
	m_nationNameVec[29] = L"柯尔克孜";
	m_nationNameVec[30] = L"土";
	m_nationNameVec[31] = L"达翰尔";
	m_nationNameVec[32] = L"仫佬";
	m_nationNameVec[33] = L"羌";
	m_nationNameVec[34] = L"布朗";
	m_nationNameVec[35] = L"撒拉";
	m_nationNameVec[36] = L"毛南";
	m_nationNameVec[37] = L"仡佬";
	m_nationNameVec[38] = L"锡伯";
	m_nationNameVec[39] = L"阿昌";
	m_nationNameVec[40] = L"普米";
	m_nationNameVec[41] = L"塔吉克";
	m_nationNameVec[42] = L"怒";
	m_nationNameVec[43] = L"乌孜别克";
	m_nationNameVec[44] = L"俄罗斯";
	m_nationNameVec[45] = L"鄂温克";
	m_nationNameVec[46] = L"德昂";
	m_nationNameVec[47] = L"保安";
	m_nationNameVec[48] = L"裕固";
	m_nationNameVec[49] = L"京";
	m_nationNameVec[50] = L"塔塔尔";
	m_nationNameVec[51] = L"独龙";
	m_nationNameVec[52] = L"鄂伦春";
	m_nationNameVec[53] = L"赫哲";
	m_nationNameVec[54] = L"门巴";
	m_nationNameVec[55] = L"珞巴";
	m_nationNameVec[56] = L"基诺";
	m_nationNameVec[57] = L"其它";
	m_nationNameVec[98] = L"外国人入籍";
}

std::wstring ReadCardInfo::GetNationName(int number)
{
	return m_nationNameVec[number];
}


void ReadCardInfo::GetCardInfo(unsigned char *msg, int msgLen)
{
	//身份证字符串定义
	//30字节姓名
	//2字节性别
	//4字节民族
	//16字节生日
	//70字节地址
	//36字节号码
	//30字节发证机关
	//32字节有效期
	const int fixMsgLen = 30 + 2 + 4 + 16 + 70 + 36 + 30 + 32;
	if (msg == NULL || msgLen < fixMsgLen)
	{
		WLog(LOG_ERR, "Card CHMsg is NULL or msg len[%d] != fixMsgLen[%d]", msgLen, fixMsgLen);
		return;
	}
	m_cardInfo = CardInfo();

	wchar_t strTmpMsg[100] = { 0 };  //中文消息必须用宽字符的字符串才能正常显示中文,否则显示为乱码
	const char* pStr = (const char*)msg;  
	memcpy(strTmpMsg, pStr, 30);
	pStr += 30;
	m_cardInfo.name = std::wstring(strTmpMsg);   //名字

	memset(strTmpMsg, 0x00, sizeof(strTmpMsg));
	memcpy(strTmpMsg, pStr, 2);
	pStr += 2;
	std::wstring sexstr = std::wstring(strTmpMsg);
	if (sexstr == L"1")  //性别
	{
		m_cardInfo.sex = L"男";
	}
	else
	{
		m_cardInfo.sex = L"女";
	}	 

	memset(strTmpMsg, 0x00, sizeof(strTmpMsg));
	memcpy(strTmpMsg, pStr, 4);
	pStr += 4;
	std::wstring nationstr = std::wstring(strTmpMsg); //数字
	int n = wcstoul(strTmpMsg, NULL, 0);
	m_cardInfo.national = GetNationName(n); //民族
	 

	memset(strTmpMsg, 0x00, sizeof(strTmpMsg));
	memcpy(strTmpMsg, pStr, 16);
	pStr += 16;
	m_cardInfo.birthData = std::wstring(strTmpMsg); //出生日期

	memset(strTmpMsg, 0x00, sizeof(strTmpMsg));
	memcpy(strTmpMsg, pStr, 70);
	pStr += 70;
	m_cardInfo.residenceAddress = std::wstring(strTmpMsg); //地址

	memset(strTmpMsg, 0x00, sizeof(strTmpMsg));
	memcpy(strTmpMsg, pStr, 36);
	pStr += 36;
	m_cardInfo.identityCardNo = std::wstring(strTmpMsg); //身份证号

	memset(strTmpMsg, 0x00, sizeof(strTmpMsg));
	memcpy(strTmpMsg, pStr, 30);
	pStr += 30;
	m_cardInfo.organIssue = std::wstring(strTmpMsg); //发证机关

	memset(strTmpMsg, 0x00, sizeof(strTmpMsg));
	memcpy(strTmpMsg, pStr, 16);
	pStr += 16;
	m_cardInfo.validStartDay = std::wstring(strTmpMsg); //办证日期

	memset(strTmpMsg, 0x00, sizeof(strTmpMsg));
	memcpy(strTmpMsg, pStr, 16);
	pStr += 16;
	m_cardInfo.validEndDay = std::wstring(strTmpMsg); //有效期
}


//将数据保存为wlt文件,再调用GetBmp通用接口将wlt文件转码成bmp文件
void ReadCardInfo::WltChangeToBmpFile(unsigned char* pphotoMsg, int len)
{
	if (!m_bClosePort)
	{
		int iret = SDT_ClosePort(m_commPort); //调用GetBmp前必须确认通信端口处于关闭状态
		m_bClosePort = true;
		WLog(LOG_DEBUG, "SDT_ClosePort ret[%d]\n", iret);
	}

	const std::string path = "./photo/";
	const std::string filename = path + "photo.wlt";
	FILE *file = fopen(filename.c_str(), "wb"); //写二进制文件,必须为二进制文件写入,数据才没错,否则会造成格式错误
	if (file == NULL)
	{
		WLog(LOG_ERR, "fopen file[%s] fail\n", filename.c_str());
		return;
	}
	int size = fwrite(pphotoMsg, len, 1, file);
	fclose(file);

	//wlt到bmp转换,生成的bmp文件为 photo.bmp
	int ret = GetBmp((char*)filename.c_str(), 2); //参数1为.wlt文件名字,参数2为接口,1表示串口,2表示usb
	if (ret == 1)
	{
		WLog(LOG_ERR, "GetBmp[%s] success\n", filename.c_str());	
	}	
}



需要包含身份证标准接口的头文件和库文件进来:

sdtapi.h  WltRS.h   sdtapi.lib  WltRS.lib

另wstring转成string的方法:

wstring wstr;

string str;

str = string(wstr.begin(),wstr.end());

直接用string的iterator型构造函数可以转换

二代身份证读卡器API接口

  • 2011年12月31日 18:45
  • 871KB
  • 下载

android系统PS2全键盘驱动(上)-使用linux的标准接口实现

android的设备带全键盘的很少,即使带全键盘的也都是USB HID键盘的居多,我们的设备类似于上网本,需要一个全键盘,但是设备上只有两个USB host口,Wifi用掉一个,剩下的一个USB ho...

C#调用C++DLL 使用 德卡 读卡器 获取身份证信息

公司一个项目用到了德卡读卡器的设备,想在原有厂商给的C++ DLL的基础上再做一层封装,方便以后项目的使用,拿来DLL和接口文档就开干了。 在这里记录下,也分享给之后或许有需要的朋友。...

SD卡标准接口协议尺寸命令手册

  • 2010年05月24日 09:24
  • 865KB
  • 下载

linux内核中GPIO的使用(二)--标准接口函数

在linux内核中,有一些基本模块可以使用标准的接口函数来操作,比如GPIO、interrupt、clock,所谓的标准接口函数是指一些与硬件平台无关的、linux下做驱动通用的函数, 常用的有: ...

camera link标准接口设计

  • 2010年05月02日 16:20
  • 1.04MB
  • 下载

新中新身份证读卡器开发问题

新中新二代身份证读卡器dkq-a16d,在C#中读卡开发时,参考随机附带的C#参考代码,能够读取成功,但读几次程序就莫名其妙的关掉了,有时连错误都捕捉不到,搞了很长时间也没搞定,后来以为会不会是win...
  • zjzhong
  • zjzhong
  • 2013年04月01日 08:45
  • 2044

神思二代身份证读卡器Demo的C++版本

在某宝上买了一个神思二代身份证读卡器,给的DEMO实在是....无语了,无奈,自己研究写了一个。 1、首先,需要把licence.dat和Termb.lic文件放到C盘根目录下。      请注意...

Asp.net和第二代身份证读卡器互联

大家都知道,Asp.net是在服务器端执行的程序,无法直接与客户端的设备进行通信,但是客户提出了能否直接在网页上调用二代身份证读卡器。   一、解决思路     经过我们的分析,理论上是完全可行...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:身份证读卡器标准接口使用
举报原因:
原因补充:

(最多只允许输入30个字)