Ürün Modülü Yazma

1.8k görüntülenme Markdown

Ürün modülü, hosting hesabı da alan adı da olmayan her şeyi sağlar: lisans, abonelik, sertifika. Arkasında sunucu kaydı yoktur.

Genel Bakış

Hosting, sunucu ya da alan adı olmayan bir hizmet Product tipine çözülür: special ve software hizmetleri ve SSL sertifikaları.

Yedi Product modülünün dördü SSL ürünüdür ve SSL'in genel tabanın altında kendi taban sınıfı vardır.

ProductModule Genel taban: modül trait'i, müşteri paneli sözleşmesi, hizmet içe aktarıcısı. Soyut değildir.
SslProductModule Soyut: sertifika panosu, ürün alanları, doğrulama ayrıştırması, yedi müşteri aksiyonu.
Services::module_type() hosting ve server Servers'a, domain Registrars'a, geri kalanı Product'a gider.
Services::run_module() Aynı tek kapı; yazmadığınız fiil atlanır.

Ön Koşullar

  • Modül Anatomisi ve Modül Yapılandırması.
  • Sertifikalar SSL tabanını, diğer her şey genel tabanı genişletir.
  • Sağlayıcı API kimlik bilgileri, $this->config'ten okunur.
  • Modüle bağlı special ya da software tipinde bir ürün.

Yapı

Sunucu dışında her modül tipiyle aynı biçim.

yerleşim
coremio/modules/Product/Acme/
├── Acme.php            extends ProductModule, sertifikalar için SslProductModule
├── ApiClient.php       kendi HTTP sarmalayıcınız
├── config.php          künye ve ayarlar formu
├── logo.png
├── lang/en.php
└── pages/
    ├── configuration.php   admin panelindeki modül ayarları ekranı
    └── dashboard.php       yönetim yüzeyi; varlığı müşteri sekmesini açar
FarkSunucu modülüÜrün modülü
Kimlik bilgileriSunucu kaydı, taban sınıf çözerModül yapılandırması, siz çözersiniz
Bağlantı testiSunucu formunda test_connect()controller_test_connection()
Ayarlar ekranıYapılandırma alanlarından üretilirpage_configuration() + kaydetme controller'ı
Kaynak limitleriget_limit(), taban sınıf çözerÜrünün modül verisinden
Müşteri araçlarıAraç kataloğu ve paylaşılan şablonlarPano sayfanız + çağrılabilir aksiyonlar
Müşteri sekmesiPano varsa her zamanİsteğe bağlı: pages/dashboard.php ekleyin

Adım Adım

Taban Sınıfı Seçin

SSL tabanı soyuttur: yazılacak yedi metot, karşılığında devralınan sertifika ekranları.

iki biçim
namespace WISECP\Modules\Product;

use Exception;
use ProductModule;

// Bir lisans, bir abonelik, bir uygulama kiracısı.
class Acme extends ProductModule
{
    public function __construct()
    {
        parent::__construct();       // zorunlu: initModule('Product') çağrısını koşar
    }
}
sertifika biçimi
namespace WISECP\Modules\Product;

use SslProductModule;

class AcmeSSL extends SslProductModule
{
    // Yedi soyut metot yazılmak zorundadır; yüzeyin geri kalanı devralınır.
    protected function initApi(): void { /* ... */ }
    public function fetchRemoteStatus(): array { return []; }
    protected function sslProductOptions(): array { return []; }
    protected function apiReissue(string $csr, string $dcv_method, string $approver_email): array|bool { return true; }
    protected function apiResendValidation(string $domain = ''): array|bool { return true; }
    protected function apiRevalidate(string $domain = ''): array|bool { return true; }
    protected function apiChangeValidationMethod(string $domain, string $method, string $approver = 'admin'): array|bool { return true; }
}

Ayarlar Ekranı

Ayarlar sayfası modülün kendisine aittir. controller_ ön ekli metotlar o sayfadan erişilebilir; tire alt çizgiye çevrilerek adla dağıtılır.

  1. page_configuration() ekranı kurar, çoğunlukla form oluşturucuyla.
  2. controller_save() gönderilen alanları save_config() ile yazar. Her sırrı önce şifreleyin.
  3. controller_test_connection() kimlik bilgilerini kanıtlar.

