一、简介

身份证阅读器使用场景比较多,围绕它按照自己的需求进行二次开发的也不少,我这次也是围绕身份证阅读器进行二次开发,不过使用的是kotlin作为开发的语言,资料比较少,参考了java的开发设计JAVA二次开发身份证阅读器

二、实际开发步骤

1、导入相关驱动与依赖

gradle导入如下,需要jna调用dll驱动文件

//jna 调用dll动态库
implementation("net.java.dev.jna:jna:3.1.0")

相关驱动如下:
sdtapi.dll
Termb.dll
WltRS.dll

2、创建相关实体类

class CPReadIdCardInfoModel(){/*** 姓名*/var name : String ?= null/*** 性别*/var sex : String ?= null/*** 民族*/var peopleNation:String ?= null/*** 出生日期*/var birthday:String ?= null/*** 居住地址*/var address : String ?= null/*** 身份证号码*/var idCardNum : String ?= null/*** 签发机构*/var department : String ?= null/*** 有效期开始日期*/var startDate : String ?= null/*** 有效期终止日期*/var endDate : String ?= null/*** 照片内容*/var bmpData : String ?= null/*** 照片内容*/var jpgData : String ?= null/*** 指纹数据*/var fpDate : String ?= null
}

3、创建JNA实现Library接口

