飞天R502

收到客户一个NFC读写卡器,是飞天R502,具体介绍请看官网资料

飞天R502产品官网

SDK,文档下载

代码

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
package com.test;

import javax.smartcardio.*;
import java.io.UnsupportedEncodingException;
import java.util.List;

public class FeiTianNfcDrive {
final static byte[] getuidcomm = {(byte) 0xFF, (byte) 0xCA, 0x00, 0x00, 0x04};
// 初始化密码
final static byte[] initpass = {(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
// 密码
final static byte[] mypassword = "123456".getBytes();

private CardChannel channel;
private Card card;

public FeiTianNfcDrive() {
this.card = connectCard();
System.out.println("【初始化设备】:设备ART " + BytesHexStrTranslate.bytesToHexFun3(card.getATR().getBytes()));
this.channel = this.card.getBasicChannel();
}

public static void main(String[] args) {
FeiTianNfcDrive blog = null;
try {
blog = new FeiTianNfcDrive();
byte[] pass = {(byte) 0xff, (byte) 0x82, 0x00, 0x01, 0x06};
byte[] password = byteMerger(pass, initpass);
blog.getUId();
blog.addPassword(password);
blog.auth((byte) 0x0c, "A");
blog.readCard((byte) 0x0c);
//blog.writeCard((byte) 0x0c, changePassword("123456", "123456"));
blog.readCard((byte) 0x0b);

} catch (Exception e) {
if (e.getMessage().contains("SCARD_W_REMOVED_CARD")) {
System.out.println("请勿中途移开卡片");
}
System.out.println("异常: " + e.toString());
} finally {
try {
blog.close();
} catch (CardException e) {
System.out.println("关闭卡片失败");
e.printStackTrace();
}
}
}

private void close() throws CardException {
// 关闭卡片连接
card.disconnect(true);
}


/**
* 连接卡片
*
* @return
*/
public static Card connectCard() {
try {
TerminalFactory factory = TerminalFactory.getDefault();
// 获取终端设备
List<CardTerminal> terminals = factory.terminals().list();
System.out.println("终端: " + terminals);
// 读取第一张卡片
CardTerminal terminal = terminals.get(0);
// 连接卡片
Card card = terminal.connect("*");
System.out.println("卡片: " + card);
return card;
} catch (Exception e) {
if (e.getMessage().contains("list() failed")) {
System.out.println("请连接读卡器");
throw new RuntimeException("请连接读卡器");
}
if (e.getMessage().contains("No card present")) {
System.out.println("请放置IC卡");
throw new RuntimeException("请放置IC卡");
}
// 220 65 164 192
System.out.println("异常: " + e.toString());
throw new RuntimeException(e.getMessage());
}
}


public void addPassword(byte[] password) throws CardException {
System.err.println("加载密码:" + transmit(password));
}

/**
* 授权验证
*
* @throws CardException
*/
public void auth(byte block, String type) throws CardException {
byte passType = (byte) ("A".equals(type) ? 0x60 : 0x61);
byte[] comm = {(byte) 0xff, (byte) 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, block, passType, 0x01};
System.err.println("授权: " + transmit(comm));
}

/**
* 读卡片信息
*
* @param block
* @throws CardException
*/
public void readCard(byte block) throws CardException {
byte[] comm = {(byte) 0xff, (byte) 0xb0, 0x00, block, 0x10};
System.err.println("读取" + block + "块数据: " + transmit(comm));
}

/**
* 写卡片信息
*
* @param block
* @param data
* @throws CardException
*/
public void writeCard(byte block, byte[] data) throws CardException {
byte[] comm = {(byte) 0xff, (byte) 0xd6, 0x00, block, 0x10};
if (data.length != 16) {
throw new RuntimeException("写入数据超出范围");
}
byte[] newComm = byteMerger(comm, data);
System.err.println("【写入数据】:即将写入的数据为: " + BytesHexStrTranslate.bytesToHexFun3(newComm));
transmit(newComm);
}


/**
* 获取修改密码的数据串
*
* @param passwordA
* @param passwordB
* @return
* @throws CardException
* @throws UnsupportedEncodingException
*/
static byte[] changePassword(String passwordA, String passwordB) throws UnsupportedEncodingException {
// 密码控制位置
final byte[] base = {(byte) 0xFF, 07, 80, 69};
byte[] passA = passwordA.getBytes("UTF-8");
byte[] passB = passwordB.getBytes("UTF-8");

if (passA.length > 6) {
throw new RuntimeException("【修改密码】:密码A的长度过长");
}
if (passB.length > 6) {
throw new RuntimeException("【修改密码】:密码A的长度过长");
}
// 1. 先将A和控制位连接起来
byte[] temp = byteMerger(passA, base);
// 最终的密码
byte[] newPass = byteMerger(temp, passB);
System.err.println("【修改密码】:发送指令: " + BytesHexStrTranslate.bytesToHexFun3(newPass));
return newPass;
}


/**
* 获取卡片ID
*
* @throws CardException
*/
public void getUId() throws CardException {
transmit(getuidcomm);
}

/**
* 发送指令
*
* @param data
* @return
* @throws CardException
*/
public byte[] transmit(byte[] data) throws CardException {
// 发送命令
System.out.println("发送指令: " + BytesHexStrTranslate.bytesToHexFun3(data));
ResponseAPDU answer = channel.transmit(new CommandAPDU(data));
System.out.println("设备响应: " + BytesHexStrTranslate.bytesToHexFun3(answer.getData()));
checkResp(answer.toString());
return answer.getData();
}

/**
* 校验响应结果
*
* @param resp
* @return
*/
public boolean checkResp(String resp) {
System.out.println(resp);
if (resp.contains("SW=9000")) {
System.out.println("响应成功");
return true;
} else {
System.out.println("响应失败");
}
return false;
}

/**
* 合并两个byte数组
*
* @param byte_1
* @param byte_2
* @return
*/
public static byte[] byteMerger(byte[] byte_1, byte[] byte_2) {
byte[] byte_3 = new byte[byte_1.length + byte_2.length];
System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
return byte_3;
}
}