Ürün Alanları

product_configuration(), yöneticinin ürün başına dolduracağı alan tanımlarını döndürür. Seçtikleri ürünün modül verisi olur ve sağlamaya $this->options['creation_info'] olarak ulaşır.

Yaşam Döngüsü

Biçim olarak sunucu modülüyle aynıdır: seçimleri oku, sağlayıcıyı çağır, saklanacağı teslim et.

  1. API istemcisini yapıcıda değil, ihtiyaç duyulan metodun içinde tembelce kurun.
  2. create() metodunu yeniden denemeye dayanıklı yazın: kuyruk onu tekrar çalıştırır, o yüzden var olan hesabı denetleyin ve kimlik bilgilerini erken kalıcılaştırın.

Müşteri Ekranı

Varsayılan olarak müşteriye hiçbir şey açılmaz; ayrıntılar Ürün Modülü Müşteri Yönetimi makalesindedir.

Referans

Genel Taban

tam imzalar
class ProductModule
{
    public bool   $client_area = false;              // yalnız müşteri panelinde basılırken true
    public string $area_link   = '';                 // hizmet kimliğini taşıyan müşteri controller bağlantısı
    public array  $client_callable_methods = [];     // müşterinin koşabileceği handle_* adları
    public array  $client_readonly_methods = [];     // GET üzerinden sunulan alt küme, CSRF jetonu yok

    public function __construct();                   // initModule('Product') çağırır
    public function get_page($page_file = '', $vars = []): string;
    public function use_controller($param = '');
    public function service_management_page(): string;
    public function has_client_management(): bool;
    public function client_overview_data(): array;
    public function client_quick_actions(int $limit = 8): array;
    protected function import_service(array $data): int;
}
use_controller($param) Tireleri alt çizgiye çevirip controller_{param} metoduna dağıtır. Metot yoksa hiçbir şey dönmez; bilinmeyen sayfa sessizce düşer.
get_page($page_file, $vars) pages/ dizininizden bir şablon yükler, $module enjekte eder; şablon yoksa paylaşılan özel ürün şablonlarına düşer.
has_client_management() pages/dashboard.php varsa ya da page_dashboard() tanımlıysa true; yalnız yönetici için false döndürecek şekilde ezin.
import_service(array $data): int Sağlayıcıda zaten var olan bir hesap için hizmet satırı oluşturur. Kimliği döndürür, sahip ya da ürün eksikse 0.

Yaşam Döngüsü İmzaları

Hiçbiri tabanda yoktur ve hiçbiri soyut değildir; çekirdek her birini method_exists() ile yoklar, yani sözleşme imzanın kendisidir.

tam imzalar
// Ayarlar ekranı. use_controller() üzerinden erişilir.
public function page_configuration(): string;
public function controller_save(): array;
public function controller_test_connection(): array;

// Ürün ve hizmet formları. İki save metodu da değerlerini REFERANSLA alır.
public function product_configuration(array $data = []): array;
public function save_product_configuration(array &$values): void;
public function service_configuration(): array;
public function save_service_configuration(array &$values): void;

// Sağlama. Dönüş tipinin burada array|bool olduğuna dikkat edin, sunucu tipinden geniştir.
public function create(): array|bool;
public function renew(): array|bool;
public function suspend(): array|bool;
public function unsuspend(): array|bool;
public function cancel(): array|bool;
public function upgrade(): array|bool;
public function change_password(string $password): bool;

// Eklentiler; biçim olarak sunucu tipiyle aynı.
public function addon_create(array $addon = []): array|bool;
public function addon_suspend(array $addon = []): array|bool;
public function addon_unsuspend(array $addon = []): array|bool;
public function addon_cancel(array $addon = []): array|bool;
public function addon_upgrade(array $addon, array $new_addon): array|bool;

// Canlı durum ve admin panosu.
public function fetchRemoteStatus(): array;
public function getDashboardData(): array;

// Metrik faturalama.
public function metrics_usage(): array;
public function metrics_usage_bulk(array $services): array;
public function metric_enable(array $metric): void;
public function metric_disable(array $metric): void;

