Как прочитать лоток от смарт-карты EMV от Java

Мне нужно прочитать номер счета от Maestro / Mastercard с помощью считывателя смарт-карт. Я использую Java 1.6 и его javax.пакет smartcardio. Мне нужно отправить команду APDU, которая попросит приложение EMV, хранящееся на чипе карты, для номера лотка. Проблема в том, что я не могу найти обычный массив байтов для создания команды APDU, которая вернет необходимые данные в любом месте...

6 ответов


вам не нужно обертывать 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, я могу прочитать номер лотка, но теперь мне нужно прочитать номер лотка MasterCard. Я не знаю, должен ли я изменить запись чтения APDU или выбрать APDU приложения. Кто-нибудь знаком с APDUs?


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();

вам нужно создать объект CommandAPDU и передать его команде transmit () -.

вы должны быть в состоянии найти точную команду в документации для вашей смарт-карты, но вот один пример:

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?

Я бы не ожидал, что мой пример будет работать на вашей карте. Я не знаю, какой APDUs поддерживает Maestro / MasterCard, поэтому я не мог бы привести вам рабочий пример.

попробуйте дать команде явную ожидаемую длину, как это:

byte[] readPan(CardChannel channel) throws CardException {
  CommandAPDU command = new CommandAPDU(0x00, 0xB2, 0x5a, 0x14, 250);
  ResponseAPDU response = channel.transmit(command);
  return response.getData();
}

то, что об использовании сканера, получая картинку карты, сканировать содержание картины с хорошей Ява ОРЗ библиотеки ( например,http://ocr4j.sourceforge.net/ например ) и поиск (обычно) 16 цифр ХХХХ-ХХХХ-ХХХХ-ХХХХ , тогда вы получите сковороду из любого EMV-карт с использованием Java.