Kung nagpapatakbo kayo ng WHMCS, gamitin ang WHMCS module sa halip — ang pahinang ito ay para sa lahat ng iba pa. May dalawang opsyon, parehong libre at parehong GPL-2.0-or-later.
HostBill
Isang hosting module na may parehong anim na aksyon tulad ng sa WHMCS.
- I-download ito at i-unzip.
- I-upload ang
zinn directory sa includes/modules/Hosting/ upang mapunta ang mga file sa
includes/modules/Hosting/zinn/class.zinn.php at includes/modules/Hosting/zinn/ZinnHostBillClient.php.
- Settings → Modules → Hosting, i-activate ang Zinn Digital®, at magdagdag ng koneksyon:
- API address:
https://api.zinndigital.com
- API key: ang inyong Zinn® API key (isang
password field, kaya iniimbak ito ng HostBill nang naka-encrypt)
- Sa produkto, itakda ang Product line (hal.
mainstream), Stack (wordpress bilang
default), at opsyonal ang Application at PHP version.
- Pindutin ang Test connection.
⛔ Huwag palitan ang pangalan ng zinn directory. Kinukuha ng loader ng HostBill ang class na hinahanap nito mula sa pangalan ng directory, kaya ang pagpapalit ng pangalan ay lumilikha ng module na inililista ng panel ngunit hindi kailanman tinatawag.
Anumang iba pa — ang PHP client
Isang file, walang dependencies, walang mga pagpapalagay sa panel. Ilagay ang ZinnProvisioning.php sa inyong sariling codebase at tumawag ng anim na method.
require_once 'ZinnProvisioning.php';
$zinn = new ZinnProvisioning(getenv('ZINN_API_KEY'));
// Kapag binayaran ang isang order — isang beses bawat CUSTOMER, pagkatapos ay isang beses bawat SERVICE:
$orgId = $zinn->account('customer-4211', 'Acme Ltd');
$siteId = $zinn->provision('service-9915', $orgId, 'acme.com', 'mainstream', 'wordpress');
// I-store ang $orgId laban sa inyong customer at ang $siteId laban sa inyong service.
$zinn->suspend($siteId, 'INV-2026-114 unpaid'); // hindi nabayaran ang isang invoice
$zinn->unsuspend($siteId); // nagbayad sila
$zinn->terminate($siteId); // nagkansela sila — nag-iiskedyul ng pagbura
// Kapag nag-click sila sa "log in to my hosting" — gawin ito sa mismong CLICK, huwag kailanman sa page render:
header('Location: ' . $zinn->signInLink($siteId));
Hindi nagsusulat ng PHP? Ang parehong mga tawag ay nasa API reference at maaari ninyo itong gawin mula sa anuman.
Ang API key
Pitong pahintulot, at wala nang iba pa: org.create, org.read, sites.create, sites.view, sites.delete, reseller.view, reseller.provision.
⛔ Hindi reseller.manage. Ang isang key na ipinapaskil ninyo sa isang billing panel ay dapat may kakayahang i-hold ang isang kliyente para sa hindi pagbabayad at i-sign in sila; hindi nito dapat magawang isulat muli ang inyong sariling mga kredensyal sa payment-gateway.
Ang dalawang panuntunan na nagdudulot ng gastos kapag nalabag ang mga ito
- I-key ang account sa inyong CUSTOMER, at ang site sa inyong SERVICE. Ang ikalawang order
ng isang customer ay dapat mapunta sa account na mayroon na sila. I-key ang pareho sa service at ang isang customer ay magkakaroon ng tatlong walang kaugnayang account at tatlong magkakahiwalay na control panel.
- Magpadala ng idempotency key sa bawat paglikha, na hango sa inyong sariling id para sa bagay na iyon. Ang bawat
billing system ay sumusubok muli — ang isang gateway callback ay dumarating nang dalawang beses, muling pinapatakbo ng isang admin ang isang nabigong provision, nagdo-double click ang isang customer. Kung wala ito, ang ikalawang pagtatangka ay lilikha ng ikalawang site at sisingilin kayo para dito. Ginagawa ito ng parehong module at ng PHP client para sa inyo; kung direktang tinatawagan ninyo ang API, ipadala ang Idempotency-Key.
Tatlong field na madaling maiwanan
Sinisira ng bawat isa ang isang buong verb, at walang lumalabas bilang anupaman kundi isang validation error — maliban sa una, na lumalabas bilang wala talaga:
- ⛔⛔ Ang isang kliyente ay dapat ilagay sa isang plano BAGO i-provision ang kanilang unang site, gamit ang
POST /v1/reseller/clients/{orgId}/plan, at ang subscription_id nito ay ipinapasa sa POST /v1/sites. Ito ang walang error na mababasa. Ang isang bagong account ng kliyente ay walang hawak na subscription at ang POST /v1/sites ay walang plan field, kaya ang isang site na na-provision nang wala nito ay magdadala ng walang plano talaga: ang inyong wholesale statement ay binuo mula sa mga live subscription ng inyong mga kliyente, kaya walang linyang itinataas at wala kayong sisingilin ng Zinn® habang tumatakbo ang hosting; walang minamanang mga allowance ang inyong kliyente, kaya walang quota na inilalapat sa kanilang site; at walang anumang babaguhin ang isang upgrade. Nagbabalik ang order ng 201, nagpo-provision ang site, at nagsisilbi ito nang perpekto. Walang anuman sa magkabilang dulo ang nag-uulat ng alinman dito.
Mahalaga ang pagkakasunod-sunod: itinatala ng POST /v1/sites ang anumang subscription na umiiral sa sandaling tumatakbo ito, kaya ang isang planong itinakda pagkatapos ay hindi retroaktibong ikinakabit.
- Nangangailangan ang
POST /v1/sites ng stack_type. Laktawan ito at walang order na magtatagumpay.
- **Nangangailangan ang
DELETE /v1/sites/{siteId} ng body na `{"confirm_domain": "<the site's own
domain>"}** — isang tina-type na kumpirmasyon, dahil ito ang mapangwasak na verb. Laktawan ito at walang pagkansela na magtatagumpay, kaya patuloy na tatakbo ang serbisyo at patuloy kayong sisingilin para dito. Basahin pabalik ang domain mula sa GET /v1/reseller/services/{siteId}` sa halip na gamitin ang inyong sariling talaan: inihahambing ito laban sa sariling primary domain ng site at hindi kailanman laban sa isang alias.
Basahin ang buong error, hindi lamang ang pangungusap
Ang mensahe ng isang pagtanggi sa validation ay sadyang generic — "The request was well-formed but failed validation." — dahil ang naaaksyunang kalahati ay nasa details, na nagpapangalan sa field at kung bakit. Idinaragdag ito ng parehong module at ng PHP client sa mensaheng ipinapakita ng mga ito sa inyong admin. Kung kayo mismo ang tumatawag sa API, basahin ang error.details; ang ilang entry ay nagdadala ng payak na halaga sa halip na isang pangungusap, na siyang paraan kung paano nakakarating sa inyo ang max_sites: 0 kapag walang espasyo ang inyong reseller plan.
Bago ang inyong unang order
Ang mga site na binibili ng inyong mga kliyente ay binibilang laban sa site allowance ng inyong reseller plan, kaya kailangan ninyo ng isang planong may espasyo dito. Hindi ito matutukoy ng isang pagsubok sa koneksyon — binabasa nito ang inyong programa at walang ipinoprovision — kaya nag-uulat ito ng isang malusog na account na hindi pa makapagbenta. Ang isang order na inilagay nang walang allowance ay tinatanggihan kalakip ang isang mensaheng eksaktong nagsasabi niyan.
I-verify ang inyong download
Ang parehong archive ay inihahatid sa pamamagitan ng TLS mula sa aming sariling hostname, hindi kailanman inire-redirect sa ibang lugar, kung saan ang kanilang mga SHA-256 checksum ay nakalimbag sa tabi ng mga link sa pag-download sa pahina ng mga download.