true, 'hosting.whmcs.api_secret' => 'test-secret', 'hosting.whmcs.allowed_ips' => [], ]); HostingPlan::query()->create([ 'slug' => 'small', 'name' => 'Small', 'cpu' => 2, 'ram' => 4096, 'disk' => 40, 'max_backups' => 4, 'is_active' => true, ]); } public function test_provision_requires_valid_signature(): void { $this->postJson('/api/whmcs/services', []) ->assertStatus(401); } public function test_provision_with_valid_signature(): void { Queue::fake(); Http::fake(['*' => Http::response(['data' => null], 200)]); $body = [ 'whmcs_service_id' => 1001, 'whmcs_client_id' => 42, 'client_email' => 'kunde@example.com', 'client_name' => 'Max Kunde', 'plan_slug' => 'small', 'hostname' => 'vm-test', 'subdomain' => 'vmtest', 'behind_traefik' => true, 'provision_mode' => 'template', 'template_slug' => 'debian-12', ]; $json = json_encode($body); $timestamp = time(); $signature = hash_hmac('sha256', $timestamp.'.'.$json, 'test-secret'); $this->postJson('/api/whmcs/services', $body, [ 'X-Whmcs-Timestamp' => $timestamp, 'X-Whmcs-Signature' => $signature, ]) ->assertStatus(202) ->assertJsonPath('vmid', 2000); $this->assertDatabaseHas('whmcs_services', ['whmcs_service_id' => 1001]); $this->assertDatabaseHas('vmid_reservations', ['vmid' => 2000, 'status' => 'reserved']); } private function signedRequest(string $method, string $uri, array $body = []): \Illuminate\Testing\TestResponse { $json = json_encode($body); $timestamp = time(); $signature = hash_hmac('sha256', $timestamp.'.'.$json, 'test-secret'); return $this->json($method, $uri, $body, [ 'X-Whmcs-Timestamp' => $timestamp, 'X-Whmcs-Signature' => $signature, ]); } }