Blog ·
Automatización de la facturación para PufferPanel
Del pedido al servidor, y de la factura impagada al servidor detenido, en PufferPanel. El ciclo de vida, la regla asíncrona y la ausencia de suspensión.
Por Provibr
La mayoría de las páginas sobre automatización de la facturación empiezan por el camino feliz. Esta empieza por el hueco, porque en PufferPanel es el hueco el que determina el diseño.
PufferPanel no tiene suspensión. Ni columna, ni endpoint. El estado de un servidor solo conoce running e installing. Todo lo que sigue se deriva de eso.
Medido contra PufferPanel 3.0.9.
Dos capas de facturación, y no son lo mismo
| Capa | Quién factura a quién | Qué cuenta |
|---|---|---|
| Su facturación | Su empresa → su cliente | Un servidor de juego, al mes, al precio que fije |
| Facturación de la plataforma | Provibr → su empresa | Capacidad: cuántos servidores de cada tipo puede hacer correr a la vez |
Lo que cobra a sus propios clientes se queda enteramente dentro de su sistema de facturación. Provibr nunca ve una factura de cliente y nunca habla con sus clientes. Su sistema de facturación posee la decisión, la capa de aprovisionamiento posee la ejecución.
El ciclo de vida, en correspondencia
| Evento de facturación | Qué debe pasar | Efecto del lado de PufferPanel |
|---|---|---|
| Pedido pagado | Crear el servidor a partir del plan | Definición completa de la plantilla enviada en línea, servidor creado, el instalador se ejecuta |
| Factura vencida | Suspender | Contenedor detenido + acceso bloqueado en la plataforma (véase más abajo) |
| Pago recibido | Reactivar | Acceso restablecido; el cliente arranca el servidor |
| Cancelación | Eliminar | Servidor detenido primero, luego eliminado |
| Subida / bajada de plan | Reinstalar | Vuelve a ejecutar la instalación de la plantilla |
Cuatro de esas cinco filas son ordinarias. La segunda no.
El hueco de la suspensión, y cómo diseñar en torno a él
Cuando una plataforma suspende un servidor de juego PufferPanel (para hacer respetar un límite de licencia, o porque lo ordenó por impago), detiene el contenedor y bloquea el acceso a ese servidor en el propio panel de la plataforma. El servidor no corre, y su cliente no puede arrancarlo desde su panel de control.
Pero el bloqueo es una noción de plataforma, no de panel. Cualquiera con acceso directo a la instalación de PufferPanel puede volver a arrancar el servidor. PufferPanel no impone nada, porque no tiene con qué imponerlo.
Vale la pena decirlo con claridad en lugar de enterrarlo, porque cambia lo que debería vender:
| Su configuración | ¿Importa el hueco? |
|---|---|
| Los clientes usan solo su panel de control; sin cuentas de panel | No. No pueden llegar a PufferPanel directamente. |
| Los clientes tienen inicios de sesión de PufferPanel | Sí. Un cliente suspendido puede deshacer la suspensión. |
| Revende a revendedores con acceso al host | Sí, y gravemente. |
Si está en la segunda o la tercera fila y la aplicación de la reclamación de pago importa, use un panel con un indicador suspended de verdad. Pelican tiene uno, y un servidor suspendido ahí sigue suspendido sin importar quién inicie sesión.
Una vía intermedia, si quiere conservar PufferPanel: cancelar antes. Puesto que una suspensión es blanda, trátela como una etapa de aviso en lugar de una etapa de aplicación, y traslade la aplicación real a la eliminación, con una política de conservación y una copia de seguridad tomada antes, comunicadas por adelantado. Esa es una decisión de producto, no técnica.
La regla que da forma a todo: nada es instantáneo
Su panel vive en su propia red, y una plataforma sensata lo alcanza a través de un agente que se conecta hacia fuera: ningún puerto entrante, ningún agujero en el cortafuegos. La consecuencia es inevitable: un endpoint que cambia una máquina no puede responder con el resultado. Responde que el pedido fue aceptado:
POST /v1/servers/{serverId}/actions/suspend
Authorization: Bearer pvk_...
Idempotency-Key: dunning-inv-10482{
"command": {
"id": "cmd_...",
"kind": "game.suspend",
"status": "pending"
}
}202 Accepted, no 200. Luego lee ese comando hasta que su estado sea definitivo: done, failed, timed_out o cancelled. Un comando fallido lleva el propio código de error del agente con sus argumentos. La lectura es distinta: un inventario, una dirección o una factura responde de inmediato, porque eso viene de una base de datos y no de su host.
Diseñe sus ganchos de reclamación de pago en torno a esto. Un gancho que trata «la API respondió» como «el trabajo está hecho» informará de una suspensión con éxito que nunca ocurrió, justo el día que importaba.
Repetir sin riesgo
Todo lo que crea algo acepta una cabecera Idempotency-Key de su propia creación. Repita la misma petición con el mismo valor y recupera el primer resultado en lugar de un segundo servidor. Indéxela sobre algo estable de su lado (el ID de la factura, el ID del servicio, la etapa de reclamación), porque los webhooks reenviados y los crons de quince minutos son normales, y ambos deberían ser inofensivos. Reutilizar ese valor para una petición distinta se rechaza a propósito: una clave que significa dos cosas no significa nada.
Los verbos, y cuándo están permitidos
Un servidor de juego acepta seis acciones por la API: start · stop · restart · kill · suspend · resume, guardadas por el estado actual del servidor:
| Acción | Permitida desde |
|---|---|
| start | stopped, error, unknown |
| stop / restart / kill | running, error, unknown |
| suspend | running, stopped, installing, error, unknown |
| resume | suspended |
| reinstall | running, stopped, error |
Puede suspender un servidor que ya está detenido, y es deliberado: una aplicación de la regla que se puede esquivar pulsando «detener» no es aplicación de nada. suspend desde installing sigue la misma lógica: una cancelación que llega a mitad de instalación no debería esperar a que la instalación termine.
El pedido pasa por un plan, y no puede ser de otra manera
En algunos paneles se puede componer un pedido a mano. En PufferPanel prácticamente no, y la razón es estructural: PufferPanel exige la definición completa de la plantilla en línea al crear un servidor. No existe un «haz uno a partir de la plantilla X» por referencia, así que la definición tiene que venir de un catálogo. Un plan de juego lleva el nombre de la plantilla y los límites de recursos; el pedido apunta al plan. Si construye su propio puente, acabará construyendo este catálogo de todos modos.
Dos detalles medidos con los que es fácil tropezar:
- Las plantillas de la comunidad usan por defecto un entorno de host, que necesita binarios que un host de panel recién instalado no tiene. Cambie a la variante docker de la plantilla, o cada pedido falla con un error de binario faltante que se lee como un fallo de la plataforma.
- La eliminación detiene el servidor primero. El demonio se niega a retirar un contenedor en ejecución; una eliminación contra un servidor en marcha devuelve un 500.
Lo que deliberadamente no está
- Sin facturación por uso. El endpoint de estadísticas de PufferPanel solo informa del porcentaje de CPU y de la memoria: sin disco, sin red, sin tiempo de actividad. Dos de las cuatro gráficas estándar de servidor de juego quedarían permanentemente vacías, así que las gráficas de uso están desactivadas para este proveedor. No es posible facturar al contador datos que no existen.
- Sin consola en el panel de control. La consola de PufferPanel se basa en sondeo en lugar de ser un terminal en vivo; un apretón de manos WebSocket conforme a la especificación en
/consoledevuelve 200 JSON en lugar de 101. Sus clientes obtienen la consola en el propio PufferPanel. - Sin colocación según la capacidad. PufferPanel expone sus nodos pero no su memoria, su disco ni su CPU, así que un panel con varios nodos se elige por orden de nombre en lugar de por espacio libre. La planificación de la capacidad es cosa suya.
- Sin cambio de plan en una sola llamada. Cambiar de plan es una reinstalación, con las consecuencias que eso implica para los datos del cliente.
- Sin bucle de reconciliación de inventario. La sincronización
_ListAccountsde WHMCS cancela cualquier servicio que falte en la respuesta, y «que falta» tiene causas inocentes: un alcance de API más estrecho, un miembro restringido a parte del inventario, un límite de tasa, una página corta cuyo cursor no se siguió. Cada una eliminaría máquinas de clientes.
Hacerlo desde WHMCS en lugar de en código
Si ya hace correr WHMCS, Provibr entrega un módulo de aprovisionamiento como un simple zip que instala por su cuenta. Un producto de WHMCS apunta a un plan de Provibr; el flujo de pedidos normal de WHMCS se encarga de crear, suspender, reactivar y cancelar. Dos decisiones en él vale la pena copiar incluso en su propio puente:
Una entrega todavía en curso cuenta como éxito. Si el presupuesto de espera se agota mientras el instalador sigue trabajando, el módulo informa de éxito: el pedido sí fue aceptado, y WHMCS no tiene un estado «en instalación» (Pending ahí significa no ha pasado nada todavía, lo cual es falso). Un comando que falla de verdad es distinto: el servicio se queda en Pending y el administrador ve por qué.
Un servidor que ya no existe es una cancelación con éxito. Un 404 significa varias cosas a la vez (ID desconocido, otra cuenta, no visible para este miembro, ya eliminado), y para un gancho de cancelación la acción correcta es la misma en todos los casos: no queda nada que limpiar.
El recuento de capacidad, y cómo se encuentra con la reclamación de pago
La facturación de la plataforma cuenta capacidad, no uso, con una regla que sorprende a todo el mundo el primer mes: cada servidor cuenta, esté en marcha o no. Solo un servidor suspendido no cuenta, y tampoco lo hace uno eliminado: detener una máquina no libera una plaza.
Eso encaja bien con la reclamación de pago: un cliente al que suspende deja de contar mientras esté suspendido, y vuelve a contar cuando paga y lo reactiva.
Hacer correr PufferPanel junto a todo lo demás
No tiene por qué elegir un solo panel. Provibr cubre sus paneles de control, sus hipervisores y sus paneles de juego en un solo panel de control, con una sola API y una sola cifra de capacidad.
POST /v1/servers/{id}/actions/suspend hace lo mismo tanto si debajo hay un servidor Pelican, un servidor PufferPanel o una cuenta de alojamiento DirectAdmin. Las diferencias viven en el proveedor, no en su código de integración, y allí donde un proveedor de verdad no puede hacer algo, obtiene un rechazo que nombra la capacidad que falta en lugar de una ausencia silenciosa de efecto.