VTOL CLIENT NET - Manual librería 2.0.x.x






REVISIONES


Fecha

Revisión

Observaciones

05/09/2012

1.0

Generación del documento

06/05/2015

1.1

Agregado de modalidad de uso "VirtualVtolClient"

27/03/2017

1.2

Soporte .NET 4

05/08/2019

1.3Soporte multiempresa, agregado de campo 0 o ID/Código de compañía
10/09/20201.4Agregado de ejemplo para la modalidad de uso estático



CONTENIDO




1. Introducción

1.1 Introducción

VTOL cuenta con una librería desarrollada en Java la cual provee las funciones necesarias para realizar autorizaciones de diversos tipos de transacciones, además de las transacciones de control propio y común a cualquier implementación de VTOL Server.
La librería es en realidad un módulo cliente que se comunica vía TCP/IP con el servidor de transacciones (VTOL).
A continuación se hará una descripción de los contenidos de la librería que ayudarán a comprender su funcionamiento. Antes se hará una introducción a la Mensajería de VTOL.

1.2 Protocolo de comunicación POS - VTOL

Se establece un protocolo de comunicación para la interacción POS - VTOL, el cual se denomina "Protocolo VTOL" o "llavecitas". Dicho protocolo se basa en un esquema recursivo compuesto por campos y separadores. A continuación se provee una especificación detallada de su estructura junto con los consecuentes diagramas para un mejor entendimiento.
Para implementar esta mensajería, VTOL provee una librería en el cual se encuentra la declaración de funciones y las definiciones de constantes y tipos necesarias. La librería es en realidad un módulo cliente que se comunica vía TCP/IP con el servidor de transacciones VTOL. El cliente podrá implementar esta mensajería sin utilizar la librería, pero deberá respetar el formato de la misma.

El formato del protocolo VTOL se basa en la siguiente estructura:

Header

Mensaje

Longitud del mensaje (4 bytes)

Indica si el mensaje requiere respuesta o no (2 bytes)

Ejemplo: {25:20020426172836;1:5;2:1;27:00;26:ISO8583;28:Aprobado}


La estructura posee dos partes separadas que son el Header y el Mensaje propiamente dicho.

1.2.1 Header

Dentro del Header viaja información específica del mensaje que se encuentra a continuación del mismo, como ser su longitud y si requiere o no una respuesta. Para ello fueron destinados 6 bytes que se distribuyen de la siguiente manera: los primeros 4 bytes son destinados a la longitud (expresado en hexadecimal, con el último byte como el más significativo) y los últimos 2 indican la necesidad de recibir o no una respuesta (expresado en hexadecimal, con el último byte como el más significativo) 
Un ejemplo de lo explicado anteriormente podría ser el siguiente:


HEADER

Longitud del mensaje

Requiere respuesta

A101

01


En este ejemplo la longitud del mensaje será:


0001   0000   0001   1010
   1         0         1         A         = 212 + 24 + 23 + 21 = 4122


Nota: Se ordena la longitud A101colocando el byte más significativo a la izquierda, con lo cual resulta: 101A.

1.2.2 Mensaje

A continuación del Header se encuentra el Mensaje propiamente dicho, el cual contiene la información que el emisor desea transmitirle al sistema receptor. 
La estructura de los mensajes son que se muestra en la siguiente ilustración:


  1. Simple



El mensaje viajará encerrado entre "{ }" (llaves). Cada campo del mismo se compondrá de la siguiente manera: los primeros dígitos indicarán el número de campo y a partir de los ":" (dos puntos) se encontrará el valor del campo. Los campos viajan separados por ";" (punto y coma).


Ejemplo:

{1:5;2:1;26:ISO8583;27:00;28:Aprobado}

El mensaje anterior posee 5 campos, los cuales se identifican con los números 1, 2, 26, 27 y 28. A continuación de cada uno de ellos (luego del separador ":") se encuentra el valor de cada campo. En el ejemplo presentado, para el campo 1 el valor es "5", para el campo 2 el valor es "1" y así sucesivamente.

1.2.3 Escape de caracteres

Para realizar el escape de un caracter especial se deberá usar "\" inmediatamente antes del carácter a escapar.


Ejemplo:

A continuación se presenta un campo cuyo valor incluye el carácter ; y se muestra como escapar el mismo:

{1:14\;56} 

1.3 Tipos de mensajes


  • Solicitud de Autorización, este mensaje lo genera el punto de venta cada vez que se requiere autorizar una operación. Se envían los datos requeridos de acuerdo al tipo de operación. Adicionalmente se envía información de control de mensajes.
  • Respuesta de Autorización, este mensaje lo genera VTOL para el punto de venta, en respuesta a cada Solicitud de Autorización y contiene información tanto de resultado de la operación como de control.
  • Confirmación (Tercer mensaje), este mensaje lo genera el punto de venta para informar como ha terminado de procesar la respuesta de una operación. No se genera respuesta para este mensaje.
  • Solicitud de Control de Pendientes, este mensaje lo genera el punto de venta, para asegurar que ha confirmado el estado de todas las operaciones.
  • Respuesta de Control de Pendientes, este mensaje lo genera VTOL para el punto de venta, en respuesta a cada Solicitud de Control de Pendientes e informa si existen operaciones pendientes de confirmación.

1.4 Estructura de los mensajes

Para referencia sobre la estructura de cada uno de los tipos de mensajes mencionados con antelación, consultar el documento "Mensajería POS – VTOL" ubicado en el repositorio del producto VTOL.

1.5 Mecanismo de "Tercer Mensaje"

1.5.1 Descripción

El tercer mensaje es un mecanismo para asegurar la consistencia y concordancia de las transacciones realizadas que son registradas en VTOL.


