一、简介

身份证阅读器使用场景比较多,围绕它按照自己的需求进行二次开发的也不少,我这次也是围绕身份证阅读器进行二次开发,不过使用的是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. 应用session对象实现用户登录
  2. 网页从web服务器受到的威胁,[多选] Web从web服务器方面和浏览器方面受到的威胁主要来自()。...
  3. CCNA学习笔记12---黄毛丫头篇(访问控制列表)
  4. 使用WebApiClient请求和管理Restful Api
  5. Linux下使用wc命令快速统计所有文件的行数
  6. 当我们在谈数字化转型的时候,我们在谈什么?
  7. jQuery实现购物车多物品数量的加减+总价计算
  8. photo player 显示 ☞ 列表选中项的处理
  9. 七周成为数据分析师 第三周:Excel篇
  10. 互联网金融学习总结(5)——市场主流的风控模型简要学习总结
  11. BSC-币安智能链主网节点搭建(详细步骤)
  12. 八段数码管数字显示实验c语言,硬件实验十 八段数码管显示
  13. python计算斜率以及给定一组点两两求斜率
  14. 407. 接雨水 II【我亦无他唯手熟尔】
  15. 汽车内饰胶市场现状及未来发展趋势
  16. 美图手机怎么投屏到电脑
  17. 计算机在化学中的应用总结感悟,计算机在化学中的应用实践总结报告
  18. python实现屏幕视频录制_用Python来做一个屏幕录制工具
  19. HtmlUnit使用体会
  20. 汉字点阵原理字模读取与显示

热门文章

  1. Google 不想与甲骨文争了,要放弃 Java APIs
  2. Android Proguard混淆详解
  3. 第三篇,网络层的IP协议
  4. 爱情大数据 | 你的专属微信聊天记录统计
  5. K12在线教育持续升温,教育需线上线下相结合!
  6. 上证指数30年k线图_上证指数历史k线图_k线图24种经典图解
  7. 自媒体推广有哪些好处?
  8. /lib//libclntsh.so: file format not recognized; treating as linker script
  9. 应付款与分工之利读后感
  10. 一元二次求解matlab程序,怎么用matlab解一元二次方程