Ürün Modülü Yazma
Ü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.
Ö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ı
specialya dasoftwaretipinde bir ürün.
Yapı
Sunucu dışında her modül tipiyle aynı biç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
| Fark | Sunucu modülü | Ürün modülü |
|---|---|---|
| Kimlik bilgileri | Sunucu kaydı, taban sınıf çözer | Modül yapılandırması, siz çözersiniz |
| Bağlantı testi | Sunucu formunda test_connect() | controller_test_connection() |
| Ayarlar ekranı | Yapılandırma alanlarından üretilir | page_configuration() + kaydetme controller'ı |
| Kaynak limitleri | get_limit(), taban sınıf çözer | Ürünün modül verisinden |
| Müşteri araçları | Araç kataloğu ve paylaşılan şablonlar | Pano sayfanız + çağrılabilir aksiyonlar |
| Müşteri sekmesi | Pano 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ı.
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
}
}
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.
page_configuration()ekranı kurar, çoğunlukla form oluşturucuyla.controller_save()gönderilen alanlarısave_config()ile yazar. Her sırrı önce şifreleyin.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.
- API istemcisini yapıcıda değil, ihtiyaç duyulan metodun içinde tembelce kurun.
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
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;
}
controller_{param} metoduna dağıtır. Metot yoksa hiçbir şey dönmez; bilinmeyen sayfa sessizce düşer.
pages/ dizininizden bir şablon yükler, $module enjekte eder; şablon yoksa paylaşılan özel ürün şablonlarına düşer.
pages/dashboard.php varsa ya da page_dashboard() tanımlıysa true; yalnız yönetici için false döndürecek şekilde ezin.
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.
// 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;
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
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;
// 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;
download_certificate: GET ile dosya akıtır, token ve POST istemez.
email, http, https, dns. Başka her şey e-postaya normalleşir.
$this->lang içine birleştirilir; çakışmada kendi dosyanız kazanır.
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ı
monthly gibi bir döngü anahtarı: dönemi, süreyi ve fiyatı çözer, fiyatı önce alıcının para biriminde arar.
period döngü çözümünü, amount fiyat aramasını atlar.
established zorla true olur ve ürünün modül verisi creation_info içine gider.
active değerine, üç tarih şimdiye düşer.
Örnek
Bir lisans modülü: ayar kaydı, sağlama, sonucun geri okunması.
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'] ?? ''),
);
}
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'] ?? ''),
],
];
}
// 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
upgrade() farklı imzaya sahiptir, çözümlenmiş limit yardımcısı ve araç kataloğu yoktur. Bir Product kum havuzu örneğinden başlayın.
Örnek, sağlayıcıyı çağırmayan sayfalarda da kurulur.
Bunu sizin yerinize yapan bir sunucu kaydı yok: kaydetmeden önce şifreleyin, kullanmadan önce çözün, gönderilen değeri geçirgen filtreyle okuyun.
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.
Müşteri paneli değerleri verildiği gibi gösterir, ham zaman damgası dahil.
İlgili Makaleler
Geri bildiriminiz için teşekkürler!
Yukarıda bulamadığınız her şey için destek ekibimiz her zaman yanınızda.