épale
Fintech · 2025 — 2026
Chatea. Paga. Sin salir de la conversación.
Mensajería cifrada y pagos en el mismo chat. La misma burbuja donde escribes es la que envía dinero, solicita un cobro o muestra el recibo de la transacción.
Desarrollo móvil Flutter: arquitectura por features, módulo de pagos/KYC y sincronización offline
Producto privado en desarrollo: el código y la ficha de tienda todavía no son públicos.

Mariana Ruiz
Escribiendo...
¿Me pasas lo del almuerzo?
Dale, ¿te lo mando por aquí?
¿No tienes que abrir el banco?
No. Se paga en el mismo chat.
Bs. 1.250,00
Salir del chat cuesta dinero
el problema
En Venezuela, pagar a otra persona significa salir del chat, abrir el banco, copiar datos, hacer la transferencia y volver a la conversación a mandar una captura como comprobante. Ese ida y vuelta rompe la conversación, genera errores de tipeo en cédulas y cuentas, y deja el 'recibo' como una imagen que nadie puede verificar. A eso se suma que un mensajero con dinero adentro necesita algo que las apps de chat comunes no piden: identidad verificada, PIN, biometría, cifrado del historial y funcionamiento con conectividad intermitente.
9:38
la solución
Épale convierte el pago en un tipo de mensaje más. Desde el menú '+' del chat se elige 'Pago' o 'Solicitar pago', se abre una hoja con monto en doble moneda (Bs y USD a tasa BCV), subtotal, comisión bancaria y total, se confirma con PIN, biometría u OTP, y el resultado queda como una burbuja de pago dentro de la conversación, con su estado (pendiente, en proceso, exitoso, rechazado, fallido) y su detalle consultable. Alrededor de eso se construyó lo que hace viable ese flujo: KYC obligatorio antes del primer pago, QR de cobro cifrados con AES-256-GCM y prefijo propio EPQ1, pagos agendados con recordatorio, historial de transacciones y ajustes de seguridad, todo sobre una base de datos local cifrada y un motor de mensajes que tolera la pérdida de conexión.
9:41

