# Integración Aplicación POS Android

# Introducción

En el presente documento se incluye la especificación técnica que deben cumplir las aplicaciones de terceros, para hacer uso del software que representa al módulo de pagos, incluido en los terminales.

Se entiende por aplicaciones de terceros cualquier servicio instalado en el terminal que no forma parte ni del sistema operativo ni de la arquitectura de pagos implementada por CardNET.

Un intent es un caso de uso concreto implementado en el módulo de pagos. Para todos los intents se sigue la misma lógica: envío de petición y recepción de respuesta. Los intents implementados son:

  • Transacción de venta
  • Transacción de anulación
  • Impresión de recibos

Del mismo modo, se dispone de un servicio REST implementado en el módulo de pagos, el cual permitirá a las aplicaciones de terceros realizar las diferentes acciones. Al consumir cada método del servicio REST se sigue la misma lógica: Envío de parámetros requeridos por el servicio y recepción de respuesta. Los métodos implementados son:

  • Transacción de venta
  • Transacción de anulación
  • Impresión de recibos

El objetivo de esta especificación es definir la manera en que una aplicación puede realizar un cobro, invocando el servicio de pago del terminal, obteniendo como respuesta el resultado de la transacción.

# Servicios de intents para el uso de la aplicación de pago

El objetivo de esta especificación es definir la manera en que una aplicación puede realizar un cobro, invocando el servicio de pago del terminal, obteniendo como respuesta el resultado de la transacción.

# Transaction Actions

  • ACTION_REQUEST = "com.necomplus.tpv.transaction.REQUEST";
  • ACTION_RESPONSE = "com.necomplus.tpv.transaction.RESPONSE";

# Request Parameters

Dato Tipo Descripción M/O
TYPE string Tipo de transacción para una venta enviar SALE, Anulación REFUD M
AMMOUNT double Monto de la transacción en formato Double ejemplos 1200 ; 2503 ; 10023 entendiéndose que los dos últimos son los centavos O
ITBIS double ITBIS de la transacción em formato Double ejemplos 1200 ; 2503 ; 10023 entendiéndose que los dos últimos son los centavos. O
TAX double ITBIS de la transacción em formato Double ejemplos 1200 ; 2503 ; 10023 entendiéndose que los dos últimos son los centavos. O
REFERENCE string Código de referencia de una transacción especifica, ejemplo: 123456 O
Data json Se entrega toda la data de la transacción que se vaya a enviar al Ágora para guardar por parte del tercero O

# Response Parameters

Dato Tipo Descripción M/O
Code string Código de respuesta de la transacción: "0" Aprobada, "1" Fallida, "2" Candelada M
Message string Mensaje que quiere que se muestre en la ventana de aprobación ejemplo “error transaction” O
Data json Se entrega toda la data de la transacción para imprimir el recibo, ver el ejemplo del JSON. O

# Ejemplo

{
  "voucherNumber": "000001",
  "authCode": 0,
  "resultMessage": "ACEPTADA",
  "ticket": {
    "AID": "A0000000041010",
    "ARC": "00",
    "ATC": "00297",
    "PSN": "00",
    "Amount": "100",
    "Authorization": "006360",
    "CardBank": "Banco XXX",
    "CardHolder": "",
    "CardIssuer": "Credito",
    "CardNumber": "************3059",
    "CardTechnology": 1, // 1 chip , 2 cless, 3 Banda
    "CardType": "",
    "Currency": "DOP",
    "Date": "20200522",
    "Id": "432864",
    "Language": "es",
    "Location": "SANTO DOMINGO",
    "MerchantId": "329811087",
    "MerchantName": "Comercio",
    "OriginalTransactionDate": "",
    "OriginalTransactionId": "",
    "PinIndicator": 0, // 1 pin
    "SignatureImage": "89504e470d0a1a0a0000000d49484452000001f400000139080600000066a0d2e0000000047...",
    "SignatureIndicator": 1,
    "Status": "0",
    "TerminalId": "00000001",
    "Time": "0106",
    "Type": "Payment"
  }
}

# Ejemplo de mensajería

/**
 * MENSAJERÍA INTENTS CARDNET
 */

// PETICIÓN DE TRANSACCIÓN ---------------------------------------------------------------------------
public static final String ACTION_REQUEST = "com.necomplus.tpv.transaction.REQUEST"; // NOMBRE PETICIÓN DE TRANSACCIÓN EN INTENT

// PARÁMETROS DE ENVÍO
public enum ParamsRequest {
    TYPE,
    AMOUNT,
    REFERENCE;

    public String getValue() {
        return ACTION_REQUEST + ".params" + this.name();
    }
}

// ParamsRequest.TYPE: Tipo de la transacción que se quiere procesar en el aplicativo Cardnet en formato String
// ejemplo: Para realizar una venta enviar "SALE"