El flujo de mensajes es el siguiente: 
Se envía un requerimiento de autorización a VTOL. Si el requerimiento es autorizado, el POS guarda el ID de la trx recibido en la respuesta.
Una vez conocido el estado final de la trx en el POS (es decir si la misma se procesa o bien se anula), el POS envía el 3er Msg con el CIT correspondiente, informando a VTOL el destino que tuvo la trx en cuestión. Las posibilidades en este caso son COMMIT o ROLLBACK.


Cada transacción aprobada debe ser confirmada o reversada con un tercer mensaje. Si se envía una transacción y no se confirma o reversa, a la próxima transacción que se envíe VTOL responderá que aún existe una transacción pendiente y hasta que no se envíe el tercer mensaje correspondiente no se podrá tratar la misma.


El tercer mensaje puede enviarse "embebido" en un requerimiento. Así en una misma transacción se enviará un requerimiento y la confirmación o reverso de una transacción pendiente. 
Importante: Una operación de venta en el POS podrá tener una o más transacciones de pago electrónico validadas por intermedio de VTOL (trx VTOL). 
Para el envío del 3er Msg debe establecerse una condición por la que se da por finalizada la venta en el POS. Esta condición podría ser el registro de la transacción o la impresión del comprobante, pero se deberá tener en cuenta que para confirmar una trx VTOL, se tiene que asegurar que la venta que contiene esa trx sea procesada por el POS, que se emitan los comprobantes correspondientes, etc. 
Por otro lado, si la venta en el POS se registra como anulada o directamente no se registra (ya sea por pedido del operador, por un error del Controlador Fiscal, etc) debemos estar seguros de que en el 3er Msg de las trx correspondientes vaya la orden de ROLLBACK para esta trx.

1.5.2 Control de operaciones pendientes (Mensaje "Checkpending")

Los mensajes de confirmación no son respondidos por VTOL Server. Además estos mensajes pueden ser embebidos en futuros mensajes de pedido de autorización esto da lugar a que algunas operaciones queden pendientes de confirmación entre dos transacciones distintas. La última transacción antes de el cierre o caída del punto de venta podría ocasionar dicha contingencia ya que no existiría un futuro mensaje de confirmación o pedido de autorización con la confirmación embebida. 
Para asegurar que ninguna transacción quedó pendiente de confirmación en VTOL se deberán aplicar los siguientes pasos:


  1. El punto de venta enviara un mensaje de chequeo de pendientes "CheckPending" a VTOL.
  2. VTOL Server verificará la existencia de transacciones pendientes en su base, en caso de existir responderá el mensaje con el identificador (ID) de la transacción pendiente.
  3. El punto de venta deberá confirmar dicha transacción (Commit/Rollback) y enviar un nuevo mensaje de chequeo de pendientes. Nótese que esto se podría realizar en un solo paso, enviando un mensaje de chequeo de pendientes con la confirmación embebida.
  4. Se deberá repetir el proceso hasta tanto existan transacciones pendientes en VTOL. Cuando ya no existan VTOL responderá APROBADA.




1.5.3 Tercer mensaje con múltiples operaciones

También existe la posibilidad de deshabilitar el chequeo de pendientes. Esto permite realizar un conjunto de transacciones que podrán ser confirmadas o reversadas posteriormente. Por ejemplo:


La implementación del Tercer Mensaje y Mensajes de Control de Pendientes, dependerá del tipo de integración que se realiza en el Punto de Venta, y quedará a elección del cliente utilizar algunos, o todos los Mensajes descriptos. 

Los campos que debe contener el tercer mensaje son los siguientes:

  • TransactionTypeFieldId debe tener el valor UnSyncCompletion
  • DateTimeFieldId
  • NodeFieldId (debe ser el valor recibido en este mismo campo en el mensaje de respuesta de la transacción original que se intenta completar)
  • TrxIdFieldId (debe ser el valor recibido en este mismo campo en el mensaje de respuesta de la transacción original que se intenta completar)
  • TrxActionFieldId (este campo define si lo que se quiere hacer es confirmar la transacción (UnSyncCommit), o bien reversarla (Rollback))

2. Uso de la librería

2.1 Implementación


Se pueden adoptar diferentes políticas al momento de implementar la librería cliente. 
Una de ellas es implementarla en cada punto de venta, por lo cual se le deberá incorporar la lógica suficiente a cada uno para que puedan manejar la librería y mediante la misma comunicarse con VTOL Server.

  • Incorporándola en cada punto de venta




Un ejemplo de este uso sería una línea de cajas de un supermercado. 
Otra forma sería centralizar todo en un módulo cliente al cual se le incorporaría la lógica para usar la librería y mediante la misma comunicarse con VTOL Server. De esta manera la implementación no impactaría en los puntos de venta.

  • Implementándola en un módulo cliente



Un ejemplo de esta modalidad sería el uso de la librería en un sitio WEB donde no necesariamente existen nodos estáticos.

2.2 Modalidades

Como se explicó con anterioridad la librería cuenta con dos modalidades, por lo tanto, en Java existen dos implementaciones:

  1. StaticVTOLClient
    1. Esta implementación está orientada a ser utilizada por cada punto de venta donde el Originador y el Nodo sean fijos.
  2. DinamicVTOLClient
    1. Esta implementación está orientada a concentrar varios puntos de venta donde el Originador sea fijo y el nodo se obtenga de forma dinámica entre la librería y VTOL (Se hace por medio de un mensaje HandShake).
  3. VirtualVTOLClient
    1. Esta implementación está orientada a ser utilizada por varios puntos de venta o en un ambiente de e-commerce donde el Originador sea fijo y VTOL gestione la asignación de nodos (Locales virtuales).

2.2.1 Pasos para el uso

Para utilizar la librería java hay que seguir los siguientes pasos:

  1. crear una instancia de VTOLClient.
  2. cargarle los parámetros correspondientes.
  3. inicializar el cliente
  4. tomar un nodo
  5. construir una transacción.
  6. enviar el mensaje.
  7. devolver el nodo.

2.2.2 Parámetros posibles de inicialización

NameDescription
DefaultTransactionStatus
  1. Estado por defecto de las transacciones asociadas a los nodos dinamicos creados si no se usa el HandShake. Valores posibles C = Commit, R = Rollback

Valor por defecto 'C'.

Encrypter
  1. Algoritmo de encriptacion. Valores posibles DES o DESede
EncrypterKey
  1. Clave de encriptacion. 8 bytes para DES o 24 bytes para DESede
HostIp
  1. Ip de vtol
HostPort
  1. Port de vtol
InitialNodeNumber
  1. Número de nodo inicial a partir del cual se crean los nodos dinámicos (se recomienda usar 1). Este valor debe ser > 0.

Nota: Usar 0 cuando se usa con VTOL NT

ResponseTimeout
  1. Tiempo maximo en (milisegundos) de espera para un respuesta de vtol server antes de salir por timeout. Superado este tiempo se lanza la excepcion VtolClientException.

Valor por defecto 30000.

CompanyIdID o Código de compañía. Al agregar éste parámetro, entonces se enviará el ID o código de compañía en cada mensaje hacia VTOL. De no agregarse, entonces no se envía.
StoreId
  1. StoreId
TimeOutConnectionHost
  1. Tiempo maximo en (milisegundos) de espera para establecer una conexion con vtol server. Superado este tiempo se lanza la excepcion VtolClientException.

Valor por defecto 20000.

TimeOutExpirationNode
  1. Tiempo maximo en (milisegundos) que esperara la libreria para liberar un nodo que esta en uso. Trascurrido el mismo, la libreria lo liberara automaticamente.

Valor por defecto 600000.

Nota:Solo para el uso de DinamicVtolClient

TimeOutObtainNode
  1. Tiempo maximo en (milisegundos) de espera para obtener un nodo (esto ocurre cuando todo los nodos estan en uso). En caso de no haber nodos disponibles y se supera el tiempo establecido, se lanza la excepcion VtolClientException. (milisegundos)

Valor por defecto 30000.

Nota:Solo para el uso de DinamicVtolClient

TotalNodeNumber
  1. Cantidad total de nodos dinámicos a crear. Si este parámetro es nulo o es cero entonces se utilizará el handshake para inicializar los nodos dinámicos.

Nota:El HandShake solo es soportado con VTOL NT

UseEncryptedData
  1. Indicador de uso de encriptacion de datos. valor True para habilitar encriptacion
UseVtolClientFinder

6.Establece la utilización o no del VTOLClientFinder.

El VTOL CLIENT FINDER es una manera de determinar que acción tomar en caso de existir una transacción pendiente al momento de intentar autorizar una transacción.

Si éste parámetro está desactivado, entonces ante una respuesta de transacción pendiente, se le devolverá el control al código de la aplicación integradora.

Si éste parámetro está activado, entonces se tomará la acción (Commit o Rollback) que es determinado por el método configurado en el parámetro CLIENTFINDER

Valor por defecto False.

VtolClientFinder
  1. Clase que implementa la interfaz IVtolClientFinder. Sera invocada en caso de que el parametro UseVtolClientFinder este en True.

Nota:Por defecto se usara la implementacion DefaultVtolClientFinder la cual siempre toma la accion de realizar un commit de la transaccion pendiente



2.2.3 Interface VTOLClientFinder

Esta interface la debe implementar una clase para poder setearse como el VTOLClientFinder de la librería. Esta clase cumple con la función de determinar qué hacer si existe una transacción para cual VTOL Server no conoce su estado. Cuando VTOL Server contesta un requerimiento indicando que una transacción está pendiente, librería llama al método getTransaction() para determinar qué acción debe tomar con esta transacción. La clase seteada por default para esta función devuelve siempre "Commit". La clase que se setee como tal, deberá buscar en la base de datos de la aplicación cual es el estado de la misma y devolverlo para su correspondiente proceso.


Nota: Para mayor información recurrir a la documentación de las clases de la librería generado por el ensamblador y distribuido junto a la librería en formato XML



2.2.4 Encriptación


La librería brinda la posibilidad de encriptar los mensajes con el algoritmo DES y Triple DES utilizando la clase DES.
Para la utilización de la encriptación se deberá configurar las siguientes constantes:

  • UseEncryptedData
  • EncrypterKey
  • Encrypter


Nota: Para mayor información recurrir a la documentación de las clases de la librería generado por el ensamblador y distribuido junto a la librería en formato XML

2.3 Integración COM

La librería "VtolClientLib.dll" está desarrollada con .NET Framework para ser utiliza desde dicho entorno. No obstante, la misma se expone para ser utilizada como objeto COM.
Para poder utilizarla como objeto COM registrarla con el archivo "REG-VtolClientLib.dll.cmd".


A continuación se listan los archivos que conforman el paquete de entrega:

  • REG-VtolClientLib.dll.cmd:
    • Sirve para registrar la librería en COM
    • Se debe modificar y cambiar el path donde tienen instalado el .NET Framework 4
  • UNREG-VtolClientLib.dll.cmd:
    • Sirve para des-registrar la librería en COM
    • Se debe modificar y cambiar el path donde tienen instalado el .NET Framework 4
  • VtolClientLib.dll
    • Ensamblado .NET
  • VtolClientLib.tlb (la que deben referenciar en caso de que lo usen por referencia explícita)
    • Archivo typelib utilizado para exportar de .NET a COM. Este es el archivo que se referencia desde un proyecto, en caso de utilizar referencia explícita (Early Binding)
    • En general al registrar la librería el archivo .tlb es creado pero por cualquier eventualidad, el mismo es entregado.


Para poder ser integrada como objeto como, la librería debe ser registrar en el sistema. Esta acción se hace ejecutando "REG-VtolClientLib.dll.cmd". Nota, el archivo TLB debe estar en el mismo directorio de donde se ejecuta el comando anterior.
Una vez realizado este paso la librería ya podría ser utilizada desde cualquier IDE que invoque objetos COM.

2.4 Ejemplos de uso de la librería

Ejemplo uso de librería en modalidad estática

Esta clase administra los nodos configurados en Vtol (VTOL_NT y RS_VTOL) para el envío de transacciones de autorización según el originador configurado para este fin.

La aplicación que hace uso de la misma, debe seguir los siguientes pasos para llevar a cabo el proceso de autorización en forma correcta:

a) Seteo de parámetros: Como primer paso se deberán setear los parámetros correspondientes por medio del método setParameter, y setear el originador que se utilizará para tomar correctamente la configuración de Vtol Server.

b) Inicialización: Se deberá llamar al método init, el cual realizará la inicialización de la librería tomando los parámetros configurados en Vtol Server.

c) Nodo: se deben setear los campos correspondientes a la transacción según el nodo correspondiente.


Ejemplo

Este ejemplo muestra como crear un cliente estático.

StaticVtolClient StaticVtolClient = new StaticVtolClient();

StaticVtolClient.SetParameter(VtolClientLib.VtolParam.CompanyId, "NAPSE"); //OPCIONAL
StaticVtolClient.SetParameter(VtolClientLib.VtolParam.StoreId, "1");
StaticVtolClient.SetParameter(VtolClientLib.VtolParam.HostIp, "127.0.0.1");
StaticVtolClient.SetParameter(VtolClientLib.VtolParam.HostPort, 3000);
StaticVtolClient.SetParameter(VtolParam.TimeOutConnectionHost, 30000);
StaticVtolClient.SetParameter(VtolParam.UseVtolClientFinder, true);
StaticVtolClient.SetParameter(VtolParam.VtolClientFinder, new DefaultVtolClientFinder());
StaticVtolClient.SetParameter(VtolParam.ResponseTimeout, 30000);
/*
StaticVtolClient.SetParameter(VtolParam.UseEncryptedData, false);
StaticVtolClient.SetParameter(VtolParam.Encrypter, "DESede");
StaticVtolClient.SetParameter(VtolParam.EncrypterKey, "SynthesisSynthesisSynthe");
*/

StaticVtolClient.Init();

VtolNode vtolNode = StaticVtolClient.CreateNode("1");

vtolNode.CreateTransaction();

//NOTA: se puede utilizar los campos por medio de las constantes FieldId o bien con numeros enteros.
vtolNode.AddField(FieldId.ServerFieldId, "VTOL"); 
vtolNode.AddField(FieldId.MessageTypeFieldId, "DATA"); 
vtolNode.AddField(FieldId.Track2FieldId, "376678303661010=0910021073837"); 
vtolNode.AddField(FieldId.CVCFieldId, "1234"); 
vtolNode.AddField(FieldId.InputModeFieldId, "MSR"); 
vtolNode.AddField(FieldId.TransactionTypeFieldId, "Sale"); 
vtolNode.AddField(FieldId.AmountFieldId, "1"); 
vtolNode.AddField(FieldId.CurrencyTypeFieldId, "$");
vtolNode.AddField(FieldId.PaymentsFieldId, "1"); 
vtolNode.AddField(FieldId.PlanFieldId, "0"); 
vtolNode.AddField(FieldId.DateTimeFieldId, DateTime.Now.ToString("yyyyMMddHHmmss"));
vtolNode.AddField(FieldId.TerminalNumberFieldId, "1"); 
vtolNode.AddField(FieldId.StoreNumberFieldId, "00180");
vtolNode.AddField(FieldId.CheckPendingMsgFieldId, "False");
vtolNode.AddField(FieldId.Track1FieldId, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

//envia la trnsaccion. Es bloqueante hasta recibir la repsuesta o darse un timeout con el server
vtolNode.SendTransaction();

String responseCodeString = vtolNode.GetField(FieldId.ResponseCodeFieldId);

if ( String.Compare(responseCodeString,"ISO8583", true) == 0) 
{
	String isoResponseCodeString = vtolNode.GetField(FieldId.ISOResponseCodeFieldId);
	if ("00".Equals(isoResponseCodeString)) 
	{
		String transactionIdString = vtolNode.GetField(FieldId.TrxIdFieldId);
		vtolNode.CreateTransaction();
		vtolNode.AddField(FieldId.ServerFieldId, "VTOL");
		vtolNode.AddField(FieldId.MessageTypeFieldId, "Data");
		vtolNode.AddField(FieldId.TransactionTypeFieldId, "UnsyncCompletion");
		vtolNode.AddField(FieldId.DateTimeFieldId, "20020426172836");
		vtolNode.AddField(FieldId.TrxIdFieldId, transactionIdString);
		vtolNode.AddField(FieldId.TrxActionFieldId, "Commit");

                 //envia el tercer mensaje. No se espera respuesta.
		vtolNode.SendTransactionWithoutResponse();
	}
}


Ejemplo

Este ejemplo completo muestra como crear un cliente estático, crear una sesión, hacer una venta y cerrar la sesión de la EMV Kit.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using Newtonsoft.Json.Linq;
using VtolClientLib;

/// <summary>
/// Esta clase contiene un ejemplo ilustrativo de 
/// Crear una conexión con vtol.
/// Crear una sesión.
/// Generar una venta.
/// Cerrar Sesión.
/// 
/// Los mensajes que se utilizan puede variar entre distintas versiones de Vtol.
/// 
/// NOTA: Siempre remitirse a la documentación de integración.
/// 
/// </summary>

namespace WindowsApplication1
{
    public partial class Form : System.Windows.Forms.Form
    {
        // Configuration Emvkit for Vtol Server
        // IP Public 200.59.130.99
        // Port 43030

        // Configuración de POS
        // Store 30
        // Node/cajas 8, 9 y 10
        // IP de EMV Kit
        private String hostIp = "127.0.0.1";
        private String hostPort = "3500";
        // private String companyId = "0";
        private String storeId = "30";
        private String nodeId = "8";

        /**
         * Atributos utilizados como variables temporales.
         * */
        private String idContext = "";
        private String providerId = "";

        public Form()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Establece la conexión con Vtol.
        /// </summary>
        /// <returns></returns>

        private VtolNode createVtolNode()
        {
            StaticVtolClient StaticVtolClient = new StaticVtolClient();
            // StaticVtolClient.SetParameter(VtolClientLib.VtolParam.CompanyId, companyId);
            StaticVtolClient.SetParameter(VtolClientLib.VtolParam.StoreId, storeId);
            
            StaticVtolClient.SetParameter(VtolClientLib.VtolParam.HostIp, hostIp);
            StaticVtolClient.SetParameter(VtolClientLib.VtolParam.HostPort, hostPort);
            //StaticVtolClient.SetParameter(VtolParam.TimeOutConnectionHost, 3000);
            StaticVtolClient.SetParameter(VtolParam.UseVtolClientFinder, true);
            StaticVtolClient.SetParameter(VtolParam.VtolClientFinder, new DefaultVtolClientFinder());
            StaticVtolClient.SetParameter(VtolParam.ResponseTimeout, 30000);

            StaticVtolClient.SetParameter(VtolParam.UseEncryptedData, false);
            /*
            StaticVtolClient.SetParameter(VtolParam.Encrypter, "DESede");
            StaticVtolClient.SetParameter(VtolParam.EncrypterKey, "SynthesisSynthesisSynthe");
            */

            StaticVtolClient.Init();

            return StaticVtolClient.CreateNode(nodeId);
        }


        /// <summary>
        /// Invoca la creación de la conexión con Vtol y crea una sesión.
        /// 
        /// Ejemplo del mensaje que se envia a Vtol.
        /// Request: {25:20200110095420;1025:0;2:1;1:1;11:createSession}
        /// </summary>
       
        private VtolNode createSession()
        {
            VtolNode vtolNode = createVtolNode();
            
            vtolNode.CreateTransaction();

            vtolNode.AddField(FieldId.DateTimeFieldId, DateTime.Now.ToString("yyyyMMddHHmmss")); // fieldid = 25
            vtolNode.AddField(FieldId.TransactionTypeFieldId, "createSession");  // fieldid = 11
            vtolNode.AddField(1025, "1");   // FieldId.TransactionControlFieldId = 1025

            //envia la transacción. Es bloqueante hasta recibir la respuesta o darse un timeout con el server
            vtolNode.SendTransaction();

            return vtolNode;
        }


        /// <summary>
        /// Invoca la creación de la conexión con Vtol y envia un cierre de sesión.
        /// 
        /// Ejemplo del mensaje que se envia a Vtol
        /// Response message: {1009:{};1008:CLOSE;25:20200110104637;2:1;1:1;11:closeSession}
        /// </summary>
        /// <returns></returns>

        private VtolNode closeSession()
        {
            VtolNode vtolNode = createVtolNode();

            // Creating transaction
            vtolNode.CreateTransaction();

            vtolNode.AddField(FieldId.DateTimeFieldId, DateTime.Now.ToString("yyyyMMddHHmmss")); // fieldid = 25
            vtolNode.AddField(FieldId.TransactionTypeFieldId, "closeSession");  // fieldid = 11
            vtolNode.AddField(1008, "CLOSE");
            vtolNode.AddField(1009, "{1,2,3}");

            // Send closeSession
            //envia la transaccion. Es bloqueante hasta recibir la respuesta o darse un timeout con el server
            vtolNode.SendTransaction();

            return vtolNode;
        }

        /// <summary>
        /// Invoca la creación de la conexión con Vtol, crea un mensaje de Venta y envia el mensaje a Vtol.
        /// 
        /// </summary>
        /// <returns></returns>

        private VtolNode createSale()
        {
            VtolNode vtolNode = createVtolNode();

            // Creating transaction
            vtolNode.CreateTransaction();

            vtolNode.AddField(3, "VTOL"); //ServerFieldId
            vtolNode.AddField(4, "DATA"); //MessageTypeFieldId
            vtolNode.AddField(6, "4507990000977787"); //CardNumberFieldId
            vtolNode.AddField(7, "2005"); //ExpiringDateFieldId 
            vtolNode.AddField(8, "648"); //CVCFieldId
            vtolNode.AddField(10, "Manual"); //InputModeFieldId
            vtolNode.AddField(11, "Sale"); //TransactionTypeFieldId
            vtolNode.AddField(12, "20000"); //AmountFieldId
            vtolNode.AddField(13, "$"); //CurrencyTypeFieldId
            vtolNode.AddField(14, "1"); //PaymentsFieldId
            vtolNode.AddField(15, "0"); //PlanFieldId
            // vtolNode.AddField(22, "123456"); // authorization code
            vtolNode.AddField(23, "online");
            // message.AddField(34, "Visa"); //hostname por donde rutear según conf de emvkit
            vtolNode.AddField(71, "True"); //VersionFieldId
            vtolNode.AddField(130, "123"); //posPeriod
            vtolNode.AddField(131, "1"); //turn
            vtolNode.AddField(132, "0000000010"); //operatorCode
            vtolNode.AddField(133, "Juan Carlos Gimenez"); //operatorName
            vtolNode.AddField(134, "0000000045"); //sellerCode
            vtolNode.AddField(135, "Miguel Perez"); //sellerName
            vtolNode.AddField(136, "AS"); //attentionMode
            vtolNode.AddField(264, "0");

            vtolNode.AddField(FieldId.DateTimeFieldId, DateTime.Now.ToString("yyyyMMddHHmmss")); // fieldid = 25            

            // Sending Sale
            // Envia la transacción. Es bloqueante hasta recibir la respuesta o darse un timeout con el server
            vtolNode.SendTransaction();

            /**
             * A partir del objeto vtolNode se inspecciona la respuesta obtenida por Vtol
             * Por ejemplo: el campo 24 contiene el trxId de la transacción
             * */

            vtolNode.GetField(24);

            return vtolNode;
        }


        /// <summary>
        /// Invoca la creación de la conexión con EmvKit.
        /// Envia una Venta a Vtol.
        /// Esta acción involucra interacción con un Pinpad.
        /// 
        /// </summary>
        /// <returns></returns>

        private VtolNode createSaleWithPinpad()
        {
            VtolNode vtolNode = createVtolNode();

            // Creando transaccion
            vtolNode.CreateTransaction();

            vtolNode.AddField(11, "Sale");
            vtolNode.AddField(25, DateTime.Now.ToString("yyyyMMddHHmmss"));
            

            // Envia la transaccion. Es bloqueante hasta recibir la respuesta o darse un timeout con el server
            vtolNode.SendTransaction();

            // A partir del objeto vtolNode se inspecciona la respuesta obtenida por Vtol
            // Por ejemplo: el campo 24 contiene el trxId de la transacción
            vtolNode.GetField(24);

            // Obtengo el codigo de proveedor y el idContext de la respuesta.            
            VtolClientLib.Message resp = vtolNode.CurrentTransaction.ResponseMessage;
            
            JObject json = JObject.Parse(resp.GetField(1104).Val.TrimStart('[').TrimEnd(']'));

            string providerCode = (string)json.GetValue("provider");

            providerId = (string)json.GetValue("provider");
            idContext = resp.GetField(1103).Val; ;

            return vtolNode;
        }


        /// <summary>
        /// Invoca la creación de la conexión con EmvKit.
        /// Envia una Venta a Vtol.
        /// 
        /// Ejemplo de Transacción que se envia a Vtol para ser procesada.
        /// Request: {
        ///     1103:20200113152911136;
        ///     1102:EL;
        ///     201:[trxNumber|valor,zetaNumber|valor,accountingDate|valor];
        ///     15:0;
        ///     14:1;
        ///     13:$;
        ///     12:10000;
        ///     11:Sale;
        ///     2:1;
        ///     25:20200113152916;
        ///     1:1}
        /// 
        /// </summary>
        /// 

        private VtolNode ProcessTrx()
        {
            VtolNode vtolNode = createVtolNode();

            // Creating transaction
            vtolNode.CreateTransaction();

            vtolNode.AddField(1, "1");
            vtolNode.AddField(2, "1");
            vtolNode.AddField(11, "Sale");
            vtolNode.AddField(12, "10000");
            vtolNode.AddField(13, "$");
            vtolNode.AddField(14, "1");
            vtolNode.AddField(15, "0");
            vtolNode.AddField(201, "[trxNumber|valor,zetaNumber|valor,accountingDate|valor]");
            vtolNode.AddField(25, DateTime.Now.ToString("yyyyMMddHHmmss"));
            // providerId, idContext son seteados en el proceso SaleWithPP
            vtolNode.AddField(1102, providerId);
            vtolNode.AddField(1103, idContext);

            // Envia la transaccion.
            vtolNode.SendTransaction();

            return vtolNode;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="vtolNode"></param>
        /// <param name="separadorField"></param>
        /// <returns></returns>

        private string printResponse(VtolNode vtolNode, string separadorField = "")
        {
            string messageLog = "";

            IEnumerator fs = vtolNode.CurrentTransaction.ResponseMessage.GetFields();

            // log("-- Response Message --");

            while (fs.MoveNext())
            {
                System.Collections.DictionaryEntry dicEntry = (System.Collections.DictionaryEntry)fs.Current;

                VtolClientLib.TransactionField tf = (VtolClientLib.TransactionField)dicEntry.Value;

                if (tf.Val != null)
                {
                    messageLog = messageLog + tf.Id + ":" + tf.Val + separadorField;
                }
                else if (tf.ListValue != null)
                {
                    string list = "";
                    foreach (string value in tf.ListValue)
                    {
                        list = list + value + ",";
                    }
                    list = list.TrimEnd(',');

                    messageLog = messageLog + tf.Id + tf.ListValue.ToString() + separadorField;
                }
                else if (tf.MapValue != null)
                {
                    messageLog = messageLog + tf.Id + tf.MapValue.ToString() + separadorField;
                }

            }

            if (separadorField == "\n")
            {
                return messageLog;
            }
            else
            {
                return "{" + messageLog + "}";
            }
        }

        private void btnCreateSession_Click(object sender, EventArgs e)
        {            
            VtolNode vtolNode = createSession();

            VtolClientLib.Message responseMessage = vtolNode.CurrentTransaction.ResponseMessage;

            string response = System.Text.Encoding.ASCII.GetString(vtolNode.CurrentTransactionFormat.Format(responseMessage));

            System.Diagnostics.Debug.WriteLine(response);
        }

        private void btnSale_Click(object sender, EventArgs e)
        {
            VtolNode vtolNode = createSale();

            VtolClientLib.Message responseMessage = vtolNode.CurrentTransaction.ResponseMessage;

            string response = System.Text.Encoding.ASCII.GetString(vtolNode.CurrentTransactionFormat.Format(responseMessage));

            System.Diagnostics.Debug.WriteLine(response);
        }

        private void btnSaleWithPP_Click(object sender, EventArgs e)
        {
            createSaleWithPinpad();
        }

        private void btnProcess_Click(object sender, EventArgs e)
        {
            ProcessTrx();
        }

        private void btnCloseSession_Click(object sender, EventArgs e)
        {
            VtolNode vtolNode = closeSession();

            VtolClientLib.Message responseMessage = vtolNode.CurrentTransaction.ResponseMessage;

            string response = System.Text.Encoding.ASCII.GetString(vtolNode.CurrentTransactionFormat.Format(responseMessage));

            System.Diagnostics.Debug.WriteLine(response);
        }
    }
}


Ejemplo uso de librería en modalidad virtual

Esta clase administra los nodos configurados en Vtol (VTOL_NT y RS_VTOL) para el envío de transacciones de autorización según el originador configurado para este fin.

La aplicación que hace uso de la misma, debe seguir los siguientes pasos para llevar a cabo el proceso de autorización en forma correcta:

a) Seteo de parámetros: Como primer paso se deberán setear los parámetros correspondientes por medio del método setParameter, y setear el originador que se utilizará para tomar correctamente la configuración de Vtol Server.

b) Inicialización: Se deberá llamar al método init, el cual realizará la inicialización de la librería tomando los parámetros configurados en Vtol Server.

