使用jnative调用c语言动态库对接华视电子身份证阅读机

2022-10-25 16:06:18 浏览数 (2)

一 身份证阅读器SDK使用手册

1. 定义

应用函数开发包含下列文件: termb.dll API函数的动态联接库 sdtapi.dll 安全模块通讯函数 UnPack.dll 身份证相片解码库 适用操作系统: Windows NT: 需要NT 3.1版或以后版本 Windows: 需要 Windows 98、Windows 2000或以后版本 适用开发语言: Visual C 5.0 及以后版本 Visual Basic 5.0 及以后版本 Delphi 3.0 及以后版本 PowerBuilder 6.0 及以后版本

2. 函数列表

//以下为主要API函数 int CVR_InitComm(int Port) 初始化连接; int CVR_Authenticate() 卡认证; int CVR_Read_Content(int active) 读卡操作。 int CVR_CloseComm() 关闭连接;

//以下为可选API函数,方便二次开发 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) 得到安全模块号

3. 函数说明

初始化连接

原 型:int CVR_InitComm (int Port) 说 明:本函数用于PC与华视电子第二代居民身份证阅读器的连接。 参 数:Port:连接串口(COM1COM16)或USB口(10011016) 值 意义 1 串口1 2 串口2 3 串口3 4 串口4 1001 USB口1 1002 USB口2 1003 USB口3 1004 USB口4

返 回 值: 值 意义 1 正确 2 端口打开失败 0 动态库加载失败

关闭串口

原 型: int CVR_CloseComm(void) 说 明:本函数用于关闭PC到阅读器的连接。 参 数:无 返 回 值: 值 意义 1 正确 0 错误

卡认证

原 型:int CVR_Authenticate (void) 说 明:本函数用于读卡器和卡片之间的合法身份确认。卡认证循环间隔大于300ms。 参 数: 返 回 值: 值 意义 说明 1 正确 卡片认证成功 2 错误 寻卡失败 3 错误 选卡失败 0 错误 初始化失败 注意:若卡片放置后发生认证错误时,应移走卡片重新放置。

读卡操作

原 型:int CVR_Read_Content(int active); 说 明:本函数用于通过阅读器从第二代居民身份证中读取相应信息。卡认证成功以后才可做读卡操作,读卡完毕若继续读卡应移走二代证卡片重新放置做卡认证。 参 数:active:兼容以前版本,无实际意义

返 回 值: 返回值 意义 1 正确 0 错误 99 异常 说明: 读卡成功后在termb.dll文件所在路径下生成wz.txt(文字信息)和zp.bmp(照片信息) wz.txt内容示例如下: 张红叶 女 汉 1988-11-18 河北省邯郸市临漳县称勾镇称勾东村复兴路25号 130423198811184328 临漳县公安局 2011.03.30-2021.03.30

读各项文字信息到自定义内存缓冲

原 型: 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) //得到安全模块号码 参数: *strTmp 返回的信息缓存指针。 *strLen 返回的信息长度指针。 返 回 值: 返回值 意义 1 正确 0 错误

注意:若采用查询方式自动判断卡片是否放置,则间隔时间建议大于300ms。

二 开始对接

主要做的功能就是使用身份证刷卡登录系统

大致流程是这样的: 前端是定时请求后台 后台流程就是

  1. 初始化连接
  2. 卡认证
  3. 读卡操作
  4. 得到身份证号信息

然后拿到这个身份证号后与数据库的用户对应身份证对比一下 如果相同 就调转到主页 完成登录

jnative 使用套路的话就是把用到的dll文件放到jdk的bin目录下面

动态链接库编译时选择的平台。如果通过x86平台编译,那么只能使用32位jdk环境加载,如果要使用64位jdk,必须使用x64平台编译。

那么怎么看dll文件是32位还是64位呢 可以装一个Visual Studio 自带工具dumpbin.exe 执行dumpbin.exe /headers 文件路径 像这样:

jnative 用法:

代码语言:javascript复制
JNative n = null;
		try
		{
			n = new JNative("Termb.dll", "CVR_InitComm");
			n.setRetVal(Type.INT); // 指定返回参数的类型
			n.setParameter(0, Port);//设置参数
			n.invoke(); // 调用方法
			return Integer.parseInt(n.getRetVal());//得到返回值
		}
		finally
		{

		}

实例:

引入jar包

代码语言:javascript复制
	<dependency>
          <groupId>org.apache</groupId>
          <artifactId>JNative</artifactId>
          <version>1.0.0</version>
      </dependency>

后台代码:

代码语言:javascript复制
		//1.打开端口
		int portReturnCode =1001;
		try
		{
			portReturnCode = CVR_InitComm(Integer.parseInt(intport));
			logger.info("打开端口返回值:"   String.valueOf(portReturnCode));
			if (portReturnCode!=1) {
				return null;
			}
		}
		catch(Exception ex)
		{
			logger.error("打开端口调用异常!"  ex.getMessage());
		}

		// 2. 认证
		int authReturnCode = 0;
		try
		{
			authReturnCode = CVR_Authenticate();
			logger.info("认证返回值:"   String.valueOf(authReturnCode));
			if (authReturnCode!=1) {
				return null;
			}
		}
		catch(Exception ex)
		{
			logger.error("认证调用异常!"  ex.getMessage());
		}

		//3. 读卡
		int readReturnCode = 0;
		try
		{
			readReturnCode = CVR_Read_Content(4);
			logger.info("读卡返回值:"   String.valueOf(readReturnCode));
			if (authReturnCode!=1) {
				return null;
			}
		}
		catch(Exception ex)
		{
			logger.error("读卡调用异常!"  ex.getMessage());
		}

		//4. 读取身份证号码
		int readIdReturnCode = 0;
		try
		{
			readIdReturnCode = GetPeopleIDCode();
			logger.info("读取身份证号码返回值:"   String.valueOf(readIdReturnCode));
			if(readIdReturnCode == 1)
			{
				logger.info("身份号码:"   strTmp.trim());

			}
		}
		catch(Exception ex)
		{
			logger.error("调用异常!"  ex.getMessage());
		}
		return strTmp.trim();
	}

调用动态库的方法:

代码语言:javascript复制
	/**
	 * 身份证阅读机打开端口
	 * @param Port
	 * @return
	 * @throws NativeException
	 * @throws IllegalAccessException
	 * @throws UnsupportedEncodingException
	 */
	private  int CVR_InitComm(int Port) throws NativeException, IllegalAccessException, UnsupportedEncodingException
	{
		JNative n = null;
		try
		{
			n = new JNative("Termb.dll", "CVR_InitComm");
			n.setRetVal(Type.INT); // 指定返回参数的类型
			n.setParameter(0, Port);
			n.invoke(); // 调用方法
			return Integer.parseInt(n.getRetVal());
		}
		finally
		{

		}
	}

	/**
	 * 身份证阅读机认证
	 * @return
	 * @throws NativeException
	 * @throws IllegalAccessException
	 */
	private  int CVR_Authenticate() throws NativeException, IllegalAccessException
	{
		JNative n = null;
		try
		{
			n = new JNative("Termb.dll", "CVR_Authenticate");
			n.setRetVal(Type.INT); // 指定返回参数的类型
			n.invoke(); // 调用方法
			return Integer.parseInt(n.getRetVal());
		}
		finally
		{

		}
	}

	/**
	 * 身份证阅读机读卡
	 * @return
	 * @throws NativeException
	 * @throws IllegalAccessException
	 */
	private  int CVR_Read_Content(int Active) throws NativeException, IllegalAccessException
	{
		JNative n = null;
		try
		{
			n = new JNative("Termb.dll", "CVR_Read_Content");
			n.setRetVal(Type.INT); // 指定返回参数的类型
			n.setParameter(0, Active);
			n.invoke(); // 调用方法
			return Integer.parseInt(n.getRetVal());
		}
		finally
		{

		}
	}

	/**
	 * 身份证阅读机获取身份证号
	 * @return
	 * @throws NativeException
	 * @throws IllegalAccessException
	 */
	private  int GetPeopleIDCode() throws NativeException, IllegalAccessException
	{
		JNative n = null;
		try
		{
			n = new JNative("Termb.dll", "GetPeopleIDCode");
			n.setRetVal(Type.INT); // 指定返回参数的类型
			Pointer a = new Pointer(MemoryBlockFactory.createMemoryBlock(4*10));
			Pointer b = new Pointer(MemoryBlockFactory.createMemoryBlock(4*30));
			n.setParameter(0,b);
			n.setParameter(1,a);
			n.invoke();
			byte[] by = new byte[120];
			by = b.getMemory();
			try
			{
				strTmp = new String(by,"gb2312");
			}
			catch (UnsupportedEncodingException ex)
			{
				logger.error("获取身份信息异常:",ex);
			}

			int asInt = a.getAsInt(0);

			a.dispose();
			b.dispose();
			return Integer.parseInt(n.getRetVal());
		}
		finally
		{

		}
	}

附上一个demo: https://github.com/xiepanpan/CVR100Demo

0 人点赞