Contactless Transactions the Easy way

Everybody knows what a pain in the “back end” chip cards can be. Insert your card, tap your foot, pray the chip misfires so you can go ahead and swipe… Okay, that might be overstating it. But you know what I mean. Standard “contact EMV” frustrates customers (and has driven many a payment-app developer to the brink of drink) because it’s slow, complex, and unforgiving.

All that changes with contactless EMV. A “tap and go” transaction typically takes less than 500 milliseconds, and can be done with your phone (which is a lot more convenient than whipping out a plastic card). And guess what? It’s easier for developers, too. You can execute a contactless transaction in just a few lines of code. And you can do it all in JavaScript, if you want to; no need to fire up Visual Studio or Xcode. No compilation cycle, no linked libraries or messy dependencies. Talk about rapid development!

Consider the following 4 lines of JavaScript:

START_CONTACTLESS_TRANSACTION = "5669564f746563683200024000211e9a031704129c01009f02060000000001009f03060000000000009f21031536314c6c";
dataObject =(s,d,t)=> ( {source:s,data:d,type:t } );
var dObj = dataObject('client', START_CONTACTLESS_TRANSACTION ,'raw command');
socket.emit( 'echo', dObj );  // send the command

Believe it or not, these 4 lines will let you run a contactless EMV transaction using any of the compact, low-cost ViVOpay VP3300-series card readers available from ID TECH (such as the VP3300 shown above). Once these 4 lines execute, you can hold your phone (or a tap-card) next to the reader, and the reader will beep, kick off an NFC conversation, then output the transaction data (over USB).

Of course, in order for these lines of code to actually do anything, you first need to install the Node script that talks to the USB device (and Node JS itself) as described in my last post. (Download the runnable script along with Node itself in one archive here.) And you’ll probably want to run the above lines of code from Firefox or Chrome, using the ViVOpay Explorer app available here.

What is ViVOpay Explorer? It’s just a very simple HTML page containing a JS console and some pre-loaded commands. The web page consists of 50 lines of HTML and 400 lines of JavaScript (including the TLV parser routine I talked about in an earlier post). When you’re using ViVOpay Explorer in Chrome or Firefox (don’t try it in Internet Explorer), you’ll see a browser page that looks something like this:

b2ap3_thumbnail_consolescreenshot1.png