// ParamsRequest.AMOUNT: Monto de la transacción en formato double
// ejemplo: 12.0 ; 25.03 ; 100.23

// ParamsRequest.REFERENCE: Indica el código de referencia a una transacción específica en formato String
// ejemplo: 123456

// RESPUESTA DE TRANSACCIÓN --------------------------------------------------------------------------
public static final String ACTION_RESPONSE = "com.necomplus.tpv.transaction.RESPONSE"; // NOMBRE RESPUESTA DE TRANSACCIÓN EN INTENT

// PARÁMETROS DE RESPUESTA
public enum ParamsResponse {
    CODE,
    MESSAGE,
    DATA;

    public String getValue() {
        return ACTION_RESPONSE + ".params" + this.name();
    }
}

// ParamsResponse.CODE: Código de respuesta transacción en formato String
// códigos de respuesta en transacciones
public static final int TX_APPROVED = 0;  // APROBADA
public static final int TX_FAILED = 1;    // TRANSACCIÓN FALLIDA
public static final int TX_CANCEL = 2;    // CANCELADA

// ParamsResponse.MESSAGE: Mensaje de la transacción en formato String
// ejemplo: "success", "cancel", "error transaction"

// ParamsResponse.DATA: Data extra en formato json como respuesta de la transacción
// ejemplo:
/**
{
    "authCode": "123456",
    "voucherNumber": "000001"
}
**/
private static final String JSON_NAME_AUTH_CODE = "authCode";
private static final String JSON_NAME_VOUCHER_CODE = "voucherNumber";

// EJEMPLO DE USO

// REGISTRAR BROADCAST PARA RECIBIR LA RESPUESTA DE LA TRANSACCIÓN
private BroadcastReceiver receiverTransaction = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null && intent.getExtras() != null) {
            int code = intent.getExtras().getInt(NameIntents.ParamsResponse.CODE.getValue());
            String message = intent.getExtras().getString(NameIntents.ParamsResponse.MESSAGE.getValue());

            if (transactionData.getCodeResult() == TX_APPROVED) {
                try {
                    String json = intent.getExtras().getString(NameIntents.ParamsResponse.DATA.getValue());
                    if (json == null) {
                        return;
                    }
                    JSONObject jsonObject = new JSONObject(json);
                    String authCode = jsonObject.getString(JSON_NAME_AUTH_CODE);
                    String referenceNumber = jsonObject.getString(JSON_NAME_VOUCHER_CODE);
                    onSuccess();
                } catch (JSONException e) {
                    Throwable ex = new Throwable(e.getMessage());
                    onError(ex);
                }
            } else {
                Throwable ex = new Throwable(message);
                onError(ex);
            }
        }
    }
};

// FILTRO DE INTENT Y REGISTRO DE RECEIVER
IntentFilter intentFilter = new IntentFilter(ACTION_RESPONSE);
context.registerReceiver(receiverTransaction, intentFilter);

// ENVIAR REQUEST A LA APLICACIÓN PARA LA VENTA
Intent intent = new Intent(ACTION_REQUEST);
intent.putExtra(NameIntents.ParamsRequest.AMOUNT.getValue(), 10.0);
intent.putExtra(NameIntents.ParamsRequest.TYPE.getValue(), "SALE");
intent.putExtra(NameIntents.ParamsRequest.REFERENCE.getValue(), "123456");
context.sendBroadcast(intent);

# Servicios REST para el uso de la aplicación de pago

El objetivo es que desde una aplicación de terceros pueda invocar la aplicación de una manera sencilla para realizar la transacción y recibir los datos con el resultado.

# Server

  • HOST: ip del terminal
  • PORT: 2001

# Sale

  • Método: POST
  • Endpoint: /tx_sale

# Parameters Request

Dato Type Descripción M/O
amount double Monto de la transacción en formato Double. Ejemplos: 1200 ; 2503 ; 10023 entendíendose que los dos últimos son los centavos. [M]

# Parameters Response

Dato Type Descripción M/O
Data json Se entrega toda la data de la transacción para imprimir el recibo. Ver el ejemplo del JSON. [O]

# Ejemplo

# Request

HOST:PORT/tx_refund?amount=500&authNumber=0000117

# Response

