Blog ·
Automatizzare la fatturazione e il provisioning Plesk
Da un ordine pagato a un abbonamento attivo e da una fattura scaduta a uno spento: chiamate, tempi misurati e quattro trappole che scattano solo in automatico.
Di Provibr
Un prodotto di hosting automatizzato ha tre momenti in cui il denaro e le macchine si toccano:
- L’ordine viene pagato. Un abbonamento deve esistere, sul piano di servizio giusto, nel giro di pochi secondi.
- La fattura è scaduta. L’abbonamento deve spegnersi e tornare nel momento in cui viene pagata.
- L’abbonamento termina. Deve essere rimosso, davvero, dati compresi.
Plesk ha chiamate per tutti e tre. Ciò che non ha è qualcosa che decida quando eseguirle, ed è la metà che si costruisce. Questa pagina parla di come collegare le due cose e di quattro comportamenti innocui quando li si attiva a mano e pericolosi quando uno scheduler li esegue alle tre di notte.
Tutto questo è stato misurato su un server Plesk Obsidian 18.0.80 in funzione, ad agosto 2026.
I tre momenti e le chiamate che li sostengono
| Momento | API | Chiamata | Durata misurata |
|---|---|---|---|
| Ordine pagato | REST | POST /clients poi POST /domains | 0,6 a 0,7 s + 4,1 a 4,5 s |
| Scaduta | XML | <webspace><set> con gen_setup.status | 0,78 s |
| Pagata alla fine | XML | la stessa chiamata, stato di nuovo a 0 | 0,78 s |
| Upgrade o downgrade | XML | <webspace><switch-subscription> | 1,5 s |
| Cancellazione | REST | DELETE /domains/{id} poi DELETE /clients/{id} | 7,7 s + |
| Lettura dello stato | XML | <webspace><get> per l’intero server | 0,33 s |
Due di questi numeri danno forma alla progettazione. Creare un abbonamento richiede quattro secondi e mezzo e cancellarlo quasi otto. È un tempo sufficiente perché un modulo d’ordine debba segnalare che qualcosa sta accadendo, sufficiente perché un budget di timeout scritto per un’API veloce interrompa a metà una chiamata che funziona, e sufficiente perché due ordini che arrivano insieme siano davvero concorrenti e non solo in teoria.
Si noti anche la riga di lettura. Una sola chiamata XML restituisce ogni abbonamento con il suo piano, stato, quota e utilizzo in un terzo di secondo, indipendentemente da quanti siano. E un sistema di fatturazione si riconcilia di continuo con il pannello.
La trappola della sospensione è un bug di fatturazione, non un dettaglio dell’API
Plesk offre due modi per sospendere, e scrivono campi diversi. In un prodotto di hosting questo smette di essere una curiosità.
Misurato, sullo stesso abbonamento:
| Cosa si fa | XML gen_info.status | Stato REST dell’abbonamento |
|---|---|---|
| niente | 0 | active |
PUT /domains/{id}/status a suspended | 0 | suspended |
XML <webspace><set> stato 16 | 16 | suspended |
Un ciclo di solleciti che sospende via REST scrive un campo che la lettura in blocco non guarda, così la piattaforma continua a segnalare l’account come attivo. Ecco perché questo danneggia proprio la fatturazione: quando la fattura viene finalmente pagata, l’automazione guarda il proprio stato, vede un account che non è mai stato sospeso e non lo riattiva. Il cliente ha pagato e resta spento, e nulla ha registrato un errore.
La regola sta in una riga: sospendere attraverso il campo che si legge. Provibr scrive <webspace><set><gen_setup><status>, dopodiché le due viste concordano.
gen_info.status è una maschera di bit; abbiamo misurato 0 per attivo, 1 per webspace-off e 16 per disattivato dall’amministratore. Trattare qualsiasi valore diverso da zero come sospeso, l’unica interpretazione che sopravvive a un valore che nessuno ha ancora visto.
Una riserva onesta: non abbiamo misurato la sospensione di un abbonamento già sospeso. Su HestiaCP questo caso non è idempotente e restituisce un errore dall’aspetto di un errore di autenticazione (esattamente ciò su cui un ciclo di solleciti inciampa ogni giorno), quindi conviene verificarlo sul proprio server prima di farci affidamento.
Una chiave scaduta è identica a un server vuoto
Questo è il guasto che può causare danni veri, e si descrive in una frase.
L’API XML restituisce HTTP 200 per una chiave errata. L’errore si trova all’interno del documento, come codice 11003. Un client che controlla il codice di stato legge quindi un errore di autenticazione come un giro riuscito che non ha trovato alcun abbonamento.
Ora si metta tutto ciò dentro un processo di riconciliazione notturno. Un giro riuscito che non ha trovato nulla significa, per qualsiasi piattaforma di hosting, che ogni account presente ieri è stato cancellato. Una sola chiave scaduta, e da un giorno all’altro il sistema segna come scomparsa l’intera base clienti.
Ne derivano due regole, e valgono per qualsiasi pannello che segnala un errore con un 200 (cosa che, tra i pannelli che abbiamo integrato, riguarda la maggior parte):
- Sull’API XML il codice di stato non porta alcuna informazione, nemmeno sull’autenticazione. Analizzare il documento.
- Una risposta illeggibile è sconosciuta, mai vuota. Un server vuoto esiste eccome, e produce un unico risultato vuoto anziché un errore: questi due casi sono davvero diversi, e distinguerli è tutto il lavoro.
REST fallisce ancora in un altro modo: una chiave inutilizzabile torna come HTTP 401 con un corpo completamente vuoto. Un test di connessione deve quindi sondare entrambe le superfici e segnalarle separatamente. Un risultato REST verde accanto a un’API XML muta significa che l’elenco degli account, l’elenco dei piani e ogni cambio di piano resteranno vuoti, e la conclusione allettante è che il cliente non abbia alcun account.
Il codice di errore non dice cosa è andato storto
Gli errori REST di Plesk portano un codice numerico, ed è allettante usarlo come discriminante. Misurato, non classifica:
- 1007 copre sia «quel dominio esiste già» sia «quel login cliente esiste già».
- 1013 copre sia «non esiste un piano di servizio simile» (REST) sia «il dominio non esiste» (XML).
- 0 significa nessun codice, non nessun errore.
Per un’integrazione di fatturazione il danno finisce nella logica dei nuovi tentativi. «Il dominio esiste già» dopo un ordine pagato può significare che il tentativo precedente è riuscito a metà e conviene guardare prima di riprovare; «nessun piano di servizio simile» significa che l’ordine non riuscirà mai e va portato davanti a una persona. Condividono una famiglia di codici. È quindi il testo a classificare, e questa corrispondenza va in un unico punto del codice anziché essere ridedotta a ogni punto di chiamata.
Esiste anche una quinta forma di errore: chiedere a REST una route che non esiste e risponde con una pagina HTML, non JSON.
Un ordine fallito può bloccare il nuovo tentativo
Misurato: creare un dominio su un piano di servizio che non esiste restituisce HTTP 404 con un messaggio chiaro, e l’oggetto dominio esiste comunque dopo, senza tipo di hosting e con document root vuota. Plesk crea prima l’oggetto e applica dopo il piano, e non annulla nulla quando il secondo passo fallisce.
In un flusso di fatturazione si legge così: il cliente ha pagato, il provisioning è fallito, e il nuovo tentativo ora fallisce in modo diverso, perché il dominio è in uso da un account che non ha mai ricevuto. Il secondo errore sembra un ordine duplicato, che è una delle cose più confuse da diagnosticare a partire da un ticket di supporto.
Ne seguono due accorgimenti a basso costo. Risolvere il piano prima di creare qualsiasi cosa: l’elenco dei piani è già disponibile, quindi conviene cercare il nome in locale e far fallire l’ordine prima di toccare il pannello, il che elimina questo errore anziché gestirlo. E fare pulizia dopo una creazione fallita, perché lasciare i rottami trasforma un ordine fallito in un nome di dominio bloccato per sempre.
Per contrasto, un errore di validazione di campo come un login cliente duplicato restituisce HTTP 400 e non lascia nulla dietro di sé. Quel controllo viene eseguito prima della creazione; solo la ricerca del piano arriva troppo tardi per essere d’aiuto.
Due chiamate che hanno ciascuna un punto intermedio
Rimuovere un abbonamento significa DELETE /domains/{id} e poi DELETE /clients/{id}. Se il primo riesce e il secondo no, resta un record cliente che non possiede nulla: invisibile nella maggior parte delle viste, e un errore di login duplicato la prossima volta che quel cliente torna. A 7,7 secondi la cancellazione è anche abbastanza lunga perché una rete la interrompa, quindi la cancellazione merita lo stesso trattamento del provisioning: rileggere poi il pannello e riconciliare con la lettura in blocco, non con la risposta ottenuta.
Gli upgrade e i downgrade hanno il loro angolo. <webspace><switch-subscription> non accetta un nome di piano, solo il GUID del piano o il suo ID esterno, là dove ovunque altrove in Plesk un pacchetto è referenziato per nome. Provibr mantiene il nome come ciò che vedono le persone e fa la traduzione da nome a GUID internamente, a partire dall’elenco dei piani che il polling recupera già. Memorizzare invece un GUID nel proprio sistema di fatturazione funziona fino al momento in cui qualcuno ricostruisce un piano.
Dove vive la fattura
I tre momenti qui sopra sono solo metà di un prodotto di hosting. L’altra metà è che aspetto ha la propria fattura.
Si paga per la capacità, per tipo di risorsa, e un account di hosting è uno di questi. Ogni abbonamento conta, che sia in esecuzione o no; solo quello sospeso non conta. È il verso giusto per i solleciti: sospendere un cliente scaduto libera lo slot mentre i suoi dati restano intatti, e riattivarlo lo rioccupa.
Superare il proprio limite non viene bloccato nel momento in cui accade. Viene rilevato, si viene informati su quale tipo di risorsa e di quanto, e si ha una giornata lavorativa per rimediare. Se scade, i server più recenti oltre il limite vengono spenti, i più recenti per primi, così che ciò che è stato costruito per primo sopravviva. Un secondo superamento entro una settimana ottiene un’ora invece di un giorno, perché altrimenti il periodo di grazia potrebbe essere rinnovato all’infinito scendendo sotto il limite e poi superandolo di nuovo. Nulla viene riavviato automaticamente una volta risolto: accendere una macchina è una decisione, e la piattaforma non la prende mentre nessuno guarda.
Ogni periodo produce una proforma che si può leggere e stampare, mentre la fattura definitiva arriva dalla contabilità come file. Una riga di fattura registra il nome del pacchetto così com’era al momento della fatturazione, quindi rinominare un piano più tardi non riscrive la storia.
Cosa fa Provibr, e cosa deliberatamente non fa
Provibr si colloca tra la fatturazione e il server Plesk. Un abbonamento è una riga ordinaria: ordinarlo, sospenderlo, riattivarlo, cambiarne il piano di servizio, eliminarlo. La sospensione passa per il campo che il polling legge. Il piano viene risolto prima della creazione, e una creazione fallita viene ripulita. Ogni mutazione si conclude rileggendo l’abbonamento, così ciò che viene memorizzato è ciò che è stato osservato e non ciò che è stato richiesto. L’agente si connette verso l’esterno dalla propria rete, così la porta 8443 non deve affacciarsi su internet.
Ciò che non fa: gestire il server Plesk in sé, o entrare dentro un abbonamento. Inoltre non chiede mai a Plesk i dataset che contengono la password FTP o l’hash della password del cliente, entrambi consegnati dal pannello in chiaro se vengono richiesti.
Da leggere poi
- Come vendere web hosting con Plesk: il modello di prodotto, le due API e ciò che non chiediamo mai al pannello.
- Fatturazione e licenza: capacità, prezzi a fasce, credito, proforma e cosa succede oltre il limite.
- Configurare Plesk: la chiave API, i piani di servizio, i piani web e l’importazione degli abbonamenti.
Misurato su Plesk Obsidian 18.0.80 ad agosto 2026, con le risposte registrate come fixture. La sospensione ripetuta, le chiavi con ambito rivenditore e il comportamento sotto un carico di traffico reale non sono stati misurati, e sono segnalati come tali più sopra.