interface TermbDLL : Library {/*** 连接读卡器*/fun CVR_InitComm(Port: Int): Int/*** 卡认证*/fun CVR_Authenticate(): Int/*** 读卡*/fun CVR_Read_Content(active: Int): Int/*** 读卡操作 含指纹*/fun CVR_Read_FPContent(active: Int): Int/*** 关闭连接*/fun CVR_CloseComm(): Int/*** 找卡*/fun CVR_FindCard(): Int/*** 选卡*/fun CVR_SelectCard(): Int/*** 获取姓名*/fun GetPeopleName(name: ByteArray?, len: IntByReference?): Int/*** 得到性别信息*/fun GetPeopleSex(sex: ByteArray?, len: IntByReference?): Int/*** 得到民族信息*/fun GetPeopleNation(strTmp: ByteArray?, strLen: IntByReference?): Int/*** 得到出生日期*/fun GetPeopleBirthday(strTmp: ByteArray?, strLen: IntByReference?): Int/*** 得到地址信息*/fun GetPeopleAddress(strTmp: ByteArray?, strLen: IntByReference?): Int/*** 得到身份证号信息**/fun GetPeopleIDCode(strTmp: ByteArray?, strLen: IntByReference?): Int/*** 得到发证机关信息*/fun GetDepartment(strTmp: ByteArray?, strLen: IntByReference?): Int/*** 得到有效开始日期*/fun GetStartDate(strTmp: ByteArray?, strLen: IntByReference?): Int/*** 得到有效截止日期*/fun GetEndDate(strTmp: ByteArray?, strLen: IntByReference?): Int/*** 得到安全模块号*/fun CVR_GetSAMID(strTmp: ByteArray?): Int/*** 得到指纹数据,不超过1024字节*/fun GetFPDate(strTmp: ByteArray?, strLen: IntByReference?): Int/*** 得到头像照片bmp数据,不超过38862字节*/fun GetBMPData(strTmp: ByteArray?, strLen: IntByReference?): Int/*** 得到头像照片base64编码数据,不超过38862*2字节*/fun Getbase64BMPData(strTmp: ByteArray?, strLen: IntByReference?): Int/*** 得到头像照片jpg数据,不超过38862字节*/fun Getbase64JpgData(strTmp: ByteArray?, strLen: IntByReference?): Intcompanion object {// termb.dll API函数的动态联接库// sdtapi.dll 安全模块通讯函数// WltRs.dll 身份证相片解码库val termbDLL = Native.loadLibrary(TermbDLL::class.java.getResource("/Termb.dll").path.substring(1), TermbDLL::class.java) as TermbDLL}
}

4、创建具体调用方法

class CPReadIdCardInfoService {var readIdCardInfoModel = CPReadIdCardInfoModel()@Throws(Exception::class)fun readIdCardInfo(): CPReadIdCardInfoModel {val instance = buildInstance()try {connAndCheckDevice(instance)//读取身份证各信息val len = IntByReference()//1、姓名val name = getPeopleName(instance, len)//2、性别val sex = getPeopleSex(instance, len)//3.民族val nation = getPeopleNation(instance,len)//4.出生日期val birthday = getPeopleBirthday(instance,len)//5.居住地址val address = getPeopleAddress(instance, len)//6.身份证号码val idCode = getPeopleIdCardNum(instance, len)//7.签发机关val department = getPeopleDepartment(instance, len)//8.有效期起始时间val startDate = getPeopleStartDate(instance,len)//9.有效期终止时间val endDate = getPeopleEndDate(instance, len)readIdCardInfoModel.name = namereadIdCardInfoModel.sex = sexreadIdCardInfoModel.peopleNation = nationreadIdCardInfoModel.birthday = birthdayreadIdCardInfoModel.address = addressreadIdCardInfoModel.idCardNum = idCodereadIdCardInfoModel.department = departmentreadIdCardInfoModel.startDate = startDatereadIdCardInfoModel.endDate = endDatereturn readIdCardInfoModel} finally {instance.CVR_CloseComm()}}private fun getPeopleName(instance: TermbDLL, len: IntByReference): String? {try {//长度更具华视文档设定val nameStrTmp = ByteArray(30)//JNA调用DLL方法instance.GetPeopleName(nameStrTmp, len)return handleResult(nameStrTmp)} catch (e: Exception) {e.printStackTrace()}return null}private fun getPeopleSex(instance: TermbDLL, len: IntByReference): String? {try {val sexStrTmp = ByteArray(2)instance.GetPeopleSex(sexStrTmp, len)return handleResult(sexStrTmp)} catch (e: Exception) {e.printStackTrace()}return null}private fun getPeopleNation(instance: TermbDLL,len: IntByReference): String? {try {val nationStrTmp = ByteArray(20)instance.GetPeopleNation(nationStrTmp,len)return handleResult(nationStrTmp)} catch (e:Exception){e.printStackTrace()}return null}private fun getPeopleBirthday(instance: TermbDLL,len: IntByReference): String? {try {val birthdayStrTmp = ByteArray(16)instance.GetPeopleBirthday(birthdayStrTmp,len)return handleResult(birthdayStrTmp)} catch (e:Exception){e.printStackTrace()}return null}private fun getPeopleAddress(instance: TermbDLL,len: IntByReference): String? {try {val addressStrTmp = ByteArray(70)instance.GetPeopleAddress(addressStrTmp,len)return handleResult(addressStrTmp)} catch (e:Exception){e.printStackTrace()}return null}private fun getPeopleIdCardNum(instance: TermbDLL,len: IntByReference): String? {try {val idCardNumStrTmp = ByteArray(36)instance.GetPeopleIDCode(idCardNumStrTmp,len)return handleResult(idCardNumStrTmp)} catch (e:Exception){e.printStackTrace()}return null}private fun getPeopleDepartment(instance: TermbDLL,len: IntByReference): String? {try {val departmentStrTmp = ByteArray(30)instance.GetDepartment(departmentStrTmp,len)return handleResult(departmentStrTmp)} catch (e:Exception){e.printStackTrace()}return null}private fun getPeopleStartDate(instance: TermbDLL,len: IntByReference): String? {try {val startDateStrTmp = ByteArray(16)instance.GetStartDate(startDateStrTmp,len)return handleResult(startDateStrTmp)} catch (e:Exception){e.printStackTrace()}return null}private fun getPeopleEndDate(instance: TermbDLL,len: IntByReference): String? {try {val endDateStrTmp = ByteArray(16)instance.GetEndDate(endDateStrTmp,len)return handleResult(endDateStrTmp)} catch (e:Exception){e.printStackTrace()}return null}private fun getPeopleBmpData(instance: TermbDLL,len: IntByReference): String? {try {val bmpDataStrTmp = ByteArray(38862)instance.GetBMPData(bmpDataStrTmp,len)return handleResult(bmpDataStrTmp)} catch (e:Exception){e.printStackTrace()}return null}private fun getPeopleInfo(instance: TermbDLL, methodName: String, len: IntByReference): String? {try {val strTmp = ByteArray(10)val method = instance.javaClass.getMethod(methodName, ByteArray::class.java, IntByReference::class.java)method.invoke(instance, strTmp, len)return handleResult(strTmp)} catch (e: Exception) {e.printStackTrace()}return null}@Throws(UnsupportedEncodingException::class)private fun handleResult(nameByte: ByteArray): String {//处理返回值防止乱码return String(nameByte, charset(CHARACTER_ENCODING)).trim() { it <= ' ' }}@Throws(Exception::class)private fun connAndCheckDevice(instance: TermbDLL) {//1、初始化连接cvrInitComm(instance)//2、读卡(同一个身份证,只要读取一次,下次读取优先从缓存中读取,并且CVR_Authenticate返回为2,卡认证失败,所以优先读卡一次)var readStatus = instance.CVR_Read_Content(1) //读取卡//2、卡认证,超出两分钟就是本次读卡失败val authenticate = getAuthenticateStatus(instance, readStatus)if (authenticate != SUCCESS) {throw Exception("读卡失败,请重新放置卡片")}if (readStatus != SUCCESS) {readStatus = instance.CVR_Read_Content(1) //读取卡}if (readStatus != SUCCESS) {throw Exception("证件信息读取失败,请重新放置证件")}println("读卡成功!");}/*** 卡认证* @param instance     DLL* @param readStatus   同一个身份证,只要读取一次,下次读取优先从缓存中读取,并且CVR_Authenticate返回为2,卡认证失败,所以优先读卡一次*/@Throws(InterruptedException::class)private fun getAuthenticateStatus(instance: TermbDLL, readStatus: Int): Int {if (readStatus == SUCCESS) {return SUCCESS}val deadline = System.nanoTime() + TimeUnit.MINUTES.toNanos(2L)var authenticate = FAIL//循环读卡,失效时间为2分钟while (authenticate != SUCCESS) {authenticate = instance.CVR_Authenticate()if (deadline == SUCCESS.toLong()) {continue}if (deadline - System.nanoTime() < 0L) {break}Thread.sleep(100)//短暂休眠}return authenticate}@Throws(Exception::class)private fun cvrInitComm(instance: TermbDLL) {val cvrInitComm = instance.CVR_InitComm(1001)if (cvrInitComm != SUCCESS) {throw Exception("读卡器连接失败,请检查设备状态")}}@Throws(Exception::class)private fun buildInstance(): TermbDLL {val dllResource = TermbDLL::class.java.getResource("/Termb.dll") ?: throw Exception("请检查设备状态")var dllPath = dllResource.pathif (StringUtils.isNullOrEmpty(dllPath)) {throw Exception("请检查设备状态")}if (StringUtils.startsWithIgnoreCase(dllPath, "/")) {dllPath = dllPath.substring(1)}return try {Native.loadLibrary(dllPath, TermbDLL::class.java) as TermbDLL} catch (e: Exception) {throw Exception("请检查设备状态")}}companion object {//成功状态码private const val SUCCESS = 1//失败状态码private const val FAIL = 0private const val CHARACTER_ENCODING = "gb2312"}
}

5、创建Controller类调用方法

@KtorExperimentalLocationsAPI
@Location("/idcard/read")
class CPReadIdCardInfoController {@Location("/add")class GetIdCard() : LocationProcess() {override suspend fun process() {println("读卡开始!")val idCardInfoService = CPReadIdCardInfoService()val readIdCardInfo = idCardInfoService.readIdCardInfo()println(readIdCardInfo.name)println(readIdCardInfo.sex)println(readIdCardInfo.peopleNation)println(readIdCardInfo.birthday)println(readIdCardInfo.address)println(readIdCardInfo.idCardNum)println(readIdCardInfo.department)println(readIdCardInfo.startDate)println(readIdCardInfo.endDate)println("读卡结束!")call.respond("success")}}
}

Kotlin之身份证阅读器(华视)二次开发相关推荐

