?? messcard.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 + -