Lectura de tarjetas

Lectura de tarjetas

ℹ️

Este proceso es obligatorio

En esta fase se procede a la recuperación de datos de la tarjeta mediante la implementación del estándar EMV, haciendo uso del kernel del dispositivo.

Requisitos

  • Inyección y configuración de llaves
  • Listado de tags EMV
  • Monto de la transacción
  • Tipo de transacción
  • Código de país
  • Código de moneda
  • Identificador de la adquirencia (Acquirer ID)

Resultado

  • Después del proceso de lectura, se obtendrá un objeto con todos los datos de la tarjeta requeridos para procesar operaciones de pago, anulaciones o devoluciones.

Paso a paso

  1. Instanciar el objeto CardProcessData.
  2. Invocar el método findCardProcess y pasarle como parámetro:
    1. El objeto OperationFlow
    2. Instancia del objeto CardData()
    3. El contexto
    4. El modo de lectura a procesar
  3. Configurar los observers para recibir el resultado de la lectura.

Instanciar objeto OperationFlow

  • Amount: Objeto que contiene información del monto de la transacción en formato ISO. Es decir, los 2 últimos dígitos representan los decimales y no lleva punto decimal. Ejemplo: $10.00 = 1000
  • Capture: Objeto que contiene información para la captura de los datos de la tarjeta. Se requiere instanciar los objetos:
    • Capture(): Instanciar el objeto así: operationFlow.capture = Capture()
    • Card(): Instanciar el objeto. Así: operationFlow.capture!!.card = Card()
    • Holder(): Instanciar el objeto. Así: operationFlow.capture!!.card.holder = Holder()
    • Identification(): Instanciar el objeto. Así: operationFlow.capture!!.card.holder.identification = Identification()
    • Terminal(): Instanciar el objeto. Así: operationFlow.terminal = Terminal()
  • TransactionType: Tipo de transacción. Este objeto es un enum con los siguientes valores:
enum class OperationType {
   PAYMENT,
   REFUND,
   ANNULMENT,
   REVERSE
}

Instanciar objeto CardData

  • countryCode: Código ISO de país. Ver Tabla de código de país. Ejemplo: 032
  • acquirerId: Código del adquirente. Ver Tabla de adquirencias. Ejemplo: GPS
  • tagList: Lista de String List<String> que contiene el listado de tags EMV que se van a recuperar durante la lectura. Este listado depende de cada adquirencia.

Instanciar objeto Amount

  • Breakdown: Listado de desglose de montos. Está compuesta por monto y descripción. Listado de valores:

    • OPERATION: si la transacción tiene propina, aquí va el valor base. Si la transacción no tiene propina, aquí va el valor total.
    • TIP: (aplica cuando la transacción tiene propina, aquí solo va el valor de la propina).
  • Currency: Código de moneda. Posibles valores:

    • ARS = Pesos Argentinos
    • MX = Pesos Mexicanos
  • Total: Monto total de la transacción en formato ISO. Ejemplo: $25.50 = 2550

Ejemplo de implementación

val cardProcessData = CardProcessData()
 cardProcessData.findCardProcess(
            operationFlow = doOperationFlow(amount),
            cardData = doCardData(),
            context = this,
            inputModeType = InputMode.ALL
        )
