Issuer‎ > ‎

Creating card agent

What is a card agent?

A card, or credential, agent is software that lives with in the mobile application and server two main purposes:

  • To provide the mobile application with an interface to the remote card credential.
  • To use its internal knowledge of a specific remote card credential to economize communication with the remote card.

The agent is the responsibility of the card or credential issuer. There is an implicit trust model between the application developer and the card credential issuer because the agent runs as part of the mobile application.

A basic, strict pass-through card agent is contained within the Issuer SDK.

Creating your first javacard applet contains the install information for the Issuer SDK. The project inside the SDK that contains an example pass-through card agent is called "CardAgent"

Two other example of card agent can be found here (also contained in the Issuer SDK):

Card Agent Programming

The first time a card agent is used with a new card in a mobile application, the agent will be downloaded to the mobile device. For example, say we have a class called CardAgent:

public class CardAgent extends Agent {

The mobile application will install and register the card agent:

	public CardAgent() {
		allowSoftTransactions();   //allow software connections to this card agent from the host mobile application
		allowNfcTransactions();    //allow communications between the NFC radio and this agent
		denySocketTransactions();  //deny any socket connection to this card agent from the host mobile device
	public static void install(CardAgentConnector cardAgentConnector) {
		new CardAgent().register(cardAgentConnector);


After the card agent is installed, the mobile SDK library interacts with the card agent via these methods:

public void create()  // activate the card (make it ready for payment)

public void activated()  //activate the card

public void deactivated()  // deactivate the card

public void disconnected()  // disconnect with the remote credential

public void sentApdu()  // callback when an APDU is successfully sent to the PCD

public void transactionStarted()  // callback when the transaction with the PCD is started

public void transactionFinished()  // callback when the transaction with the PCD is done

//  Callback when an answer from the card holder is posted
public void messageApproval(boolean approved,ApprovalData approvalData)

public abstract void process (APDU apdu) throws ISOException  //handle APDU from PCD


Messaging with the mobile application is done via this set of methods:

protected final String getVersion()  //get the mobile lib version

protected final void setProprietary()  //tell the mobile lib that this is a proprietary (non 7816-4 based card)

protected final void allowNfcTransactions() //allow PCD to communication with card agent
protected final void denyNfcTransactions() 

protected final void allowSoftTransactions() //allow the mobile app to communicate with agent
protected final void denySoftTransactions()

protected final void allowSocketTransactions() //allow the mobile app to use a socket server to connect to agent
protected final void denySocketTransactions() 

protected final void setBusy() //tell the mobile app the agent is busy
protected final void clearBusy()

protected final boolean getTransacting() //is PCD actively transacting with this agent
protected final boolean getTransactionFinished() //has transaction with PCD finished?
protected final void transactionFailure() //tell the mobile device the transaction failed

protected final void connect() //connect with the remote card
protected final void disconnect() 

protected final void deactivate() //tell the mobile app the agent is deactivated

protected final void transceive(TransceiveData transceiveData)  // transceive data with the remote card

// Because the agent state is stored remotely and connectivity can sometimes be suspect,
// the transaction flag is a way the mobile application can manage a small flag to tell the
// agent that a remote action needs to happen.  it is a safety to protect against the 
// inability to save the agent state and the app being closed
protected final boolean getDoTransactionFlag() 
protected final void setDoTransactionFlag()
protected final void clearDoTransactionFlag()

//post a message to the mobile application
//some messages may require an action by the mobile application user (getApproval)
//in that event, the approval data will get passed back from the user to the agent
//in messageApproval() above
protected final void postMessage(String msg, boolean getApproval, ApprovalData approvalData)

protected final void saveState() //save the state of the card agent (this is a remote storage)

Transceive Data

One of the more important functions that we need to address is using transceive to communicate with the remote card. It is important to know that transceive is a blocking method if TransceiveData requires a response in any of the packed commands, otherwise, there is no reason to block once the data has been sent to the remote card.

Using TransceiveData:

// Instantiate a new object "data", telling the remote card this data will be
// transmitted over the NFC_CHANNEL (T=CL)
// other options would be DEVICE_CHANNEL (T=T0), SOCKET_CHANNEL, or SOFT_CHANNEL 
TransceiveData data = new TransceiveData(TransceiveData.NFC_CHANNEL);

// Set the timeout for waiting for a response

// Tell the card to reset itself
// and do NOT have the card send a response back!

// Select the visa AID on the remote card, and do NOT send response back
data.packApdu(new byte[]{0x00,(byte)0xA4,0x04,0x00,0x07,(byte)0xA0,0x00,0x00,0x00,0x03,0x10,0x10,0x00}, false);

// Send GPO command on the remote card, and do NOT send the response back
data.packApdu(new byte[]{(byte)0x80,(byte)0xA8,0x00,0x00,0x04,(byte)0x83,0x02,(byte)0x80,0x00,0x00}, false);

// Send Read Record command to remote card, and DO wait on this response
data.packApdu(new byte[]{0x00,(byte)0xB2,0x01,0x0C,0x00}, true);

// Send all the communication data now!
try {
} catch (IOException e) {
      //connection problems must have happened

// Get the read record response
byte[] rsp = data.getNextResponse()					

Go on to Testing the card agent