1

我正在尝试通过我的 LG P710 Optimus L7 2 读取智能卡。
我正在关注本教程

我可以选择“1PAY.SYS.DDF01”目录
我可以选择应用程序

但我无法执行“获取处理选项”它总是导致 6700 错误(Lc 或 Le 错误)

这是我的代码

NfcAdapter mNFCAdapter;
Intent intent;
PendingIntent pendingIntent;
private TextView mTextView;
String[][] techList;
IntentFilter[] filters = new IntentFilter[3];

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    mTextView = (TextView) findViewById(R.id.title);

    mNFCAdapter = NfcAdapter.getDefaultAdapter(this);

    intent = new Intent(getApplicationContext(), getClass());
    intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

    pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);


    techList = new String[][]{
            new String[]
                    { MifareClassic.class.getName() },
            new String[]
                    { IsoDep.class.getName() }
            };

    filters[0] = new IntentFilter();
    filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
    filters[0].addCategory(Intent.CATEGORY_DEFAULT);
    // add type of tag data you want to have - here ndef -> plain text
    try {
        filters[0].addDataType(MIME_TEXT_PLAIN);
    } catch (MalformedMimeTypeException e) {
        e.printStackTrace();
    }

    filters[1] = new IntentFilter();
    filters[1].addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
    filters[1].addCategory(Intent.CATEGORY_DEFAULT);

    filters[2] = new IntentFilter();
    filters[2].addAction(NfcAdapter.ACTION_TECH_DISCOVERED);
    filters[2].addCategory(Intent.CATEGORY_DEFAULT);

}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    String action = intent.getAction();
    mTextView.setText(action);
    Toast.makeText(getApplicationContext(), action, Toast.LENGTH_SHORT).show();

    Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    IsoDep tagIsoDep;

    if((tagIsoDep = IsoDep.get(tagFromIntent)) != null)
        if(handleIsoDep(tagIsoDep))
            return;

}
     private boolean handleIsoDep(IsoDep tag){
    try{ 
        tag.connect(); 
        tag.setTimeout(20); 
        byte[] responseAPDU;


        //2PAY.SYS.DDF01
        byte[] select_Dir = new byte[]{ 
                (byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x0e,
                (byte)0x32, (byte)0x50, (byte)0x41, (byte)0x59, (byte)0x2e,
                (byte)0x53, (byte)0x59, (byte)0x53, (byte)0x2e, (byte)0x44, 
                (byte)0x44, (byte)0x46, (byte)0x30, (byte)0x31
        };

        //Select CC Applet
        byte[] select_Applet = new byte[]{ 
                (byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)7, 
                (byte)0xa0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x04,
                (byte)0x30, (byte)0x60
        };

        //Send GET PROCESSING OPTIONS command
        byte[] Send_Get = new byte[]{ 
                (byte)0x80,(byte)0xA8,(byte)0x00,(byte)0x00,(byte)0x02,
                (byte)0x83,(byte)0x00,
                (byte)0x00
        };


        responseAPDU = tag.transceive(select_Dir); 
        mTextView.setText(mTextView.getText() + handleResponse(responseAPDU));

这将返回 APDU 状态字 9000 -> 成功

        responseAPDU = tag.transceive(select_Applet); 
        mTextView.setText(mTextView.getText() + handleResponse(responseAPDU));

这将返回 APDU 状态字 9000 -> 成功

        responseAPDU = tag.transceive(Send_Get); 
        mTextView.setText(mTextView.getText() + handleResponse(responseAPDU));

而这个正在制造问题:它返回 6700 -> 错误的 Lc 或 Le

        mTextView.setText(mTextView.getText() + "\n\nDone");
        tag.close();

     } catch (IOException e) {
            e.printStackTrace();
            return false;
    }
    return true;
}

函数handleResponse 只是将“responseAPDU”从二进制解析为十六进制并突出显示状态字

谁能告诉我出了什么问题?或者只是帮助我?

PS 对不起英语不好 ;)


作为对我的应用程序选择的回应,我得到:

6f298407a0000000043060a51e50074d41455354524f5f2d046465656e9f38039f5c08bf0c059f4d020b0a9000

6F -> FCI Template 29  
84 -> DF Name 07 A0 00 00 00 04 30 60  
A5 -> FCI Properietary Template 1E  
50 -> Application Lable 07 4D 41 45 53 54 52 4F 5F 2D 04 64 65 6E  
9F38 -> PDOL 03 9F 5C 08  
BF0C -> FCI Issuer Data 05  
9F4D -> Log Entry 02 0B  
0A Additional Issuer Data

但我不知道要从 GET PROCESSING OPTIONS 将什么插入到数据字段中。
参考 EMV Book 3,“5.4 使用数据对象列表 (DOL) 的规则”一节中的指南。
那么我只需要设置数据字段 83 03 9F 5C 08
和 Lc = 5 吗?

4

1 回答 1

8

为了帮助您,需要整个 ADPU 对话框(命令/响应)。

但是,根据您的代码:硬编码您的 select_Dir 和 select_Applet 命令是正确的,但您不能硬编码 GET PROCESSING OPTIONS 命令,其语法取决于卡 (ICC) 对您的 select_Applet 命令的响应。

EMV 4.3 书 1“表 45:ADF 的选择响应消息数据字段 (FCI)”,解释了对 SELECT 命令的成功卡响应包含“处理选项数据对象列表”(PDOL,标签 9F38)。这是卡处理交易所需的字段列表(例如:金额,...)。这些字段值将由终端(您的手机)通过 GET PROCESSING OPTIONS 命令数据字段(标签 83)返回到卡,如EMV 4.3 第 3 册中的“6.5.8.3 命令消息中发送的数据字段”部分所述

命令消息的数据字段是根据 ICC 提供的 PDOL编码的数据对象,如第 5.4 节中定义的,并由标签“83”引入。当ICC不提供数据对象列表时,终端将模板的长度字段设置为零。否则,模板的长度字段是传输到ICC的数据对象的值字段的总长度。

知道 :

  • 您选择的 AID (A0 00 00 00 04 30 60) 是 Mastercard Maestro,它不可能有一个空的 PDOL
  • 但是您的 GET PROCESSING OPTIONS 命令未在其数据字段中列出任何值
  • 您的 GET PROCESSING OPTIONS 数据字段的长度与 PDOL 中卡片询问的字段的总长度可能不匹配,因此卡片返回 6700 检查错误(EMV 手册 1,“表 33:GET RESPONSE错误条件”)。

您已将卡请求的 PDOL 标识为:9F38 -> 03 9F 5C 08。03 告诉您 PDOL 为 3 个字节长。9F5C是请求字段的标签,08是电话要返回的字段值的长度。

标签 9F5C 在 EMV Contactless 2.3 Book C2 kernel 2 规范中定义,“A.1.59 DS Requested Operator ID”部分。DS 请求的操作员 ID 定义为

包含终端确定的用于数据存储的操作员标识符。它在 GET PROCESSING OPTIONS 命令中发送到卡。

我不熟悉这个标签,所以我不能告诉你什么是合适的值。但是,这里是 GET PROCESSING OPTIONS 命令的数据字段应该是什么样子,假设 DS 请求的操作员 ID 的值为 01 02 03 04 05 06 07 08,并给出了EMV 手册 3中的数据对象列表格式指南,“ 5.4 使用数据对象列表 (DOL) 的规则”:

83 08 01 02 03 04 05 06 07 08

和 Lc = 10

于 2013-12-28T04:00:19.437 回答