Se utilizzate WHMCS, usate invece il modulo WHMCS — questa pagina riguarda tutto il resto. Sono disponibili due opzioni, entrambe gratuite ed entrambe sotto licenza GPL-2.0-or-later.
HostBill
Un modulo di hosting con le stesse sei azioni di quello per WHMCS.
- Scaricarlo ed estrarlo.
- Caricare la cartella
zinn all'interno di includes/modules/Hosting/ in modo che i file si trovino in includes/modules/Hosting/zinn/class.zinn.php e includes/modules/Hosting/zinn/ZinnHostBillClient.php.
- Settings → Modules → Hosting, attivare Zinn Digital® e aggiungere una connessione:
- API address:
https://api.zinndigital.com
- API key: la vostra chiave API Zinn® (un campo
password, quindi HostBill la memorizza crittografata)
- Sul prodotto impostare Product line (es.
mainstream), Stack (wordpress per impostazione predefinita) e facoltativamente Application e PHP version.
- Premere Test connection.
⛔ Non rinominare la directory zinn. Il caricatore di HostBill ricava la classe cercata dal nome della cartella, di conseguenza una ridenominazione genera un modulo che il pannello elenca ma non richiama mai.
Qualsiasi altra soluzione — il client PHP
Un solo file, nessuna dipendenza, nessun presupposto sul pannello. Inserite ZinnProvisioning.php nel vostro codice sorgente e invocate sei metodi.
require_once 'ZinnProvisioning.php';
$zinn = new ZinnProvisioning(getenv('ZINN_API_KEY'));
// When an order is paid — once per CUSTOMER, then once per SERVICE:
$orgId = $zinn->account('customer-4211', 'Acme Ltd');
$siteId = $zinn->provision('service-9915', $orgId, 'acme.com', 'mainstream', 'wordpress');
// Store $orgId against your customer and $siteId against your service.
$zinn->suspend($siteId, 'INV-2026-114 unpaid'); // an invoice goes unpaid
$zinn->unsuspend($siteId); // they pay
$zinn->terminate($siteId); // they cancel — schedules a deletion
// When they click "log in to my hosting" — mint it on the CLICK, never on page render:
header('Location: ' . $zinn->signInLink($siteId));
Non utilizzate PHP? Le medesime chiamate sono presenti nella documentazione API e possono essere effettuate da qualsiasi linguaggio.
La chiave API
Sette permessi, e non uno di più: org.create, org.read, sites.create, sites.view, sites.delete, reseller.view, reseller.provision.
⛔ Non reseller.manage. Una chiave inserita in un pannello di fatturazione deve poter sospendere un cliente per mancato pagamento ed effettuarne l'accesso; non deve poter modificare le credenziali del vostro gateway di pagamento.
Le due regole che costano denaro se violate
- Assegnare come chiave dell'account il vostro CLIENTE e come chiave del sito il vostro SERVIZIO. Un secondo ordine di un cliente deve confluire nell'account già esistente. Se si assegna la chiave di entrambi al servizio, un unico cliente si ritroverà con tre account non collegati e tre pannelli di controllo distinti.
- Inviare una chiave di idempotenza a ogni creazione, derivata dal vostro identificativo per l'elemento. Ogni sistema di fatturazione ritenta l'operazione: una notifica del gateway arriva due volte, un amministratore esegue nuovamente un provisioning non riuscito, un cliente fa doppio clic. In assenza di essa, il secondo tentativo crea un secondo sito con conseguente addebito. Entrambi i moduli e il client PHP gestiscono questo passaggio automaticamente; se interrogate direttamente l'API, trasmettete
Idempotency-Key.
Tre campi facili da tralasciare
Ciascuno di essi compromette un'intera operazione e nessuno si manifesta se non come errore di validazione — tranne il primo, che non produce assolutamente nulla:
- ⛔⛔ Un cliente deve essere associato a un piano PRIMA del provisioning del suo primo sito, tramite
POST /v1/reseller/clients/{orgId}/plan, e il relativo subscription_id deve essere passato a POST /v1/sites. Questo è il caso in cui non viene generato alcun errore da leggere. Il nuovo account di un cliente non include alcun abbonamento e POST /v1/sites non dispone di un campo relativo al piano, pertanto un sito di cui viene effettuato il provisioning senza di esso non ha alcun piano assegnato: l'estratto conto all'ingrosso viene generato a partire dagli abbonamenti attivi dei Suoi clienti, per cui non viene addebitata alcuna voce e Zinn® non Le addebita nulla per l'intera durata dell'hosting; il Suo cliente non eredita alcuna quota, per cui al suo sito non viene applicato alcun limite; e non vi è alcunché da modificare con un upgrade. L'ordine restituisce 201, il provisioning del sito viene eseguito e il servizio funziona perfettamente. Nessun avviso viene segnalato su alcuno dei due lati.
L'ordine delle operazioni è fondamentale: POST /v1/sites registra l'abbonamento presente al momento della sua esecuzione, pertanto un piano impostato in un momento successivo non si applica retroattivamente.
POST /v1/sites richiede stack_type. In sua assenza, nessun ordine può andare a buon fine.
DELETE /v1/sites/{siteId} richiede un corpo {"confirm_domain": "<the site's own domain>"} — una conferma digitata, trattandosi del verbo distruttivo. Omettendola, nessuna cancellazione può andare a buon fine, con la conseguenza che il servizio continua a funzionare e Le verrà ancora fatturato. Legga nuovamente il dominio da GET /v1/reseller/services/{siteId} anziché usare il Suo registro interno: esso viene confrontato con il dominio primario effettivo del sito e mai con un alias.
Legga l'intero errore, non solo la frase
Il messaggio di rifiuto di una convalida è volutamente generico — "The request was well-formed but failed validation." — poiché la parte operativa si trova in details, dove viene indicato il campo e la motivazione. Entrambi i moduli e il client PHP lo accodano al messaggio mostrato al Suo amministratore. Se effettua direttamente le chiamate API, legga error.details; alcune voci contengono un valore semplice anziché una frase, ed è così che max_sites: 0 Le viene notificato quando il Suo piano rivenditore non ha più spazio disponibile.
Prima del Suo primo ordine
I siti acquistati dai Suoi clienti vengono conteggiati a fronte del limite di siti del Suo piano rivenditore, pertanto è necessario un piano con capienza residua. Un test di connessione non può rilevare questa condizione — esegue la lettura del Suo programma senza effettuare il provisioning di nulla — segnalando quindi un account integro che tuttavia non è ancora in grado di vendere. Un ordine inviato senza quota disponibile viene rifiutato con un messaggio che indica esattamente questo.
Verifichi il Suo download
Entrambi gli archivi vengono distribuiti tramite TLS dal nostro stesso hostname, senza mai essere reindirizzati altrove, con i relativi checksum SHA-256 riportati accanto ai link di download nella pagina dei download.