cardProcessData.selectApp.observe(this, selectAppObserver)
cardProcessData.navigate.observe(this, navigateObserver)
 
 
private fun doOperationFlow(inputAmount: String): OperationFlow {
    operationFlow.amount = Amount()
    val breakdownList = Breakdown()
    breakdownList.description = OPERATION 
    breakdownList.amount =
        StringUtils.notFormatAmount(inputAmount) 
 
    operationFlow.capture = Capture()
    operationFlow.capture!!.card = Card()
    operationFlow.apply {
        amount?.let {
            it.total =
                StringUtils.notFormatAmount(inputAmount) 
            it.currency = Currency.ARS.name
            it.breakdown = listOf(breakdownList)
        }
    }
    operationFlow.transactionType = OperationType.PAYMENT
 
    //inicializar otros objetos
    operationFlow.capture!!.card.holder = Holder()
    operationFlow.capture!!.card.holder.identification = Identification()
    operationFlow.terminal = Terminal()
 
    OperationFlowHolder.operationFlow = operationFlow
    return operationFlow
    }
 
    private fun doCardData(): CardData {
        return CardData(
            countryCode = Country.ARG.code,
            acquirerId = Acquirer.GPS.name,
            tagList = doTagListTest()
        )
    }
 
    private val navigateObserver: (Any) -> Unit = {
        when (it) {
            is Bundle -> {
                val status = it.get("status")
                val statusResult: StatusResult = status as StatusResult
                val intent = Intent(this, CardErrorActivity::class.java)
                intent.putExtra("status", statusResult)
                startActivity(intent)
            }
 
            is String -> {
                //Validar BIN
                val bundle = Bundle().apply {
                    putString("bin", it)
                }
                val intent = Intent(this, CardRulesValidationActivity::class.java).apply {
                    putExtras(bundle)
                }
                startActivity(intent)
            }
        }
    }

Listado de TAGs EMV por adquirencia

🇦🇷 Global Processing
  • 9F26
  • 82
  • 9F36
  • 9F10
  • 9F33
  • 95
  • 9F37
  • 9A
  • 9C
  • 9F02
  • 9F03
  • 9F27
  • 9F34
  • 5F2A
  • 9F1A
  • 5F25
  • 84
  • 9F1E
  • 9F6E
🇲🇽 Banorte
  • 4F
  • 50
  • 57
  • 5A
  • 82
  • 84
  • 8A
  • 95
  • 9A
  • 9B
  • 9C
  • 5F20
  • 5F24
  • 5F25
  • 5F28
  • 5F2A
  • 5F30
  • 5F34
  • 9F02
  • 9F03
  • 9F07
  • 9F09
  • 9F0D
  • 9F0E
  • 9F0F
  • 9F10
  • 9F12
  • 9F15
  • 9F1A
  • 9F1C
  • 9F1E
  • 9F21
  • 9F26
  • 9F27
  • 9F33
  • 9F34
  • 9F35
  • 9F36
  • 9F37
  • 9F39
  • 9F41
  • 9F53
  • 9F6E

Códigos de respuesta

El resultado se recibe mediante el observer navigateObserver. En la siguiente tabla se muestran los posibles objetos que se pueden recibir como respuesta:

ObjetoDescripción
ReaderStatusEste objeto se devuelve en caso de fallo durante el proceso de lectura.
StringEste objeto se devuelve cuando el proceso de lectura es exitoso, retorna el BIN de la tarjeta, los primeros 8 dígitos del número de la tarjeta.

Objeto ReaderStatus

  • type: Campo de tipo MessageType, posibles valores:
    • ERROR → El proceso de lectura terminó con errores.
    • INFO → Se recomienda mostrar el mensaje informativo en la pantalla de la terminal.
    • SUCCESS → El proceso de lectura terminó correctamente.
  • code: Campo de tipo ReaderCode, posibles valores:
    • SUCCESS → Indica que el proceso interno del kernel se ejecutó sin errores.
    • FALLBACK → Indica que la lectura fue fallback.
    • ERROR → Indica que el proceso interno del kernel se ejecutó con errores.
  • description: Campo de tipo String, contiene una descripción del código de error.

Lista de posibles códigos de error

CódigoDescripción
MULT_CARDSe detectaron varias tarjetas contactless en el lector.
USE_ICC_CARDNo se detectó el chip de la tarjeta, se permite deslizar la banda.
NO_EMV_APPSNo se encontró configuración EMV para esta tarjeta, se permite deslizar la banda.
TIMEOUT_ERRORSe excedió el tiempo máximo de lectura.
BAD_SWIPE_ERRORLa banda de la tarjeta está dañada.