Zeal Communicator SDK
Intégrate en el flujo de pago de Zeal en terminales Android: descuentos, recompensas, recibos digitales y devoluciones, con el Communicator SDK tipado en Kotlin.
La API de terceros es un servicio que ofrece Zeal para dar soporte a una aplicación de pago autónoma en terminales Android durante el flujo de pago. Esta guía especifica cómo una aplicación de pago se integra con la aplicación autónoma de Zeal.
Cómo funciona. La API de terceros utiliza mensajes de broadcast de Android encaminados a través de receptores declarados en el manifiesto. No hay endpoints REST que llamar desde fuera del dispositivo.
Cada evento de tarjeta identifica la tarjeta por su huella de la tarjeta (Card Fingerprint, loyalty_token), un
identificador único de tarjeta que tu app de pago genera al leerla. Lee Huella de la tarjeta
antes de empezar.
Instalación
Paso 1 · Agrega el repositorio Maven
Agrega el siguiente repositorio Maven a dependencyResolutionManagement en settings.gradle:
dependencyResolutionManagement {
repositories {
maven {
url = uri("https://maven.pkg.github.com/zeal-io/Zeal-POS-App-Communicator-SDK")
credentials {
username = "*USERNAME*"
password = "*PASSWORD*"
}
}
}
}Paso 2 · Agrega la dependencia
dependencies {
// ...
implementation "com.zeal.zealmodule:zeal_communicator_sdk:1.2.28"
}Paso 3 · Inicializa la app de Zeal
Llama a este método al principio del ciclo de vida de la app, o antes de iniciar el flujo de pago, para inicializar la app de Zeal con los datos de tu comercio:
FlowHandler() .setTerminalInfo(context, "serialNumber", "terminalId", "merchantId")
Configuración compartida
Todas las acciones siguientes usan el mismo preámbulo: importa el SDK, crea un FlowHandler y
elige un contexto más el tipo de transacción.
import com.zeal.zeal_communicator_sdk.* val flowHandler = FlowHandler() val context: Context = this // reemplázalo por tu contexto real val transactionType: TransactionTypes = TransactionTypes.Sale // o Void / Refund
Acciones de transacción disponibles
FlowHandler usa digitalReceipt con DigitalReceiptRequest.Tipos de transacción
El enum TransactionTypes define los tipos de transacción disponibles:
enum class TransactionTypes {
Sale,
Void,
Refund,
PreAuth,
Completion
}Valores de tran_status
Cada respuesta incluye un tran_status que describe el resultado del canje:
tran_status {
FULLY_COVERED, // el descuento cubre el monto íntegro de la transacción
NEW_AMOUNT, // el descuento cubre parcialmente el monto; se devuelve el resto
SAME_AMOUNT, // no se produjo ningún canje
ERROR, // error en el lado de Zeal o del canje
CANCEL // se omitió o se decidió no canjear puntos
}Modelo de respuesta base
Todas las clases de respuesta extienden BaseResponse:
package com.zeal.zeal_communicator_sdk.communicationResponses
open class BaseResponse(
var third_party_request_type: String,
var tran_status: String,
var message: String
)Los modelos de solicitud y respuesta de cada acción están documentados en la ruta de venta y en la
sección Devolución y reversión más abajo: AfterCardDetectedRequest, DigitalReceiptRequest,
RefundTransactionRequest, MarkAsReverseRequest y sus respuestas correspondientes.
Huella de la tarjeta
loyalty_token lleva la huella de la tarjeta (Card Fingerprint), también llamada identificador único de
tarjeta (Unique Card Identifier). Es el valor que le indica a Zeal qué tarjeta se ha usado: tu app de pago
lo envía con cada evento de tarjeta (afterCardDetected, digitalReceipt y refund), y Zeal reconoce por él a un
cliente que vuelve.
Tu app de pago obtiene la huella de la tarjeta al leerla, dentro de su propio procesamiento seguro de tarjetas, de una de estas dos formas:
- Hash con clave: un HMAC-SHA-256 del PAN completo, con una clave que guardas tú.
- Consulta a una bóveda: una bóveda de tokenización (vault) que devuelve el mismo identificador cada vez que ve la misma tarjeta, de modo que la huella no se deriva del propio PAN.
El número de tarjeta (PAN) nunca se envía a Zeal. El BIN (cardBin) y los cuatro últimos dígitos (masked_pan) que
también envías no se usan para identificarla.
La huella de la tarjeta debe cumplir tres requisitos:
Si tu app de pago ya genera un hash estable por tarjeta para sus propios fines, como un hash del PAN que expone el SDK de tu terminal, puedes enviar ese valor como huella de la tarjeta, siempre que cumpla los tres requisitos.
Zeal no prescribe cómo generarla: prescribe estabilidad e irreversibilidad.
¿No puedes generar una huella de la tarjeta que cumpla estos requisitos? Ponte en contacto con Zeal antes de desarrollar la integración.
AfterCardDetected
Se activa tras la lectura de la tarjeta y antes de su verificación. Ejecuta este paso primero en la ruta de venta y continúa después con el Recibo digital.
Enviar una acción
Construye un AfterCardDetectedRequest, con la huella de la tarjeta en loyalty_token,
y suscríbete en FlowHandler:
val request = AfterCardDetectedRequest( loyalty_token = "HhYDMww7aJgcdyJPU6QVWpFAZPNRhSzkqNpErHM3hikU", // huella de la tarjeta, nunca el PAN currency_code = "818", decimal_shift = "2", amount = "100.00", phone_number = "", masked_pan = "1111", cardBin = "411111", par = "V0010013000000000000000000001" // opcional ) flowHandler.afterCardDetected( context, transactionType, request ).subscribe({ response -> // AfterCardDetectedResponse — revisa tran_status, amount, transaction_id }) { throwable -> if (throwable is NotRegisteredFlowException) { // la aplicación de destino no ha registrado ninguna acción para este paso } else { // otra excepción } }
Modelos de solicitud y respuesta
package com.zeal.zeal_communicator_sdk.communicationRequests class AfterCardDetectedRequest( var loyalty_token: String, // huella de la tarjeta, nunca el número de tarjeta var currency_code: String, var decimal_shift: String, // opcional var amount: String, // en formato double var phone_number: String = "", var masked_pan: String = "", // últimos 4 dígitos del número de tarjeta var cardBin: String = "", // primeros 6 u 8 dígitos del número de tarjeta var par: String? = null // opcional — referencia de cuenta de pago EMV )
package com.zeal.zeal_communicator_sdk.communicationResponses class AfterCardDetectedResponse( tran_status: String, // FULLY_COVERED, NEW_AMOUNT, SAME_AMOUNT, ERROR, CANCEL var transaction_id: String? = null, // id de canje necesario para completar el canje al final third_party_request_type: String, var decimal_shift: String, var amount: String, var currency_code: String ) : BaseResponse(third_party_request_type, tran_status)
Recibo digital
Se activa después de que se aprueba la transacción y antes de imprimir el recibo. Llámalo después
de AfterCardDetected en la ruta de venta. La acción en el cable es eReceipt;
el método y los modelos del SDK usan digitalReceipt / DigitalReceipt*. Envía en loyalty_token la misma
huella de la tarjeta que en AfterCardDetected.
Enviar una acción
val request = DigitalReceiptRequest( currency_code = "818", decimal_shift = "2", amount = "100.00", entry_mode = "CHIP", card_brand = "VISA", card_type = "CREDIT", customer_receipt_data = "...", merchant_receipt_data = "...", loyalty_token = "HhYDMww7aJgcdyJPU6QVWpFAZPNRhSzkqNpErHM3hikU", // huella de la tarjeta, nunca el PAN third_party_approval_code = "123456", third_party_tran_date = "20260422", third_party_tran_time = "143055", phone_number = "", par = "V0010013000000000000000000001" // opcional ) flowHandler.digitalReceipt( context, transactionType, request ).subscribe({ response -> // DigitalReceiptResponse — payment_reference para llamadas posteriores a reverse }) { throwable -> if (throwable is NotRegisteredFlowException) { // la aplicación de destino no ha registrado ninguna acción para este paso } else { // otra excepción } }
Modelos de solicitud y respuesta
package com.zeal.zeal_communicator_sdk.communicationRequests class DigitalReceiptRequest( var currency_code: String, var decimal_shift: String, var amount: String, var entry_mode: String, var card_brand: String, var card_type: String, var customer_receipt_data: String, var merchant_receipt_data: String, var loyalty_token: String, // huella de la tarjeta, nunca el número de tarjeta var third_party_approval_code: String, var third_party_tran_date: String, var third_party_tran_time: String, var phone_number: String = "", var par: String? = null // opcional — referencia de cuenta de pago EMV )
package com.zeal.zeal_communicator_sdk.communicationResponses
class DigitalReceiptResponse(
tran_status: String,
third_party_request_type: String,
var payment_reference: String? = null
) : BaseResponse(third_party_request_type, tran_status)Devolución y reversión
La devolución y la reversión están separadas de la ruta de venta. Úsalas al deshacer beneficios de una venta completada, no como el siguiente paso tras el recibo digital.
Devolución
Se activa cuando se realiza una devolución. Marca la transacción como devuelta y revierte los
beneficios de la venta original; vincula con un transaction_id opcional o procésala de forma
independiente.
Enviar una acción
val request = RefundTransactionRequest( transaction_id = "sale-txn-id", // opcional — vincular a la venta original currency_code = "818", decimal_shift = "2", amount = "100.00", card_brand = "VISA", card_type = "CREDIT", loyalty_token = "HhYDMww7aJgcdyJPU6QVWpFAZPNRhSzkqNpErHM3hikU", // huella de la tarjeta, nunca el PAN masked_pan = "1111", card_expiration_date = "1230", auth_code = "123456", par = "V0010013000000000000000000001" // opcional ) flowHandler.refund( context, TransactionTypes.Refund, request ).subscribe({ response -> // RefundTransactionResponse }) { throwable -> if (throwable is NotRegisteredFlowException) { // la aplicación de destino no ha registrado ninguna acción para este paso } else { // otra excepción } }
Modelos de solicitud y respuesta
package com.zeal.zeal_communicator_sdk.communicationRequests class RefundTransactionRequest( val transaction_id: String? = null, // id de la venta original (opcional) val currency_code: String, val decimal_shift: String, val amount: String, val card_brand: String, val card_type: String, val loyalty_token: String, // huella de la tarjeta, nunca el número de tarjeta val masked_pan: String? = null, val card_expiration_date: String? = null, val auth_code: String? = null, val par: String? = null // opcional — referencia de cuenta de pago EMV )
package com.zeal.zeal_communicator_sdk.communicationResponses class RefundTransactionResponse( tran_status: String, third_party_request_type: String, message: String = "" ) : BaseResponse(third_party_request_type, tran_status, message)
Reversión
Se activa cuando hay que revertir una venta completada. Pasa el payment_reference del
recibo digital para deshacer puntos, recompensas o cupones asociados.
Enviar una acción
val request = MarkAsReverseRequest( payment_reference = "payment-ref-from-digital-receipt", reversal_payment_reference = "", // opcional par = "V0010013000000000000000000001" // opcional ) flowHandler.reverse( context, TransactionTypes.Void, request ).subscribe({ response -> // MarkAsReverseResponse }) { throwable -> if (throwable is NotRegisteredFlowException) { // la aplicación de destino no ha registrado ninguna acción para este paso } else { // otra excepción } }
Modelos de solicitud y respuesta
package com.zeal.zeal_communicator_sdk.communicationRequests class MarkAsReverseRequest( var payment_reference: String, // referencia/id de pago de la venta original var reversal_payment_reference: String = "", // opcional var par: String? = null // opcional — referencia de cuenta de pago EMV )
package com.zeal.zeal_communicator_sdk.communicationResponses class MarkAsReverseResponse( tran_status: String, third_party_request_type: String, message: String = "" ) : BaseResponse(third_party_request_type, tran_status, message)