ak = $ak; $this->sk = $sk; $this->region = $region; $this->projectId = $projectId; } private function sign($method, $url, $headers, $body = '') { $parsedUrl = parse_url($url); $host = $parsedUrl['host']; $path = $parsedUrl['path'] ?? '/'; $query = $parsedUrl['query'] ?? ''; $time = gmdate('Ymd\THis\Z'); $date = gmdate('Ymd'); // Ajouter les headers requis $headers['Host'] = $host; $headers['X-Sdk-Date'] = $time; // Trier les headers ksort($headers); // Construire les headers canoniques $canonicalHeaders = ''; $signedHeaders = []; foreach ($headers as $key => $value) { $lowerKey = strtolower($key); $canonicalHeaders .= $lowerKey . ':' . trim($value) . "\n"; $signedHeaders[] = $lowerKey; } $signedHeadersStr = implode(';', $signedHeaders); // Hash du body $hashedPayload = hash('sha256', $body); // Requête canonique $canonicalRequest = $method . "\n" . $path . "\n" . $query . "\n" . $canonicalHeaders . "\n" . $signedHeadersStr . "\n" . $hashedPayload; // String to sign $algorithm = 'SDK-HMAC-SHA256'; $hashedCanonicalRequest = hash('sha256', $canonicalRequest); $stringToSign = $algorithm . "\n" . $time . "\n" . $hashedCanonicalRequest; // Calculer la signature $signature = hash_hmac('sha256', $stringToSign, $this->sk); // Construire l'en-tête Authorization $authorization = $algorithm . ' ' . 'Access=' . $this->ak . ', ' . 'SignedHeaders=' . $signedHeadersStr . ', ' . 'Signature=' . $signature; $headers['Authorization'] = $authorization; return $headers; } public function call($service, $method, $endpoint, $data = null) { $host = "$service.{$this->region}.myhuaweicloud.com"; $url = "https://$host$endpoint"; $body = $data ? json_encode($data) : ''; $headers = [ 'Content-Type' => 'application/json' ]; $signedHeaders = $this->sign($method, $url, $headers, $body); $curlHeaders = []; foreach ($signedHeaders as $key => $value) { $curlHeaders[] = "$key: $value"; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $curlHeaders); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); if ($method === 'POST') { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $body); } $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); return [ 'code' => $httpCode, 'body' => json_decode($response, true), 'raw' => $response, 'error' => $error ]; } public function listVPCs() { return $this->call('vpc', 'GET', "/v1/{$this->projectId}/vpcs"); } public function listSubnets() { return $this->call('vpc', 'GET', "/v1/{$this->projectId}/subnets"); } public function listSecurityGroups() { return $this->call('vpc', 'GET', "/v1/{$this->projectId}/security-groups"); } public function listFlavors() { return $this->call('ecs', 'GET', "/v1/{$this->projectId}/cloudservers/flavors"); } public function createServer($name, $flavorId, $imageId, $vpcId, $subnetId, $securityGroupId, $password) { $data = [ 'server' => [ 'name' => $name, 'flavorRef' => $flavorId, 'imageRef' => $imageId, 'vpcid' => $vpcId, 'nics' => [['subnet_id' => $subnetId]], 'security_groups' => [['id' => $securityGroupId]], 'root_volume' => ['volumetype' => 'SSD', 'size' => 40], 'adminPass' => $password, 'availability_zone' => $this->region . 'a', 'count' => 1 ] ]; return $this->call('ecs', 'POST', "/v1/{$this->projectId}/cloudservers", $data); } }