Wednesday, April 16, 2014

Host Card Emulation Series: Google Cloud Messaging

Notifications can be an integral part of securing cloud based payment transactions.  Most mobile OS platforms support notification resources that can be leveraged by the platform developers for different reasons.  In the case of cloud based payments, notifications can be used to help secure and enforce authentic transactions at the POS.

The only relevant mobile OS platform at the time of this publication that supports payments that are accepted by existing mainstream acquirers is the AOSP or Android.  HCE (Host Card Emulation) was released inside Android 4.4 last October, so this blog post will focus on using Google Cloud Messaging or GCM.

An overview of the GCM architecture:

As you can see above the GCM and mobile device form an independent channel from the application itself.  This is done because Android OS manages registration of any particular application and therefore managing the communication with that registration which includes OS and device level security precautions.  

For a third party system to send a notification using GCM, the system follows step (a) above and that notification message is expected to be delivered using GCM channels, that is it.

This architecture can be used as a security measure to protect data that is ultimately relayed to a POS from a mobile application.  This simple diagram can indicate how payment transactional data can be protected using 2 different delivery channels
As you see above, the message that is to be delivered to the mobile application is split and actually delivered over 2 different channels.  So now with contactless or EMV (Cloud Based) credentials, payment information can be protected by these means:

1)  Dynamic Transaction Data:  each transaction data delivered to the POS is dynamic or changing from transaction to transaction so that a single transaction data can't be used more than one time

2)  2 Channel Delivery:  each dynamic transaction data above is split and delivered to the mobile device using SSL as one channel and GCM as a separate channel


Using GCM with SimplyTapp Platform

The example below provides a hands-on approach to accomplishing these tasks on the SimplyTapp platform.  The platform has Notification messaging built into it so that you do not have to concern yourself with the technical details of delivering messages over the network.  The interface abstracts the complexity and simply offers a "send to agent" api taking a single message as a string from the card applet service api framework.  This message has a known destination of the matching card agent for the card applet service.  The SimplyTapp platform handles all the routing and delivery to the proper place.

First things first, After downloading the IssuerSdk, unpack it, and go into IssuerSdkBundle and edit CardAgentTesterApp/build.gradle directory and make sure the agentToTest flag is uncommented for "CardAgent-GCM":

//
//  Swap the line below if you wish to test CardAgent-PayPass or
//  CardAgent-VisaMSD-SwipeYours instead of the CardAgent directory's code
// 
//def agentToTest = "CardAgent"
//def agentToTest = "CardAgent-PayPass"
//def agentToTest = "CardAgent-VisaMSD-SwipeYours"
def agentToTest = "CardAgent-GCM"


then build for eclipse:
> gradle eclipse

CardApplet service:

Import CardApplet-GCM into eclipse as a java project.  In the CardApplet.java file look at the code:

private short ATC = 0;

