⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 messcard.java

📁 关于食堂卡的重点难点分析关于食堂卡的重点难点分析关于食堂卡的重点难点分析关于食堂卡的重点难点分析
💻 JAVA
字号:
Package MessCard;

import javacard.framework.*

public class MessCard extends Applet{
/*常量声明*/

// MessCard应用支持的CLA
final static byte MessCard _CLA=(byte)0x80;

// MessCard应用支持的INS   Install指令
final static byte VERIFY=(byte)0x20;
final static byte CREDIT=(byte)0x30;
final static byte DEBIT=(byte)0x40;
final static byte GET_BALANCE=(byte)0x50;

//最大余额  0x7fff是十六进制要运算就要转换为十进制它的十进制是32767
final static short MAX_BALANCE=0x7FFF;
//消费最大值
final static short MAX_TRANSACTION_AMOUNT=0x7F;

//PIN锁定前语序的最大错误尝试次数
final static byte PIN_TRY_LIMIT=(byte)0x03;
//PIN值的最大长度
final static byte MAX_PIN_SIZE=(byte)0x08;

/*MessCard应用返回的错误吗*/
//表明PIN认证错误
final static short SW_VERIFICATION_FAILED=0x6300;
//表明在消费进行之前需要先进行PIN认证
final static short SW_PIN_VERIFICATION_REQUIRED=0x6301;
//表明消费额小于零或大于最大允许值
//amount>MAX_TRANSACTION_AMOUNT or amount<0
final static short SW_INVALID_TRANSACTION_AMOUNT=0x6A83;

//表明余额已超出最大允许值
final static short SW_EXCEED_MAXIMUM_BALANCE=0x6A84;
//表明余额为负值
Final static short SW_NEGATIVE_BALANCE=0x6A85;

/*实例化变量声明*/
//食堂卡应用PIN值
OwnerPIN pin;
//食堂卡应用的余额
short balance;
private MessCard(byte[] bArray,short bOffset,byte bLength){
//MessCard应用构造函数,推荐将应用所需的所有变量,
//同意放到构造函数内进行分配,这样将减少内存泄漏的可能

//以为定的参数创建OwnerPIN 对象实例PIN
pin=new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);

//计算install方法输入参数在输入数组中的偏移量
byte iLen=bArray[bOffset];//AID length
bOffset=(short)(bOffset+iLen+1);
byte cLen=bArray[bOffset];//info length
bOffset=(short)(bOffset+cLen+1);
byte aLen=bArray[bOffset];//applet data length

//去安装参数作为食堂卡的初始PIN
pin.update(bArray,(short)(bOffset+1),aLen);
register();

}

public static void install(byte[] bArray,short bOffset,byte bLength){
   
   new MessCard(bArray,bOffset,bLength);
}

  public boolean select(){
  
    if(pin.getTriesRemaining()==0)
       
       return false;
   
}

public void deselect(){
   //当MessCard应用被取消选择时,将PIN的状态清空为初始值
    pin.reset(); 
}