The grey area, under “Console,” is a live REPL (in this case, a jQuery Terminal) in which you can execute arbitrary JavaScript code, in real time.  To the upper right, you’ll find text areas (showing “http://localhost” and “9901”) next to a Connect button. Pressing the button causes ViVOpay Explorer to look for a Websocket connection on 127.0.0.1, port 9901. The bottom half of the page is a log area where various kinds of status information (e.g. USB traffic readouts) appear in real time, in response to commands.

Clicking the small question mark next to the dropdown menu brings up a small Help panel telling you how to make use of ViVOpay Explorer. In a nutshell, here’s what you need to do:

1. Download the Node driver (11 meg Zip archive) and unpack it to your local Windows machine. (It comes with a copy of node.exe, plus scripts and supporting files; everything you need is in the archive. But don’t try to run it on Mac or Linux. It’s a Windows-specific build of Node.)

2. In the unpacked Zip folder, find start.bat and run it. (Keep it running. Don’t close its window.) This starts the Node-based driver that talks to USB, and also starts up a Websockets server.

3. Plug a ViVOpay VP3300-series credit card reader (UniPay III, BTPay Mini, etc.) from ID TECH into your USB drive. The Node driver will auto-detect the device and connect to it.

4. Click the Connect button (above, right). You should see a message below: “Connected to the driver on port 9901.” This means your browser is now talking to the driver via Websockets on http://localhost:9901.

5. Select the Ping reader command from the dropdown menu. This will execute a script that pings the connected USB device.

If Step 5 succeeds, you should see a logged response (on the main screen, under the Console) that looks something like:

OUT:
{
“source”:”client”
“data”:”5669564f74656368320018010000b3cd”
“type”:”raw command”
}

IN:
{
“source”:”usb”
“data”:”5669564f74656368320018000000fa83″
“type”:”data”
}

These are the JSON messages that went out (to the USB device) and in (to the browser), over Websockets, during the ping. Notice that the bespoke JSON objects follow a very simple schema: There are three fields, called source, data, and type. For outbound (browser to driver) messages, the source property should have a value of “client”; the data field will contain a hex string, representing the command being sent to the USB device; and the type field will contain “raw command,” to alert the driver to the fact that the data command should be passed straight through to the USB device.

Sending a JSON object (or any other message) from browser to driver is easy. In your browser code, just do socket.emit( 'echo', myObject ). To receive data from the driver, just set a listener: socket.on( 'message', myListener ), where myListener can be an anonymous function, like function( m ) { log( m ); }. Obviously, you should set the listener first, before sending anything to the driver. Otherwise, the driver could respond before you’re ready to grab the response.

How to Start a Contactless Transaction: Strategy 1

To put the reader in NFC mode and make it read a contactless card or wallet, you can simply issue the appropriate firmware command (as a hex string):

START_CONTACTLESS_TRANSACTION = "5669564f746563683200024000211e9a031704129c01009f02060000000001009f03060000000000009f21031536314c6c";
dataObject =(s,d,t)=> ( {source:s,data:d,type:t } ); // a function to create data objects
var dObj = dataObject('client', START_CONTACTLESS_TRANSACTION ,'raw command');
socket.emit( 'echo', dObj );  // send the command

The first line declares the command as a string. To know how to construct such commands, you’ll want to consult the technical documentation for your reader. (You can download ID TECH documentation from the Downloads Page on the ID TECH Public Knowledge Base.) This particular command contains a default Amount of $1.00 and a date that’s (by now) out of date, so obviously, this code (while it does work!) should be considered proof-of-concept quality, not production quality. If this were production code, you’d want to craft it to contain a real Amount, the actual Transaction Date, etc.

Getting the command to the reader is a two-step process: First, you need to send it to the driver in a JSON object via Websockets; then let the driver convey it to the USB reader. Packaging the command in a JSON object the driver can consume is super-easy: See the 2nd and 3rd lines of code above. The fourth line emits the data object onto the socket.

Again, bear in mind, before doing any of this, you should attach a listener (or callback) to the socket, so you can process the response from the reader. That can be as simple as:

socket.on( 'message', ( m )=>{ log( m ) } );

How to Start a Contactless Transaction: Strategy 2

There’s a second strategy for getting the transaction kicked off. Recall how we said before that the kickoff is a two-step process:

1. Send a message from browser to driver.

2. Get the message from driver to USB device.

The “message” is a big ugly firmware hex string.

The “driver,” in this case, is just a Node script (about 350 lines of JavaScript) running in Node’s process space. Source code for the driver is in the driver folder. Look for usb-websocket-shim.js.

You can modify the driver code very easily to contain (already cached in a String) the magic firmware command that kicks off the transaction (or a function that crafts the string). Doing this lets you hide the magic firmware command behind an API of your choosing, so that your payment app (represented here by ViVOpay Explorer) only has to send a very simple message (of your choosing) to the driver, to begin the transaction.

What’s the point of doing that? What’s the point of hiding the firmware command in the driver itself?

I can think of a couple pretty good reasons for doing this.

First, it makes sense to remove device dependencies from the payment app, and put them in the device driver, which is logically much closer to the device. Think about it. Do you really want your payment app to have intimate knowledge of firmware commands? Wouldn’t it be better to free the app from having intimate knowledge of hardware? Shouldn’t the app just know about business logic?

Secondly: Pushing the magic command down into the driver lets you write your own API to the command, giving you the opportunity to introduce a much simplified API that the payment app can consume. (See an example below.)

Beyond this, there’s scope reduction to consider. As a practical matter, most payment apps and point-of-sale systems are written in such a way that the POS or payment app provides little more than a transaction amount to the transaction subsystem; and the transaction subsystem (which talks to the card reader) hands back an authorization code and printable receipt info. Sensitive card data never reaches the payment app.

So in the “scope reduction” case, what you’d want to to is have code inside the driver that responds to incoming Websockets messages like this:

shim.on( 'message', ( msg )=> {
   if ( msg.source == 'POS' && msg.type == 'start contactless transaction' ) {
      sendDataCommand( START_CONTACTLESS_TRANSACTION, deviceHandle );
   }
}

And this is, in fact, already implemented in our Node driver. (See my previous post for a listing of the driver code.) Which means that all we need to do to kick off a contactless transaction from the payment app (or ViVOpay Explorer) is do:

    var dObj = dataObject( 'POS', null, 'start contactless transaction');
    socket.emit( 'echo' , dObj );

In ViVOpay Explorer, I’ve wrapped all the necessary code (including code for a callback that parses the TLV data from the transaction and displays it onscreen) in a function called startContactlessTransaction().

Remember that for more information on how the Node-based driver enables USB connectivity, you can consult my earlier posts (scroll down for links). Also be sure to consult ID TECH’s free Downloads page for additional product documentation, white papers, SDK doc, etc.

To get an eval kit containing one of ID TECH’s card readers, call us any time at the number shown below:

Toll Free Number
1-800-984-1010

Leave a comment

You must be logged in to post a comment.