public void process(APDU apdu) {
  // Good practice: Return 9000 on SELECT
  if (selectingApplet()) {
    //no perso required for this card, so enable on first select
    Calendar exp = Calendar.getInstance();
    exp.set(Calendar.YEAR, 2014);
    exp.set(Calendar.MONTH, 4);
    try {
      setStatePersonalized("5413123456784800", exp, """");
    } catch (IOException e) {
    }
    return;
  }

  byte[] buf = apdu.getBuffer();
  switch (buf[ISO7816.OFFSET_INS]) {
  case (byte) 0x01:  //command to send a message via GCM
    short len = apdu.setIncomingAndReceive();
    //convert bytes to ASCII
    byte[] bytes = new byte[len];
    Util.arrayCopy(apdu.getBuffer(), (short)5, bytes, (short)0, len);
    String msg = "";
    try {
      msg = new String(bytes, "UTF-8");
      //echo back the Google Cloud Messaging Notification
      this.sendToAgent("Applet Message No.: "+ATC+"\nData: " + msg);
      ATC++;
    } catch (IOException e) {
    }
    break;
  default:
    // good practice: If you don't know the INStruction, say so:
    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
  }
}

The code above in the applet is pretty simple.  upon select, it switches the state of the card to personalized if it isn't personalized already.  Also it supports only one command (0x01) that is a simple echo of an incoming data message to the GCM service.  The key method to send a message via GCM is :

sentToAgent("this is a string destined to my agent over GCM");

An IOException() may be thrown in the event that the card agent has not yet been loaded by the mobile application.


CardAgent:

Import the CardAgent-GCM into eclipse as a java project.  In the CardAgent.java file look at the code:

@Override
public void messageFromRemoteCard(String msg)
{
  try {
    //post the message to the app, get the response back to message approval
    postMessage("GCM message from applet:\n"+msg+"\n\nTry Again?"truenull);
  } catch (IOException e) {
  }

}

when the card agent receives a message from the GCM server, this method posts the message to the mobile application.

the next code effectively collects a message from the application user and relays that message to the remote card applet service :

public void post()
{
  //post a message to the app, get a response back to message approval with approval data
  //the message must be less than 32 bytes as defined by the 32
  ApprovalData.StringData stringData = new ApprovalData.StringData((short)0,(short)32);
  ApprovalData approvalData = new ApprovalData(stringData);
  try {
    postMessage("Enter A GCM Message"false, approvalData);
  } catch (IOException e) {
  }
}

@Override
public void messageApproval(boolean approval, ApprovalData approvalData)
{
  if(approvalData!=null && approvalData.getApprovalData()!=null)
  {
    ApprovalData.StringData data = (ApprovalData.StringData)approvalData.getApprovalData();
    if(data!=null && data.getAnswer()!=null)
    {
      byte[] msg = data.getAnswer().getBytes();
      try {
        connect();
      } catch (IOException e) {
      }
      try {
        TransceiveData batchCommands = new TransceiveData(TransceiveData.NFC_CHANNEL);
        batchCommands.setTimeout((short) 5000);

        // In this example we just pack a single APDU command to send a message after card reset
        // and select of applet
        batchCommands.packCardReset(false);
        // select applet
        byte[] apduData = new byte[10];
        apduData[0] = 0x00;
        apduData[1] = (byte)0xa4;
        apduData[2] = 0x04;
        apduData[3] = 0x00;
        apduData[4] = 0x05;
        apduData[5] = 0x00;
        apduData[6] = 0x01;
        apduData[7] = 0x02;
        apduData[8] = 0x03;
        apduData[9] = 0x04;
        batchCommands.packApdu(apduData, false);
        //send message to applet to relay over GCM
        short len = (short)msg.length;
        apduData = new byte[5+len];
        apduData[0] = 0x00;
        apduData[1] = 0x01;
        apduData[2] = 0x00;
        apduData[3] = 0x00;
        apduData[4] = (byte)len;
        System.arraycopy(msg, 0, apduData, 5, msg.length);
        batchCommands.packApdu(apduData, true);  //make sure this completes before disconnecting
        transceive(batchCommands);
      } catch (IOException e) {
      }
      try {
        disconnect();
      } catch (IOException e) {
      }
    }
  }
  else if(approval)
    post();
}

@Override
public void create() {
  post();

}

the transceive function sends apdu commands to the card applet service for processing and the payload of the second APDU indicates the message to send in ascii format from  data.getAnswer().getBytes();


Running a test:

Now, let's try it out.  Import CardAgentTesterApp into eclipse as an android project.  After import is completed, browse to the com.simplytapp.config.Constants.java file and adjust the contents to match your PC settings that are running the CardApplet simulator when you start the card applet:

package com.simplytapp.config;

public class Constants {

    /*setup to communicate to the remoteSE simulator
     * make sure that you have the IsserSdk simulator 
     * running in order for the cardAgent to connect to it.
     * It is important that if you are using the same eclipse
     * client to run the SESDK as this card agent project that
     * you run the SESDK NOT in debug mode as it can tend to
     * slow the response from the SESDK down to non-realistic
     * latencies.  anyway, adjust the ipaddress and port 
     * for the running SESDK below accordingly for your environment
     */
  //address of a running SE simulator
  final public static String ip="192.168.1.66"
  //port address of a running SE simulator
  final public static int port=3000;            


}

Also, make sure your mobile device has WIFI on and is connected to your internal network so that it can reach the simulator config as defined above.

Next, you start the CardApplet project inside eclipse which will prompt you to enter commands in the command window.  First highlight the project "CardApplet-GCM" and click the debug button.  You may have to select the main class for the project.  if so select "com.simplytapp.cardwrapper.CardWrapper".  You should see this in the command window:

# SimplyTapp simulator running on port 3000
# gpjNG connected on port 3000
# Connected to card NFC interface
# using gpjNG!
# type: help
# to get started
#
Found card in terminal: SimplyTapp
ATR: 3B 00 
>

at the command prompt enter:

>/card
ATR: 3B 00 
Command  APDU: 00 A4 04 00 07 A0 00 00 01 51 00 00 
Response APDU: 6F 0F 84 08 A0 00 00 01 51 00 00 A5 04 9F 65 01 FF 90 00 
(16 ms)
Successfully selected Security Domain GP211 A0 00 00 01 51 00 00 
>auth
Command  APDU: 80 50 00 00 08 F4 AA A8 1A ED CB 4C 84 
Response APDU: 00 00 00 00 00 00 00 00 00 00 FF 02 00 00 6C 55 44 79 7A 91 94 AC C7 A2 F3 8D E7 1B 90 00 
(27 ms)
Command  APDU: 84 82 00 00 10 10 2F AA 11 12 B3 0C 93 52 3C 41 C3 46 65 5C 92 
Response APDU: 90 00 
(6 ms)
>install -i 0001020304 |com.st |CardApplet
Command  APDU: 80 E6 0C 00 1E 06 63 6F 6D 2E 73 74 0A 43 61 72 64 41 70 70 6C 65 74 05 00 01 02 03 04 01 00 02 C9 00 00 
Response APDU: 00 90 00 
(17 ms)
>exit-shell
exiting shell, leaving port open

this installs the new applet as AID 0001020304 which is the proper AID for this demo.  after installation you will see that we exit-shell which will leave the simulator running and ready to connect up to the card on the port 3000 as shown above in this configuration.

after the simulator is running the card applet service, you can then run the card applet tester app on your device.  

Once the app starts, you should get a prompt like this:  


After clicking the "Ok" button, the text will go to the card agent which will connect to the remote card applet and send the message to the remote card applet.  The card applet will then, in turn, add the message counter information setup in the example code to the message and send the message to GCM for delivery back to the card agent in the mobile application.  So you should end up seeing a full circle message delivery and notification from your mobile device that looks like this:


This test can be repeated as long as you like and it's only purpose is to demonstrate how to use GCM to transport information from the remote card applet service to its card agent.


Monday, March 31, 2014

Host Card Emulation Series: Card Agents and APDUs

In Android 4.4 to support HCE, HostApduService declares processCommandApdu() method that the developer needs to implement. The method processCommandApdu() is called when the service receives an Application Protocol Data Unit (APDU) sent by contactless/NFC reader. The developer needs to implement how to process APDUs specific to the card application(s) the service supports. The implementation can become complex if the service supports multiple card applications.

SimplyTapp SDK provides a robust architecture where each card application is implemented in a "card agent". Using SimplyTapp SDK, there is no need for the developer to implement a complex processCommandApdu() method for a service that supports multiple card applications. Instead the developer implements process() method in the card agent for each card application. A mobile application can support multiple card agents and card agents can be remotely deployed to the mobile application, similar to remotely deploying Java Card applet (aka cardlet) to the Secure Element. Essentially SimplyTapp SDK provides an architecture that is familiar to Java Card developers.

I will describe how the card agent processes different APDU cases as defined in ISO/IEC 7816-4 specification.
ISO 7816-4 Case 1 No Lc
No Le
Example: 80100000
ISO 7816-4 Case 2 No Lc
1-byte Le (1 to 256, Le=0x00 represents 256)
Example: 8012000000
ISO 7816-4 Case 3 1-byte Lc (1 to 255)
No Le
Example: 80140000081112131415161718
ISO 7816-4 Case 4 1-byte Lc (1 to 255)
1-byte Le (1 to 256, Le=0x00 represents 256)
Example: 8016000008212223242526272800

Here is sample code for card agent implementation that demonstrates how to process the example APDUs. The class extends com.simplytapp.virtualcard.Agent.
 import javacard.framework.APDU;  
 import javacard.framework.ISO7816;  
 import javacard.framework.ISOException;  
   
 import com.simplytapp.virtualcard.Agent;  
   
 public class CardAgent extends Agent {  
   
   public void process(APDU apdu) throws ISOException {  
     byte[] apduBuffer = apdu.getBuffer();  
     byte claByte = apduBuffer[ISO7816.OFFSET_CLA];  
     byte insByte = apduBuffer[ISO7816.OFFSET_INS];  
   
     if (claByte == (byte) 0x80) {  
       if (insByte == (byte) 0x10) {  
         // Process case 1 command APDU.  
         processCase1Apdu();  
   
         // Return SW=0x9000.  
       }  
       else if (insByte == (byte) 0x12) {  
         // Process case 2 command APDU.  
   
         // Copy response data to APDU buffer.  
         System.arraycopy(responseData, 0,   
             apduBuffer, 0, responseData.length);  
   
         short le = apdu.setOutgoing();  
         if (responseData.length > le) {  
           le = (short) responseData.length;  
         }  
         apdu.setOutgoingLength(le);  
         apdu.sendBytes((short) 0, le);  
         // Return response data with SW=0x9000.  
       }  
       else if (insByte == (byte) 0x14) {  
         // Process case 3 command APDU.  
         short lc = apdu.setIncomingAndReceive();  
   
         // Save command data from APDU buffer.  
         System.arraycopy(apduBuffer, ISO7816.OFFSET_CDATA,   
             commandData, 0, lc);  
   
         // Return SW=0x9000.  
       }  
       else if (insByte == (byte) 0x16) {  
         // Process case 4 command APDU.  
         short lc = apdu.setIncomingAndReceive();  
   
         // Save command data from APDU buffer.  
         System.arraycopy(apduBuffer, ISO7816.OFFSET_CDATA,   
             commandData, 0, lc);  
   
         // Copy response data to APDU buffer.  
         System.arraycopy(responseData, 0,   
             apduBuffer, 0, responseData.length);  
   
         short le = apdu.setOutgoing();  
         if (responseData.length > le) {  
           le = (short) responseData.length;  
         }  
         apdu.setOutgoingLength(le);  
         apdu.sendBytes((short) 0, le);  
         // Return response data with SW=0x9000.  
       }  
     }  
   }  
   
 }  

The card agent can also process extended length APDUs as defined in ISO/IEC 7816-4 specification. The maximum supported length using extended length is 32767 to be consistent with Java Card API.
ISO 7816-4 Case 1 Not Applicable
ISO 7816-4 Case 2 No Lc
3-byte Le (1 to 32767, Le=0x000000 represents 32767)
Example: 80120000000000
ISO 7816-4 Case 3 3-byte Lc (1 to 32767)
No Le
Example: 801400000000081112131415161718
ISO 7816-4 Case 4 3-byte Lc (1 to 32767)
2-byte Le (1 to 32767, Le=0x0000 represents 32767)
Example: 8016000000000821222324252627280000

Here is sample code for card agent implementation that demonstrates how to process the example extended length APDUs. The class extends com.simplytapp.virtualcard.Agent and implements javacardx.apdu.ExtendedLength.
 import javacard.framework.APDU;  
 import javacard.framework.ISO7816;  
 import javacard.framework.ISOException;  
 import javacardx.apdu.ExtendedLength;  
   
 import com.simplytapp.virtualcard.Agent;  
   
 public class CardAgent extends Agent implements ExtendedLength {  
   
   public void process(APDU apdu) throws ISOException {  
     byte[] apduBuffer = apdu.getBuffer();  
     byte claByte = apduBuffer[ISO7816.OFFSET_CLA];  
     byte insByte = apduBuffer[ISO7816.OFFSET_INS];  
   
     if (claByte == (byte) 0x80) {  
       if (insByte == (byte) 0x12) {  
         // Process case 2 command APDU.  
   
         // Copy response data to APDU buffer.  
         System.arraycopy(responseData, 0,   
             apduBuffer, 0, responseData.length);  
   
         short le = apdu.setOutgoing();  
         if (responseData.length > le) {  
           le = (short) responseData.length;  
         }  
         apdu.setOutgoingLength(le);  
         apdu.sendBytes((short) 0, le);  
         // Return response data with SW=0x9000.  
       }  
       else if (insByte == (byte) 0x14) {  
         // Process case 3 command APDU.  
         short receivedLen = apdu.setIncomingAndReceive();  
   
         // Save command data from APDU buffer.  
         System.arraycopy(apduBuffer, apdu.getOffsetCdata(),   
             commandData, 0, receivedLen);  
   
         short lc = apdu.getIncomingLength();  
         // Check if additional command data not yet received.  
         if (receivedLen != lc) {  
           short commandDataOffset = receivedLen;  
   
           // Receive more command data until no more available.  
           receivedLen = apdu.receiveBytes((short) 0);  
           while (receivedLen != 0) {  
             // Save additional command data from APDU buffer.  
             System.arraycopy(apduBuffer, 0,   
                 commandData, commandDataOffset, receivedLen);  
             commandDataOffset += receivedLen;  
             receivedLen = apdu.receiveBytes((short) 0);  
           }  
         }  
   
         // Return SW=0x9000.  
       }  
       else if (insByte == (byte) 0x16) {  
         // Process case 4 command APDU.  
         short receivedLen = apdu.setIncomingAndReceive();  
   
         // Save command data from APDU buffer.  
         System.arraycopy(apduBuffer, apdu.getOffsetCdata(),   
             commandData, 0, receivedLen);  
   
         short lc = apdu.getIncomingLength();  
         // Check if additional command data not yet received.  
         if (receivedLen != lc) {  
           short commandDataOffset = receivedLen;  
   
           // Receive more command data until no more available.  
           receivedLen = apdu.receiveBytes((short) 0);  
           while (receivedLen != 0) {  
             // Save additional command data from APDU buffer.  
             System.arraycopy(apduBuffer, 0,   
                 commandData, commandDataOffset, receivedLen);  
             commandDataOffset += receivedLen;  
             receivedLen = apdu.receiveBytes((short) 0);  
           }  
         }  
   
         // Copy response data to APDU buffer.  
         System.arraycopy(responseData, 0,   
             apduBuffer, 0, responseData.length);  
   
         short le = apdu.setOutgoing();  
         if (responseData.length > le) {  
           le = (short) responseData.length;  
         }  
         apdu.setOutgoingLength(le);  
         apdu.sendBytes((short) 0, le);  
         // Return response data with SW=0x9000.  
       }  
     }  
   }  
   
 }  

Friday, March 14, 2014

Host Card Emulation Series: Contactless Debit, A Merchants Advantage

Contactless Debit, A Merchants Advantage



Host Card Emulation (HCE) brings new opportunity for merchants. In a recent trip to Whole Foods, who installed contactless terminals some time ago, I decided to try my debit card using the Tapp mobile test wallet.  After grabbing some lunch I headed to the register, and proceeded to checkout.  I tapped my phone to the contactless terminal and VOILA! The terminal asked me for my pin, I entered it, grabbed my lunch and off I went.

So why is this important?  The answer requires a look back at where the dynamics of the payments industry was just a few years ago.

The “Way back Machine”

In the semi-beginning, circa 2011, NFC mobile wallets meant Google Wallet, ISIS and the MNOs controlled SE model.  The idea was pretty straight forward one device, one SE, maybe one credit card, and POW!!! BAMM!! Goldmine! Right...Wrong! What happened? A back lash by merchants, banks and just about everyone but the MNOs.  In front of the new push for mobile payments stood a number of hurdles that needed to be cleared.  One of the most sizable hurdles being the merchants feeling that Contactless = Higher Transaction Costs.

Merchants viewed NFC as a more expensive transaction form and in the SE model that was largely true. For example, the average cost of a debit transaction tops out at around $0.30 in the US compared to the potentially much higher cost credit transaction, roughly $0.10 + 1.7% or more.  So what happened? Merchants, led by Walmart, huddled together in an attempt to break down mobile payment progress and keep transaction costs down. They called it MCX. Their message could generally be summed up with the following statement “Hell No, We Won’t Go!”  This stance led to a lot of head scratching as how mobile payment adoption would or could progress. But quietly the ground began to soften and HCE took root. 

“Bing, please enter PIN”

Coming back to my experience at Whole Foods and why it is important. 

The goal of any merchant is to sell goods or services to customers in exchange for assets, typically money, that has a greater value to the merchant than the goods and services being sold.  Pretty straight forward, but how that exchange actually takes place is where we will have our conversation. 
When it comes to merchants convincing consumers to part with their money they want to make it as easy as possible. Today there are, generally speaking, a handful of payments options as presented below:

  • Cash – used often and easily accepted;
  • Check – rarely used anymore and rather hard and slow to use;
  • Credit – used often and extremely easy for both cashier and customer;
  • Debit – used most often and equal to credit for ease of use;
  • GiftCard/Stored Value – used on a regular basis and considered as easy to use as other plastic forms. 

Each payment option has advantages and disadvantages regarding availability, ease of use and cost of managing and accepting.   More importantly all these payment form factors excluding only cash and check can be all accepted over the contactless channel. This means that merchants now have increased opportunity to influence customers when it comes to selecting payment forms like debit and gift/stored value cards over their more expensive siblings.

It means the power of payment is now in the hands of the merchant.  To illustrate a practical example of this is the case study of Spec’s, a merchant that communicates to their customers the importance of selecting the right payment form.

Debit Strategy: Spec’s


Spec’s is a merchant in Texas that manages their transaction cost extremely well.  Every check out register displays the options and cost of the options and every cashier asks the customer if they would like a 5% discount for using Cash or Debit.  Pretty easy to make that decision for me.  I simply present my debit card and save the money up front.  It is not just Spec’s that takes this simplified approach but other merchants as well. 

Conclusion

HCE offers merchants and banks alike new opportunities to influence consumers’ payment behavior like never before.  As Spec’s demonstrates, customer are willing to pay cash or use debit when offered discounts at the register. Speaking from experience I know this is true. However, merchants should understand that offering consumers incentive to select the less expensive debit or gift/stored value card is a window that will not stat open forever as the pace of adoption continues to accelerate. There are already merchants implementing effective transactions cost reducing strategies.  Moving these same strategies into the mobile space only enhance the merchants’ position in a consumers mind at the time of check out.


Wednesday, January 22, 2014

Host Card Emulation Series: Stored-Value Cards and HCE


This post will focus on using stored-value cards for payment at contact-less NFC terminals through an HCE (Host Card Emulation) solution. HCE technology present in NFC payment apps can be used with various different cards. A large number of retailers are offering company branded stored-value cards to consumers. This use case will look at precisely that, using stored-value cards at NFC terminals.

     For this example we are using the McDonald's Arch Card. 
     

           



           
              McDonald's Arch Card











McDonald’s for some time has had contact-less NFC capable payment terminals installed and operational in all of  its franchises in the U.S. This example will use the re-loadable Arch card to pay as well as re-load balance at contact-less NFC terminals. The Arch Card is available for purchase at various locations including all McDonald's restaurants. This specific card as well others with similar architecture are able to be loaded into the system SimplyTapp has created utilizing HCE. For this example I will be using the “Tapp“Application now available for free on Google Play store.

Simple process of loading your Arch Card for payment into Tapp app:
  1. Downloaded Tapp app from Google Play store.
  2. Log in and select to add a card from the add card button indicated by + sign in the action bar.
  3. Select Mcdonald's Arch Card and purchase.
  4. Refresh card list and Arch card will be loaded into Tapp App.
  5.      Select Arch Card for payment.
At this point my Tapp app is ready to make payments with your Arch Card at McDonald’s contact-less terminals, which are standard at all locations in the U.S.


Paying with your KitKat Android  4.4 device using the HCE architecture found in the Tapp app provides a great user experience.  There is no specific or additional  instructions necessary when using your digital copy of your Arch Card loaded into your Tapp app.  Flow of transaction was similar to a typical experience, order was placed and cashier simply asked cash or card. Card was indicated as form of pay and at this time phone was placed over terminal and payment was made with my Arch Card. The experience for the merchant as well as the user was seamless. A video of the experience is found below:

  Pay with Arch Card:
                                        https://www.youtube.com/watch?v=6Off6nvl3t8

At McDonald’s I was also able to add additional funds to my re-loadable Arch Card that was previously loaded in my Tapp app. The process was simple and strait forward. I told the cashier that I had a re-loadable Arch Card and I wished to add additional funds to it.  The cashier rang me up and I handed cash over. I then placed my phone over the terminal and card was reloaded. From a user experience reloading and payment were the same. A video of the experience is found below:

   Reload Arch Card:
                                      https://www.youtube.com/watch?v=iCJTJSWhFEc

All of my transactions with my Arch Card can be monitored through McDonald's website.The Tapp app does not currently possess functionality to update balances on application. The HCE digital transaction shown in videos above are reflected in the following statement.








Having the Tapp app with HCE capabilities it allowed me to use the Arch Card at  McDonald's terminal from my mobile phone. My completely digital transaction added to my user experience and gave a great glimpse in to the future of payments from the view point of stored-value cards. The pairing of HCE and stored-value cards offer a great way to add value on either side of the transaction.





Tuesday, January 7, 2014

Host Card Emulation Series: SwipeYours - Tap Using A Card From Your Wallet

While various Android HCE (Host Card Emulation) examples have been popping up, until now there has been no simple examples that could be easily tested with live payment terminals. SwipeYours fills this space.

SwipeYours is a small, self contained app from which your card data never leaves the phone except to make NFC payments.  It uses the Visa-MSD (Magnetic Stripe Data) protocol to make tap payments. While Visa-MSD is now deprecated, it is supported by most NFC payment terminals in North America and this is unlikely to change in the near future. In Austin, TX we’ve successfully used SwipeYours at all of the following:

  • CVS drugstore
  • McDonald’s
  • Jack in the Box
  • Taco Bell
  • Jamba Juice
  • Valero Gas Stations


Links:


What you need to use SwipeYours:
  • A magnetic stripe reader to pull your card data. These can be purchased cheaply on both Amazon and Ebay in the US.
  • An NFC phone running Android 4.4+ (KitKat or above).
  • A non-chipped Visa credit or debit card. If the card already has a smart chip for native tap payments, the authorization processor is most likely expecting a different variation of Visa MSD than what we can provide. 
  • An issuing bank (or its outsourced processor) that does not check the delivery method: swipe, dip or tap.The processor has access to the delivery method of the card data and can reject a tap transaction if it wants to. All tested prepaid Visa cards have not had this issue and most major banks like Chase work fine. Capital One cards and the processor for some small credit unions, unfortunately, do have this issue.

Small Print Disclaimer:

SimplyTapp does not encourage the storage of payment credentials on your phone and provides secure cloud based solutions.  I have provided the source code and Google play download via my personal Github and Google accounts respectively.  Adding your own magnetic stripe data to SwipeYours may work, but it is not a supported payment method by Visa or your issuing bank.  


Visa-MSD Payment example:

Applications implementing HCE send and receive data with a POS (Point Of Sale) terminal using a byte array abstraction called an APDU (Application Protocol Data Unit).

The MainActivity of SwipeYours logs these APDU exchanges to the screen so developers can better understand how the process works.  Below I’ll show the data from a typical Visa-MSD transaction performed by SwipeYours.  If you want to better understand the values in the hex strings below, the source code to the SwipeYours PaymentService has lots of detailed comments.

POS SwipeYours

PaymentService Received PPSE select: 00A404000E325041592E5359532E444446303100

Here the POS sent our app a PPSE (Proximity Payment Service Environment) select.  This is the first APDU sent in any payment transaction.  It asks the payment device to send a list of supported payment types.

The AID (Application IDentifier) in the request is highlighted in red. It's the ASCII string 2PAY.SYS.DDF01 represented in hexadecimal.  If you are not using HCE (Host Card Emulation), these select statements would be delivered to a JavaCard applet registered to that AID.  JavaCard is a subset of Java designed for low power chips.

With HCE, there is no requirement to use JavaCard applets.  The PaymentService entry in our Android manifest specifies a list of AID values that should be directed to our service.


POS SwipeYours

Response: 6F23840E325041592E5359532E4444463031A511BF0C0E610C4F07A00000000310108701019000

Our PPSE response contains a single AID value letting the POS know that we only support Visa credit and debit transactions.  


POS SwipeYours

PaymentService Received Visa-MSD select: 00A4040007A000000003101000

Now the POS selects the only payment AID that we offered above.


POS SwipeYours

Response: 6F1E8407A0000000031010A513500B56495341204352454449549F38039F66029000

SwipeYours sends Visa-MSD select response. For trivia sake, the second value in red above is the ASCII string VISA CREDIT represented in hexadecimal.

POS SwipeYours

PaymentService Received GPO: 80A80000048302800000

POS sends the Get Processing Options (GPO) command.


POS SwipeYours

Response: 80060080080101009000

Payment devices supporting Visa transactions can support different payment protocols (Visa uses the term "path" instead of protocol).  Our response lets the POS terminal know that we only support Visa-MSD.   Our GPO response above lets the POS know that we only support Visa -MSD.


POS SwipeYours

PaymentService Received READ REC: 00B2010C00

POS sends Read Record command. It's a short command requesting the payment data.


POS SwipeYours

Response: 701557134046460664629718D16101210000018100000F9000

Here SwipeYours sends your credit card data to the terminal in the read record response. The format of the data is known as track 2 equivalent data. Its a fairly straight forward transformation of the track 2 portion of the card's magstripe data. You replace the '=' with a valid hex digit 'D' and you add a single 'F' to the end if needed to create an even number of hex digits. The extra 'F' digit was necessary in this example, because each hex value is 4 bits of binary data and we need an even number of hex digits to convert to a whole number of 8-bit bytes.


Here is the track 2 data that was used to create the APDU above:

;4046460664629718=16101210000018100000?


The track 2 syntax is:

  • Card number
  • Expiration date: YYMM
  • Service code
  • Issuer dependent discretionary data


How to decipher the service code, XXX:

  1. Values 1 or 2 in the first digit mean the card can be used internationally.  Values 6 or 7 say the card is restricted to the issuer's country or some group of countries. 2 and 7 indicate that the card has a built in chip for tap payments and the magstripe data on these cards will probably not work with SwipeYours.
  2. The middle digit specifies who provides authorization processing.  Value 0 means normal, 2 is by the issuer or their processor, and 4 is the issuer unless a bilateral agreement applies.
  3. The last digit specifies allowed services and pin requirements.  Values 0, 1 and 6 mean that there are are no restrictions. Values 2, 5 and 7 are restricted to goods and services (i.e. no cash). 3 is ATM only. 4 is cash only /// Values 1, 2 and 4 indicate that no pin is required. Values 0, 3 and 5 indicate that a pin is required. 6 and 7 say the pin is required when a pin input device is present.