我需要使用智能卡读卡器从Maestro/Mastercard中读取账号。我正在使用Java 1.6及其javax.smartcardio包。我需要发送APDU命令,该命令将请求存储在卡片芯片上的EMV应用程序的PAN号码。问题在于,我无法找到正常的字节数组来构造返回所需数据的APDU命令...
您不需要进一步包装APDU。API层应该负责这个。
看起来0x6D00响应只是意味着应用程序不支持INS。
现在只是故障排除,但您开始选择MasterCard应用程序,对吗?
即,像这样:
void selectApplication(CardChannel channel) throws CardException {
byte[] masterCardRid = new byte[]{0xA0, 0x00, 0x00, 0x00, 0x04};
CommandAPDU command = new CommandAPDU(0x00, 0xA4, 0x04, 0x00, masterCardRid);
ResponseAPDU response = channel.transmit(command);
return response.getData();
}
这里是一些实际工作的例子:
CardChannel channel = card.getBasicChannel();
byte[] selectMaestro={(byte)0x00, (byte)0xA4,(byte)0x04,(byte)0x00 ,(byte)0x07 ,(byte)0xA0 ,(byte)0x00 ,(byte)0x00 ,(byte)0x00 ,(byte)0x04 ,(byte)0x30 ,(byte)0x60 ,(byte)0x00};
byte[] getProcessingOptions={(byte)0x80,(byte)0xA8,(byte)0x00,(byte)0x00,(byte)0x02,(byte)0x83,(byte)0x00,(byte)0x00};
byte[] readRecord={(byte)0x00,(byte)0xB2,(byte)0x02,(byte)0x0C,(byte)0x00};
ResponseAPDU r=null;
try {
ATR atr = card.getATR(); //reset kartice
CommandAPDU capdu=new CommandAPDU( selectMaestro );
r=card.getBasicChannel().transmit( capdu );
capdu=new CommandAPDU(getProcessingOptions);
r=card.getBasicChannel().transmit( capdu );
capdu=new CommandAPDU(readRecord);
r=card.getBasicChannel().transmit( capdu );
这个代码可以读取Maestro卡的PAN号码,但现在我需要读取MasterCard的PAN号码。我不知道是应该更改读取记录APDU还是选择应用程序APDU。有谁熟悉APDU吗?
atr = open();
prints(atr);
prints("[Step 1] Select 1PAY.SYS.DDF01 to get the PSE directory");
cmd = new ISOSelect(ISOSelect.SELECT_AID, EMV4_1.AID_1PAY_SYS_DDF01);
card_response = execute(cmd);
prints(card_response);
SFI = NumUtil.hex2String((byte)((1 < < 3) | 4));
// try SFI 1 record 1
prints("[Step 2] Send READ RECORD with 0 to find out where the record is");
read = new EMVReadRecord(SFI, "01", "00");
card_response = execute(read);
prints(card_response);
byte_size = NumUtil.hex2String(card_response.getStatusWord().getSw2());
prints("[Step 3] Send READ RECORD with 1C to get the PSE data");
read = new EMVReadRecord(SFI, "01", byte_size);
card_response = execute(read);
prints(card_response);
// the AID is A0000000031010
prints("[Step 4] Now that we know the AID, select the application");
cmd = new ISOSelect(ISOSelect.SELECT_AID, "A0000000031010");
card_response = execute(cmd);
prints(card_response);
prints("[Step 5] Send GET PROCESSING OPTIONS command");
cmd = new EMVGetProcessingOptions();
card_response = execute(cmd);
prints(card_response);
// SFI for the first group of AFL is 0C
prints("[Step 6] Send READ RECORD with 0 to find out where the record is");
read = new EMVReadRecord("0C", "01", "00");
card_response = execute(read);
prints(card_response);
byte_size = NumUtil.hex2String(card_response.getStatusWord().getSw2());
prints("[Step 7] Use READ RECORD with the given number of bytes to retrieve the data");
read = new EMVReadRecord("0C", "01", byte_size);
card_response = execute(read);
prints(card_response);
data = new TLV(card_response.getData());
close();
byte[] readFile(CardChannel channel) throws CardException {
CommandAPDU command = new CommandAPDU(0xB0, 0x60, 0x10, 0x00);
ResponseAPDU response = channel.transmit(command);
return response.getData();
}
你有查看文档吗?0x6D00是什么意思?看起来可能是不支持ENVELOPE命令。你尝试过使用T=0协议而不是T=1吗?
我不认为我的示例会在你的卡上运行。我不知道Maestro/MasterCard支持哪些APDU,所以我无法给你一个可行的示例。
尝试像这样明确地指定期望的长度:
byte[] readPan(CardChannel channel) throws CardException {
CommandAPDU command = new CommandAPDU(0x00, 0xB2, 0x5a, 0x14, 250);
ResponseAPDU response = channel.transmit(command);
return response.getData();
}
使用一个扫描仪,获取卡片的照片,使用优秀的Java OCR库(例如http://ocr4j.sourceforge.net/)扫描照片内容并搜索通常为16位数字序列XXXX-XXXX-XXXX-XXXX,然后您就可以使用Java从任何EMV卡中获取PAN。