public void process(APDU apdu){

  //APDU对象为JCRE临时入口点对象,他可被任何应用所访问,
  //负责传递终端发送的APDU命令。通过APDU.getBuffer()命令,
  //既可以得到APDU对象的通信缓冲区,即APDU命令数组
  byte[] buffer=apdu.getBuffer();

  //判断命令头是否正确
  buffer[ISO7816.OFFSET_CLA]=(byte)(buffer[ISO7816.OFFSET_CLA]&(byte)0xFC);

//若为SELECT命令,则直接返回,不做其他操作
if((buffer[ISO7816.OFFSET_CLA]==0)&&
(buffer[ISO7816.OFFSET_INS]==(byte)(0xA4)) )
   
return; 
//若为其他命令,则判断命令CLA和INS是否能够为MessCard应用所支持,
//若为支持范围外的其他值,则返回对象的错误状态字
if(buffer[ISO7816.OFFSET_CLA]!=MessCard_CLA)
   ISOExecption.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
Switch(buffer[ISO7816.OFFSET_INS]){
 
  case GET_BALANCE:
   getBalance(apdu);
retuen;

case DEBIT:
   debit(apdu);
   return;

case CREDIT:
credit(apdu);
return;

case VERIFY:
verify(apdu);
return;

default:
   ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
 
}

}

  private void credit(APDU apdu){
  
  //食堂卡应用鉴权
    if(!pin.is Validated())
    
      ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);

      byte[] buffer=apdu.getBuffer();

      //取命令LC,并将之存储在numBytes中
         byte numBytes=buffer[ISO7816.OFFSET_LC];
      //接收APDU命令数据,并将之存储到APDU通信缓冲区的
      //ISO7816.OFFSET_CDATA处,接着5字节的APDU命令头
      byte byteRead=(byte)(apdu.setIncomingAndReceive());

      //判断LC是否为1否则抛出异常,本应用只支持一个字节长度的存钱消费
      if((numBytes!=1)||(byteRead!=1))
       ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
       
       //取将存入的值
       byte creditAmount=buffer[ISO7816.FOFFSET_CDATA];
       
       //判断消费额度是否满足要求
       if((creditAmount)>MAX_TRANSACTION_AMOUNT)||(CREDITaMOUNT<0)
          )ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);

       //判断若进行存钱消费,余额是否超出允许最大值
       if((short)(balance+creditAmount)>MAX_BALANCE)
         ISOException.throwIt(SW_EXCEED_MAXIMUM_BALANCE);
       //若以上条件满足,则更新食堂卡余额
       blance=(short)(balance+creditAmount);

}
private void debit(APDU apdu){

   //食堂卡应用鉴权
   if(!pin.isValidated())
     ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);

   byte [] buffer=apdu.getBuffer();
   byte numBytes=(byte)(buffer[ISO7816.OFFSET_LC]);
    byte byteRead=(byte)(apdu.setIncomingAndReceive());
    
    if((numBytes!=1)||(byteRead!=1))
       ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    //取即将消费的值
    byte debitAmount=buffer[ISO7816.OFFSET_CDATA];
    
    //判断消费消费额度是否满足要求
    if((debitAmount>MAX_TRANSACTION_AMOUNT)||(debitAmount<0))
       ISOException.throwIt(SW_INVALID_TRANSACTION_AMOUNT);

    //判断食堂卡余额是否大于消费的数额,即食堂卡是否透支
    if((short)(balance-debitAmount)<(short)0)
           ISOException.throwIt(SW_NEGATIVE_BALANCE);

    //若以上条件全部满足,最后更改食堂卡余额
    balance=(short)(balance-debitAmount);


}

     private void getBalance(APDU apdu){

      byte[] buffer=apdu.getBuffer();

      //设置通信传输方向为卡片到终端,同时也表示卡片运行结束,
      //准备发送命令响应给终端,其中le为APDU命令中的LE,
      //表示终端要求卡片返回的响应数据的长度
      short le=apdu.setOutgoing();
    if(le<2)
       ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

    //设置卡片发送数据的实际长度
    apdu.setOutgoingLength((byte)2);
    
    //复制余额数据岛APDU缓存区中,准备发送给终端

    buffer[0]=(byte)(balance>>8);
     buffer[1]=(byte)(balance&0xFF);

     //调用通信函数发送余额数据
     apdu.sendBytes((short)0,(short)2);

}

       private void verify(APDU apdu){

           byte[] buffer=apdu.getBuffer();

           //接收终端发送的PIN数据,并将之存储到APDU通信缓冲区中
           byte byteRead=(byte)(apdu.setIncomingAndReceive());

           //判断数据终端数据的PIN是否和卡片内的PIN值相符
           if(pin.check(buffer,ISO7816.OFFSET_CDATA.byteRead)==false)
              ISOException.throwIt(SW_VERIFICATION_FAILED);

     
}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -