Smart COMM .Net

Los pasos, para integrar tu Punto de venta con la Smart PinPad de NetPay, se detallan a continuación:

1. Instalación del driver.

Las terminales se conectan al punto de venta a través del puerto USB, es necesario instalar los
drivers correspondientes para que Windows pueda detectar del dispositivo. Para instalar los drivers del dispositivo es necesario descomprimir el archivo USBDriver_V2.22_20180726.zip, ejecutar el instalador USBDriver.exe y seguir las instrucciones en pantalla.

Al haber instalado los drivers, Windows detectará el dispositivo Pin Pad y le asignará un puerto serial de trabajo. Para detectar el puerto serial asignado, se puede visualizar en el Panel de Control, en la sección de Dispositivos de Hardware, bajo el menú de Puertos (COM & LPT).

2. Demo de punto de venta.

Se cuenta con un Demo de punto de venta para simular las transacciones de Venta, Cancelación y Reimpresión.

Para ejecutar el Demo de COMM primero debes descargar el smartPinPadTester del Drive, descomprimir el archivo, ejecutar y realizar las referencias al .dll dependiendo la arquitectura x64 o x86 como se indica en el punto 3. Instalación de componentes.

*Demo COMM Versión 5**Demo COMM Versión 5*

Demo COMM Versión 5

3. Instalación de componentes.

Para realizar la integración con la terminal se incluye los siguientes archivos los cuales deberán de ser importados en el proyecto del punto de venta. Los archivos DLL tienen como Target .NET 3.5 Framework o superior.

NetPayConnect.dll (Conector para la terminal Smart PinPad).
Newtonsoft.Json.dll (Librería auxiliar para manejo de objetos JSON).

Actualmente el NetPayConnect.dll cuenta con varias versiones disponibles para descargar:

  • NetPayConnect.dll_v1.3
  • NetPayConnect.dll_v1.4
  • NetPayConnect.dll_v1.5

La versión 1.5 cuenta con un Timer que se habilita al momento de enviar la solicitud a la PinPad y que se mantiene a la espera de respuesta. Esta versión mejora temas relacionados con el rendimiento del punto de venta y la inhibición, por lo cual, esta se considera una versión mucho mas estable a sus antecesoras.

Es importante señalar que la versión 1.5 es implementada de manera diferente a la 1.3 o la 1.4, por lo cual se necesitan configuraciones adicionales que se estarán explicando a lo largo de la documentación.

Los archivos dll pueden ser descargados por este enlace Versiones .dll

📘

Nota.

Dependiendo el tipo de desarrollo hay que verificar si se encuentra en arquitectura x64 o x86 ya que se deberá agregar las dll correspondientes.

Ejemplo de agregar como referencia el dll correspondiente a la arquitectura en su punto de venta.

Ingresar al menú de Proyecto->click derecho en la opción de Referencias.

Agregar referencias->

Presionar el botón de Examinar y seleccionar el archivo correspondiente x64 o x86 y presionar Agregar.

Ingresar a la carpeta donde se encuentra el dll según la arquitectura.

Seleccionar el archivo dll y presionar Aceptar.

Después de agregar la referencia compilar el proyecto.
Menú Compilar-> Compilar solución.

4. Integración de las librerías.

El componente NetPayConnect.dll es una librería que puede ser integrada en cualquier lenguaje de desarrollo basado en Windows, que soporte este tipo de librería. La librería contiene una clase llamada Operator que es utilizado para mandar a llamar los métodos.

4.1 Creación del objeto.

Creamos un objeto de tipo Operator para poder acceder a sus métodos.

NetPayConnect.Operator connectorPAX = new NetPayConnect.Operator();

4.2 Envío de petición de venta a Smart PinPad.

Una vez instanciado el objeto podemos acceder a los siguientes métodos:

Método.

Descripción.

SetAmount

Se asigna el monto a cobrar. Recibe valor de tipo Double. (solo acepta 2 decimales).

setMSI

Se asigna el número de meses sin intereses al momento de procesar la transacción.
Por default se envía el valor 0 (Sin meses).
Posibles valores que acepta: 3, 6, 9, 12, 18.

setFolio

Se asigna el folio personalizado a utilizar en el Ticket.

sendData

Una vez asignado el monto como mínimo se manda a llamar este método para procesar la transacción en la PinPad.

ReceiveData (versión 1.5 .dll)

Recibe información por parte de la PinPad y la almacena en un objeto "response" dentro de la clase Connector.

getResponse

Puedes recuperar la información almacenada en el objeto "response" llamando a este método.

setTip

Se asigna un monto designado a propina. Recibe valores de tipo Double. (solo acepta 2 decimales).

findPortByDescription

Devuelve el puerto al que está conectada la PinPad.

🚧

Nota.

Para realizar una transacción de prueba debemos de utilizar al menos el método de setAmount() para colocar el monto a cobrar y procesar la transacción con el método sendData().

A continuación presentaremos ejemplos de como utilizar estos métodos en las librerías existentes.

  • La versión 1.5 de NetPayConnect.dll requiere que se implemente un Timer en su punto de venta para su correcto funcionamiento. Más adelante se presentará ejemplo en código.

🚧

Nota.

En la versión 1.5 de la NetPayConnect.dll se recomienda implementar el Timer seteando su valor entre 500-1000 ms. Esta configuración simplemente es una recomendación, sin embargo sugerimos que sea un valor menor a 2000 ms ya que algunos procesos de la Smart PinPad son muy rápidos y puede que esto provoque que la respuesta no sea recibida.

  • En cambio la versión 1.4 de NetPayConnect.dll no requiere dicho Timer, pero puede llegar a mostrar problemas relacionados con inhibición.

Para evitar algún inconveniente, se recomienda la implementación de la versión 1.5 de NetPayConnect.dll.

Ejemplo botón venta en las librerías más recientes:

private void Venta_Click(object sender, EventArgs e){
    //al presionar el boton se habilita el timer que estara esperando respuesta de la PinPad
    timer1.Enabled = true;
    //se RECOMIENDA bloquear el boton hasta concretar la venta satisfactoriamente para evitar
    //dobles instancias y se habilita cuando se recibe informacion.
    button1.Enabled = false;
    string result = "";
    string msiValue = ((KeyValuePair<string, string>)comboBox1.SelectedItem).Value;
        try
        {
          //hacemos set al valor Amount (campo obligatorio para llamar el sendData())
          connectorPAX.SetAmount(Convert.ToDouble(textBox1.Text));
          //hacemos set al valor Tip (no obligatorio)
          if (textBox5.Text == "")
          {
            connectorPAX.SetTip(0.0);
          }
          else
          {
            connectorPAX.SetTip(Convert.ToDouble(textBox5.Text));
          }
          //hacemos set al valor folio (no obligatorio)
          connectorPAX.SetFolio(textBox2.Text);
          //hacemos set al valor MSI (no obligatorio)
          connectorPAX.SetMSI(Convert.ToInt32(msiValue));
          //validamos la checkbox para imprimir o no el ticket
          connectorPAX.setDisablePrintAnimation(checkBox1.Checked);
          //enviamos la transacción a la PinPad
          connectorPAX.sendData();
        }
    catch (Exception ec)
    {
      Console.WriteLine(ec.Message);
    }
}
private void Venta_Click(object sender, EventArgs e){
    //se RECOMIENDA bloquear el boton para evitar temas de dobles instancias 
    button1.Enabled = false;
    String result= "";
    string msiValue = ((KeyValuePair<string, string>)comboBox1.SelectedItem).Value;
    try {
    //hacemos set al valor Amount (campo obligatorio para llamar el sendData())
    connectorPAX.SetAmount(Convert.ToDouble(textBox1.Text));
    //hacemos set al valor folio (no obligatorio)
    connectorPAX.SetFolio(textBox2.Text);
    //hacemos set al valor MSI (no obligatorio)
    connectorPAX.SetMSI(Convert.ToInt32(msiValue));
    //validamos la checkbox para imprimir o no el ticket
    connectorPAX.setDisablePrintAnimation(checkBox1.Checked);

    //enviamos la informacion a la PinPad para realizar la venta
    connectorPAX.sendData();
    }
    catch (Exception ec){

    Console.WriteLine(ec.Message);
    }
    
    //...
    //CODIGO PARA RECIBIR RESPUESTA
    //...
}

📘

Nota

Como se pudo ver en el ejemplo anterior, algunos botones se desactivan o se esconden durante el proceso de respuesta, se recomienda hacer esto en el botón de Venta para evitar problema de duplicado de instancias o problemas con hilos.

Del mismo modo se recomienda implementar esto en los botones de Cancelación y Reimpresión

4.3 Recibiendo la respuesta.

Podemos obtener la respuesta en formato JSON al momento de enviar una transacción de la
siguiente manera.

En la versión 1.5 del .dll el Timer manda a llamar a otro método llamado getResponseData(), ambos están por fuera del botón de venta y esta implementación mejora considerablemente el rendimiento del punto de venta.

En la versión 1.4 del .dll se manda a llamar el método getResponse() justo después de enviar venta.

Ejemplo de como recibir la respuesta de la PinPad:

//El timer se habilita y manda a llamar al metodo getResponseData para esperar la informacion de regreso.
private void Timer_Tick(object sender, EventArgs e)
    {
      getResponseData();
    }


//Se activa el metodo getResponseData el cual estara a la espera de valores
private void getResponseData()
    {
      //El metodo ReceiveData estara esperando datos del puerto para guardarlos en getResponse()
      connectorPAX.ReceiveData();
            //Si getResponse no esta vacio, se recupera la informacion obtenida 
          if (connectorPAX.getResponse() != null)
          {
            //VALORES RECUPERADOS
            textBox.Text += System.Environment.NewLine + "Amount: " + connectorPAX.getAmount();
            textBox.Text += System.Environment.NewLine + "Message: " + connectorPAX.getMessage();
            textBox.Text += System.Environment.NewLine + "OrderId: " + connectorPAX.getOrderId();
            //...VALORES RECUPERADOS 
            //Se apaga el timer una vez que la informacion haya llegado
            timer1.Enabled = false;
            //se habilita el boton una vez se haya recibido la informacion
            button1.Enabled = true;
          }
        }
private void Venta_Click(object sender, EventArgs e){
  
    //...
    //CODIGO PARA ENVIAR VENTA
    //...
  
    //Si getResponse no esta vacio, se recupera la informacion obtenida 
    if (connectorPAX.getResponse() != null)
    {
      //VALORES RECUPERADOS
      textBox.Text += System.Environment.NewLine + "Amount: " + connectorPAX.getAmount();
      textBox.Text += System.Environment.NewLine + "Message: " + connectorPAX.getMessage();
      textBox.Text += System.Environment.NewLine + "OrderId: " + connectorPAX.getOrderId();
      //...VALORES RECUPERADOS 
      //Se habilita el boton de venta despues de recibir informacion.
      button1.Enabled = false;
    }
}

📘

Observación

El botón de venta se activa después de recibir la respuesta, esto se puede implementar también en el botón de cancelación y reimpresión, a manera de sugerencia, para evitar problemas de instancias o hilos.

Forma 1 de recibir la respuesta: Usando el objeto getResponse() se obtendrá lo siguiente:

{
    "data": {
        "affiliation": "7389108",
        "applicationLabel": "Debit MasterCard",
        "arqc": "44F30DA9ED36D1D3",
        "aid": "A0000000032010",
        "amount": "100.0",
        "authCode": "TEST00",
        "bankName": "SANTANDER",
        "cardExpDate": "01/26",
        "cardType": "D",
        "cardTypeName": "MASTERCARD",
        "cityName": "Guadalupe NUEVO LEON",
        "responseCode": "00",
        "folioNumber": "",
        "hasPin": true,
        "hexSign": "",
        "isQPS": 0,
        "message": "Transacción exitosa",
        "moduleCharge": "1",
        "moduleLote": "1",
        "customerName": "NOMBRE CLIENTE        /",
        "terminalId": "1310000001",
        "orderId": "211018115515-1490293212",
        "preAuth": "0",
        "preStatus": 0,
        "promotion": "00",
        "rePrintDate": "1.3.1_20211018",
        "rePrintMark": "MASTER",
        "reprintModule": "C",
        "cardNumber": "1234",
        "storeId": "9194",
        "storeName": "CICAP",
        "streetName": "AVE PABLO LIVAS 7200",
        "ticketDate": "OCT. 18, 21 11:55:18 ",
        "tipAmount": "0.0",
        "tipLessAmount": "100.0",
        "transDate": "2021-10-18 11:55:16.CDT",
        "transType": "A",
        "transactionCertificate": "411D6DCB7F34B45C"
    },
    "idReport": 1
}
{
    "data": {
        "affiliation": "7389108",
        "applicationLabel": "Debit MasterCard",
        "arqc": "44F30DA9ED36D1D3",
        "aid": "A0000000032010",
        "amount": "100",
        "authCode": "TEST00",
        "bankName": "SANTANDER",
        "cardExpDate": "01/26",
        "cardType": "D",
        "cardTypeName": "MASTERCARD",
        "cityName": "Guadalupe,NUEVO LEON",
        "responseCode": "00",
        "folioNumber": "",
        "hasPin": false,
        "hexSign": "null",
        "isQPS": 0,
        "message": "Transaccion Valida",
        "moduleCharge": "1",
        "moduleLote": "1",
        "customerName": "NOMBRE CLIENTE        /",
        "terminalId": "1310000001",
        "orderId": "211018115515-1490293212",
        "preAuth": "0",
        "preStatus": 0,
        "promotion": "0",
        "rePrintDate": "1.3.1_20211018",
        "rePrintMark": "MASTER",
        "reprintModule": "C",
        "cardNumber": "1234",
        "storeId": "9194",
        "storeName": "CICAP",
        "streetName": "AVE PABLO LIVAS 7200",
        "ticketDate": "OCT. 18, 21 11:55:18",
        "tipAmount": "0",
        "tipLessAmount": "0",
        "transDate": "2021-10-18 11:55:15.0",
        "transType": "A",
        "transactionCertificate": "79835BDB5404064F"
    },
    "idReport": 1
}
{
    "data": {
        "affiliation": "7389108",
        "applicationLabel": "Debit MasterCard",
        "arqc": "79835BDB5404064F",
        "aid": "A0000000032010",
        "amount": "100.0",
        "authCode": "TEST00",
        "bankName": "SANTANDER",
        "cardExpDate": "01/06",
        "cardType": "D",
        "cardTypeName": "MASTERCARD",
        "cityName": "Guadalupe NUEVO LEON",
        "responseCode": "00",
        "folioNumber": "",
        "hasPin": false,
        "hexSign": "",
        "isQPS": 0,
        "message": "Transacción exitosa",
        "moduleCharge": "2",
        "moduleLote": "1",
        "customerName": "NOMBRE CLIENTE        /",
        "terminalId": "1310000001",
        "orderId": "211018115515-1490293212",
        "preAuth": "0",
        "preStatus": 0,
        "promotion": "00",
        "rePrintDate": "1.3.1_20211018",
        "rePrintMark": "MASTERCARD",
        "reprintModule": "C",
        "cardNumber": "1234",
        "storeId": "9194",
        "storeName": "CICAP",
        "streetName": "AVE PABLO LIVAS 7200",
        "ticketDate": "OCT. 18, 21 11:55:18",
        "tipAmount": "null",
        "tipLessAmount": "100.0",
        "transDate": "2021-10-18 12:00:22.CDT",
        "transType": "V",
        "transactionCertificate": null
    },
    "idReport": 1
}

Forma 2 de recibir la respuesta: Extraer información del objeto de forma manual.
Nota: Para los casos que no se pueden utilizar objetos JSON se puede extraer el objeto
directamente desde sus propiedades como se muestra en el siguiente ejemplo:

textBox4.Text += System.Environment.NewLine + "Afiliacion: " +
connectorPAX.getAffiliation();
textBox4.Text += System.Environment.NewLine + "ApplicationLabel: " +
connectorPAX.getApplicationLabel();
textBox4.Text += System.Environment.NewLine + "ARQC: " +
connectorPAX.getARQC();
textBox4.Text += System.Environment.NewLine + "AID: " +
connectorPAX.getAID();
textBox4.Text += System.Environment.NewLine + "Amount: " +
connectorPAX.getAmount();
textBox4.Text += System.Environment.NewLine + "AuthCode: " +
connectorPAX.getAuthCode();
textBox4.Text += System.Environment.NewLine + "BankName: " +
connectorPAX.getBankName();
textBox4.Text += System.Environment.NewLine + "CardExpDate: " +
connectorPAX.getCardExpDate();
textBox4.Text += System.Environment.NewLine + "CardType: " +
connectorPAX.getCardType();
textBox4.Text += System.Environment.NewLine + "CardTypeName: " +
connectorPAX.getCardTypeName();
textBox4.Text += System.Environment.NewLine + "CityName: " +
connectorPAX.getCityName();
textBox4.Text += System.Environment.NewLine + "ResponseCode: " +
connectorPAX.getResponseCode();
textBox4.Text += System.Environment.NewLine + "HasPin: " +
connectorPAX.getHasPin();
textBox4.Text += System.Environment.NewLine + "HexSign: " +
connectorPAX.getHexSign();
textBox4.Text += System.Environment.NewLine + "IsQps: " +
connectorPAX.getIsQPS();
textBox4.Text += System.Environment.NewLine + "Message: " +
connectorPAX.getMessage();
textBox4.Text += System.Environment.NewLine + "ModuleCharge: " +
connectorPAX.getModuleCharge();
textBox4.Text += System.Environment.NewLine + "ModuleLote: " +
connectorPAX.getModuleLote();
textBox4.Text += System.Environment.NewLine + "CustomerName: " +
connectorPAX.getCustomerName();
textBox4.Text += System.Environment.NewLine + "TerminalId: " +
connectorPAX.getTerminalId();
textBox4.Text += System.Environment.NewLine + "OrderId: " +
connectorPAX.getOrderId();
textBox4.Text += System.Environment.NewLine + "PreAuth: " +
connectorPAX.getPreAuth();
textBox4.Text += System.Environment.NewLine + "PreStatus: " +
connectorPAX.getPreStatus();
textBox4.Text += System.Environment.NewLine + "Promotion: " +
connectorPAX.getPromotion();
textBox4.Text += System.Environment.NewLine + "RePrintDate: " +
connectorPAX.getRePrintDate();
textBox4.Text += System.Environment.NewLine + "RePrintMark: " +
connectorPAX.getRePrintMark();
textBox4.Text += System.Environment.NewLine + "ReprintModule: " +
connectorPAX.getReprintModule();
textBox4.Text += System.Environment.NewLine + "CardNumber: " +
connectorPAX.getCardNumber();
textBox4.Text += System.Environment.NewLine + "StoreName: " +
connectorPAX.getStoreName();
textBox4.Text += System.Environment.NewLine + "StreetName: " +
connectorPAX.getStreetName();
textBox4.Text += System.Environment.NewLine + "TicketDate: " +
connectorPAX.getTicketDate();
textBox4.Text += System.Environment.NewLine + "TipAmount: " +
connectorPAX.getTipAmount();
textBox4.Text += System.Environment.NewLine + "TipLessAmount: " +
connectorPAX.getTipLessAmount();
textBox4.Text += System.Environment.NewLine + "TransDate: " +
connectorPAX.getTransDate();
textBox4.Text += System.Environment.NewLine + "TransType: " +
connectorPAX.getTransType();
textBox4.Text += System.Environment.NewLine +
"TransactionCertificate: " + connectorPAX.getTransactionCertificate();
textBox4.Text += System.Environment.NewLine + "FolioId: " +
connectorPAX.getFolioNumber();

Ejemplo de recepción de respuesta.

