package com.hxzkoa.udp; import java.io.UnsupportedEncodingException; import java.util.Iterator; import java.util.List; import com.hxzkoa.json.tb_adress_and_port; import com.hxzkoa.util.StringUtil; import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.ptr.IntByReference; public class IDcard { private static final String CHARACTER_ENCODING = "gb2312"; public static IntByReference strLen = null; public static String name;// 姓名 public static String sex;// 性别 public static String minzu;// 民族 public static String chushengdate;// 出生日期 public static String address;// 地址 public static String idnum;// 身份证号 public static String fazhengjiguan;// 发证机关 public static String startdate;// 开始日期 public static String jizhidate;// 截至日期 public static String UID;// UID public static IntByReference len = new IntByReference(); public static boolean renzheng = false; public static String state;// 状态 public static int i = 0; public static int kaohao; /** * 动态链接库编译时选择的平台。如果通过x86平台编译,那么只能使用32位jdk环境加载,如果要使用64位jdk,必须使用x64平台编译。 * * 接口内部需要一个公共静态常量:INSTANCE,通过这个常量,就可以获得这个接口的实例,从而使用接口的方法,也就是调用外部dll/so的函数。 * 该常量通过Native.loadLibrary()这个API函数获得,该函数有2个参数: * * 第一个参数是动态链接库dll/so的名称,但不带.dll或.so这样的后缀,这符合JNI的规范,因为带了后缀名就不可以跨操作系统平台了。 * 搜索动态链接库路径的顺序是:先从当前类的当前文件夹找,如果没有找到,再在工程当前文件夹下面找win32/win64文件夹, * 找到后搜索对应的dll文件,如果 找不到再到WINDOWS下面去搜索,再找不到就会抛异常了。 * 第二个参数是本接口的Class类型。JNA通过这个Class类型,根据指定的.dll/.so文件,动态创建接口的实例。 * 该实例由JNA通过反射自动生成。 * * 接口中只需要定义你要用到的函数或者公共变量,不需要的可以不定义,注意参数和返回值的类型,应该和链接库中的函数类型保持一致。 * 定义好接口后,就可以使用接口中的函数即相应dll/so中的函数了 */ interface DLibrary extends Library { // 此处我的jdk版本为64位,故加载64位的Dll DLibrary INSTANCE = (DLibrary) Native.loadLibrary("Termb", DLibrary.class); // JNA.dll 中定义的函数 /** * 本函数用于PC与华视电子第二代居民身份证阅读器的连接 * * @param Port * 连接串口(COM1~COM16)或USB口(1001~1016) * @return 1 正确 2 端口打开失败 0 动态库加载失败 */ int CVR_InitComm(int Port);// 初始化连接; int CVR_SetBaudRate(int nBaudRate); // 设置波特率 /** * 本函数用于关闭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_FPContent(); // 读卡操作,含指纹。 int CVR_FindCard(); // 找卡 int CVR_SelectCard();// 选卡 int GetPeopleName(byte[] strTmp, IntByReference strLen);// 得到姓名信息 int GetPeopleSex(byte[] strTmp, IntByReference strLen);// 得到性别信息 int GetPeopleNation(byte[] strTmp, IntByReference strLen);// 得到民族信息 int GetPeopleBirthday(byte[] strTmp, IntByReference strLen);// 得到出生日期 int GetPeopleAddress(byte[] strTmp, IntByReference strLen);// 得到地址信息 int GetPeopleIDCode(byte[] strTmp, IntByReference strLen);// 得到身份证号信息 int GetDepartment(byte[] strTmp, IntByReference strLen);// 得到发证机关信息 int GetStartDate(byte[] strTmp, IntByReference strLen);// 得到有效开始日期 int GetEndDate(byte[] strTmp, IntByReference strLen);// 得到有效截止日期 int CVR_GetSAMID(byte[] SAMID);// 得到安全模块号 int CVR_GetIDCardUID(byte[] pUidBuff, int nBuffLen);// 取得身份证UID int GetFPDate(byte[] pData, IntByReference pLen);// 得到指纹数据,不超过1024字节 int GetBMPData(byte[] pData, IntByReference pLen);// 得到头像照片bmp数据,不超过38862字节 int Getbase64BMPData(byte[] pData, IntByReference pLen);// 得到头像照片base64编码数据,不超过38862*2字节 int Getbase64JpgData(String pData, IntByReference pLen);// 得到头像照片jpg数据,不超过38862字节 // 读卡含税原型int M1_MF_HL_Request (byte Mode, byte* SNR, byte* TagType); /** * @param Mode[in]:读卡模式 * ;0:IDLE模式,只选择天线范围内IDLE模式的卡片; 1:ALL模式,选择天线范围内的所有卡片 * @param SNR[out]:卡号数据,长度为4 * @param TagType[out]:标签类型,长度为2 **/ int M1_MF_HL_Request(byte Mode, int[] SNR, short[] TagType); // 原型int M1_MF_HL_Auth (byte Mode, byte* SNR, byte Block, byte* Key); /** * @paramMode[in]:读卡模式;0:IDLE模式,只选择天线范围内IDLE模式的卡片 ;1:ALL模式,选择天线范围内的所有卡片 * @paramModeSNR[out]:卡号数据,长度为4 * @paramModeBlock [in]:卡片Block块地址值 * @paramModeKey [in]:卡片密码,长度为6 */ int M1_MF_HL_Auth(byte Mode, int[] SNR, byte Block, int[] Key); // 含税原型int M1_MF_HL_Read (byte Mode, byte* SNR, byte Block, byte* Key, // byte* buffer, UINT nBuff); /** * @param Mode[in]:读卡模式 * @param 0:IDLE模式,只选择天线范围内IDLE模式的卡片 * @param 1:ALL模式,选择天线范围内的所有卡片 * @param SNR[out]:卡号数据,长度为4 * @param Block * [in]:卡片Block块地址值 * @param Key * [out]:卡片密码,长度为6 * @param buffer * [out]:卡区的数据,长度为16 **/ int M1_MF_HL_Read(byte Mode, int[] SNR, byte Block, int[] Key, int buffer); // 写卡 /** * Mode[in]:读卡模式 0:IDLE模式,只选择天线范围内IDLE模式的卡片 1:ALL模式,选择天线范围内的所有卡片 * SNR[out]:卡号数据,长度为4 Block [in]:卡片Block块地址值 Key [out]:卡片密码,长度为6 buffer * [out]:写入卡区的数据,长度为17 [0]:代表Block块如04 [1]:代表写入块区内的数据,传入此处数组地址 */ // int M1_MF_HL_Write (byte Mode, byte* SNR, byte Block, byte* Key, // byte* buffer); /** * FisCardID [out]:金融卡卡号数据 LifeEndData [out]:金融卡有效期 FisCardIDLen * [out]:金融卡卡号长度 **/ // int M1_MF_GetFisCardID(BYTE* FisCardID, BYTE* LifeEndData,int* // FisCardIDLen); } /** 初始化连接 */ public static String chushi(List adress_and_portList) { String state = CVR_InitComm(adress_and_portList);// 初始化连接 CVR_SetBaudRate();// 设置波特率 return state; } public static int RedaCard() { // 1.打开串口;2.设置波特率;3.寻卡;4.选卡;5.读卡操作;6.关闭连接 // CVR_Authenticate();//卡认证 int red = Read_Content();// 读卡 // close();//关闭连接 return red; } /** 读M1卡 */ public static int Read_M1() { byte Mode = 0; int[] SNR = { 1, 2 }; short[] TagType = { 1, 2 }; int bb = DLibrary.INSTANCE.M1_MF_HL_Request(Mode, SNR, TagType); kaohao = SNR[0]; if (bb == 4) { state = "身份证信息读取成功,读卡成功请取走卡!"; } else { state = "读定位卡失败!"; } System.out.println("返回值" + bb); System.out.println("卡类型" + TagType[0]); System.out.println("卡号" + SNR[0]); return bb; } /** 寻M1卡 */ public static int M1_MF_HL_Request(List adress_and_portList) { close(); chushi(adress_and_portList); CVR_Authenticate(); int cc = Read_M1(); return cc; } // public static void main(String[] args) { // chushi(); // CVR_Authenticate(); // Read_M1(); // } /** 寻M1卡 */ public static int M1_MF_HL_Read() { byte Mode = 0; int[] SNR = { 1, 2 }; short[] TagType = { 1, 2 }; byte Block = 0; int[] Key = { 1, 2 }; int buffer = 16; int bb = DLibrary.INSTANCE.M1_MF_HL_Read(Mode, SNR, Block, Key, buffer); kaohao = SNR[0]; if (bb == 4) { state = "读卡成功请取走卡!"; } else { state = "读定位卡失败!"; } System.out.println("返回值" + bb); System.out.println("卡类型" + TagType[0]); System.out.println("卡号" + SNR[0]); return bb; } /** 初始化端口 */ public static String CVR_InitComm(List adress_and_portList) { String baoliu = get_adr_port("faka", adress_and_portList).getBaoliu(); if (StringUtil.checkIsNumber(baoliu)) { int com = Integer.parseInt(baoliu); int a = DLibrary.INSTANCE.CVR_InitComm(com);// 初始化连接; if (a != 1) { System.out.println("com" + com + "打开失败!"); state = "com" + com + "打开失败!请检查设备占用端口是否正确或者设备是否连接..."; } else { state = "发卡设备准备就绪..."; } } else { state = "端口无法识别..."; } return state; } /** 卡认证 */ public static boolean CVR_Authenticate() { System.out.println("卡认证操作!"); int ee = DLibrary.INSTANCE.CVR_Authenticate(); if (ee != 1) { renzheng = false; } else { renzheng = true; } return renzheng; } /** 关闭连接 */ public static void close() { int ff = DLibrary.INSTANCE.CVR_CloseComm(); if (ff != 1) { state = "关闭连接失败"; // SendTag.set_state("关闭连接失败"); } else { // SendTag.set_state("定位卡读取成功请取走定位卡..."); } } /** 设置波特率 */ public static void CVR_SetBaudRate() { DLibrary.INSTANCE.CVR_SetBaudRate(9600); } /** 读卡操作 */ public static void CVR_Read_FPContent() { int hh = DLibrary.INSTANCE.CVR_Read_FPContent(); if (hh != 1) { System.out.println("读卡操作失败"); // SendTag.set_state("读卡失败..."); } } public static int Read_Content() { int ii = DLibrary.INSTANCE.CVR_Read_Content(1); if (ii != 1) { System.out.println("获取信息失败"); // SendTag.set_state("获取信息失败..."); } else { System.out.println(getPeopleSex()); System.out.println(getPeopleName()); System.out.println(getMinzu()); System.out.println(getChushengdate()); System.out.println(getAddress()); System.out.println(getIdnum()); System.out.println(getFazhengjiguan()); System.out.println(getStartdate()); System.out.println(getJizhidate()); // getimage(); // SendTag.set_state("读取"+getPeopleName()+"身份证信息成功,请取走身份证..."); } return ii; } /** 获取姓名 */ @SuppressWarnings("unused") private static String getPeopleName() { try { // 长度更具华视文档设定 byte[] nameStrTmp = new byte[30]; // JNA调用DLL方法 DLibrary.INSTANCE.GetPeopleName(nameStrTmp, len); name = handleResult(nameStrTmp); } catch (Exception e) { e.printStackTrace(); } return name; } /** 获取性别 */ private static String getPeopleSex() { try { byte[] strTmp = new byte[2]; DLibrary.INSTANCE.GetPeopleSex(strTmp, len); sex = handleResult(strTmp); } catch (Exception e) { e.printStackTrace(); } return sex; } /** 获取民族 */ @SuppressWarnings("unused") private static String getMinzu() { try { byte[] strTmp = new byte[2]; DLibrary.INSTANCE.GetPeopleNation(strTmp, len); minzu = handleResult(strTmp); } catch (Exception e) { e.printStackTrace(); } return minzu; } /** 获取出生日期 */ public static String getChushengdate() { try { byte[] strTmp = new byte[50]; DLibrary.INSTANCE.GetPeopleBirthday(strTmp, len); chushengdate = handleResult(strTmp); } catch (Exception e) { e.printStackTrace(); } return chushengdate; } /** 获取地址 */ public static String getAddress() { try { byte[] strTmp = new byte[100]; DLibrary.INSTANCE.GetPeopleAddress(strTmp, len); address = handleResult(strTmp); } catch (Exception e) { e.printStackTrace(); } return address; } /** 获取身份证号 */ public static String getIdnum() { try { byte[] strTmp = new byte[50]; DLibrary.INSTANCE.GetPeopleIDCode(strTmp, len); idnum = handleResult(strTmp); } catch (Exception e) { e.printStackTrace(); } return idnum; } /** 获取发证机关 */ public static String getFazhengjiguan() { try { byte[] strTmp = new byte[50]; DLibrary.INSTANCE.GetDepartment(strTmp, len); fazhengjiguan = handleResult(strTmp); } catch (Exception e) { e.printStackTrace(); } return fazhengjiguan; } /** 获取有效日期开始 */ public static String getStartdate() { try { byte[] strTmp = new byte[50]; DLibrary.INSTANCE.GetStartDate(strTmp, len); startdate = handleResult(strTmp); } catch (Exception e) { e.printStackTrace(); } return startdate; } /** 获取有效日期结束 */ public static String getJizhidate() { try { byte[] strTmp = new byte[50]; DLibrary.INSTANCE.GetEndDate(strTmp, len); jizhidate = handleResult(strTmp); } catch (Exception e) { e.printStackTrace(); } return jizhidate; } /** 获取有效日期结束 */ public static String getuid() { try { byte[] strTmp = new byte[50]; DLibrary.INSTANCE.CVR_GetIDCardUID(strTmp, 10); UID = handleResult(strTmp); } catch (Exception e) { e.printStackTrace(); } return UID; } /** 获取身份证照片 */ public static void getimage() { try { byte[] strTmp = new byte[50]; DLibrary.INSTANCE.GetBMPData(strTmp, len); } catch (Exception e) { e.printStackTrace(); } } public static void setState(String state) { IDcard.state = state; } public static String handleResult(byte[] nameByte) throws UnsupportedEncodingException { // 处理返回值防止乱码 return new String(nameByte, CHARACTER_ENCODING).trim(); } public static String getState() { return state; } public static void setI(int i) { IDcard.i = i; } /** 通过name找到某个端口地址对象 */ public static tb_adress_and_port get_adr_port(String name, List adress_and_portList) { tb_adress_and_port adr_and_port = null; if (adress_and_portList.size() != 0) { Iterator it = adress_and_portList.iterator(); while (it.hasNext()) { tb_adress_and_port get_adr_port1 = it.next(); String name1 = get_adr_port1.getName().trim(); if (name1.equals(name.trim())) { adr_and_port = get_adr_port1; break; } else { adr_and_port = new tb_adress_and_port(); adr_and_port.setBaoliu("9600"); } } } return adr_and_port; } }