Publicación técnica
Transacciones sin contacto de forma sencilla
Todo el mundo sabe lo molestas que pueden llegar a ser las tarjetas con chip. Introduces la tarjeta, das golpecitos con el pie, rezas para que el chip falle y poder pasarla por la banda… Vale, quizá esté exagerando. Pero ya me entiendes. El EMV de contacto estándar frustra a los clientes (y ha llevado a más de un desarrollador de aplicaciones de pago al borde de la desesperación) porque es lento, complejo e implacable.
Todo esto cambia con el EMV sin contacto. Una transacción «tap and go» suele tardar menos de 500 milisegundos y puede realizarse con el móvil (mucho más cómodo que sacar una tarjeta de plástico). ¿Y sabes qué? También es más fácil para los desarrolladores. Puedes ejecutar una transacción sin contacto en apenas unas líneas de código. Y, si quieres, puedes hacerlo todo en JavaScript; no hace falta abrir Visual Studio ni Xcode. Sin ciclos de compilación, sin librerías enlazadas ni dependencias engorrosas. ¡Eso sí que es desarrollo rápido!
Fíjate en las siguientes 4 líneas de JavaScript:
Aunque no te lo creas, estas 4 líneas te permitirán ejecutar una transacción EMV sin contacto utilizando cualquiera de los lectores de tarjetas compactos y económicos de la serie VP3300 disponibles de ID TECH (como el VP3300 que se muestra arriba). Una vez ejecutadas estas 4 líneas, podrás acercar el móvil (o una tarjeta contactless) al lector, y este emitirá un pitido, iniciará una comunicación NFC y enviará los datos de la transacción (a través de USB).
Por supuesto, para que estas líneas de código hagan algo, primero hay que instalar el script de Node que se comunica con el dispositivo USB (y el propio Node JS) como se explica en mi última entrada. (Descarga el script ejecutable junto con el propio Node en un solo archivo aquí). Y probablemente querrás ejecutar las líneas de código anteriores desde Firefox o Chrome, usando la aplicación disponible aquí.
¿Qué es ViVOpay Explorer? No es más que una página HTML muy sencilla que contiene una consola JS y algunos comandos precargados. La página web se compone de 50 líneas de HTML y 400 líneas de JavaScript (incluida la rutina del analizador TLV de la que hablé en una entrada anterior). Cuando uses ViVOpay Explorer en Chrome o Firefox (no lo intentes con Internet Explorer), verás una página del navegador parecida a esta:
El área gris, bajo «Console», es un REPL en vivo (en este caso, un jQuery Terminal) en el que puedes ejecutar código JavaScript arbitrario en tiempo real. Arriba a la derecha encontrarás campos de texto (que muestran «http://localhost» y «9901») junto a un botón Conectar . Al pulsar el botón, ViVOpay Explorer busca una conexión Websocket en 127.0.0.1, puerto 9901. La mitad inferior de la página es un área de registro donde aparecen, en tiempo real, distintos tipos de información de estado (por ejemplo, lecturas del tráfico USB) en respuesta a los comandos.
Al hacer clic en el pequeño signo de interrogación que hay junto al menú desplegable, se abre un panel de ayuda que te explica cómo utilizar ViVOpay Explorer. En resumen, esto es lo que tienes que hacer:
1. Descarga el driver de Node (archivo Zip de 11 MB) y descomprímelo en tu equipo Windows local. (Incluye una copia de node.exe, además de scripts y archivos de soporte; todo lo que necesitas está en el archivo. Pero no intentes ejecutarlo en Mac o Linux. Es una compilación de Node específica para Windows).
2. En la carpeta Zip descomprimida, localiza start.bat y ejecútalo. (Déjalo en ejecución. No cierres su ventana). Esto inicia el driver basado en Node que se comunica con el USB, y también arranca un servidor de Websockets.
3. Conecta un lector de tarjetas de la serie VP3300 (UniPay III, BTPay Mini, etc.) de ID TECH a tu puerto USB. El driver de Node detectará automáticamente el dispositivo y se conectará a él.
4. Haz clic en el botón Connect (arriba a la derecha). Debería aparecer un mensaje abajo: «Connected to the driver on port 9901». Esto significa que tu navegador ya se está comunicando con el driver mediante Websockets en http://localhost:9901.
5. Selecciona el comando Ping al lector en el menú desplegable. Esto ejecutará un script que envía un ping al dispositivo USB conectado.
Si el paso 5 funciona, deberías ver una respuesta registrada (en la pantalla principal, debajo de la Consola) parecida a esta:
OUT:
{
"source":"client"
"data":"5669564f74656368320018010000b3cd"
"type":"raw command"
}
IN:
{
"source":"usb"
"data":"5669564f74656368320018000000fa83″
"type":"data"
}
Estos son los mensajes JSON que se enviaron (al dispositivo USB) y se recibieron (en el navegador), a través de Websockets, durante el ping. Observa que los objetos JSON personalizados siguen un esquema muy sencillo: hay tres campos, denominados source, data y type. Para los mensajes salientes (del navegador al controlador), la propiedad source debe tener el valor «client»; el campo data contendrá una cadena hexadecimal que representa el comando enviado al dispositivo USB; y el campo type contendrá «raw command», para indicar al controlador que el comando de data debe transmitirse directamente al dispositivo USB.
Enviar un objeto JSON (o cualquier otro mensaje) desde el navegador al controlador es muy sencillo. En el código de tu navegador, basta con hacer socket.emit( 'echo', myObject ). Para recibir datos del controlador, basta con configurar un listener: socket.on( 'message', myListener ), donde myListener puede ser una función anónima, como function( m ) { log( m ); }. Lógicamente, debes configurar el listener primero, antes de enviar nada al controlador. De lo contrario, el controlador podría responder antes de que estés listo para capturar la respuesta.
Cómo iniciar una transacción sin contacto: Estrategia 1
Para poner el lector en modo NFC y hacer que lea una tarjeta o billetera sin contacto, basta con enviar el comando de firmware adecuado (como cadena hexadecimal):
La primera línea declara el comando como una cadena. Para saber cómo construir este tipo de comandos, conviene consultar la documentación técnica de tu lector. (Puedes descargar la documentación de ID TECH desde la Página de descargas de la Base de Conocimientos Pública de ID TECH.) Este comando concreto contiene un importe predeterminado de 1,00 $ y una fecha que (a estas alturas) está caducada, por lo que, obviamente, este código (¡aunque funciona!) debe considerarse como prueba de concepto, no apto para producción. Si fuera código de producción, querrías diseñarlo para que contuviera un Importe real, la Fecha de Transacción real, etc.
Hacer llegar el comando al lector es un proceso en dos pasos: primero, debes enviarlo al controlador en un objeto JSON mediante Websockets; después, dejar que el controlador lo transmita al lector USB. Empaquetar el comando en un objeto JSON que el controlador pueda procesar es facilísimo: consulta la 2.ª y 3.ª líneas de código de arriba. La cuarta línea emite el objeto de datos al socket.
De nuevo, ten en cuenta que, antes de hacer nada de esto, debes asociar un listener (o callback) al socket, para poder procesar la respuesta del lector. Puede ser tan sencillo como:
Cómo iniciar una transacción sin contacto: Estrategia 2
Existe una segunda estrategia para poner en marcha la transacción. Recuerda que antes dijimos que el arranque es un proceso de dos pasos:
1. Enviar un mensaje del navegador al controlador.
2. Hacer llegar el mensaje del controlador al dispositivo USB.
El «mensaje» es una larga y poco vistosa cadena hexadecimal de firmware.
El «controlador», en este caso, no es más que un script de Node (unas 350 líneas de JavaScript) que se ejecuta en el espacio de procesos de Node. El código fuente del controlador se encuentra en la carpeta driver. Busca usb-websocket-shim.js.
Puedes modificar muy fácilmente el código del controlador para que contenga (ya almacenado en una String) el comando mágico de firmware que inicia la transacción (o una función que construya esa cadena). Hacer esto te permite ocultar el comando mágico de firmware detrás de una API a tu elección, de modo que tu aplicación de pagos (representada aquí por ViVOpay Explorer) solo tenga que enviar al controlador un mensaje muy sencillo (a tu elección) para iniciar la transacción.
¿Qué sentido tiene hacer eso? ¿Qué sentido tiene ocultar el comando de firmware en el propio controlador?
Se me ocurren un par de razones bastante buenas para hacerlo.
En primer lugar, tiene sentido eliminar las dependencias de hardware de la aplicación de pagos y trasladarlas al controlador del dispositivo, que lógicamente está mucho más cerca del dispositivo. Piénsalo. ¿De verdad quieres que tu aplicación de pagos tenga un conocimiento detallado de los comandos de firmware? ¿No sería mejor liberar a la aplicación de tener un conocimiento detallado del hardware? ¿No debería la aplicación ocuparse únicamente de la lógica de negocio?
En segundo lugar: trasladar el comando mágico al controlador te permite escribir tu propia API para dicho comando, dándote la oportunidad de introducir una API mucho más simplificada que la aplicación de pagos pueda consumir. (Más abajo verás un ejemplo).
Además, hay que considerar la reducción del alcance. En la práctica, la mayoría de las aplicaciones de pago y los sistemas de punto de venta están diseñados de manera que el POS o la aplicación de pagos proporciona poco más que un importe de transacción al subsistema de transacciones; y ese subsistema (que se comunica con el lector de tarjetas) devuelve un código de autorización y la información del recibo imprimible. Los datos sensibles de la tarjeta nunca llegan a la aplicación de pagos.
Así pues, en el caso de la «reducción de alcance», lo que querrías es tener dentro del controlador un código que responda a mensajes entrantes de Websockets como este:
Y, de hecho, esto ya está implementado en nuestro controlador Node. (Consulta mi publicación anterior para ver el listado del código del controlador.) Lo que significa que todo lo que tenemos que hacer para iniciar una transacción sin contacto desde la aplicación de pagos (o ViVOpay Explorer) es:
En ViVOpay Explorer, he envuelto todo el código necesario (incluido el código de un callback que analiza los datos TLV de la transacción y los muestra en pantalla) en una función llamada startContactlessTransaction().
Recuerda que, para más información sobre cómo el controlador basado en Node habilita la conectividad USB, puedes consultar mis publicaciones anteriores (desplázate hacia abajo para ver los enlaces). No dejes tampoco de consultar la página de descargas gratuita de ID TECH para obtener documentación adicional de productos, white papers, documentación del SDK, etc.
Para obtener un kit de evaluación con uno de los lectores de tarjetas de ID TECH, llámanos en cualquier momento al número que aparece a continuación:
