VTOL CLIENT NET - Manual librería 2.0.x.x
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
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:
- 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:
- El punto de venta enviara un mensaje de chequeo de pendientes "CheckPending" a VTOL.
- 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.
- 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.
- 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:
- StaticVTOLClient
- Esta implementación está orientada a ser utilizada por cada punto de venta donde el Originador y el Nodo sean fijos.
- DinamicVTOLClient
- 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).
- VirtualVTOLClient
- 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:
- crear una instancia de VTOLClient.
- cargarle los parámetros correspondientes.
- inicializar el cliente
- tomar un nodo
- construir una transacción.
- enviar el mensaje.
- devolver el nodo.
2.2.2 Parámetros posibles de inicialización
Name | Description |
---|---|
DefaultTransactionStatus |
Valor por defecto 'C'. |
Encrypter |
|
EncrypterKey |
|
HostIp |
|
HostPort |
|
InitialNodeNumber |
Nota: Usar 0 cuando se usa con VTOL NT |
ResponseTimeout |
Valor por defecto 30000. |
CompanyId | ID 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 |
|
TimeOutConnectionHost |
Valor por defecto 20000. |
TimeOutExpirationNode |
Valor por defecto 600000. Nota:Solo para el uso de DinamicVtolClient |
TimeOutObtainNode |
Valor por defecto 30000. Nota:Solo para el uso de DinamicVtolClient |
TotalNodeNumber |
Nota:El HandShake solo es soportado con VTOL NT |
UseEncryptedData |
|
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 |
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.
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
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();