Afiliacion: 7389108
ApplicationLabel: VISA
ARQC: B3815181F196389B
AID: A0000000032010
Amount: 123.0
AuthCode: TEST00
BankName: AZTECA
CardExpDate: 01/26
CardType: D
CardTypeName: VISA
ResponseCode: 00
HasPin: False
HexSign: 
00000100000001DA0000009E000000040800031CFF02
FF02D300A76532632F7F2F2B74EB3DDE4A08C3C534AE
000B6AFA5F6B44A912EBB0A60C4206C0FF02039D9FEE
15B843DC3722399D609DDCD17026DAE3D358E02E47E6
BE965B8EBA5D0E56967C9D64FF026D3E9E6F1C9D0F88
13D50C4E83764CD71B623485A8E50EDB9E3F1330B2BA
FF02FF02FF02FF02FF02FF029467FF02E0FF02EB0CA6
DEB49F60FF02BCA8BC803614E03B177B828428A2F888
E8BE8A19F85E54C680E630E5F33D3F491E42EDA3F484
F54B482FF4FF02358A7F1DCB544BB50792E1573048C4
40607F927A353AC4B1AEF28981ABFF023C00198F1E04
BFD7692BDDAE884B00EFD5DA18D5915F7B659ED8A453
0E992072533170E0976C78FF02A22091C9C30EFB3108
FF0239AD4B3B65B0FCC379CEC0552BE507CA00DA2484
69604B8BFF0207E346CFDE54EC186DB3CBCDD76540FF
0215B619E5CEDC2A4B92FF024CB17A2B7FB1C6B5A3FF
0220352633D35B827F62FF02356DF5C051BAC080FF02
D3A7674F8AA2E4A022E0FF02E3679A3F34E0CD2EF155
99064160320B96E2A10BF9ADB389D5D1BE99E5B08DD9
C2E4B988614A29B6777F939A29E0DDCE3BE1F4ADDB50
22E3A412FF02371FEDFC71431D91BEC0979E97442C71
E53B71FA1633A1760839FBBAC354B82461D80980FF02
3ABF11E4B19CEB9EFA9242BFC3860DB64ED210CC5FC0
327DB08CBFEA60FF0211A7BC314499B24224E9C221FF
233C2579FE2E4A17CFF02F8FF02F2C0FF02BCB4FF02F
0FF02FAEAE0FF02FF02FF0084DE67F5E39C9E9D77428
1E182EA3C5191E18B63A983B74FF5AA2A60EA604498D
1F5A4A47F4CE5406B885554A401E6C68699F6B3F7C47
BBC5C425C5480FF0271C4A0054CFE278E48375D13848
F4F1741FF000236F5EC1DB423323A478F4EF65920A48
0FF02360CEDB743D40280FF02FF02FF02
IsQps: 0
Message: Transacción exitosa
ModuleCharge: 3
ModuleLote: 1
CustomerName:                           
TerminalId: 1310000001
OrderId: 211018122312-1490293212
PreAuth: 0
PreStatus: 0
Promotion: 00
RePrintDate: 1.3.1_20211018
RePrintMark: VISA
ReprintModule: C
CardNumber: 5678
StoreName: CICAP
StreetName: AVE PABLO LIVAS 7200
TicketDate: OCT. 18, 21 12:23:14 
TipAmount: 0.0
TipLessAmount: 123.0
TransDate: 2021-10-18 12:23:12.CDT
TransType: A
TransactionCertificate: 0C9DD851CECB2E3F
FolioId: 
StoreId: 9194

4.4 Solicitud de cancelación de una transacción

Mensaje para cancelar una venta (Auth) realizada el mismo día. Solo se ocupa el parámetro orderId y se manda a llamar el método sendCancel():

connectorPAX.sendCancel(orderId);

4.5 Reimpresión de Ticket de una transacción previa.

Para mandar a reimprimir un ticket ya generado se utiliza el método sendPrint(). Recibe por parámetro el orderId de la transacción a reimprimir.

connectorPAX.sendPrint(orderId);

📘

Nota.

Manejo de Errores.
Al usar la librería el objeto getResponse() si este viene nulo significa que no hay comunicación con la PinPad y esto se puede deber a que no este conectado o no estén bien instalados los drivers.

🚧

Opcional Deshabilitar la animación e impresión de ticket en la terminal

Este tipo de implementación es opcional y es dirigido a los comercios que tienen integraciones con kioskos y que requieren que la terminal solo realice el cobro lo que se tiene que realizar es deshabilitar la animación y la impresión de tiket en la terminal de esta forma

connectorPAX.setDisablePrintAnimation(true); 
connectorPAX.SetAmount(Convert.ToDouble(textBox1.Text)); 

connectorPAX.SetFolio(textBox2.Text); 

connectorPAX.setDisablePrintAnimation (checkBox1.Checked);

Did this page help you?