// Müşteri aksiyonları. Buradaki ad, bildirilen adın başına handle_ eklenmiş halidir.
public function handle_reset_usage(): array;
Bu tipte upgrade() argüman almaz

Sunucu modülü yeni ürünü upgrade(array $new_product = []) olarak alır. Ürün modülleri upgrade(): array|bool yazar ve yeni durumu hizmetten okur.

SSL Sözleşmesi

siz yazarsınız
abstract protected function initApi(): void;
abstract public function fetchRemoteStatus(): array;
abstract protected function sslProductOptions(): array;
abstract protected function apiReissue(string $csr, string $dcv_method, string $approver_email): array|bool;
abstract protected function apiResendValidation(string $domain = ''): array|bool;
abstract protected function apiRevalidate(string $domain = ''): array|bool;
abstract protected function apiChangeValidationMethod(string $domain, string $method, string $approver = 'admin'): array|bool;
devraldıklarınız
// Askıya alma bir sertifika için anlamsızdır, bu yüzden ikisi de sizin yerinize yanıtlanır.
public function suspend(): array|bool;
public function unsuspend(): array|bool;

// Ürün alanları: sertifika açılır listesi artı dahil SAN sayısı.
public function product_configuration(array $data = []): array;
public function save_product_configuration(array &$values): void;

// Yedi müşteri aksiyonu; her biri sahiplik, CSRF ve aktif hizmet denetimiyle korunmuş.
public function handle_reissue(): array;
public function handle_resend_validation(): array;
public function handle_revalidate(): array;
public function handle_change_validation_method(): array;
public function handle_add_san(): array;
public function handle_remove_san(): array;
public function handle_download_certificate(): string;

// Sertifika durumu çevresindeki yardımcılar.
public function stagedSans(): array;
public function certificateId(): string;
public static function collectExpiringServices(string $module, int $maxDays = 30): array;
client_callable_methods Yedi aksiyon adının hepsi tabanca doldurulur; yeniden bildirmeyin.
client_readonly_methods Yalnız download_certificate: GET ile dosya akıtır, token ve POST istemez.
dcv_methods email, http, https, dns. Başka her şey e-postaya normalleşir.
paylaşılan sertifika metinleri Kurulumda $this->lang içine birleştirilir; çakışmada kendi dosyanız kazanır.
fetchRemoteStatus() biçimi Okunanlar: status, domain, ssl_type, sans, sans_included, sans_addon, sans_max, issued_at, expires_at, validation_method, approver_email, dcv_file, dcv_dns, serial_number, signature_algo, key_size, issuer, crt_code ve ca_code.

import_service() Anahtarları

owner_id, product_id İkisi de zorunlu tam sayı; eksik ya da bilinmeyen biri hiçbir şey yazmadan 0 döndürür.
cycle monthly gibi bir döngü anahtarı: dönemi, süreyi ve fiyatı çözer, fiyatı önce alıcının para biriminde arar.
period, period_time, amount, amount_cid Açık ezmeler: period döngü çözümünü, amount fiyat aramasını atlar.
options Hizmet seçeneklerine birleşir; established zorla true olur ve ürünün modül verisi creation_info içine gider.
name, status, cdate, duedate, renewaldate Ad ürün adına, durum active değerine, üç tarih şimdiye düşer.

Örnek

Bir lisans modülü: ayar kaydı, sağlama, sonucun geri okunması.

ayarlar
public function controller_save(): array
{
    $endpoint = Filter::init("POST/api_endpoint", "hclear");
    if (!$endpoint) throw new Exception($this->lang['err-endpoint-required']);

    $this->save_config([
        'api_endpoint' => $endpoint,

        // Geçirgen: başka her filtre anahtarı güçlü kılan şeyi siler.
        'api_key'      => $this->encode_str(Filter::init("POST/api_key", "password")),
        'mode'         => Filter::init("POST/mode", "letters"),
    ]);

    return ['status' => 'successful'];
}

public function controller_test_connection(): array
{
    $this->initApi();
    $this->api->call('ping');

    return ['status' => 'successful', 'message' => $this->lang['connection-ok']];
}

