Blog ·
Automatizar la facturación en ISPConfig
ISPConfig responde HTTP 200 a todo, fallos incluidos. Qué implica para un gancho de facturación y cómo encaja el ciclo de la cuenta en su API remota.
Por Provibr
ISPConfig tiene un comando para cada momento en el que el dinero y las máquinas se tocan: crear la cuenta, suspenderla, moverla a otro paquete, eliminarla. Lo que no tiene es nada que decida cuándo ejecutarlos.
Conectar las dos mitades es, en su mayor parte, trabajo corriente. Dos cosas de ISPConfig no lo son, y las dos rompen en silencio un primer intento: el código de estado de una llamada no dice absolutamente nada, y una cuenta no es un cliente.
El código de estado no dice nada
Todo vuelve como HTTP 200. Los errores de validación, el «eso no existe», una contraseña equivocada, un método que el usuario remoto no tiene permiso de llamar: todos ellos, 200. El veredicto es un campo code dentro del cuerpo JSON.
code | Significado |
|---|---|
ok | Funcionó; response lleva el resultado |
remote_fault | Falló: validación, objeto ausente, autenticación, permiso. message lo explica |
invalid_method | Método desconocido, o un método que no está en esa clase |
permission_denied | Al usuario remoto le falta esa función |
La clasificación se hace sobre code y sobre el texto, nunca sobre el estado. La razón por la que esto importa más en una integración de facturación que en ninguna otra cosa es el sondeo: un cliente que trata el 200 como éxito lee un fallo de autenticación como un inventario vacío correcto, y a continuación marca como desaparecidas todas las cuentas de ese cliente. Una sola sesión caducada, y su reconciliación elimina un negocio de alojamiento.
El campo message viene en dos sabores, y la diferencia es útil. Los errores de validación de la propia capa de formularios del panel son una lista de claves de traducción separadas por <br>, no frases: domain_error_unique para un dominio que ya está alojado. Las comprobaciones de la biblioteca remota son frases corrientes en inglés: Invalid client_id 99999. A las claves se las compara; a las frases se las cita.
Una cuenta es un sitio web, no un cliente
ISPConfig separa dos cosas que la mayoría de los paneles de control funden en una. Un client es un inicio de sesión en el panel con límites para toda la cuenta. Un web_domain es un sitio alojado. Un cliente puede poseer varios sitios web.
Una cuenta de alojamiento de Provibr es un sitio web, identificada por su dominio. Crear una necesita por tanto un propietario, así que el agente crea un cliente nuevo y un sitio web debajo, y deriva el inicio de sesión del cliente a partir del dominio para poder volver a encontrar siempre al propietario.
Esa decisión es lo que hace seguro el camino de la eliminación, y el camino de la eliminación es donde esta integración estuvo a punto de torcerse. Más sobre eso abajo.
El ciclo de vida, en correspondencia
| Evento de facturación | Llamada de ISPConfig | Respuesta en caso de éxito |
|---|---|---|
| Pedido pagado | client_add, y luego sites_web_domain_add | code: ok, dos veces |
| Factura vencida | sites_web_domain_set_status(id, "inactive") | code: ok |
| Pago recibido | sites_web_domain_set_status(id, "active") | code: ok |
| Subida / bajada de plan | client_update con una nueva plantilla de cliente | code: ok |
| Cancelación | sites_web_domain_delete, y quizá luego el cliente | code: ok |
La suspensión es idempotente en los dos sentidos
La suspensión cambia el indicador active del sitio web entre y y n. No hay máscaras de bits ni estados parciales: un sitio está encendido o está apagado.
Una segunda suspensión sobre un sitio ya suspendido responde code: ok con una respuesta de 0, es decir, cero filas cambiadas. Eso no es un error, y un ciclo de reclamación de pago que suspende todo lo vencido, incluido lo que suspendió ayer, no tiene nada de lo que disculparse. Vale la pena apreciar lo rara que es esa propiedad: Facturación y aprovisionamiento en HestiaCP cuenta cómo esa misma segunda suspensión es allí un HTTP 401, indistinguible de un secreto equivocado, en un panel que bloquea su dirección tras cinco inicios de sesión rechazados.
Algo que conviene conocer, aunque la integración no lo use: ISPConfig tiene además un bloqueo a nivel de cliente, y activarlo pone todos los sitios web de ese cliente en inactivo de golpe. Un cliente que se bloquea a sí mismo en el panel, o un bloqueo de revendedor por encima de él, aparece por tanto en el sondeo como suspendido. Eso es correcto, y no es algo que haya hecho su sistema de facturación.
Cambiar de paquete aquí es una acción de verdad
Un paquete de ISPConfig es una plantilla de cliente: un conjunto de límites con nombre, construido por un administrador en el panel. La API remota no puede crear ninguna, lo cual está bien, porque un plan debería referirse a un paquete en lugar de inventarlo. Provibr pasa el nombre del paquete y el agente busca el identificador de la plantilla.
Eso convierte a ISPConfig en uno de los paneles de control donde un cambio de plan es de verdad un cambio de plan. CloudPanel y CyberPanel tienen que rechazarlo de plano; aquí ocurre y los límites se mueven al instante.
Dos avisos medidos para quien escriba esto por su cuenta. Hay que enviar una actualización mínima, que no lleve más que la plantilla nueva: una actualización con el registro entero del cliente volvió como remote_fault sin ningún mensaje utilizable, y lo mismo pasó con una que combinaba una plantilla explícita con límites explícitos. Y conviene saber que la plantilla prevalece sobre los límites que se envíen también, que es el sentido correcto pero sorprende la primera vez.
La señal de listo es global del servidor
Crear un sitio web responde en milisegundos, y esa respuesta significa aceptado, no terminado. La fila de la base de datos existe; el host virtual y el directorio raíz los deja escritos el demonio del servidor de forma asíncrona.
La señal que hay que esperar es el recuento de la cola de trabajos de ese servidor, que se midió cayendo de tres a cero en unos ocho segundos sobre una máquina tranquila, y en unos veintitrés segundos en una ejecución anterior. Es un contador global, no uno por comando. En un servidor multiinquilino con carga puede quedarse por encima de cero por los trabajos de otros clientes, o llegar a cero mientras el trabajo propio sigue pendiente.
Así que la regla es un tiempo de espera con un mensaje veraz en lugar de una espera infinita: sondear hasta que la cola esté vacía o hasta que se agote el presupuesto de creación de 180 segundos, y entonces informar de la cuenta como creada, porque lo está. «El sitio se está terminando de configurar» es mejor cosa que decirle a un cliente que paga que un indicador de progreso que no para nunca.
Eliminar es una cuestión de privacidad, no de limpieza
Esta es la parte del artículo que hay que quedarse si no se guarda ninguna otra, y en realidad no va de ISPConfig.
El camino de la eliminación tenía un defecto que ningún banco de pruebas podía ver: comparaba dos campos que en realidad nunca son iguales, así que la rama que eliminaba al cliente propietario era código muerto. Cada eliminación dejaba atrás un inicio de sesión del panel con el nombre del cliente, su dirección de correo, sus datos de contacto y su contraseña. El comando respondía ok, el sitio web desaparecía, el contador bajaba a cero, y los datos personales de una persona que había pedido irse se quedaban en el nodo.
Nada por encima del panel puede ver eso. Un proceso de purga y una exportación de datos personales limpian nuestro lado; no tienen ninguna visión de lo que queda en su nodo de alojamiento. La regla que salió de ahí merece que se la copie:
> Un camino de eliminación se mide contra la propia base de datos del panel, y nunca contra «el comando devolvió ok».
En ISPConfig son cuatro recuentos, y los cuatro tienen que ser cero: sitios web, clientes, inicios de sesión del sistema y el directorio del cliente en disco. Y hay que medirlo con el panel y no con el ayudante de limpieza de la prueba propia, porque el ayudante puede arrastrar el mismo malentendido y entonces la máquina parece limpia mientras la integración pierde datos.
La regla de eliminación segura en sí cabe en una línea: eliminar el sitio web; eliminar al cliente propietario solo si no le queda ningún sitio web. ISPConfig tiene una llamada que elimina a un cliente y todo lo que hay debajo, y sobre una cuenta importada eso se llevaría por delante los otros sitios del cliente. Nunca hay que eliminar más de lo que se pidió.
Nada es instantáneo
Su panel solo es alcanzable a través del agente que está dentro de su propia red, y ese agente marca hacia fuera, así que un endpoint que cambia una cuenta no puede responder con el resultado. Responde que el pedido fue aceptado y le entrega un comando a seguir hasta que su estado sea definitivo: terminado, fallido, expirado o cancelado. La lectura nunca funciona así, porque un inventario o una factura viene de una base de datos y no de su host.
La consecuencia práctica para un gancho de facturación: no hay que marcar el pedido como completo sobre la respuesta de aceptación. Todo lo que crea algo acepta además una clave de idempotencia de su propia cosecha, así que un webhook reintentado y un doble clic no cuestan nada.
Dónde vive la factura
Provibr no factura a sus clientes, no los persigue, y no sabe qué les cobra. Esa relación es suya.
Lo que Provibr factura es la capacidad reservada: cuántas cuentas de alojamiento se pueden hacer correr a la vez, a un precio unitario que baja por tramos a medida que sube el recuento. Para una cuenta de alojamiento no existe un «detenido»: hay activo y suspendido, y una cuenta suspendida no cuenta. Así que la acción de reclamación de pago que ya se quería por razones comerciales es también la que libera la plaza que se está pagando.
Lo que no se automatiza
Provibr gestiona cuentas, no el panel. No instala ISPConfig, no lo actualiza, y no toca buzones, bases de datos ni DNS: un cliente que elimina su propio buzón lo hace sin que nada por encima del panel lo sepa ni le importe. No hay consola para una cuenta de alojamiento, ni reinstalación, ni suspensión parcial.
Si todavía se está antes de la parte de facturación, la pieza acompañante es Cómo vender alojamiento web con ISPConfig, que cubre el usuario remoto, el acotado y el modelo de un panel con varios servidores. Las credenciales, el certificado y la pantalla de paquetes están documentados en la página de documentación de ISPConfig.
Preguntas frecuentes
¿Por qué toda llamada a la API de ISPConfig devuelve HTTP 200?
Porque su API remota lleva el veredicto en el cuerpo y no en la línea de estado. El campo code dice ok, remote_fault, invalid_method o permission_denied. Un cliente que se fía del estado lee un fallo de autenticación como una respuesta vacía correcta.
¿Una cuenta de ISPConfig es un cliente o un sitio web?
Un sitio web. ISPConfig mantiene separados el client, que es un inicio de sesión en el panel con límites, y el web_domain, que es un sitio alojado, y un cliente puede poseer varios sitios. Una cuenta de alojamiento se identifica aquí por su dominio.
¿Puede un sistema de facturación suspender dos veces el mismo sitio de ISPConfig?
Sí. La segunda llamada responde ok con cero filas cambiadas, lo cual no es un error. Reactivar también es idempotente, así que un ciclo nocturno de reclamación de pago no necesita ningún estado propio.
¿Al eliminar una cuenta de ISPConfig se elimina el inicio de sesión del cliente en el panel?
Tiene que hacerlo, y vale la pena verificarlo en la instalación propia. El comportamiento correcto es eliminar el sitio web y después al cliente propietario solo cuando a ese cliente no le queda ningún sitio web. Una eliminación que deja al cliente atrás deja en el nodo el nombre, la dirección y la contraseña del cliente.
¿Se puede cambiar un paquete de ISPConfig desde un sistema de facturación?
Sí. Un paquete es una plantilla de cliente, y asignar otra distinta mueve los límites de inmediato. En la actualización hay que enviar solo la plantilla nueva; una carga más completa se midió fallando sin un mensaje de error utilizable.