飞天R502
收到客户一个NFC读写卡器,是飞天R502,具体介绍请看官网资料
代码
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;
}
}