{
  "amount": "1500 DOP",
  "amountOriginalFormat": "1500",
  "approbationNumber": "419886",
  "bankCode": "0081",
  "bankName": "Popular",
  "cancellationsAmount": 0.0,
  "cancellationsNumber": 0,
  "cardInformation": {
    "aid": "A0000000041010",
    "apLabel": "DEBIT MASTERCARD",
    "cardNetworkId": "INTERNACIONAL NO UE",
    "cardSubType": "MASTERCARD",
    "cardType": "MASTERCARD",
    "isCTL": true,
    "isChip": false,
    "isMagneticSwipe": false,
    "maskedPAN": "***********9547",
    "needPin": false,
    "needSignature": false,
    "posEntryMode": 4,
    "posEntryModeText": "CONTACTLESS",
    "sequenceNumber": 0,
    "txType": 0
  },
  "commerceData": {
    "commerceAddress": "Avenida Doctor Jimenez Diaz, 19",
    "commerceName": "Necomplus",
    "uniqueCode": "202124004"
  },
  "copyTx": false,
  "creditsAmount": 0.0,
  "creditsNumber": 0,
  "cvm": 5,
  "isTip": false,
  "op": 1,
  "referenceNumber": "0000118",
  "refundCancellationsNumber": 0,
  "refundsAmount": 0.0,
  "refundsCancellationsAmount": 0.0,
  "refundsNumber": 0,
  "responseCode": "",
  "sessionDate": "210921",
  "sessionNumber": "001",
  "signatureCaptured": false,
  "terminal": "00000001",
  "totalTransAmount": 0.0,
  "totalTransNumber": 0,
  "transNumber": "0000118",
  "tvp": "T0000113",
  "txDateDay": "21/09/21",
  "txDateHour": "22:43:17",
  "txDateTime": "21/09/21 22:43:17",
  "txnDateType": 0,
  "txnMessage": "OPERACION ACEPTADA",
  "txnResult": 4,
  "txnType": 3,
  "typeTransaction": "000011"
}

# Intents para Impresión

// PRINTER INTENTS IMPLEMENTATION
// para generar el recibo como imagen

JSONOBJECT jsonData = {
    "typeFace": "Droid Sans Mono",
    "advancePaper": true,
    "letterSpacing": 0,
    "grayLevel": 2,
    rows: [
        {
            "type": "IMAGE",
            "image": "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",
            "align": "CENTER"
        },
        {
            "type": "BR",
        },
        {
            "type": "TEXT",
            "text": "PRUEBA ",
            "rightText": "CONCEPTO",
            "align": "LEFT",
            "fontSize": 23,
            "isBold": false,
            "isUnderline": true,
            "isInverse": true
        },
    ]
}
// implementation
-----------------------------------------------------------------------------------------------------------
public class PrinterReceiver extends BroadcastReceiver {
    public static final String ACTION_REQUEST_PRINTER = "com.necomplus.tpv.device.print.request";
    public static final String ACTION_RESPONSE_PRINTER = "com.necomplus.tpv.device.print.response";
    public static final String ACTION_PARAM_PRINTER_JSON_DATA = "com.necomplus.tpv.device.print.params.DATA_VOUCHER";
    public static final String ACTION_PARAM_PRINTER_RESULT = "com.necomplus.tpv.device.print.params.RESULT";

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null && intent.getExtras() != null) {
            String result = intent.getExtras().getInt(ACTION_PARAM_PRINTER_RESULT);
        }
    }
}
// Registrar broadcast
---------------------------------------------------------------------------------------------------------
PrinterReceiver printerReceiver = new PrinterReceiver();
registerReceiver(printerReceiver, new IntentFilter(printerReceiver.ACTION_RESPONSE_PRINTER));
// envio de la petición
Intent intent = new Intent(ACTION_REQUEST_PRINTER);
intent.putExtra(ACTION_PARAM_PRINTER_JSON_DATA, jsonData));
mContext.sendBroadcast(intent);
// tipos de elementos para enviar en la petición
// ---------------------------------------------------------------------------------------------
IMAGE
{
    "type": "IMAGE", // tipo de elemento Imagen
    "image": "BASE64", // datos de la imagen enviado en base64
    "align": "CENTER" // alineación de la imagen
},
TEXT
{
    "type": "TEXT", // tipo de elemento Texto
    "text": "ISO Payment API", // Texto principal a escribir
    "rightText": "text", // Texto que se alinea a la derecha del voucher
    "align": "LEFT", // Alineación del texto general
    "fontSize": 23, // tamaño fuente del texto
    "isBold": false, // bandera para indicar si el texto es resaltado
    "isUnderline": true, // bandera para indicar si el texto lleva subrayado
},
BARCODE
{
    "type": "BARCODE", // tipo de elemento código de barras
    "content": "12345670", // datos para el código de barras
    "height": 32, // altura del código de barras
    "margin": 5, // margen vertical
    "scale": 2, // escala de la imagen
    "format": "EAN_8", // formato del código de barras
    "align": "CENTER" // alineación del código de barras
},
QR
{
    "type": "QR",
    "content": "Copyright © 2020 by ITOS TECHNOLOGY S.L",
    "size": 64,
    "align": "CENTER"
},
SALTO DE LÍNEA
{
    "type": "BR", // tipo de elemento salto de linea
}