c) Nodo: se deben setear los campos correspondientes a la transacción según el nodo correspondiente.


Ejemplo

VirtualVtolClient virtualVtolClient = new VirtualVtolClient();

virtualVtolClient.SetParameter(VtolClientLib.VtolParam.CompanyId, "NAPSE"); //OPCIONAL
virtualVtolClient.SetParameter(VtolParam.StoreId, storeId);
virtualVtolClient.SetParameter(VtolParam.HostIp, IP);
virtualVtolClient.SetParameter(VtolParam.HostPort, 3000);
virtualVtolClient.SetParameter(VtolParam.TimeOutConnectionHost, 3000);
virtualVtolClient.SetParameter(VtolParam.ResponseTimeout, 30000);
virtualVtolClient.SetParameter(VtolParam.UseVtolClientFinder, false);
//virtualVtolClient.SetParameter(VtolParam.VtolClientFinder, new DefaultVtolClientFinder());
virtualVtolClient.SetParameter(VtolParam.UseEncryptedData, false);
virtualVtolClient.SetParameter(VtolParam.EncrypterKey, string.Empty);
virtualVtolClient.SetParameter(VtolParam.Encrypter, string.Empty);


virtualVtolClient.Init();

VtolNode _vtolNode = this.virtualVtolClient.getNode();  //POS