  1. JNA二次开发华视身份证阅读器

    JNA二次开发华视身份证阅读器 前言 添加依赖 SDK资料 编写代码 遇到的问题(坑) 前言 这两天了解了一下java调用dll动态库的方法,总的有三种:JNI.JNA.JNative,其中JNA调用 ...

  2. python能调用身份证读卡器吗_最近的项目中用到读卡器,用的华视身份证阅读器,附上SDK使用手册...

    最近的项目中用到读卡器,用的华视身份证阅读器,附上SDK使用手册 1.定义 应用函数开发包含下列文件: termb.dll      API函数的动态联接库 sdtapi.dll     内部动态库 ...

  3. 最近的项目中用到读卡器,用的华视身份证阅读器,附上SDK使用手册

    <script type="text/javascript">// </script> <script type="text/javascr ...

  4. 华视100UC 身份证阅读器 Java

    华视100UC 身份证阅读器 Java 哪位大佬有64位可用的dll文件,施舍给小弟吧,万分感谢 功能 环境 个人想法(有不对的地方希望大佬指正) 对于dll文件的想法 目录结构 1. pom.xml ...

  5. VUE实现华视身份证阅读器读取身份证信息

    VUE实现华视身份证阅读器读取身份证信息 话不多上直接上代码,写的不怎么规范多多包涵,我是在模态框实现的,在这里就只提供模态框代码. 最后附上华视身份证阅读器安装文件和浏览器插件链接: [https: ...

  6. 华视身份证阅读器SDK使用手册

    华视身份证阅读器SDK使用手册 V1.33 华视电子读写设备有限公司  2008年07月11日 概述 本手册是操作身份证阅读器动态库应用函数的定义格式.调用方法和返回值的说明.在使用前,请确认授权文件 ...

  7. VUE实现华视身份证阅读器读取身份证信息(本文分两种情况,第一中是点击按钮读取信息,一种是自动读取信息)

    本文是用了vue+element来实现华视身份证读卡器读取身份信息的,当然在开发之前要做好前提准备,就是厂家提供对应设备的api和安装对应的驱动.本文通过两种方法来实现读取信息,第一种是点击按钮读取信 ...

  8. 二代身份证读取 中控ID180 二三代身份证阅读器 Vue版本

    二代身份证读取 中控ID180 二三代身份证阅读器 Vue版本 设备 设备名称:台式身份证阅读机 产品型号:ID180 设备驱动和文档 链接:https://pan.baidu.com/s/1nAYk ...

  9. Node.js 调用 dll动态库 以华旭身份证阅读器为例

    需求来源 由于使用Electron使用开发桌面端,同时也需要连接硬件设备,单纯使用js方法无法完成,需要通过Node调用dll动态库方式完成. 版本说明: node v12.18.3 (32位) np ...

最新文章

  1. 游戏中每日刷新实现思路浅析
  2. SpringBoot中使用Thymeleaf常用功能(三):测试Thymeleaf循环取数据
  3. 【面向对象】类的特殊成员方法
  4. 开放下载!《阿里云存储白皮书》全面解读阿里云存储二十年的技术演进
  5. 从浏览器端JavaScript代码进行服务器端日志记录
  6. error c4996: 'fopen' This function or variable may be unsafe如何解决
  7. 狗窝里的小日子- 5 ...
  8. 企业微信H5_网页jssdk调用 config和agentconfig的区别
  9. 云计算技术 基础知识整理
  10. 4.2-软件开发中,“思维导图”的作用与绘制方法介绍
  11. linux日期时间转换函数,Linux时间戳、日期转换函数
  12. aac和mp3在码率压缩的一些事
  13. 「算法学习」:求平方根
  14. 三、GTK-按钮(微调按钮、复选按钮、单选按钮)、快捷键、热键
  15. 菜鸟攒机之深度学习(上)
  16. 2022年,AI将给网络安全领域带来什么?
  17. 遇到pdf文件损坏打不开要如何解决?
  18. 通过蒲公英让两台异地电脑组建局域网
  19. C语言实现二叉排序树
  20. shell批量修改文件名

热门文章

  1. 双向链表list(十二)
  2. 计算机处理器哪个最好,电脑处理器,哪个比较好
  3. 国外问卷调查详细讲解
  4. 大数据专业就业前景及就业方向
  5. 常见文件类型的图标介绍
  6. win10注册表损坏开机蓝屏修复
  7. easyui tabs 的href和content属性
  8. 一个基于 Vue3 Vite 的相册应用
  9. 绿色IT,从环保到经济效益
  10. 粗糙集约简 程序 matlab,粗糙集属性约简matlab程序