华视100UC 身份证阅读器 Java

哪位大佬有64位可用的dll文件,施舍给小弟吧,万分感谢

功能

读取身份证上的数据,将照片保存到指定路径

环境

  1. jdk1.8 32位
  2. window 11
  3. Maven
  4. 乱找的dll,找了一堆,终于发现可以用的了。我分享的dll文件是可以读出照片的。官方开发包的dll只能读出信息,读不出图片,求赐教

个人想法(有不对的地方希望大佬指正)

  1. 所有阅读器采用的是相同的内部硬件,厂商只是套了个外壳
  2. 代码看上去很多,大部分都是类似的方法,如果只获取身份证其中一项信息,代码会很少
  3. 官方下载的说明文档里说只要调用接口中CVR_Read_ContentCVR_Read_FPContent方法就可以在对应的位置生成两个文件一个是txt文档记录身份证上的信息,一个是bmp身份证图片,这套dll只能生成在默认的路径C:\Users\用户\AppData\Local\Temp\chinaidcard
  4. 用官方提供的开发包,死活弄不出图片,在网上找了其他的安装包,把下图中3个dll文件复制到程序中,居然能用了。jdk64位的还是弄不出图片。
  5. 要不是我水平差,要不就是华视故意的,官网提供的dll文件居然不能用,如果是故意的那这公司可真的恶心。
  6. 感觉Termb和WltRS这两个dll文件是配套的,换其中一个,程序可能就跑不起来。

对于dll文件的想法

  1. 目前网上可以找到的读取身份证信息的程序都是用的32位dll,没找到64位的dll。
  2. 使用官方开发包内的64位dll可以读取身份证的信息,就是无法读取图片。感觉还是dll的事情,找了两天也没找到可用的。无论问哪儿要开发包,客服都要让我提供购买的订单号,上级单位发下来的设备,我去哪儿要订单号。
  3. 对华视公司的看法,小气、没格局。要个最新的开发包非要个订单号,给产品照片都不行,产品的开发包也藏着掖着,官网提供的开发包里面写的是乱七八糟,特指java的demo,其他语言我看不懂。既然想卖产品那应该是应用的越广泛卖的越好,别人用你的设备做更广泛的应用,设备就能卖的更多,所以要你开发包,你应该高兴才对。看看自己做的程序,做了十几年了,界面还是难看的要死。

目录结构

在这里插入图片描述

1. pom.xml

依赖

    <dependency>
      <groupId>net.java.dev.jna</groupId>
      <artifactId>jna</artifactId>
      <version>5.11.0</version>
    </dependency>

2. 拷贝dll文件到resources

下载

3. 接口映射Termb.dll中的方法

使用jna连接dll文件,接口中所有方法都是Termb中的方法

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.ptr.IntByReference;

public interface CardLibrary extends Library {
	// 参数1:只写名称,不写后缀,符合jni规范,可跨平台操作,linux中后缀为so
	CardLibrary INSTANCE = Native.load("Termb", CardLibrary.class);
	/**
	 * 本函数用于PC与华视电子第二代居民身份证阅读器的连接
	 * @param Port 连接串口(COM1~COM16)或USB口(1001~1016)
	 * @return 1 正确 2 端口打开失败 0 动态库加载失败
	 */
	int CVR_InitComm(int Port);

	/**
	 * 本函数用于关闭PC到阅读器的连接。
	 * @return 1 正确 0 错误
	 */
	int CVR_CloseComm();

	/**
	 * 本函数用于读卡器和卡片之间的合法身份确认。卡认证循环间隔大于300ms。 若卡片放置后发生认证错误时,应移走卡片重新放置。
	 * @return 1 正确 卡片认证成功 2 错误 寻卡失败 3 错误 选卡失败 0 错误 初始化失败
	 */
	int CVR_Authenticate();

	/**
	 * 本函数用于通过阅读器从第二代居民身份证中读取相应信息。卡认证成功以后才可做读卡操作, 读卡完毕若继续读卡应移走二代证卡片重新放置做卡认证。
	 * 读卡成功后在termb.dll文件所在路径下生成wz.txt(文字信息)和zp.bmp(照片信息) wz.txt内容示例如下: 张红叶 女 汉
	 * 1988-11-18 河北省邯郸市临漳县称勾镇称勾东村复兴路25号 130423198811184328 临漳县公安局
	 * 2011.03.30-2021.03.30 读各项文字信息到自定义内存缓冲
	 * @param active 兼容以前版本,无实际意义, 1 读取基本信息,2 只读文字信息 ,3 只读最新住址信息,5 芯片管理
	 * @return 1 正确 0 错误 99 异常
	 */
	int CVR_Read_Content(int active);