Ocho piezas que hacen viable un chat con dinero dentro
El pago vive dentro del chat
Los tipos de mensaje receipt_payment y receive_payment son ciudadanos de primera clase del pipeline: se emiten por Socket.IO, se guardan en la tabla payments de la base local y se pintan como una burbuja con monto, concepto, comisión y equivalente en dólares.
Billetera con KYC, PIN y biometría
La sección Pagos exige identidad verificada: escaneo del documento con reconocimiento de texto ML Kit, prueba de vida facial con retos (sonreír, parpadear, girar la cabeza, acercarse) y confirmación de cada operación con PIN o local_auth.
QR de cobro cifrado extremo a extremo
Cada QR de cobro se serializa y cifra con AES-256-GCM (IV aleatorio de 12 bytes, prefijo EPQ1) antes de convertirse en imagen, así un lector genérico no puede interpretar ni alterar el payload de pago.
Historial local cifrado con SQLCipher
Nueve tablas (chats, mensajes, contactos, reacciones, pagos, mensajes de IA, perfil, metadata, contactos no registrados) viven en una SQLite cifrada cuya clave de 32 bytes se genera por dispositivo con Random.secure() y se guarda en el almacenamiento seguro del sistema.
Diseñado para conexión intermitente
El socket mantiene una cola de emisiones pendientes que se drena al reconectar, workmanager sincroniza mensajes en segundo plano y la base local es la fuente de verdad de la UI, de modo que la app se usa igual sin señal.
Mensajes de una sola vista
El modo 'Una vista' abre imágenes, videos y audios en un visor que bloquea capturas de pantalla con screen_protector y se apoya en el sensor de proximidad, marcando el mensaje como visto al cerrarlo.
Asistente Épale integrado
Un módulo de chat con IA, con su propia instancia de Dio y su tabla de mensajes, resuelve dudas sobre el uso de la app y consultas generales desde una pestaña de conversaciones aparte.
Tres idiomas y seis temas
1.562 claves traducidas a español, inglés y portugués, más cuatro paletas (turquesa, verde, azul, morado) en variante clara y oscura que el usuario elige desde ajustes de tema.
La burbuja se despega y abre la billetera
Dentro del mismo módulo viven el QR cifrado, las cuentas vinculadas y el comprobante del pago.
EPQ1·AES-256-GCM
**** 4417
Cuenta vinculada
Bs. · Banesco
comprobante
Bs. 1.250,00
Mariana Ruiz
Ref. EP-2409183
07/09/2026 · 9:41
QR cifrado
Payload AES-256-GCM con IV de 12 bytes y prefijo EPQ1 en base64url.
Cuentas vinculadas
Cuenta favorita preseleccionada y comisión bancaria desglosada.
Comprobante
Ticket con recorte perforado: referencia, fecha y destinatario.
710
archivos Dart
~142k
líneas de código
7
módulos de features
58
rutas en go_router
45
pantallas
143
providers de Riverpod
9
tablas SQLCipher (esquema v30)
15
tipos de evento Socket.IO
12
tipos de mensaje soportados
3
idiomas (es, en, pt)
1.562
claves de traducción
18
pruebas E2E con Patrol
El historial vive cifrado en el propio teléfono
La base local es la fuente de verdad de la interfaz, así que también es el sitio donde hay que poner el candado.
SQLCipher, clave por dispositivo
9 tablas y esquema en la versión 30. La clave de 32 bytes se genera una sola vez con Random.secure() y se guarda en flutter_secure_storage: nunca está en el código ni en el servidor.
AES-256-GCM en los QR de cobro
IV aleatorio de 12 bytes, base64url y prefijo EPQ1. Un lector genérico sólo ve una cadena opaca que no puede interpretar ni alterar.
PIN, biometría y OTP
Cada operación de dinero se confirma con PIN de 4 dígitos, local_auth o un código de un solo uso autocompletado con smart_auth.
Mensajes de una sola vista
El visor seguro bloquea capturas con screen_protector, se apoya en el sensor de proximidad y marca el contenido como visto al cerrarse.
sqflite_sqlcipher · flutter_secure_storage · encrypt · local_auth · screen_protector
Siete módulos, tres capas cada uno
Pasa el cursor por un módulo para seguir su columna: cada feature atraviesa dominio, infraestructura y presentación sin saltarse ninguna.
Clean Architecture por features. Cada módulo (auth, chat, payments, ai_chat, camera, home, shared) se divide en domain (entidades, contratos de repositorio y casos de uso, sin imports de framework), infrastructure (implementaciones, datasources remotos y locales, mappers y errores propios) y presentation (pantallas, widgets y providers de Riverpod). La navegación es un go_router único con 58 rutas y redirecciones que fuerzan la secuencia registro → OTP → perfil → home. La capa de red usa tres instancias de Dio (API, almacenamiento con timeouts largos y servicio de IA) con refresco automático de token ante un 401 y verificación de conectividad previa. El tiempo real corre sobre Socket.IO autenticado con Bearer, con 15 tipos de evento y una cola de emisiones pendientes que se drena al reconectar. La persistencia es SQLite cifrada con SQLCipher (9 tablas, versión de esquema 30) con streams por chatId para actualizar la UI, y las credenciales y claves viven en flutter_secure_storage. Las dependencias se registran con get_it + injectable generados por build_runner, y la configuración de entorno (API, socket, almacenamiento, servicio de IA y KYC) llega por flutter_dotenv.
Seis pantallas, una sola conversación
Recreadas en HTML y CSS con los colores, los textos y la disposición reales de la app. Arrastra para recorrerlas.
Mensajes
Mariana Ruiz
Escribiendo...
Grupo Familia
🖼 Foto
Carlos Medina
🧾 Pago #1042
Andreína P.
Borrador: nos vemos a las 6
Luis Ferrer
🎙 Nota de voz
Asistente Épale
¿En qué te ayudo hoy?
Yudith Rojas
📍 Ubicación
Mensajes (lista de chats)
Filtros, borradores, fijados y no leídos

Mariana Ruiz
Escribiendo...
¿Me pasas lo del almuerzo?
9:38
Va por aquí mismo, no hago transferencia 😌
9:39
Bs. 1.250,00
Bs. 380,00
Cuota del condominio
Conversación con burbuja de pago
El pago como un mensaje más
Pagos
QR de Mesa 4
2 códigos QR
Bs.1.250,00
QR Finaliza en 1h 20min
Tasas del día 07/09/2026 valor BCV
USD 36,45
EUR 39,80
Generar QR de cobro
Crea un código QR para recibir un pago.
Pago o cobro por QR
Escanea un QR para pagar o cobrar.
Pagos agendados
Programa pagos a tus contactos de épale.
Pago a usuario
Realiza pagos a tus contactos de épale.
Pago de servicios
Realiza pagos de tus servicios.
Cuentas vinculadas
Administre sus cuentas bancarias.
Historial
Transacciones enviadas y recibidas.
Ajustes
Gestione su PIN y autenticación biométrica.
Pagos (centro de la billetera)
QR activos, tasa BCV y accesos

Pago
Monto
Introduce tu PIN
o usa tu huella
Hoja de pago y confirmación
Doble moneda, comisión y PIN
Pago exitoso
Bs. 1.250,00

