Blog ·
Automatizar la facturación y el aprovisionamiento en Plesk
De un pedido pagado a una suscripción activa, y de una factura vencida a una cuenta apagada: las llamadas, los tiempos medidos y cuatro trampas automáticas.
Por Provibr
Un producto de alojamiento automatizado tiene tres momentos en los que el dinero y las máquinas se tocan:
- El pedido se paga. Una suscripción debe existir, sobre el plan de servicio correcto, en cuestión de segundos.
- La factura está vencida. La suscripción debe apagarse, y volver en cuanto se pague.
- La suscripción termina. Debe eliminarse, de verdad, datos incluidos.
Plesk tiene llamadas para los tres. Lo que no tiene es nada que decida cuándo ejecutarlas, y esa es la mitad que hay que construir. Esta página trata de conectar ambas cosas, y de cuatro comportamientos que son inofensivos cuando se ejecutan a mano y peligrosos cuando un planificador los ejecuta a las tres de la madrugada.
Todo esto se midió contra un servidor Plesk Obsidian 18.0.80 en funcionamiento en agosto de 2026.
Los tres momentos y las llamadas que hay debajo
| Momento | API | Llamada | Duración medida |
|---|---|---|---|
| Pedido pagado | REST | POST /clients y luego POST /domains | 0,6 a 0,7 s + 4,1 a 4,5 s |
| Vencido | XML | <webspace><set> con gen_setup.status | 0,78 s |
| Pagado al final | XML | la misma llamada, estado de vuelta a 0 | 0,78 s |
| Subida o bajada de plan | XML | <webspace><switch-subscription> | 1,5 s |
| Cancelación | REST | DELETE /domains/{id} y luego DELETE /clients/{id} | 7,7 s + |
| Lectura del estado | XML | <webspace><get> para todo el servidor | 0,33 s |
Dos de esas cifras dan forma al diseño. Una suscripción tarda cuatro segundos y medio en crearse y casi ocho en eliminarse. Es lo bastante largo como para que un formulario de pedido tenga que indicar que algo está pasando, lo bastante largo como para que un presupuesto de tiempo de espera escrito para una API rápida corte por la mitad una llamada que funciona, y lo bastante largo como para que dos pedidos que llegan a la vez sean realmente concurrentes en lugar de serlo solo en teoría.
Fíjese también en la fila de lectura. Una sola llamada XML devuelve todas las suscripciones con su plan, su estado, su cuota y su uso en un tercio de segundo, con independencia de cuántas haya, y un sistema de facturación se reconcilia con el panel sin parar.
La trampa de la suspensión es un fallo de facturación, no un detalle de API
Plesk ofrece dos maneras de suspender, y escriben campos diferentes. En un producto de alojamiento esto deja de ser una anécdota.
Medido, sobre la misma suscripción:
| Lo que se hace | XML gen_info.status | Estado REST de la suscripción |
|---|---|---|
| nada | 0 | active |
PUT /domains/{id}/status a suspendido | 0 | suspended |
XML <webspace><set> estado 16 | 16 | suspended |
Un ciclo de reclamación de pago que suspende por REST escribe un campo que la lectura en bloque no mira, de modo que la plataforma sigue informando de la cuenta como activa. Aquí está por qué eso perjudica a la facturación en concreto: cuando por fin se paga la factura, la automatización mira su propio estado, ve una cuenta que nunca fue suspendida, y no la reactiva. El cliente ha pagado y sigue apagado, y nada ha registrado un error.
La regla cabe en una línea: suspenda por el campo que lee. Provibr escribe <webspace><set><gen_setup><status>, tras lo cual ambas vistas coinciden.
gen_info.status es una máscara de bits; medimos 0 para activo, 1 para webspace desactivado y 16 para deshabilitado por el administrador. Trate como suspendido todo lo que no sea cero: la única lectura que sobrevive a un valor que nadie ha visto todavía.
Una reserva honesta: no medimos la suspensión de una suscripción ya suspendida. En HestiaCP ese caso no es idempotente y devuelve un error con forma de error de autenticación (exactamente aquello con lo que un ciclo de reclamación tropieza a diario), así que establézcalo en su propio servidor antes de fiarse de ello.
Una clave caducada tiene exactamente el mismo aspecto que un servidor vacío
Este es el fallo que puede causar un daño real, y se describe en una sola frase.
La API XML devuelve HTTP 200 para una clave errónea. El error está dentro del documento, como código 11003. Un cliente que comprueba el código de estado lee, por tanto, un fallo de autenticación como una ronda con éxito que no encontró ninguna suscripción.
Ahora coloque eso dentro de una tarea de reconciliación nocturna. Una ronda con éxito que no encontró nada significa, para cualquier plataforma de alojamiento, que todas las cuentas que ayer estaban ahí han sido eliminadas. Una sola clave caducada, y de la noche a la mañana el sistema marca a toda la base de clientes como desaparecida.
De ahí salen dos reglas, y se aplican a cualquier panel que informe del fallo con un 200, lo que, de los paneles que hemos integrado, es el caso de la mayoría:
- En la API XML el código de estado no lleva información alguna, ni siquiera sobre la autenticación. Analice el documento.
- Una respuesta ilegible es desconocida, nunca vacía. Un servidor vacío sí existe, y produce un único resultado vacío en lugar de un error. Esos dos casos son de verdad diferentes, y distinguirlos es todo el trabajo.
REST falla de otra forma más: una clave inutilizable vuelve como HTTP 401 con un cuerpo completamente vacío. Así que una prueba de conexión tiene que sondear ambas superficies e informar de ellas por separado. Un resultado REST en verde con una API XML muda significa que la lista de cuentas, la lista de planes y todo cambio de plan quedarán vacíos, y la conclusión tentadora es que el cliente no tiene ninguna cuenta.
El código de error no dice qué salió mal
Los errores REST de Plesk llevan un código numérico, y es tentador basar en él un conmutador. Medido, no clasifica:
- 1007 cubre a la vez «ese dominio ya existe» y «ese inicio de sesión de cliente ya existe».
- 1013 cubre a la vez «no existe ese plan de servicio» (REST) y «el dominio no existe» (XML).
- 0 significa ningún código, no ningún error.
Para una integración de facturación, el daño aterriza en la lógica de reintento. «El dominio ya existe» tras un pedido pagado puede significar que el intento anterior tuvo éxito a medias y que conviene mirar antes de volver a intentarlo; «no existe ese plan de servicio» significa que el pedido no tendrá éxito jamás y corresponde a un humano. Comparten una familia de códigos. Por eso es el texto el que clasifica, y esa correspondencia debe estar en un único lugar del código en vez de volver a deducirse en cada punto de llamada.
Existe también una quinta forma de fallo: pídale a REST una ruta que no existe y responde con una página HTML, no con JSON.
Un pedido fallido puede bloquear el reintento
Medido: crear un dominio contra un plan de servicio que no existe devuelve HTTP 404 con un mensaje claro, y el objeto dominio existe de todos modos después, sin tipo de alojamiento y con una raíz de documentos vacía. Plesk crea primero el objeto y aplica el plan después, y no revierte nada cuando el segundo paso falla.
En un flujo de facturación eso se lee así: el cliente pagó, el aprovisionamiento falló, y el reintento falla ahora de forma diferente, porque el dominio está en uso por una cuenta que nunca recibió. El segundo fallo parece un pedido duplicado, que es una de las cosas más desconcertantes de depurar a partir de un ticket de soporte.
De ahí salen dos medidas baratas. Resuelva el plan antes de crear nada: ya tiene la lista de planes, así que busque el nombre en local y haga fallar el pedido antes de tocar el panel, lo que elimina este fallo en vez de gestionarlo. Y limpie después de una creación fallida, porque dejar los escombros convierte un pedido fallido en un nombre de dominio bloqueado para siempre.
Como contraste, un error de validación de campo como un inicio de sesión de cliente duplicado devuelve HTTP 400 y no deja nada detrás. Esa comprobación se ejecuta antes de la creación; solo la búsqueda del plan llega demasiado tarde para salvarle.
Dos llamadas que tienen cada una un medio
Eliminar una suscripción significa DELETE /domains/{id} y luego DELETE /clients/{id}. Si la primera tiene éxito y la segunda no, queda un registro de cliente que no posee nada: invisible en la mayoría de las vistas, y un error de inicio de sesión duplicado la próxima vez que ese cliente vuelva. Con 7,7 segundos, la eliminación es también lo bastante larga como para que una red la interrumpa, así que la cancelación merece el mismo trato que el aprovisionamiento: vuelva a leer el panel después y reconcilie contra la lectura en bloque, no contra la respuesta que obtuvo.
Las subidas y bajadas de plan tienen su propio rincón. <webspace><switch-subscription> no acepta un nombre de plan, solo el GUID o el ID externo del plan, allí donde en todo el resto de Plesk un paquete se referencia por su nombre. Provibr conserva el nombre como aquello que ven los humanos y hace la traducción de nombre a GUID internamente a partir de la lista de planes que el sondeo ya obtiene. Almacenar un GUID en su sistema de facturación en su lugar funciona justo hasta que alguien reconstruye un plan.
Dónde vive la factura
Los tres momentos de arriba son solo la mitad de un producto de alojamiento. La otra mitad es qué aspecto tiene su propia factura.
Se paga por capacidad, por tipo de recurso, y una cuenta de alojamiento es uno de ellos. Cada suscripción cuenta, esté en marcha o no; solo una suspendida no cuenta. Ese es el sentido correcto para la reclamación de pago: suspender a un cliente vencido libera la plaza mientras sus datos quedan intactos, y reactivarlo la vuelve a ocupar.
Superar el límite no se bloquea en el momento en que ocurre. Se detecta, se indica qué tipo de recurso y por cuánto, y se dispone de un día laborable para corregirlo. Si ese plazo vence, los servidores más recientes por encima del límite se apagan, los más recientes primero, para que sobreviva lo que se construyó antes. Un segundo exceso dentro de una semana concede una hora en lugar de un día, porque si no el periodo de gracia podría renovarse indefinidamente bajando del límite y volviendo a superarlo. Nada se vuelve a arrancar en su lugar cuando se resuelve: encender una máquina es una decisión, y la plataforma no la toma mientras nadie mira.
Cada periodo produce una proforma que puede leer e imprimir, y la factura definitiva llega desde la contabilidad como un fichero. Una línea de factura registra el nombre del paquete tal como estaba en el momento de facturar, de modo que renombrar un plan más adelante no reescribe el historial.
Lo que hace Provibr, y lo que deliberadamente no hace
Provibr se coloca entre su facturación y su servidor Plesk. Una suscripción es una fila corriente: pídala, suspéndala, reactívela, cámbiele el plan de servicio, elimínela. La suspensión pasa por el campo que lee el sondeo. El plan se resuelve antes de la creación, y una creación fallida se limpia. Cada mutación termina volviendo a leer la suscripción, de modo que lo que se almacena es lo que se observó y no lo que se pidió. El agente marca hacia fuera desde su propia red, así que el puerto 8443 no tiene que dar la cara a internet.
Lo que no hace: gestionar el propio servidor Plesk, ni entrar dentro de una suscripción. Tampoco pide nunca a Plesk los conjuntos de datos que contienen la contraseña FTP o el hash de la contraseña del cliente. Ambos los entrega el panel en texto plano si se los pide.
Leer a continuación
- Cómo vender alojamiento web con Plesk: el modelo de producto, las dos API y lo que nunca le pedimos al panel.
- Facturación y licencia: capacidad, precios por tramos, crédito, proformas y qué pasa al superar el límite.
- Configuración de Plesk: la clave de API, los planes de servicio, los planes web y la importación de suscripciones.
Medido contra Plesk Obsidian 18.0.80 en agosto de 2026, con las respuestas registradas como fixtures. La suspensión repetida, las claves acotadas a revendedor y el comportamiento bajo una carga de tráfico real no se midieron, y se señalan como tales más arriba.