Un proveedor de internet tiene dos fuentes de verdad: el sistema de facturación y el router. La automatización de facturación para MikroTik consiste en mantenerlas de acuerdo, y los errores caros viven en el hueco entre ambas: un cliente que pagó y sigue cortado, un cliente que dejó de pagar y sigue conectado, o una renovación aplicada dos veces porque una pasarela repitió su webhook. Cuando construimos Linkhive, nuestra plataforma de facturación autoalojada en Laravel para proveedores de banda ancha y Wi-Fi, estos tres fallos marcaron el diseño más que cualquier función.
La automatización de facturación para MikroTik empieza con pasos repetibles
El ciclo de facturación de Linkhive es una lista ordenada de pasos: crear facturas de renovación, renovar con el saldo prepago, completar facturas pagadas, enviar recordatorios, caducar y suspender, y después gestionar los vales. El programador lo ejecuta cada 15 minutos, y en hosting sin cron el mismo ciclo se ejecuta con el tráfico web, como máximo cada 15 minutos.
Las ejecuciones frecuentes solo son seguras si una segunda ejecución no cambia nada. Por eso cada paso pregunta si su trabajo ya está hecho. Antes de facturar una renovación busca una factura de ese cliente, paquete y periodo. Antes de enviar un recordatorio revisa si el registro de mensajes ya tiene uno de hoy. Cada paso se ejecuta además en su propio try/catch: el fallo se registra y los demás pasos continúan, así que un registro defectuoso no detiene todas las suspensiones de la red.
Los plazos son configurables. Por defecto la factura se emite tres días antes de caducar, los recordatorios salen tres días y un día antes, y el servicio se corta tras dos días de gracia.

Una actualización atómica evita la renovación doble
Un mismo pago puede llegar por tres vías a la vez: el navegador del cliente que vuelve de la pasarela, el webhook de la pasarela y el ciclo de facturación que recoge una factura pagada. Si cada vía comprueba «¿ya se renovó?» y luego renueva, dos pueden pasar la comprobación a la vez y el cliente recibe dos meses por el precio de uno.
Comprobar y después escribir deja ese hueco, así que convertimos ambas cosas en una sola sentencia:
$claimed = Invoice::whereKey($invoice->id)
->whereNull('fulfilled_at')
->update(['fulfilled_at' => now()]);
if ($claimed === 0) {
return false; // another request got here first
}
La base de datos deja que solo un UPDATE coincida con esa fila, llegue quien llegue primero. Los demás ven cero filas afectadas y paran. Los pagos reciben un trato parecido: approvePayment() bloquea la fila con lockForUpdate() dentro de una transacción, de modo que llamarlo dos veces aplica el dinero una sola vez.
Pregunta a la pasarela, nunca al navegador
Todo lo que llega a una URL de retorno se puede falsificar, así que solo se trata como un indicio. Con Stripe, Linkhive guarda el ID de la sesión de Checkout al iniciar el pago y luego consulta esa sesión en la API de Stripe al volver. El dinero solo se registra si la sesión coincide y Stripe la marca como pagada, con la referencia correcta, el importe exacto y la moneda correcta. PayPal sigue el mismo patrón, y los drivers de SSLCommerz, bKash y Nagad confirman importe y referencia con sus propias API.

Un router caído no debe deshacer un pago
El diseño tentador habla con el router dentro de la transacción del pago. Entonces un reinicio del router convierte un pago con tarjeta correcto en una página de error. En Linkhive, cada cambio en el router pasa por una clase, Provisioner, que nunca lanza excepciones. Primero se registra el dinero. Si no se puede llegar al router, el fallo se escribe en un registro de aprovisionamiento y la suscripción queda marcada para reintentar.
Una tarea horaria reintenta las suscripciones marcadas durante un máximo de tres días. Lee el estado actual de la suscripción en lugar de repetir la orden antigua: una suscripción activa se activa y cualquier otra se suspende. Si un cliente pagó mientras el router estaba caído, el reintento lo reconecta y no aplica la suspensión obsoleta.
Para la automatización de facturación para MikroTik, el driver trabaja con la API de RouterOS, en el puerto 8728 o por TLS en el 8729, con un cliente escrito por nosotros. Actualiza /ppp/secret para PPPoE o /ip/hotspot/user para hotspot y después corta la sesión activa para que el cliente se reconecte con el perfil correcto. FreeRADIUS está detrás de la misma interfaz de driver, así que al código de facturación no le importa cuál use cada proveedor.

Demuéstralo con pruebas que ataquen las reglas
Estas reglas fallan en silencio, así que la automatización de facturación para MikroTik necesita pruebas que intenten romperlas. Linkhive incluye 147 pruebas automáticas que pasan en SQLite y en MySQL 8.4. Ejecutan el ciclo repetidamente para comprobar la idempotencia, envían retornos falsificados y prueban importes y monedas que no coinciden. El análisis estático con Larastan en nivel 5 no informa de errores.

Ideas clave
- Escribe los pasos de facturación para que una segunda ejecución no cambie nada y ejecútalos a menudo.
- Reclama el trabajo con un único
UPDATEatómico, no con una lectura seguida de una escritura. - Confirma cada pago con la API de la pasarela, incluidos importe y moneda.
- Deja las llamadas al router fuera de las transacciones de pago y registra los fallos para reintentar.
- Reintenta desde el estado actual, nunca repitiendo una orden antigua.
Puedes verlo todo en la demo en vivo de Linkhive, leer el resumen de funciones en Charming Theme o conseguir Linkhive en Vibe96.
¿Gestionas una red de banda ancha o Wi-Fi y las hojas de cálculo ya no bastan? Hablemos. ArtinTech Solution crea este tipo de facturación e integraciones con nuestro servicio de desarrollo Laravel.