База знань

Продавайте хостинг Zinn® через HostBill, Blesta або власну систему

Продавайте хостинг Zinn® через HostBill, Blesta або власну систему: безкоштовний модуль HostBill, однофайловий клієнт PHP, два правила, порушення яких коштує грошей, і два поля запиту, які легко пропустити.

Якщо ви використовуєте WHMCS, натомість застосовуйте модуль WHMCS — ця сторінка призначена для всього іншого. Є два варіанти, обидва безкоштовні та обидва ліцензовані під GPL-2.0-or-later.

HostBill

Модуль хостингу з тими самими шістьма діями, що й модуль для WHMCS.

  1. Завантажте його та розархівуйте.
  2. Завантажте каталог zinn до includes/modules/Hosting/, щоб файли опинилися за шляхами
  3. includes/modules/Hosting/zinn/class.zinn.php та includes/modules/Hosting/zinn/ZinnHostBillClient.php.

  4. Settings → Modules → Hosting, активуйте Zinn Digital® і додайте підключення:
  • API address: https://api.zinndigital.com
  • API key: ваш API-ключ Zinn® (поле типу password, тому HostBill зберігає його в зашифрованому вигляді)
  1. У продукті вкажіть Product line (наприклад, mainstream), Stack (за замовчуванням wordpress), а також, за бажанням, Application і PHP version.
  2. Натисніть Test connection.

⛔ Не перейменовуйте каталог zinn. Завантажувач HostBill визначає потрібний клас за назвою каталогу, тому перейменування призведе до того, що модуль відображатиметься в панелі, але ніколи не викликатиметься.

Усе інше — клієнт PHP

Один файл, жодних залежностей, жодних прив'язок до конкретної панелі. Додайте ZinnProvisioning.php до власної кодової бази та викликайте шість методів.

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));

Не пишете на PHP? Ті самі виклики описані в довіднику з API, і ви можете здійснювати їх з будь-якого середовища.

Ключ API

Сім дозволів і не більше: org.create, org.read, sites.create, sites.view, sites.delete, reseller.view, reseller.provision.

⛔ Не reseller.manage. Ключ, який ви вставляєте в білінгову панель, повинен мати можливість заблокувати клієнта за несплату та виконати його вхід; він не повинен мати змоги змінювати облікові дані вашого власного платіжного шлюзу.

Два правила, порушення яких коштує грошей

  1. Прив'язуйте обліковий запис до вашого КЛІЄНТА, а сайт — до вашої ПОСЛУГИ. Друге замовлення клієнта повинно потрапляти до облікового запису, який у нього вже є. Прив'яжіть обидва до послуги — і один клієнт отримає три незв'язані облікові записи та три окремі панелі керування.
  2. Надсилайте ключ ідемпотентності під час кожного створення, згенерований на основі вашого власного ідентифікатора об'єкта. Кожна білінгова система робить повторні спроби — зворотний виклик шлюзу надходить двічі, адміністратор повторно запускає невдале надання послуги, клієнт двічі клікає. Без цього друга спроба створить другий сайт, і вам буде виставлено за нього рахунок. Обидва модулі та клієнт PHP роблять це за вас; якщо ви звертаєтеся до API безпосередньо, надсилайте Idempotency-Key.

Три поля, які легко пропустити

Кожне з них порушує роботу цілої операції, і жодне не відображається інакше, як помилка валідації — крім першого, яке відображається як взагалі нічого:

  • ⛔⛔ Клієнта необхідно перевести на тариф ДО розгортання його першого сайту, використовуючи
  • POST /v1/reseller/clients/{orgId}/plan, і передати його subscription_id у POST /v1/sites. Це випадок, коли помилки для зчитування немає. Новий обліковий запис клієнта не містить підписки, а POST /v1/sites не має поля тарифу, тому сайт, розгорнутий без нього, залишається взагалі без тарифу: ваша оптова виписка формується на основі активних підписок ваших клієнтів, тому жоден рядок не додається і Zinn® не виставляє вам рахунків упродовж усього часу роботи хостингу; ваш клієнт не успадковує лімітів, тому до його сайту не застосовується жодна квота; і для оновлення немає чого змінювати. Замовлення повертає 201, сайт розгортається й працює бездоганно. Жодна зі сторін ні про що з цього не повідомляє.

