activate('ABZ-XXXX-XXXX-XXXX-XXXX'); * if (!$result['valid']) { * die('License invalid: ' . $result['message']); * } */ class AIBuildZoneLicense { private string $serverUrl; private ?string $apiSecret; private int $timeout; public function __construct(string $serverUrl, ?string $apiSecret = null, int $timeout = 10) { $this->serverUrl = rtrim($serverUrl, '/'); $this->apiSecret = $apiSecret; $this->timeout = $timeout; } public function activate(string $licenseKey, ?string $domain = null, ?string $product = null): array { return $this->request('activate', $licenseKey, $domain, $product); } public function verify(string $licenseKey, ?string $domain = null, ?string $product = null): array { return $this->request('verify', $licenseKey, $domain, $product); } public function deactivate(string $licenseKey, ?string $domain = null): array { return $this->request('deactivate', $licenseKey, $domain, null); } public function currentDomain(): string { $host = $_SERVER['HTTP_HOST'] ?? ($_SERVER['SERVER_NAME'] ?? 'localhost'); $host = preg_replace('/:\d+$/', '', $host); return strtolower(trim($host)); } private function request(string $action, string $key, ?string $domain, ?string $product): array { $domain = $domain ?: $this->currentDomain(); $url = $this->serverUrl . '/api/license.php'; $payload = [ 'action' => $action, 'key' => trim($key), 'domain' => $domain, 'product' => $product, 'php_version' => PHP_VERSION, ]; $postData = http_build_query(array_filter($payload, function ($v) { return $v !== null && $v !== ''; })); if (function_exists('curl_init')) { $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postData, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => $this->timeout, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_USERAGENT => 'AIBuildZone-Client/1.0', ]); $raw = curl_exec($ch); $err = curl_error($ch); curl_close($ch); if ($raw === false) { return ['valid' => false, 'status' => 'network_error', 'message' => 'Connection failed: ' . $err]; } } else { $ctx = stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: application/x-www-form-urlencoded\r\nUser-Agent: AIBuildZone-Client/1.0\r\n", 'content' => $postData, 'timeout' => $this->timeout, ], ]); $raw = @file_get_contents($url, false, $ctx); if ($raw === false) { return ['valid' => false, 'status' => 'network_error', 'message' => 'Unable to connect to license server.']; } } $data = json_decode($raw, true); if (!is_array($data)) { return ['valid' => false, 'status' => 'parse_error', 'message' => 'Invalid server response.']; } // Optional signature verification if ($this->apiSecret && !empty($data['signature'])) { $str = ($data['license_key'] ?? '') . '|' . ($data['domain'] ?? '') . '|' . ($data['status'] ?? '') . '|' . ($data['timestamp'] ?? ''); $expected = hash_hmac('sha256', $str, $this->apiSecret); if (!hash_equals($expected, $data['signature'])) { return ['valid' => false, 'status' => 'tampered', 'message' => 'Response signature verification failed.']; } } return $data; } } // If accessed directly from browser, trigger a download of this file if (PHP_SAPI !== 'cli' && basename($_SERVER['SCRIPT_NAME'] ?? '') === 'sample-client.php') { header('Content-Type: text/plain; charset=utf-8'); header('Content-Disposition: attachment; filename="LicenseClient.php"'); readfile(__FILE__); exit; }