yzt
2023-05-05 4c558c77a6a9d23f057f094c4dc3e315eabef497
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
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;
    }
}