Послідовність має значення: POST /v1/sites фіксує будь-яку підписку, яка існує на момент його виконання, тому встановлений згодом тариф не застосовується заднім числом.

  • POST /v1/sites вимагає stack_type. Пропустіть його — і жодне замовлення не буде успішним.
  • **DELETE /v1/sites/{siteId} вимагає тіло `{"confirm_domain": "<the site's own
  • domain>"}** — явне підтвердження введенням, оскільки це деструктивна дія. Пропустіть його — і жодне скасування не вдасться, тому послуга продовжуватиме працювати, а вам і надалі виставлятимуться за неї рахунки. Зчитуйте домен із GET /v1/reseller/services/{siteId}`, а не з власного запису: він звіряється з власним основним доменом сайту і ніколи з псевдонімом.

Читайте помилку повністю, а не лише одне речення

Повідомлення про відхилення валідації навмисно зроблене загальним — "The request was well-formed but failed validation." — оскільки корисна для дій частина міститься в details, де зазначено поле та причину. Обидва модулі та PHP-клієнт додають його до повідомлення, яке показують вашому адміністратору. Якщо ви викликаєте API самостійно, зчитуйте error.details; деякі записи містять лише значення, а не речення, і саме так ви отримуєте max_sites: 0, коли у вашому реселерському тарифі немає вільного місця.

Перед вашим першим замовленням

Сайти, які купують ваші клієнти, враховуються в ліміт сайтів вашого реселерського тарифу, тому вам потрібен тариф із вільним місцем. Перевірка з'єднання не може цього виявити — вона зчитує вашу програму й нічого не розгортає — тому вона повідомляє про справний обліковий запис, який поки що не може здійснювати продажі. Замовлення, розміщене без доступного ліміту, відхиляється з повідомленням, яке саме про це й зазначає.

Перевірте ваше завантаження

Обидва архіви передаються через TLS із нашого власного імені хоста, ніколи не перенаправляються в інше місце, а їхні контрольні суми SHA-256 зазначені поруч із посиланнями для завантаження на сторінці завантажень.

Останнє з блогу

Що ми писали про хостинг, SEO та роботу сайтів у великих масштабах.

SEO та лінкбілдінг із рівня хостингу: Погляд оператора 2026 року

Як хостинг впливає на індексацію та передачу ваги посилань (link equity) у 2026 році: підтримка сторінок у пошуковому індексі, перевірка старих доменів перед створенням сайтів, лінкбілдинг без слідів (footprint) та відвертий погляд на те, що інфраструктура може і чого не може зробити для SEO.

Читати допис →

Як зробити WordPress швидким та безпечним: контрольний список оптимізації та плагінів

Практичний контрольний список для швидкого та безпечного WordPress: кешування на рівні сервера, об'єктний кеш для кожного сайту, кілька дійсно вартих плагінів, підтримання стека в актуальному стані та сторінки WooCommerce, які в жодному разі не можна кешувати.

Читати допис →

Як вибрати керований вебхостинг у 2026 році: Посібник для покупця

Що насправді відрізняє якісний керований хостинг від дешевого сервера з панеллю керування — міграції, резервні копії, ізоляція, справжнє кешування та чесне масштабування — і як оцінити його, перш ніж брати на себе зобов'язання.

Читати допис →

Читати блог →

Усе ще потрібна допомога?

Підтримка включена до кожного тарифу, служба працює 24 годин на добу, і ви можете писати нам будь-якою з наших 58 мов — ми відповідаємо вашою.

Звернутися до служби підтримки → Усі статті →