Comprobante del pago
Ticket con recorte perforado
Verificación de identidad
Paso 3 de 5 · Prueba de vida
Sonríe
Mantén el rostro dentro del óvalo
Verificación de identidad (KYC + prueba de vida)
Retos de prueba de vida
← arrastra →
Las maquetas reproducen la interfaz real; los datos que muestran son de ejemplo.
Todo lo que ya contesta la app
Dieciocho capacidades que hoy están dentro del binario, contadas como lo que son: mensajes de ida y vuelta.
Siete problemas y su recibo
reto 01
Los mensajes enviados mientras el teléfono estaba sin señal se perdían o llegaban desordenados al volver la conexión.
cómo se resolvió
La base local cifrada pasó a ser la fuente de verdad: el mensaje se persiste como 'enviando' y se pinta de inmediato, mientras el socket acumula las emisiones en una cola pendiente que se drena al reconectar y workmanager corre una sincronización en segundo plano que reconcilia el historial contra el último id conocido.
reto 02
En la sincronización de mensajes creados por el servidor mientras el usuario estaba offline, el backend omitía el receiverId en los chats 1:1, así que el remitente no podía resolver con quién era la conversación y el mensaje se descartaba sólo de su lado.
cómo se resolvió
El parseo de la respuesta de sincronización ahora deriva el receiverId a partir de los miembros del chat (el miembro distinto al emisor) en chats privados de dos personas, evitando la llamada de creación de chat con id vacío que devolvía 400.
reto 03
Un QR de cobro es un objeto público: cualquiera puede fotografiarlo y un lector genérico podría leer o alterar monto y destinatario.
cómo se resolvió
El payload se cifra con AES-256-GCM usando un IV aleatorio de 12 bytes y se codifica en base64url con el prefijo propio EPQ1, de modo que sólo la app reconoce y descifra el código; un escáner cualquiera sólo ve una cadena opaca.
reto 04
El historial de chat y de pagos queda en el teléfono, un dispositivo que puede perderse o clonarse.
cómo se resolvió
Toda la base SQLite se cifra con SQLCipher y la clave de 32 bytes se genera una sola vez por dispositivo con Random.secure() y se guarda en el almacenamiento seguro del sistema, nunca en el código ni en el servidor.
reto 05
Las solicitudes de pago programadas debían dispararse a una hora exacta aunque la app estuviera cerrada y sin conexión, algo que el cliente no puede garantizar.
cómo se resolvió
Se implementó un motor local de mejor esfuerzo (sondeo cada 30 segundos mientras la app vive, más disparo al volver al primer plano) apoyado en la cola de mensajes pendientes para la durabilidad, y se documentó explícitamente que la ejecución garantizada corresponde al backend, que envía un recordatorio push al vencimiento.
reto 06
Los mensajes de 'una sola vista' pierden todo el sentido si el receptor puede hacer una captura de pantalla.
cómo se resolvió
El visor seguro bloquea capturas con screen_protector mientras está abierto, se apoya en el sensor de proximidad para la reproducción al oído y marca el contenido como visto al cerrarse, dejando la burbuja en estado 'Visto'.
reto 07
Probar de verdad un flujo que mezcla SMS, permisos nativos de contactos y envío de mensajes reales es imposible con tests de widget.
cómo se resolvió
Se montó una suite E2E con Patrol (18 archivos, page objects por pantalla) que corre en un teléfono físico, atraviesa los diálogos nativos del sistema, usa un datasource de autenticación falso para saltarse el SMS real y muestra un HUD en pantalla con el estado de cada paso.
Con qué está construida
Núcleo
Arquitectura y estado
Datos y tiempo real
Pagos, identidad y seguridad
Multimedia
Firebase y notificaciones
Contactos y telefonía
Calidad y entrega
Épale es una app móvil Flutter que une, en una sola conversación, mensajería estilo WhatsApp y pagos reales en bolívares: la misma burbuja donde escribes es la que envía dinero, solicita un cobro o muestra el recibo de la transacción.
El proyecto está construido con Clean Architecture estricta (domain → infrastructure → presentation) sobre 7 módulos de features, 710 archivos Dart y unas 142.000 líneas, con Riverpod para estado, go_router para 58 rutas con redirecciones según sesión, y get_it + injectable para inyección de dependencias generada por código.
La base local es una SQLite cifrada con SQLCipher (9 tablas, migración 30) cuya clave se genera por dispositivo con Random.secure() y vive en el llavero seguro: la app funciona sin conexión y el socket, la cola de emisiones pendientes y el sincronizador en segundo plano reconcilian todo al reconectar.
El módulo de pagos suma verificación de identidad (KYC con escaneo de documento y prueba de vida facial), PIN y biometría, QR de cobro cifrado con AES-256-GCM, pagos agendados, pago a usuario, recargas de servicios y conversión Bs/USD con tasa BCV del día.
Todo el producto está localizado en español, inglés y portugués (1.562 claves de traducción) y cuenta con 18 pruebas E2E Patrol que automatizan el recorrido real en un teléfono físico, incluidos los diálogos nativos de permisos.
Piezas de marca
Turquesa confiable: el verde azulado de una app financiera seria, suavizado por aguamarinas luminosos (#A9FFF0, #47EBAF) y grises muy claros. Superficies blancas, esquinas redondeadas de 12 px, tipografía sans de sistema y el wordmark 'épale' en minúsculas y trazo redondo sobre el degradado teal.










Mensajería cifrada y pagos en el mismo chat
entregado
Épale
¿Quieres algo así para tu producto?
Mensajería en tiempo real, base local cifrada, KYC con prueba de vida y pagos dentro del chat: si tu producto necesita mover dinero donde la gente ya está hablando, ése es el terreno que conozco.