# Código de Respuesta

  • Succes
  • -1001 Printer Print Failure
  • -1002 Failed to set the string in buffer
  • -1003 Failed to set the image in buffer
  • -1004 Printer Busy
  • -1005 Out of paper
  • -1006 Wrong Package
  • -1007 Printer Hardware Failure
  • -1008 OverTemperature
  • -1009 Printing has not finished
  • -1999 Exception error

# Formatos de Código de barras

  • CODABAR
  • CODE_39
  • CODE_93
  • CODE_128
  • EAN_8
  • EAN_13
  • ITF
  • UPC_A
  • UPC_E

# Servicios REST para impresión

POST

# Printer

https://192.168.1.70:2001/v1/device/printer

# Request JSON Object

Para imprimir textos, imágenes o QR codes se deben desarrollar los siguientes objetos JSON:

  • typeFace: Tipografía, los que soportamos son:
    • Monospace
    • Sans-Serif
    • Droid Sans
    • Droid Sans Mono
  • advancePaper: avance de papel
  • letterSpacing: Espacio en píxeles, el valor por defecto es 4.
  • grayLevel: Establece escala de grises, si no se setea el valor por defecto es 0. Los valores disponibles son:
    • 0: Lighter grayscale
    • 1: Medium grayscale
    • 2: Darker grayscale
  • rows: Lista de columnas a imprimir: Text, Image, Barcode o QR rows.

# Response

  • resultCode: Result code value

# Códigos de respuesta:

  • 0 Succes
  • -1001 Printer Print Failure
  • -1002 Failed to set the string in buffer
  • -1003 Failed to set the image in buffer
  • -1004 Printer Busy
  • -1005 Out of paper
  • -1006 Wrong Package
  • -1007 Printer Hardware Failure
  • -1008 OverTemperature
  • -1009 Printing has not finished
  • -1999 Exception error

# Text Row

  • type: Row Type
  • text: text to print
  • align: Align type
  • fontSize: text font size
  • isBold: Flag to print the text with bold style
  • isUnderline: Flag to print the text with underline style

# Text Row with right text

  • type: Row Type
  • text: text to print on the left
  • rightText: text to print on the right
  • align: Align type
  • fontSize: text font size
  • isBold: Flag to print the text with bold style
  • isUnderline: Flag to print the text with underline style

# Image row

  • type: Row Type
  • align: Align type
  • image: Base64 encoded image

# BarcodeRow

  • type: Row Type
  • align: Align type
  • content: content to include in the barcode
  • height: Height of the barcode
  • margin: print margin
  • scale: Scale
  • format: Barcode Format type

# QRCodeRow

  • type: Row Type
  • align: Align type
  • content: content to include in the QR Code
  • size: Size of the QR generated

# Row Types

Row types available:

  • TEXT: Text row
  • IMAGE: Image row
  • BARCODE: Barcode row
  • QR: QR code row

# Align types

  • LEFT: Align item to the left
  • RIGHT: Align item to the right
  • CENTER: Align item to the center

# BarcodeFormat types

  • CODABAR
  • CODE_39
  • CODE_93
  • CODE_128
  • EAN_8
  • EAN_13
  • ITF
  • UPC_A
  • UPC_E

# Ejemplo

curl --location --request POST 'https://192.168.1.70:3001/v1/device/printer' \
--header 'X-SOURCE;' \
--data-raw '{
    "typeFace": "Droid Sans Mono",
    "advancePaper": true,
    "letterSpacing": 0,
    "grayLevel": 2,
    "rows": [
        {
            "type": "IMAGE",
            "image": "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",
            "align": "CENTER"
        },
        {
            "type": "TEXT",
            "text": "ITOS TECHNOLOGY",
            "align": "CENTER",
            "fontSize": 32,
            "isBold": true,
            "isUnderline": false
        },
        {
            "type": "TEXT",
            "text": "ISO Payment API",
            "align": "LEFT",
            "fontSize": 23,
            "isBold": false,
            "isUnderline": true
        },
        {
            "type": "TEXT",
            "text": "Date & Time: ",
            "rightText":"{{current_timestamp}}",
            "fontSize": 23,
            "isBold": false,
            "isUnderline": false
        },
        {
            "type": "TEXT",
            "text": "Version: ",
            "rightText":"1.0-alpha",
            "fontSize": 23,
            "isBold": false,
            "isUnderline": false
        },
        {
            "type": "BARCODE",
            "content": "1234566666666",
            "height": 32,
            "margin": 5,
            "scale": 2,
            "format": "ITF",
            "align": "CENTER"
        },
        {
            "type": "QR",
            "content": "Copyright © 2020 by ITOS TECHNOLOGY S.L",
            "size": 64,
            "align": "CENTER"
        }
    ]
}'