private function initApi(): void
{
    // Tembel: örnek, ağa hiç ulaşmayan bağlamlarda da kurulur.
    if (isset($this->api)) return;

    include_once __DIR__ . DS . 'ApiClient.php';
    $this->api = new ApiClient(
        $this->config['settings']['api_endpoint'] ?? '',
        $this->decode_str($this->config['settings']['api_key'] ?? ''),
    );
}
sağlama
public function create(): array|bool
{
    // Yöneticinin üründe yapılandırdığı; sipariş anındaki kopya tercih edilir.
    $module_data = ($this->options['creation_info'] ?? []) ?: ($this->product['module_data'] ?? []);

    $plan  = $module_data['plan'] ?? 'starter';
    $seats = (int) ($module_data['seats'] ?? 1);

    // Eklentiler taban hakkın üzerine eklenir; gereksinimler alıcının yazdıklarıdır.
    $seats += (int) ($this->addon_params['extra_seats'] ?? 0);
    $company = $this->requirement_params['company_name'] ?? '';

    $this->initApi();

    // Yeniden deneme güvenliği: kuyruk bu metodu bir hatadan sonra tekrar koşar.
    $existing = $this->options['config']['id'] ?? '';
    if ($existing) return true;

    $result = $this->api->call('licences', [
        'plan'    => $plan,
        'seats'   => $seats,
        'company' => $company,
        'email'   => $this->user['email'] ?? '',
    ], 'POST');

    return [
        'config' => [
            'id'  => $result['licence_id'] ?? '',
            'key' => $this->encode_str($result['licence_key'] ?? ''),
        ],
        'login' => [
            'username' => $result['username'] ?? '',
            'password' => $this->encode_str($result['password'] ?? ''),
        ],
    ];
}
saklanan sonucun geri okunması
// Sonraki her fiil, create() metodunun döndürdüğünden başlar. Çekirdek bu koşmadan
// önce 'config' ve 'login' anahtarlarını hizmet seçeneklerine birleştirdi.
public function cancel(): array|bool
{
    $licenceId = $this->options['config']['id'] ?? '';
    if (!$licenceId) return true;             // hiçbir zaman bir şey sağlanmadı

    $this->initApi();
    $this->api->call('licences/' . $licenceId, [], 'DELETE');

    return true;
}

// Admin panosu ve müşteri özeti için canlı sağlayıcı durumu.
public function fetchRemoteStatus(): array
{
    $licenceId = $this->options['config']['id'] ?? '';
    if (!$licenceId) return [];

    $this->initApi();
    $remote = $this->api->call('licences/' . $licenceId);

    return [
        'status'     => $remote['state'] ?? 'unknown',
        'seats_used' => (int) ($remote['seats_used'] ?? 0),

        // Döndürmeden önce biçimlendirin: müşteri paneli bu değerleri olduğu gibi basar.
        'expires_at' => DateManager::format(Config::get("options/date-format"), $remote['expires'] ?? ''),
    ];
}

Tuzaklar

Bir sunucu modülünü kopyalayıp sunucu kısımlarını silmeyin

upgrade() farklı imzaya sahiptir, çözümlenmiş limit yardımcısı ve araç kataloğu yoktur. Bir Product kum havuzu örneğinden başlayın.

API istemcisini tembelce kurun, asla yapıcıda değil

Örnek, sağlayıcıyı çağırmayan sayfalarda da kurulur.

Modül yapılandırmasındaki sır şifrelenmelidir

Bunu sizin yerinize yapan bir sunucu kaydı yok: kaydetmeden önce şifreleyin, kullanmadan önce çözün, gönderilen değeri geçirgen filtreyle okuyun.

Hatayı fırlatarak bildirin

Bir hata dizesi atayıp false döndürmek kalıntıdır. Çevrilmiş bir exception fırlatın; kuyruk mesajı kaydeder ve yeniden dener.

Tarihleri ve sayıları döndürmeden önce biçimlendirin

Müşteri paneli değerleri verildiği gibi gösterir, ham zaman damgası dahil.

Faydalı oldu mu?

Geri bildiriminiz için teşekkürler!

Hâlâ Yardıma mı İhtiyacınız Var?

Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.