210 lines
7.0 KiB
PHP
210 lines
7.0 KiB
PHP
<?php
|
|
/**
|
|
* API Client for ZitiNexus Portal communication
|
|
*/
|
|
|
|
require_once 'config.php';
|
|
|
|
class ApiClient {
|
|
private $apiEndpoint;
|
|
private $userAgent;
|
|
private $timeout;
|
|
private $maxRetries;
|
|
|
|
public function __construct($apiEndpoint = DEFAULT_API_ENDPOINT) {
|
|
$this->apiEndpoint = rtrim($apiEndpoint, '/');
|
|
$this->userAgent = 'ZitiRouter-EnrollmentUI/' . APP_VERSION;
|
|
$this->timeout = 60;
|
|
$this->maxRetries = 3;
|
|
}
|
|
|
|
/**
|
|
* Register router with ZitiNexus Portal
|
|
*/
|
|
public function registerRouter($hashKey) {
|
|
$url = $this->apiEndpoint . '/api/router/register';
|
|
$payload = json_encode(['hashKey' => $hashKey]);
|
|
|
|
logMessage('INFO', "Registering router with API: $url");
|
|
|
|
$response = $this->makeRequest('POST', $url, $payload);
|
|
|
|
if (!$response['success']) {
|
|
logMessage('ERROR', "API registration failed: " . $response['error']);
|
|
return $response;
|
|
}
|
|
|
|
$data = json_decode($response['body'], true);
|
|
|
|
if (!$data || !isset($data['success']) || !$data['success']) {
|
|
$errorMsg = isset($data['error']['message']) ? $data['error']['message'] : 'Registration failed';
|
|
logMessage('ERROR', "Registration failed: $errorMsg");
|
|
return [
|
|
'success' => false,
|
|
'error' => $errorMsg
|
|
];
|
|
}
|
|
|
|
logMessage('SUCCESS', "Router registered successfully");
|
|
return [
|
|
'success' => true,
|
|
'data' => $data['data']
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Report enrollment status to portal
|
|
*/
|
|
public function reportStatus($callbackUrl, $hashKey, $status, $routerInfo = null, $errorMessage = null) {
|
|
if (empty($callbackUrl)) {
|
|
logMessage('WARNING', 'No callback URL provided, skipping status report');
|
|
return ['success' => true];
|
|
}
|
|
|
|
// Fix callback URL domain mismatch if needed
|
|
$fixedCallbackUrl = $this->fixCallbackUrl($callbackUrl);
|
|
|
|
$payload = [
|
|
'hashKey' => $hashKey,
|
|
'status' => $status
|
|
];
|
|
|
|
if ($status === 'success' && $routerInfo) {
|
|
$payload['routerInfo'] = $routerInfo;
|
|
} elseif ($status === 'failed' && $errorMessage) {
|
|
$payload['error'] = $errorMessage;
|
|
}
|
|
|
|
logMessage('INFO', "Reporting status '$status' to: $fixedCallbackUrl");
|
|
|
|
$response = $this->makeRequest('POST', $fixedCallbackUrl, json_encode($payload));
|
|
|
|
if ($response['success']) {
|
|
logMessage('SUCCESS', 'Status reported successfully');
|
|
} else {
|
|
logMessage('WARNING', 'Failed to report status: ' . $response['error']);
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Make HTTP request with retry logic
|
|
*/
|
|
private function makeRequest($method, $url, $data = null) {
|
|
$retryCount = 0;
|
|
|
|
while ($retryCount < $this->maxRetries) {
|
|
$ch = curl_init();
|
|
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => $url,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => $this->timeout,
|
|
CURLOPT_CONNECTTIMEOUT => 30,
|
|
CURLOPT_USERAGENT => $this->userAgent,
|
|
CURLOPT_HTTPHEADER => [
|
|
'Content-Type: application/json',
|
|
'Accept: application/json'
|
|
],
|
|
CURLOPT_SSL_VERIFYPEER => true,
|
|
CURLOPT_SSL_VERIFYHOST => 2,
|
|
CURLOPT_FOLLOWLOCATION => true,
|
|
CURLOPT_MAXREDIRS => 3
|
|
]);
|
|
|
|
if ($method === 'POST' && $data) {
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
|
}
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$error = curl_error($ch);
|
|
|
|
curl_close($ch);
|
|
|
|
if ($response === false) {
|
|
logMessage('ERROR', "cURL error: $error");
|
|
$retryCount++;
|
|
if ($retryCount < $this->maxRetries) {
|
|
$waitTime = $retryCount * 2;
|
|
logMessage('INFO', "Retrying in {$waitTime}s... (attempt $retryCount/$this->maxRetries)");
|
|
sleep($waitTime);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if ($httpCode === 200) {
|
|
return [
|
|
'success' => true,
|
|
'body' => $response,
|
|
'http_code' => $httpCode
|
|
];
|
|
} elseif ($httpCode === 429) {
|
|
// Rate limited
|
|
$retryCount++;
|
|
if ($retryCount < $this->maxRetries) {
|
|
$waitTime = $retryCount * 2;
|
|
logMessage('WARNING', "Rate limited. Waiting {$waitTime}s before retry $retryCount/$this->maxRetries");
|
|
sleep($waitTime);
|
|
}
|
|
continue;
|
|
} else {
|
|
$errorMsg = "HTTP $httpCode";
|
|
if ($response) {
|
|
$responseData = json_decode($response, true);
|
|
if ($responseData && isset($responseData['error']['message'])) {
|
|
$errorMsg .= ': ' . $responseData['error']['message'];
|
|
} elseif ($responseData && isset($responseData['message'])) {
|
|
$errorMsg .= ': ' . $responseData['message'];
|
|
}
|
|
}
|
|
|
|
return [
|
|
'success' => false,
|
|
'error' => $errorMsg,
|
|
'http_code' => $httpCode,
|
|
'body' => $response
|
|
];
|
|
}
|
|
}
|
|
|
|
return [
|
|
'success' => false,
|
|
'error' => 'Max retries exceeded',
|
|
'http_code' => 0
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Fix callback URL domain mismatch
|
|
*/
|
|
private function fixCallbackUrl($callbackUrl) {
|
|
// Replace api.zitinexus.com with backend.zitinexus.com to match script's API endpoint
|
|
if (strpos($callbackUrl, 'api.zitinexus.com') !== false) {
|
|
$fixedUrl = str_replace('api.zitinexus.com', 'backend.zitinexus.com', $callbackUrl);
|
|
logMessage('INFO', "Fixed callback URL domain: $fixedUrl");
|
|
return $fixedUrl;
|
|
}
|
|
|
|
return $callbackUrl;
|
|
}
|
|
|
|
/**
|
|
* Validate hash key format
|
|
*/
|
|
public static function validateHashKey($hashKey) {
|
|
return preg_match('/^[a-fA-F0-9]{32}$/', $hashKey);
|
|
}
|
|
|
|
/**
|
|
* Validate API endpoint format
|
|
*/
|
|
public static function validateApiEndpoint($endpoint) {
|
|
return filter_var($endpoint, FILTER_VALIDATE_URL) &&
|
|
(strpos($endpoint, 'http://') === 0 || strpos($endpoint, 'https://') === 0);
|
|
}
|
|
}
|
|
?>
|