מאגר ידע

מכור את האחסון של 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 (ברירת המחדל היא
  2. wordpress), ורשות עבור Application ו-PHP version.

  3. לחצו על 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. הגדירו את המפתח לפי ה-CUSTOMER שלכם, ואת האתר לפי ה-SERVICE שלכם. ההזמנה השנייה
  2. של לקוח חייבת להגיע אל החשבון שכבר יש לו. הגדירו את שניהם על השירות ולקוח אחד ימצא את עצמו עם שלושה חשבונות לא קשורים ושלושה לוחות בקרה נפרדים.

  3. שלחו מפתח ייחוד (idempotency key) בכל יצירה, הנגזר מהמזהה שלכם עבור פריט זה. כל
  4. מערכת חיוב מבצעת ניסיונות חוזרים — קריאה חוזרת משער התשלומים מגיעה פעמיים, מנהל מערכת מריץ מחדש הקצאה שנכשלה, לקוח לוחץ פעמיים. בלעדיו, הניסיון השני יוצר אתר שני ואתם מחויבים עליו. גם המודולים וגם לקוח ה-PHP עושים זאת עבורכם; אם אתם קוראים ל-API ישירות, שלחו את Idempotency-Key.

שלושה שדות שקל לשכוח

כל אחד מהם שובר פועל שלם, ואף אחד מהם אינו מוצג כמשהו מעבר לשגיאת אימות — למעט הראשון, שמוצג כשום דבר כלל:

  • ⛔⛔ חובה להציב לקוח במסלול (plan) לפני הקצאת האתר הראשון שלו, באמצעות
  • 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}` במקום להשתמש ברישום שלכם שלכם: הוא מודר מול שם המתחם הראשי של האתר ולא מול שמות כינוי (alias).

קראו את השגיאה כולה, ולא רק את המשפט

הודעת סירוב אימות היא גנרית בכוונה — "The request was well-formed but failed validation." — מכיוון שהמחצית הניתנת לפעולה נמצאת ב-details, המציינת את השדה ואת הסיבה לכך. גם המודולים וגם לקוח ה-PHP מצרפים זאת להודעה שהם מציגים למנהל המערכת שלכם. אם אתם קוראים ל-API בעצמכם, קראו את error.details; חלק מהרשומות נושאות ערך גולמי במקום משפט, שזו הדרך שבה max_sites: 0 מגיע אליכם כאשר למסלול המשווק שלכם אין מקום.

לפני ההזמנה הראשונה

אתרים שהלקוחות שלכם קונים נספרים מול מכסת האתרים של מסלול המשווק שלכם, כך שאתם זקוקים למסלול עם מקום פנוי בו. בדיקת חיבור אינה יכולה לזהות זאת — היא קוראת את התוכנית שלכם ואינה מקיצה דבר — כך שהיא מדווחת על חשבון תקין שעדיין אינו יכול למכור. הזמנה המבוצעת ללא מכסה נדחית עם הודעה המציינת בדיוק זאת.

אמת את ההורדה שלך

שני הארכיונים מועברים באמצעות TLS משם המארח שלנו בלבד, ולעולם אינם מופנים למקום אחר, כאשר סכומי ה-SHA-256 שלהם מודפסים לצד קישורי ההורדה בעמוד עמוד ההורדות.

עדיין תקועים?

התמיכה כלולה בכל תוכנית והמענים ניתנים בשפה שלך.

צור קשר עם התמיכה כל המאמרים