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<tb_adress_and_port> 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<tb_adress_and_port> 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<tb_adress_and_port> 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<tb_adress_and_port> adress_and_portList) {
|
tb_adress_and_port adr_and_port = null;
|
if (adress_and_portList.size() != 0) {
|
Iterator<tb_adress_and_port> 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;
|
}
|
}
|