_vtolNode.CreateTransaction();

_vtolNode.AddField(FieldId.TransactionTypeFieldId, "Sale");
_vtolNode.AddField(FieldId.ServerFieldId, "VTOL");
_vtolNode.AddField(FieldId.MessageTypeFieldId, "DATA");
_vtolNode.AddField(FieldId.DateTimeFieldId, DateTime.Now.ToString("yyyyMMddHHmmss"));
_vtolNode.AddField(FieldId.InputModeFieldId, "MOTO");
_vtolNode.AddField(FieldId.CardNumberFieldId, "5432219380000102");
_vtolNode.AddField(FieldId.ExpiringDateFieldId, "2010");
_vtolNode.AddField(FieldId.CVCFieldId, "123");
_vtolNode.AddField(FieldId.CurrencyTypeFieldId, "$");
_vtolNode.AddField(FieldId.PaymentsFieldId, "1");
_vtolNode.AddField(FieldId.PlanFieldId, "0");
_vtolNode.AddField(FieldId.AmountFieldId, "1");


//envia la trnsaccion. Es bloqueante hasta recibir la repsuesta o darse un timeout con el server
_vtolNode.SendTransaction();

Message _responseMessage = _vtolNode.CurrentTransaction.ResponseMessage;

String _responseCodeString = _responseMessage.GetField(FieldId.ResponseCodeFieldId).Val;

if (_responseCodeString.Equals("ISO8583", StringComparison.OrdinalIgnoreCase))
{
    String _isoResponseCodeString = _responseMessage.GetField(FieldId.ISOResponseCodeFieldId).Val;

    if ("00".Equals(_isoResponseCodeString))
    {   
        //aprobada  
        String _transactionIdString = _responseMessage.GetField(FieldId.TrxIdFieldId).Val;
        _vtolNode.CreateTransaction();
        _vtolNode.AddField(FieldId.ServerFieldId, "VTOL");
        _vtolNode.AddField(FieldId.MessageTypeFieldId, "Data");
        _vtolNode.AddField(FieldId.TransactionTypeFieldId, "UnSyncCompletion");
        _vtolNode.AddField(FieldId.DateTimeFieldId, DateTime.Now.ToString("yyyyMMddHHmmss"));
        _vtolNode.AddField(FieldId.TrxIdFieldId, _transactionIdString);
        _vtolNode.AddField(FieldId.TrxActionFieldId, "Commit");

        _vtolNode.SendTransactionWithoutResponse();
    }
}


Ejemplo uso de librería en modalidad dinámica

Esta clase administra la creacion de nodos dinamicos para validar contra VTOL Server segun el originador configurado para este fin.

La aplicación que hace uso de la misma, debe seguir los siguientes pasos para llevar a cabo el proceso de autorización en forma correcta:

1) Seteo de parámetros: Como primer paso se deberán setear los parámetros correspondientes por medio del método setParameter, y setear el originador que se utilizará para tomar correctamente la configuración de Vtol Server.

2) Inicialización: Se deberá llamar al método init, el cual realizará la inicialización de la librería tomando los parámetros configurados en Vtol Server.

3) Nodo: se deben setear los campos correspondientes a la transacción, no su id.

4) Autorizacion: Se envia la transaccion para su validacion y autorizacion a VTOL Server.

5) Respuesta: Se recibe la respuesta la cual se debe analizar y procesar, incluso enviar el tercer mensaje segun corresponda.

6) Liberacion de nodo: finalizado el uso del nodo, debe ser devuelto a la lista de nodos libres que maneja la libreria (metodo FreeNode).


Ejemplo

Este ejemplo muestra como crear un cliente dinamico

//Se crea la instancia de la libreria dinamica de VTOL. 
//Se espera que esta instancia sea unica en el sistema, por lo cual no se debe destruir luego de su uso. Aqui se usa de esta forma por ser un mero ejemplo
DinamicVtolClient dinamicVtolClient = new DinamicVtolClient();

//Configuracion de VTOL Server
dinamicVtolClient.SetParameter(VtolParam.HostIp, "10.4.13.33");
dinamicVtolClient.SetParameter(VtolParam.HostPort, "3000");

//Configuracion de compañia y tienda
dinamicVtolClient.SetParameter(VtolParam.CompanyId, "NAPSE"); //OPCIONAL
dinamicVtolClient.SetParameter(VtolParam.StoreId, "1"); 

//Configuracion de Timeout 
dinamicVtolClient.SetParameter(VtolParam.ResponseTimeout, "30000");
dinamicVtolClient.SetParameter(VtolParam.TimeOutObtainNode, "100000");
dinamicVtolClient.SetParameter(VtolParam.TimeOutConnectionHost, "20000");
dinamicVtolClient.SetParameter(VtolParam.TimeOutExpirationNode, "600000");

//Configuracion de la encripcion
dinamicVtolClient.SetParameter(VtolParam.UseEncryptedData, "False");
dinamicVtolClient.SetParameter(VtolParam.EncrypterKey, "");
dinamicVtolClient.SetParameter(VtolParam.Encrypter, "");

//Configuracion de la creacion de los nodos dinamicos
dinamicVtolClient.SetParameter(VtolParam.TotalNodeNumber, "10");  
dinamicVtolClient.SetParameter(VtolParam.InitialNodeNumber, "1");
dinamicVtolClient.SetParameter(VtolParam.UseVtolClientFinder, "False");

//inicializacion de la libreria. Se debe llamar una sola vez en la vida de esta instancia.
dinamicVtolClient.Init();

//se obtiene un nodo libre de la lista de nodos disponibles para poder construir una transaccion y autorizar con VTOL Server.
VtolNode node = dinamicVtolClient.GetNode();

//Se crea una Transaccion
node.CreateTransaction();

//Se configura la transaccion agregando campos
node.AddField(FieldId.ServerFieldId, "VTOL"); 
node.AddField(FieldId.MessageTypeFieldId, "DATA"); 
node.AddField(FieldId.CardNumberFieldId, "3700000000000001"); 
node.AddField(FieldId.ExpiringDateFieldId, "201412"); 
node.AddField(FieldId.CVCFieldId, "1234"); 
node.AddField(FieldId.InputModeFieldId, "Manual"); 
node.AddField(FieldId.TransactionTypeFieldId, "Sale"); 
node.AddField(FieldId.AmountFieldId, "1000"); 
node.AddField(FieldId.CurrencyTypeFieldId, "$");
node.AddField(FieldId.PaymentsFieldId, "1"); 
node.AddField(FieldId.PlanFieldId, "0"); 
node.AddField(FieldId.DateTimeFieldId, DateTime.Now.ToString("yyyyMMddHHmmss"));

//se envia la transaccion a VTOL Server para su validacion y autorizacion
node.SendTransaction();

//Se recibe respuesta y codigo de la misma.
string _responseCodeString = node.CurrentTransaction.ResponseMessage.GetField(26).Val;

if (_responseCodeString.Equals("ISO8583"))
{
    String _isoResponseCodeString = node.CurrentTransaction.ResponseMessage.GetField(27).Val;

    if ("00".Equals(_isoResponseCodeString)){ 
        //La transaccion fue aprobada. Se debe enviar tercer mensaje

        //Se obtiene el trxID de la transaccion para poder enviar en tercer mensaje
        String _transactionIdString = node.CurrentTransaction.ResponseMessage.GetField(24).Val;

        node.CreateTransaction();
        node.AddField(3, "VTOL");
        node.AddField(4, "Data");
        node.AddField(11, "UnSyncCompletion");
        node.AddField(25, DateTime.Now.ToString("yyyyMMddHHmmss"));
        node.AddField(24, _transactionIdString);
        node.AddField(19, "Commit");

        //se envia el tercer mensaje. Notese que no se espera respuesta.
        node.SendTransactionWithoutResponse();
    }
    else { 
        //la transaccion fue denegada. Seguir un flujo alternativo
    }
}
else
{
    //Se recibiò un error por parte de VTOL (puede ser desde una transaccion pendiente hasta un error de formato). Seguir un flujo alternativo
}

//se libera el nodo para un proximo uso.
dinamicVtolClient.FreeNode(node);

//se finaliza la instancia de la libreria dinamica
dinamicVtolClient.End();






  • Sem rótulos