La respuesta corta: guarda la operación antes de llamar al proveedor y trata “no sé qué pasó” como un estado propio, que bloquea el reintento hasta consultarlo. Casi todos los dobles cobros nacen de un botón “Reintentar” que asume que el primer intento falló.
El momento que nadie prueba
En un cobro electrónico hay tres resultados posibles, no dos: aprobado, rechazado y desconocido. El tercero ocurre cuando la solicitud salió, el proveedor quizá la procesó y la respuesta nunca volvió, porque se cayó la red o porque la aplicación se cerró.
Cuando programé mi primer flujo de este tipo, el camino feliz me tomó poco. Casi todo el trabajo estuvo en ese tercer resultado. Si tu módulo lo trata como un rechazo, el cajero vuelve a cobrar. Si el primer intento sí pasó, el cliente pagó dos veces y te enteras en la conciliación.
Reserva primero, llama después
La regla que ahora aplico en cualquier operación de dinero o de puntos es escribir en un diario local antes de salir a la red. En Android uso una tabla transaccional que reserva la operación de forma atómica. El orden importa:
- Escribe la operación en el diario con estado “reservada” y su referencia.
- Llama al proveedor.
- Actualiza el diario con la autorización o el rechazo.
- Si al abrir la aplicación encuentras una operación que quedó “reservada”, márcala como incierta. No la reenvíes.
El paso 4 es el que cubre la muerte del proceso. Si el sistema operativo cierra la aplicación entre los pasos 2 y 3, al volver sabes que hay algo sin resolver, y el reenvío queda bloqueado hasta aclararlo con el proveedor o con el supervisor.
Maneja el dinero como texto, y sospecha de la moneda
En una de las integraciones en las que trabajé, el punto de venta entrega el importe en centavos como texto y la moneda puede llegar como código ISO numérico o alfabético: 600 o PYG son la misma moneda. Mis reglas para esta capa son aburridas a propósito:
- Valida el importe con una expresión estricta, solo dígitos. Rechaza lo demás en vez de interpretarlo.
- Usa decimales exactos, nunca punto flotante.
- Normaliza la moneda en un solo sitio y falla si no la reconoces.
- Haz que los redondeos inesperados lancen error. Si una división no da exacta, prefiero una excepción a un centavo perdido.
Verifica la autorización, no solo el “aprobado”
Con la redención de puntos aparece una trampa más. El programa aprueba unidades y tu caja cobra pesos, de modo que hay una conversión de por medio. Antes de aceptar, recalculo el valor aprobado y compruebo dos cosas: que trae una referencia de autorización y que no supera lo que se pidió. Una aprobación sin referencia, para mí, no es una aprobación.
Qué pedirle a quien te lo desarrolle
Si estás contratando este módulo, haz estas tres pruebas el día de la entrega:
- Desconecta la red justo después de enviar el cobro. Observa qué le muestra la caja al cajero.
- Cierra la aplicación a la fuerza durante el cobro y vuelve a abrirla. Busca la operación pendiente.
- Intenta cobrar otra vez la misma venta. No debería dejarte sin una decisión explícita.
Si alguna termina en un segundo cobro silencioso, el módulo todavía no está listo, por bien que funcione con buena conexión.