	/**
	 * 与 int CVR_Read_Content(int active);平级
	* 本函数用于通过阅读器从第二代居民身份证中读取相应信息。卡认证成功以后才可做读卡操作,读卡完毕若继续读卡应移走二代证卡片重新放置做卡认证。
	* 参数: 无
	*
	* */
	int CVR_Read_FPContent();
	/**
	 * 获取各种信息
	 * */
	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  GetBMPData(byte[] strTmp, IntByReference strLen);
	int  GetJpgData(byte[] strTmp, IntByReference strLen);
	int  CVR_GetSAMID(byte[] strTmp, byte[] strLen);
}

4. 调用接口中的方法

import com.sun.jna.ptr.IntByReference;
import java.io.FileOutputStream;


/**
 * a参数在说明文档中确定了最大的长度
 * b参数是C++的int类型长度为4个字节
 * 方法中a参数返回查询到的值,b参数返回a的长度
 * java中数组在创建时就需要确定好长度,所以b参数没有意义
 * */
public class Card {

	/**
	 * 得到姓名信息
	 * @return 姓名信息
	 * @throws Exception
	 */
	public static String GetPeopleName() throws Exception {
		try {
			byte[] a = new byte[30];
			byte[] b = new byte[4];
			return CardLibrary.INSTANCE.GetPeopleName(a, b) == 1 ? new String(a,"gb2312").trim() : "";
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return "";
	}

	/**
	 * 得到性别信息
	 * @return 性别信息
	 * @throws Exception
	 */
	public static String GetPeopleSex() throws Exception {
		try {
			byte[] a = new byte[2];
			byte[] b = new byte[4];
			return CardLibrary.INSTANCE.GetPeopleSex(a, b) == 1 ? new String(a,"gb2312").trim() : "";
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return "";
	}

	/**
	 * 得到民族信息
	 * @return 民族信息
	 * @throws Exception
	 */
	public static String GetPeopleNation() throws Exception {
		try {
			byte[] a = new byte[20];
			byte[] b = new byte[4];
			return CardLibrary.INSTANCE.GetPeopleNation(a, b) == 1 ? new String(a,"gb2312").trim() : "";
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return "";
	}

	/**
	 * 得到出生日期信息
	 * @return 到出生日期信息
	 * @throws Exception
	 */
	public static String GetPeopleBirthday() throws Exception {
		try
		{
			byte[] a = new byte[16];
			byte[] b = new byte[4];
			return CardLibrary.INSTANCE.GetPeopleBirthday(a,b) == 1 ?  new String(a).trim() :  "";
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return "";
	}

	/**
	 * 得到地址信息
	 * @return 地址信息
	 * @throws Exception
	 */
	public static String GetPeopleAddress() throws Exception {
		try
		{
			byte[] a = new byte[70];
			byte[] b = new byte[4];
			return CardLibrary.INSTANCE.GetPeopleAddress(a,b) == 1 ?  new String(a,"gb2312").trim() :  "";
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return "";
	}

	/**
	 * 得到卡号信息
	 * @return 卡号信息
	 * @throws Exception
	 */
	public static String GetPeopleIDCode() throws Exception {
		try
		{
			byte[] a = new byte[36];
			byte[] b = new byte[4];
			return CardLibrary.INSTANCE.GetPeopleIDCode(a,b) == 1 ?  new String(a).trim() :  "";
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return "";
	}

	/**
	 * 得到发证机关信息
	 * @return 发证机关信息
	 * @throws Exception
	 */
	public static String GetDepartment() throws Exception {
		try
		{
			byte[] a = new byte[30];
			byte[] b = new byte[4];
			return CardLibrary.INSTANCE.GetDepartment(a,b) == 1 ?  new String(a,"gb2312").trim() :  "";
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return "";
	}

	/**
	 * 得到有效开始日期
	 * @return 有效开始日期
	 * @throws Exception
	 */
	public static String GetStartDate() throws Exception {
		try
		{
			byte[] a = new byte[16];
			byte[] b = new byte[4];
			return CardLibrary.INSTANCE.GetStartDate(a,b) == 1 ?  new String(a,"gb2312").trim() :  "";
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return "";
	}

	/**
	 * 得到有效截止日期
	 * @return 有效截止日期
	 * @throws Exception
	 */
	public static String GetEndDate() throws Exception {
		try
		{
			byte[] a = new byte[16];
			byte[] b = new byte[4];
			return CardLibrary.INSTANCE.GetEndDate(a,b) == 1 ?  new String(a,"gb2312").trim() :  "";
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return "";
	}

	/**
	 * 得到安全模块号码
	 * @return 安全模块号码
	 * @throws Exception
	 */
	public static String CVR_GetSAMID() throws Exception {
		try
		{
			byte[] a = new byte[4*10];
			byte[] b = new byte[4];
			return CardLibrary.INSTANCE.CVR_GetSAMID(a,b) == 1 ?  new String(a).trim() :  "";
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return "";
	}

	/**
	 * 获取照片,将图片写到指定路径
	 * @return 获取成功 boolean
	 * @throws Exception
	 */
	public static boolean GetBMPData() throws Exception {
		try
		{
			byte[] a = new byte[38862];
			IntByReference len = new IntByReference();
			FileOutputStream fos = new FileOutputStream("D:\\123.bmp");
			if (CardLibrary.INSTANCE.GetBMPData(a,len) == 1){
				fos.write(a,0,len.getValue());
				fos.flush();
				fos.close();
				return true;
			}else return false;
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return false;
	}
	/**
	 * 获取照片,将图片写到指定路径
	 * @return 获取成功 boolean
	 * @throws Exception
	 */
	public static boolean GetJpgData() throws Exception {
		try
		{	// 返回固定的38862字节,使用看图软件另存后5000字节左右,
			// 说明文档中没有明确说明返回的字节数。
			byte[] a = new byte[38862];
			IntByReference len = new IntByReference();
			FileOutputStream fos = new FileOutputStream("D:\\123.jpg");
			if (CardLibrary.INSTANCE.GetJpgData(a,len) == 1){
				System.out.println("len = " + len);
				fos.write(a,0,len.getValue());
				fos.flush();
				fos.close();
				return true;
			}else return false;
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
		return false;
	}
}

5. 连接、认证、获取信息、关闭 阅读器

public class CardMain {
	
	public static void main(String[] args) {
		// 测试所有端口,打开连接
		int init = 0;
		for (int i = 1001; i < 1016; i++) {
			init = CardLibrary.INSTANCE.CVR_InitComm(i);
			if(init == 1) {
				System.out.println("初始化硬件成功");
				break;
			}
		}
		// 验证初始化信息
		if (init != 1) {
			System.out.println("初始化硬件失败");
			return;
		}
		// 卡认证
		int auth = 0;
		while (true) {
			auth = CardLibrary.INSTANCE.CVR_Authenticate();
			if (auth == 1){
				System.out.println("读卡器和卡片之间的合法身份确认:身份认证成功");
			}

			if (auth != 1) {
				System.out.println("读卡器和卡片之间的合法身份确认:身份认证失败");
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} else {
				break;
			}
		}
		
		// 读取卡信息,认证成功后文本信息和照片的默认保存路径
		//C:\Users\用户\AppData\Local\Temp\chinaidcard
		int read = CardLibrary.INSTANCE.CVR_Read_Content(1); //默认路径文件:config.ini fp.dat wz.txt xp.bmp xp.jpg zp.bmp xp.wlt
		// 使用手册上说:执行后会在运行目录下生成以下文件信息。使用这套dll还是会生成到默认路径
//		int read = CardLibrary.INSTANCE.CVR_Read_FPContent();		//默认路径文件:config.ini fp.dat wz.txt xp.bmp xp.jpg zp.bmp
		if (read != 1) {
			System.out.println("获取信息失败");
		} else {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("成功获取信息");
			try {
				System.err.println(Card.GetPeopleName());
				System.err.println(Card.GetPeopleSex());
				System.err.println(Card.GetPeopleNation());
				System.err.println(Card.GetPeopleBirthday());
				System.err.println(Card.GetPeopleAddress());
				System.err.println(Card.GetPeopleIDCode());
				System.err.println(Card.GetDepartment());
				System.err.println(Card.GetStartDate());
				System.err.println(Card.GetEndDate());
				System.err.println(Card.CVR_GetSAMID());
				if (Card.GetBMPData())
				System.err.println("bmp图片获取成功");
				if (Card.GetJpgData())
				System.err.println("jpg图片获取成功");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		int i = CardLibrary.INSTANCE.CVR_CloseComm();
		if (i == 1){
			System.out.println("关闭连接成功");
		}
	}
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值