准备工作:
环境:windows、jdk(32bit)
华视SDK开发包:
- sdtapi.dll(函数的动态联接库)
- Termb.dll(安全模块通讯函数)
- WltRS.dll(身份证相片解码库)
JNA实现library接口:
注意:
将**sdtapi.dll、Termb.dll、WltRS.dll放到工程目录的lib目录中。
将**sdtapi.dll、Termb.dll、WltRS.dll放到jdk/bin目录下。
直接上代码:
-
public interface IdCardSdk extends Library { IdCardSdk INSTANCE = Native.load("Termb", IdCardSdk.class); /** 函数调用流程 初始化->卡认证->读卡->函数取信息->关闭连接 注意:若采用查询方式自动判断卡片是否放置,则间隔时间建议大于600ms。 */ /** * 1. 初始化链接 * 原 型:int CVR_InitComm (int Port) * 说 明:本函数用于PC与华视电子第二代居民身份证阅读器的连接。 * 参 数:Port:连接串口(COM1~COM16)或USB口(1001~1016) * * 参数名 含义 取值范围 * int Port 端口编号 见下表 * 端口编号: 1=串口1 2=串口2 ... 16=串口16 * 1001=USB口1 1002=USB口2 ... 1016=USB口16 * * 返回值:1:正确 2:端口打开失败 -1:未知错误 -2:动态库加载失败 * @return */ int CVR_InitComm(int Port); /** * 2. 关闭端口 * 原 型:int CVR_CloseComm(void) * 说 明:本函数用于关闭PC到阅读器的连接。 * 参 数:无 * 返回值:1:关闭成功 0:端口号不合法 -1:端口已经关闭 -2:动态库加载失败 * @return */ int CVR_CloseComm(); /** * 3. 卡认证 * 原 型:int CVR_Authenticate (void) * 说 明:本函数用于读卡器和卡片之间的合法身份确认。卡认证循环间隔大于300ms。 * 参 数: * 返回值:1:正确 卡片认证成功 2:错误 寻卡失败 3:错误 选卡失败 4:错误 未连接读卡器 4:错误 动态库未加载 * (若卡片放置后发生认证错误时,请移走卡片重新放置。) */ int CVR_Authenticate(); //此处读卡分为两种 根据需要选择 /** * 4. 读卡操作1(与读卡操作2平级,根据需要选择) * 原 型:int CVR_Read_Content(int active); * 说 明:本函数用于通过阅读器从第二代居民身份证中读取相应信息。卡认证成功以后才可做读卡操作,读卡完毕若继续读卡应移走二代证卡片重新放置做卡认证。 * 参 数: * 参数名 含义 取值范围 * int active 临时目录中保存的文件种类 见取值说明 * 取值说明: * 值 意义 * 1 wz.txt,xp.wlt,zp.bmp,fp.dat * 2 wz.txt,xp.wlt,fp.dat * 4 wz.txt,zp.bmp,fp.dat * 保存目录为临时目录,例如win7环境下路径: * C:\Users\mac\AppData\Local\Temp\chinaidcard。其中mac是用户名称。 * 以上为示例路径,请根据客户开发环境,确定实际路径,该路径不能更改。 * 文件说明: * 文件名 意义 * wz.txt 身份证基本信息,如姓名、性别等 * xp.wlt 加密的头像数据 * zp.bmp 解密的头像数据 * fp.dat 指纹数据,若无指纹则该文件大小仍为1024字节,每个字节均为0 * * * 返回值:1:正确 0:错误,读身份证失败 4:错误,身份证读卡器未连接 99:动态库未加载 */ int CVR_Read_Content(int active); /** * 5. 读卡操作2(与读卡操作1平级,根据需要选择) * 原 型:int CVR_Read_FPContent() * 说 明:本函数用于通过阅读器从第二代居民身份证中读取相应信息。卡认证成功以后才可做读卡操作,读卡完毕若继续读卡应移走二代证卡片重新放置做卡认证。 * 参 数: 无 * 执行后会在运行目录下生成以下文件信息 * 文件说明: * 文件名 意义 * wz.txt 身份证基本信息,如姓名、性别等 * xp.wlt 加密的头像数据 * zp.bmp 解密的头像数据 * fp.dat 指纹数据,若无指纹则该文件大小仍为1024字节,每个字节均为0 * * 返回值:1:正确 0:错误,读身份证失败 4:错误,身份证读卡器未连接 99:动态库未加载 */ int CVR_Read_FPContent(); /** * 6. 获取民族代码 * 原 型:int GetNationCode(unsigned char * nationData, int * pLen); * 说 明:本函数获取民族代码 * 参 数: * 参数名 含义 取值范围 * unsigned char * nationData 缓冲区地址 * int * pLen 缓冲区长度指针 4字节 * 返 回 值:1:正确 0:错误 */ int GetNationCode(String nationData,int pLen); /** * * 其他函数 * int GetPeopleName(char *strTmp, int *strLen) //得到姓名信息 * int GetPeopleSex(char *strTmp, int *strLen) //得到性别信息 * int GetPeopleNation(char *strTmp, int *strLen) //得到民族信息 * int GetPeopleBirthday(char *strTmp, int *strLen) //得到出生日期 * int GetPeopleAddress(char *strTmp, int *strLen) //得到地址信息 * int GetPeopleIDCode(char *strTmp, int *strLen) //得到卡号信息 * int GetDepartment(char *strTmp, int *strLen) //得到发证机关信息 * int GetStartDate(char *strTmp, int *strLen) //得到有效开始日期 * int GetEndDate(char *strTmp, int *strLen) //得到有效截止日期 * int CVR_GetSAMID(char * SAMID) //得到安全模块号码 * * 返 回 值:1:正确 0:错误 */ int GetPeopleName(byte[] strTmp,byte[] strLen); int GetPeopleSex(byte[] strTmp,byte[] strLen); int GetPeopleNation(byte[] strTmp,byte[] strLen); int GetPeopleBirthday(byte[] strTmp,byte[] strLen); int GetPeopleAddress(byte[] strTmp,byte[] strLen); int GetPeopleIDCode(byte[] strTmp,byte[] strLen); int GetDepartment(byte[] strTmp,byte[] strLen); int GetStartDate(byte[] strTmp,byte[] strLen); int GetEndDate(byte[] strTmp,byte[] strLen); int CVR_GetSAMID(byte[] strTmp,byte[] strLen); /** * 获取证件图片 * int GetBMPData (unsigned char *pData, int * pLen) * 得到头像照片bmp二进制数据,不超过38862字节 * 得到头像照片bmp二进制数据,不超过38862字节 * 得到头像照片bmp二进制数据,不超过38862字节 * int Getbase64BMPData (unsigned char *pData, int * pLen) * 得到头像照片bmp数据base64编码,不超过38862*2字节 * 得到头像照片bmp数据base64编码,不超过38862*2字节 * 得到头像照片bmp数据base64编码,不超过38862*2字节 * int GetJpgData(unsigned char * jpgData, int * pLen) * 得到头像照片jpg二进制数据 * 得到头像照片jpg二进制数据 * 得到头像照片jpg二进制数据 * int Getbase64JpgData (unsigned char *pData, int * pLen) * 得到头像照片jpg数据base64编码,不超过38862*2字节 * 得到头像照片jpg数据base64编码,不超过38862*2字节 * 得到头像照片jpg数据base64编码,不超过38862*2字节 * */ int GetBMPData (Pointer pData, IntByReference pLen); int Getbase64BMPData (Pointer pData, IntByReference pLen); int GetJpgData (Pointer pData, IntByReference pLen); int Getbase64JpgData (Pointer pData, IntByReference pLen); }
方法调用:
注意:
- 此处图片均为base64
- 出生日期需要格式化
public class Cvr100IdCardReader{
private final static byte[] RTN_RES = new byte[4];
//此处1001端口对应的是usb口1 以此类推 1002 usb口2 ...1016 usb口16
private final static int PORT = 1001;
//成功状态码
private static final int SUCCESS = 1;
//失败状态码
private static final int FAIL = 0;
//返回数据的字符编码
private static final String ENCODING = "gb2312";
//长度
private static final IntByReference len = new IntByReference();
/**
* 获取姓名
*
* @return 姓名
*/
private String GetPeopleName() {
try {
byte[] a = new byte[30];
return IdCardSdk.INSTANCE.GetPeopleName(a, RTN_RES) == 1 ? handleResult(a) : "";
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
/**
* 获取性别
*
* @return 性别
*/
private String GetPeopleSex() {
try {
byte[] a = new byte[2];
return IdCardSdk.INSTANCE.GetPeopleSex(a, RTN_RES) == 1 ? handleResult(a) : "";
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
/**
* 获取民族
*
* @return 民族
*/
private String GetPeopleNation() {
try {
byte[] a = new byte[20];
return IdCardSdk.INSTANCE.GetPeopleNation(a, RTN_RES) == 1 ? handleResult(a) : "";
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
/**
* 获取出生日期
*
* @return 出生日期
*/
private String GetPeopleBirthday() {
try {
byte[] a = new byte[16];
return IdCardSdk.INSTANCE.GetPeopleBirthday(a, RTN_RES) == 1 ? handleResult(a) : "";
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
/**
* 获取户籍地址
*
* @return 户籍地址
*/
private String GetPeopleAddress() {
try {
byte[] a = new byte[70];
return IdCardSdk.INSTANCE.GetPeopleAddress(a, RTN_RES) == 1 ? handleResult(a) : "";
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
/**
* 获取证件号码
*
* @return 证件号码
*/
private String GetPeopleIDCode() {
try {
byte[] a = new byte[36];
return IdCardSdk.INSTANCE.GetPeopleIDCode(a, RTN_RES) == 1 ? handleResult(a) : "";
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
/**
* 获取发证机关
*
* @return 发证机关
*/
private String GetDepartment() {
try {
byte[] a = new byte[30];
return IdCardSdk.INSTANCE.GetDepartment(a, RTN_RES) == 1 ? handleResult(a) : "";
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
/**
* 获取有效开始日期
*
* @return 有效开始日期
*/
private String GetStartDate() {
try {
byte[] a = new byte[16];
return IdCardSdk.INSTANCE.GetStartDate(a, RTN_RES) == 1 ? handleResult(a) : "";
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
/**
* 获取有效截止日期
*
* @return 有效截止日期
*/
private String GetEndDate() {
try {
byte[] a = new byte[16];
return IdCardSdk.INSTANCE.GetEndDate(a, RTN_RES) == 1 ? handleResult(a) : "";
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
/**
* 获取安全模块号码
*
* @return 安全模块号码
*/
private String CVR_GetSAMID() {
try {
byte[] a = new byte[4 * 10];
return IdCardSdk.INSTANCE.CVR_GetSAMID(a, RTN_RES) == 1 ? handleResult(a) : "";
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
private String Getbase64BMPData() {
String base64 = "";
try {
Pointer bmpBuffer = Pointer.NULL;
bmpBuffer = new Memory(38862 * 2);
IntByReference bmpLen = new IntByReference();
bmpLen.setValue(38862 * 2);
if (IdCardSdk.INSTANCE.Getbase64BMPData(bmpBuffer, bmpLen) == 1) {
byte[] byteArray = bmpBuffer.getByteArray(0, bmpLen.getValue());
base64 = new String(byteArray);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return base64;
}
private String Getbase64JpgData() {
String base64 = "";
try {
Pointer bmpBuffer = Pointer.NULL;
bmpBuffer = new Memory(38862 * 2);
IntByReference bmpLen = new IntByReference();
bmpLen.setValue(38862 * 2);
if (IdCardSdk.INSTANCE.Getbase64JpgData(bmpBuffer, bmpLen) == 1) {
byte[] byteArray = bmpBuffer.getByteArray(0, bmpLen.getValue());
base64 = new String(byteArray);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return base64;
}
/**
* 读卡
*/
public IdCardInfo readIdCard() {
isDisplayWork = false;
IdCardInfo idCard = new IdCardInfo();
try {
//1、初始化连接,打开连接
int initComm = 0;
for (int i = 1001; i < 1003; i++) {
initComm = IdCardSdk.INSTANCE.CVR_InitComm(i);
if (initComm == 1) {
idCard.setResult(true);
idCard.setMsg("读卡器初始化成功");
break;
}
}
if (initComm != SUCCESS) {
idCard.setResult(false);
idCard.setMsg("读卡器连接失败,请检查设备状态");
return idCard;
}
//2、读卡(同一个身份证,只要读取一次,下次读取优先从缓存中读取,并且CVR_Authenticate返回为2,卡认证失败,所以优先读卡一次)
//读取卡
int readStatus = IdCardSdk.INSTANCE.CVR_Read_Content(4);
//2、卡认证,超出两分钟就是本次读卡失败
int authenticate = getAuthenticateStatus(IdCardSdk.INSTANCE, readStatus);
if (authenticate != SUCCESS) {
idCard.setResult(false);
idCard.setMsg("读卡失败,请重新放置卡片");
return idCard;
}
//读取卡
if (readStatus != SUCCESS) {
readStatus = IdCardSdk.INSTANCE.CVR_Read_Content(4);
}
if (readStatus != SUCCESS) {
idCard.setResult(false);
idCard.setMsg("证件信息读取失败,请重新放置证件");
return idCard;
}
String name = GetPeopleName();
String sex = GetPeopleSex();
String nation = GetPeopleNation();
String birthday = GetPeopleBirthday();
String address = GetPeopleAddress();
String idCode = GetPeopleIDCode();
String department = GetDepartment();
String startDate = GetStartDate();
String endDate = GetEndDate();
String samId = CVR_GetSAMID();
String bmpBase64 = Getbase64BMPData();
String jpgBase64 = Getbase64JpgData();
//赋值
idCard.setName(name);
idCard.setSex(sex);
idCard.setNation(nation);
idCard.setBirthday(fmtDate(birthday));
idCard.setAddress(address);
idCard.setIdCard(idCode);
idCard.setDepartment(department);
idCard.setStartDate(fmtDate(startDate));
idCard.setEndDate(fmtDate(endDate));
idCard.setSamId(samId);
idCard.setBmpBase64(bmpBase64);
idCard.setJpgBase64(jpgBase64);
idCard.setResult(true);
idCard.setMsg("读取成功");
} catch (Exception e) {
e.printStackTrace();
} finally {
IdCardSdk.INSTANCE.CVR_CloseComm();
isDisplayWork = true;
}
return idCard;
}
/**
* 卡认证
*
* @param idCardSdk
* @param readStatus
* @return
* @throws InterruptedException
*/
private int getAuthenticateStatus(IdCardSdk idCardSdk, int readStatus) throws InterruptedException {
if (readStatus == SUCCESS) {
return SUCCESS;
}
final long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(10L);
int authenticate = FAIL;
//循环读卡,失效时间为10s
while (authenticate != SUCCESS) {
authenticate = idCardSdk.CVR_Authenticate();
if (deadline == SUCCESS) {
continue;
}
if (deadline - System.nanoTime() < 0L) {
break;
}
Thread.sleep(100);//短暂休眠
}
return authenticate;
}
/**
* 处理返回结果字符
*
* @param nameByte
* @return
* @throws UnsupportedEncodingException
*/
private static String handleResult(byte[] nameByte) throws UnsupportedEncodingException {
return new String(nameByte, ENCODING).trim();
}
/**
* 日期格式化
*
* @param str = yyyyMMdd
* @return yyyy-MM-dd
* @throws ParseException
*/
private String fmtDate(String str) throws ParseException {
Date date = new SimpleDateFormat("yyyyMMdd").parse(str);
String strDate = new SimpleDateFormat("yyyy-MM-dd").format(date);
return strDate;
}
}
产出:
得到证件信息