
Automatización de suspensión de cuentas por impago mediante hooks de WHMCS
Como reseller o administrador de hosting, mantener una política clara frente a impagos es esencial para la estabilidad operativa. WHMCS ofrece un sistema de hooks que permite automatizar tareas como la suspensión de servicios cuando un cliente no paga. En esta guía técnica y práctica veremos cómo funcionan los hooks, un ejemplo concreto en PHP, consideraciones de seguridad y recomendaciones para integrar la solución sin afectar la experiencia del cliente ni la integridad del sistema.
Por qué automatizar la suspensión por impago
Automatizar reduce trabajo manual, evita errores y asegura que la política comercial se aplica de forma consistente. Los beneficios clave:
- Consistencia operativa: reglas aplicadas igualmente a todos los clientes.
- Escalabilidad: soporta grandes volúmenes de cuentas sin intervención humana.
- Auditoría y trazabilidad: logs automáticos para facturación y contabilidad.
- Menor riesgo de deuda acumulada y mejor gestión de recursos.
Cómo funcionan los hooks de WHMCS
Los hooks son puntos de extensión que ejecutan código PHP en eventos específicos del ciclo de vida de WHMCS (cron diario, actualización de facturas, cambios de estado). Un hook típico para suspender por impago se engancha al evento que prefieras —por ejemplo, DailyCronJob para revisiones periódicas— y realiza acciones como identificar facturas vencidas y suspender servicios asociados mediante la API interna.
Conceptos clave
- Evento: punto de ejecución (p. ej.
DailyCronJob,InvoicePaid). - Hook file: archivo PHP en
includes/hooksque WHMCS carga automáticamente. - LocalAPI: función
localAPI()para invocar comandos internos (suspender servicio, enviar notificación). - Capsule: la capa de acceso a base de datos basada en Illuminate/DB para consultas seguras.
Ejemplo práctico: hook para suspender servicios tras X días de impago
A continuación tienes un ejemplo realista y comentado para incorporar en tu entorno de pruebas. Este hook se ejecuta en DailyCronJob, busca facturas vencidas con más de D días de antigüedad y suspende servicios asociados usando la localAPI. Ajusta los parámetros, roles y pruebas antes de usarlo en producción.
<?php
use WHMCS\Database\Capsule;
add_hook('DailyCronJob', 1, function($vars) {
$daysOverdue = 7; // número de días tras el vencimiento para suspender
$adminUser = 'admin'; // usuario admin con permisos para localAPI
// Consulta segura con Capsule
$overdueInvoices = Capsule::table('tblinvoices')
->select('tblinvoices.id', 'tblinvoices.userid')
->join('tblinvoiceitems', 'tblinvoices.id', '=', 'tblinvoiceitems.invoiceid')
->where('tblinvoices.status', 'Unpaid')
->whereRaw('tblinvoices.duedate <= DATE_SUB(CURDATE(), INTERVAL ? DAY)', [$daysOverdue])
->groupBy('tblinvoices.id')
->get();
foreach ($overdueInvoices as $invoice) {
// Obtener servicios activos del cliente
$services = Capsule::table('tblhosting')
->where('userid', $invoice->userid)
->where('domainstatus', 'Active')
->get();
foreach ($services as $service) {
// Intentamos suspender vía API del módulo
$command = 'ModuleSuspend';
$postData = ['serviceid' => $service->id];
$results = localAPI($command, $postData, $adminUser);
// Si falla la suspensión por módulo, marcamos el servicio como 'Suspended' en BD
if ($results['result'] !== 'success') {
Capsule::table('tblhosting')
->where('id', $service->id)
->update(['domainstatus' => 'Suspended']);
}
// Registrar auditoría (tabla propia o log)
logActivity("Automated suspension: service {$service->id} for invoice {$invoice->id}");
}
}
});
?>
Notas sobre el ejemplo
- Prueba primero en un entorno de staging y con un usuario administrador de pruebas.
- No olvides ajustar
$daysOverduea la política contractual y legal de tu país. - La función
localAPIrequiere un usuario con permisos administrativos configurado en WHMCS.
Validaciones y buenas prácticas de seguridad
Automatizar acciones que afectan cuentas de clientes exige rigor en seguridad y control. Recomendaciones imprescindibles:
- Principio de menor privilegio: usa un usuario API con permisos mínimos necesarios.
- Saneamiento y consultas preparadas: usa
Capsulepara evitar inyección SQL (ver documentación en PHP.net). - Registro detallado: guarda eventos en logs para auditoría y resolución de disputas.
- Idempotencia: asegura que re-ejecuciones no provoquen estados inconsistentes.
- Rate limiting: evita saturar los módulos o servidores al procesar grandes lotes.
- Revisión legal: confirma que los términos de servicio permiten suspensión automática por impago.
Para sanitizar y validar datos en PHP consulta la guía oficial en PHP.net. Para aspectos de seguridad web generales, incluidas prácticas de validación y manejo de errores, la guía de OWASP es una referencia obligada.
Integración con comunicaciones y flujos de cobro
No basta con suspender: el proceso debe integrarse con notificaciones y flujos de cobro para maximizar la recuperación y minimizar la fricción con clientes:
- Enviar recordatorios automáticos antes y después del vencimiento.
- Ofrecer enlaces de pago y métodos rápidos (pagos en un clic, pasarelas compatibles).
- Actualizar el estado del cliente y tickets para seguimiento interno.
- Proveer un proceso de reactivación automático al recibir el pago (ej. mediante hook
InvoicePaid).
Ejemplo: reactivación con InvoicePaid
Un hook simple en InvoicePaid puede reactivar servicios suspendidos automáticamente tras confirmar el pago.
<?php
add_hook('InvoicePaid', 1, function($vars) {
$invoiceId = $vars['invoiceid'];
$adminUser = 'admin';
// Lógica: buscar servicios relacionados y ejecutar ModuleUnsuspend
$services = Capsule::table('tblhosting')
->where('userid', $vars['userid'])
->where('domainstatus', 'Suspended')
->get();
foreach ($services as $service) {
localAPI('ModuleUnsuspend', ['serviceid' => $service->id], $adminUser);
logActivity("Automated unsuspend: service {$service->id} after invoice {$invoiceId} paid");
}
});
?>
Pruebas, monitoreo y despliegue
Proceso recomendado antes de producción:
- Crear un entorno de staging con datos anónimos.
- Ejecutar cron diario manualmente y revisar logs.
- Simular fallos del módulo, permisos insuficientes y errores de red.
- Implementar alertas operativas en caso de tasas inusuales de suspensión.
Monitorear métricas como número de suspensiones diarias, tasas de recuperación y tickets abiertos ayudará a afinar la política y detectar falsos positivos.
Consideraciones finales y cumplimiento
Automatizar suspensiones mejora la eficiencia pero conlleva responsabilidad. Asegúrate de que tu política de cobranza y los avisos a clientes respeten la legislación local y las cláusulas del contrato de servicio. Además, documenta cada decisión y conserva registros por el periodo legal requerido.
Conclusión
Implementar hooks en WHMCS para suspender cuentas por impago es una solución técnica y operativa efectiva para resellers que buscan controlar riesgo y optimizar recursos. Con un hook bien diseñado, pruebas en staging, control de permisos y un plan de comunicaciones automatizado, puedes aplicar una política de suspensión justa y trazable. Aplica las buenas prácticas de seguridad (consultando referencias en PHP.net y OWASP), realiza pruebas exhaustivas y monitoriza el comportamiento tras el despliegue para ajustar tiempos y excepciones según tus necesidades comerciales.
Si buscas ampliar esto con gestión de avisos por correo, integración con pasarelas específicas o una política de reactivación condicionada, la arquitectura de hooks de WHMCS te permite extender la lógica con modularidad y control.