Seguridad y alta del integrador
La verificación en el teléfono (desde FINORA Pago 0.15.0; versión recomendada 0.16.0), la verificación del integrador en el servidor, la entrega de la lista desde el servidor y su edición desde la consola están desplegadas. FINORA Pago 0.16.0 está en el canal beta del marketplace y se entrega bajo acuerdo.
Cómo te reconoce FINORA Pago
- Android dice quién llama. FINORA Pago lee el paquete de la app que lo invocó con
startActivityForResult. No hay ningún campo en la solicitud que identifique al llamador. - Tu firma, en cada llamada. FINORA Pago comprueba que el certificado con que está firmada tu app coincide con una huella SHA-256 que autorizó el comercio. En Android 9 o superior respeta la rotación de llaves; en versiones anteriores exige que todos los firmantes coincidan. Si alguien instala una copia de tu app firmada con otra llave, deja de estar autorizada en el acto.
- La lista del comercio, cerrada por defecto. La lista de integradores es un parámetro administrado del terminal (
PAGO_INTEGRADORES) que el servidor de FINORA entrega a FINORA Pago 0.15.0 o superior con sus parámetros. No se puede editar en el teléfono. Sin lista, vacía o mal formada: ninguna app está autorizada. - Permisos por app. Para cada app, el comercio decide qué acciones puede pedir (cobrar, anular, consultar el estado), un monto máximo por cobro y en qué sucursales. Si pides algo fuera de eso recibes
NO_AUTORIZADOy no se crea nada en el servidor. - Doble verificación. El servidor de FINORA vuelve a comprobar tu paquete y tu huella contra la misma lista al crear el cobro y al anularlo, y deja registrado en la intención qué app la creó.
- Protección de la pantalla. La pantalla de cobro ignora toques que lleguen a través de ventanas superpuestas y, en Android 12 o superior, oculta las superposiciones de otras apps.
- Sin datos de tarjeta. Tu app nunca recibe datos de tarjeta: solo últimos 4 dígitos y marca.
A una app no autorizada, FinoraPago.estado() solo le responde autorizado = false y el motivo: ningún dato del terminal ni del comercio.
Obtener la huella SHA-256 del certificado
Lo que se autoriza es la huella del certificado de firma, no la del APK. Usa la del certificado con que se firma lo que de verdad se instala en los equipos.
# Desde tu almacén de llaves
keytool -list -v -keystore mi-llave.jks -alias mi-alias | grep SHA256
# Desde el APK ya firmado
apksigner verify --print-certs app-release.apk | grep SHA-256
# Desde Gradle, para cada variante
./gradlew :app:signingReport
Si publicas con Play App Signing, la llave que firma lo instalado es la de Google: copia la huella de Play Console → Integridad de la app → Certificado de la llave de firma de apps. La huella se acepta con o sin : y en mayúsculas o minúsculas, pero sin espacios: no se recorta, y un espacio (al principio, al final o entre los pares) la vuelve inválida.
Si vas a rotar tu llave, entrega al comercio las dos huellas antes de publicar la versión nueva.
La lista de integradores (PAGO_INTEGRADORES)
Es un texto JSON de hasta 8000 caracteres cuya raíz es un array, con una entrada por app. FINORA Pago, el servidor y la consola aplican exactamente las mismas reglas.
[
{
"paquete": "com.ejemplo.reparto",
"huellas": [
"9A:1F:3C:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:C3"
],
"acciones": ["COBRAR", "REVERSAR", "ESTADO"],
"montoMaximoCentavos": 5000000,
"sucursales": ["CENTRO", 42]
},
{
"paquete": "com.ejemplo.kiosco",
"huellas": ["0f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0"],
"acciones": ["*"]
}
]
Reglas del valor completo
| Caso | Resultado |
|---|---|
Ausente, vacío o [] | Ninguna app autorizada |
| Más de 8000 caracteres | Ninguna app autorizada |
JSON que no se puede leer, incluido texto después del array ([...]x, [...]], [...] {}) | Ninguna app autorizada. Los espacios y saltos de línea al final sí se admiten |
La raíz no es un array (por ejemplo, {"integradores": [...]}) | Ninguna app autorizada. El envoltorio no se acepta |
| Una entrada inválida | Se descarta solo esa entrada; las demás siguen valiendo y se registra un aviso sin datos sensibles |
Reglas de cada entrada
| Campo | Obligatorio | Regla | Si no se cumple |
|---|---|---|---|
paquete | Sí | Texto con un nombre de paquete Android válido: el applicationId exacto de tu app | Entrada inválida |
huellas | Sí | Array con al menos una huella SHA-256 del certificado: 64 caracteres hexadecimales. Solo se normaliza quitando : y pasando a mayúsculas; un espacio la vuelve inválida. No se acepta huella como texto suelto | Entrada inválida |
acciones | Sí | Array no vacío con valores de COBRAR, REVERSAR, ESTADO, o exactamente ["*"] (todas) | Entrada inválida (ausente, vacía, valor desconocido o * mezclado con otras) |
montoMaximoCentavos | No | Entero mayor que cero: tope por cobro. Ausente o null = sin tope | 0, negativo, decimal, texto o fuera de un entero de 64 bits: entrada inválida |
sucursales | No | Array de sucursales permitidas. Un número JSON es el id de la sucursal; un texto JSON no vacío es su código (store_code o outlet_code), exacto. Ausente o null = todas las del comercio | []: entrada inválida |
Reglas comunes
FINORA Pago, el servidor y la consola aplican estas reglas sin excepción:
nulles lo mismo que no poner el campo enmontoMaximoCentavos(sin tope) ysucursales(todas).- No se recorta ningún campo de
PAGO_INTEGRADORESni el código de sucursal de tu solicitud." com.ejemplo.reparto"no es tu paquete y" CENTRO"no es"CENTRO". La huella solo se normaliza quitando:y pasando a mayúsculas. Los demás campos de texto de tu solicitud (referencia externa, descripción, pedido, medio, moneda, documento del pagador, clave de idempotencia y motivo de la anulación) sí se recortan. - Los códigos de sucursal son exactos: distinguen mayúsculas y no se normalizan (
"Centro"no es"CENTRO"), tanto en la lista como en el código que envías. - Id y código juntos: si tu solicitud trae código e id de sucursal, los dos tienen que estar permitidos y ser la misma sucursal. Si uno no está permitido recibes
NO_AUTORIZADO; si no son la misma sucursal,PETICION_INVALIDAconSUCURSAL_INVALIDA.
En el servidor, los reversos automáticos de FINORA Pago y la anulación del operador (ANULACION_OPERADOR) quedan exentos del control del integrador: no exigen tu paquete ni tu huella. La protección principal entre integradores es la verificación de la firma en el teléfono: FINORA Pago solo atiende SDK_REVERSAR de la app firmada con una huella autorizada y solo sobre los cobros que esa misma app aprobó. Detalles en Anular un cobro.
Sin la acción ESTADO, FinoraPago.estado() te responde autorizado = false: pídela si quieres comprobar el estado antes de mostrar el botón de cobro.
Qué hace el comercio
- Recibe de ti: el
applicationId, la huella (o huellas), las acciones que necesitas, las sucursales y un tope razonable por cobro. - En la consola de FINORA, abre los parámetros administrados de FINORA Pago para Android y edita la lista de integradores (Apps integradoras autorizadas (SDK), grupo Integración), para todo el comercio o para un terminal concreto. Sin una lista por sucursal en el valor, aplica a todas las sucursales.
- El terminal recibe la lista en su siguiente actualización de parámetros, o al pulsar «Revisar de nuevo» en FINORA Pago.
- Tú compruebas con
FinoraPago.estado(context).autorizadoy haces un cobro de prueba en la variante de demostración.
Para dar de baja una app basta con quitar su entrada: el terminal deja de aceptarla en su siguiente actualización de parámetros y el servidor deja de aceptarla en el acto.