# Lizenzserver Nutzungsanleitung

## Übersicht
Der Lizenzserver läuft unter: `https://api-software-undso.z5m7q9dk3ah2v1plx6ju.com`

## API Endpoints

### 1. Lizenz aktivieren
**POST** `/api/license/activate`

Aktiviert eine Lizenz für eine bestimmte Maschine.

```json
{
  "license_key": "XXXX-XXXX-XXXX-XXXX",
  "machine_id": "UNIQUE-MACHINE-ID",
  "hardware_hash": "SHA256-HARDWARE-FINGERPRINT",
  "os_info": {
    "os": "Windows",
    "version": "10.0.19041"
  },
  "app_version": "1.0.0"
}
```

**Antwort bei Erfolg:**
```json
{
  "success": true,
  "message": "License activated successfully",
  "activation_id": 123,
  "expires_at": "2025-12-31T23:59:59",
  "features": {
    "all_features": true
  }
}
```

### 2. Lizenz verifizieren (Heartbeat)
**POST** `/api/license/verify`

Sollte alle 15 Minuten aufgerufen werden.

```json
{
  "license_key": "XXXX-XXXX-XXXX-XXXX",
  "machine_id": "UNIQUE-MACHINE-ID",
  "hardware_hash": "SHA256-HARDWARE-FINGERPRINT",
  "activation_id": 123
}
```

**Antwort:**
```json
{
  "valid": true,
  "message": "License is valid",
  "expires_at": "2025-12-31T23:59:59",
  "features": {
    "all_features": true
  },
  "requires_update": false,
  "update_url": null
}
```

### 3. Version prüfen
**POST** `/api/version/check`

```json
{
  "current_version": "1.0.0",
  "license_key": "XXXX-XXXX-XXXX-XXXX"
}
```

**Antwort:**
```json
{
  "latest_version": "1.1.0",
  "current_version": "1.0.0",
  "update_available": true,
  "is_mandatory": false,
  "download_url": "https://download.example.com/v1.1.0",
  "release_notes": "Bug fixes and improvements"
}
```

### 4. Lizenzinfo abrufen
**GET** `/api/license/info/{license_key}`

Liefert detaillierte Informationen über eine Lizenz.

## Authentifizierung

Alle API-Anfragen benötigen einen API-Key im Authorization Header:

```
Authorization: Bearer YOUR-API-KEY-HERE
```

## Client-Integration Beispiel (Python)

```python
import requests
import hashlib
import platform
import uuid
import json
from datetime import datetime, timedelta

class LicenseClient:
    def __init__(self, api_key, server_url="https://api-software-undso.z5m7q9dk3ah2v1plx6ju.com"):
        self.api_key = api_key
        self.server_url = server_url
        self.headers = {"Authorization": f"Bearer {api_key}"}
        
    def get_machine_id(self):
        """Eindeutige Maschinen-ID generieren"""
        return str(uuid.getnode())  # MAC-Adresse
        
    def get_hardware_hash(self):
        """Hardware-Fingerprint erstellen"""
        machine_id = self.get_machine_id()
        cpu_info = platform.processor()
        system_info = f"{platform.system()}-{platform.machine()}"
        
        combined = f"{machine_id}-{cpu_info}-{system_info}"
        return hashlib.sha256(combined.encode()).hexdigest()
        
    def activate_license(self, license_key):
        """Lizenz aktivieren"""
        data = {
            "license_key": license_key,
            "machine_id": self.get_machine_id(),
            "hardware_hash": self.get_hardware_hash(),
            "os_info": {
                "os": platform.system(),
                "version": platform.version(),
                "machine": platform.machine()
            },
            "app_version": "1.0.0"
        }
        
        response = requests.post(
            f"{self.server_url}/api/license/activate",
            headers=self.headers,
            json=data,
            verify=True  # SSL-Zertifikat prüfen
        )
        
        return response.json()
        
    def verify_license(self, license_key, activation_id):
        """Lizenz verifizieren (Heartbeat)"""
        data = {
            "license_key": license_key,
            "machine_id": self.get_machine_id(),
            "hardware_hash": self.get_hardware_hash(),
            "activation_id": activation_id
        }
        
        response = requests.post(
            f"{self.server_url}/api/license/verify",
            headers=self.headers,
            json=data,
            verify=True
        )
        
        return response.json()
        
    def check_version(self, license_key, current_version):
        """Version prüfen"""
        data = {
            "current_version": current_version,
            "license_key": license_key
        }
        
        response = requests.post(
            f"{self.server_url}/api/version/check",
            headers=self.headers,
            json=data,
            verify=True
        )
        
        return response.json()

# Verwendungsbeispiel
if __name__ == "__main__":
    client = LicenseClient("YOUR-API-KEY")
    
    # Lizenz aktivieren
    result = client.activate_license("USER-LICENSE-KEY")
    if result["success"]:
        activation_id = result["activation_id"]
        print(f"Lizenz aktiviert! Activation ID: {activation_id}")
        
        # Lizenz verifizieren
        verify_result = client.verify_license("USER-LICENSE-KEY", activation_id)
        if verify_result["valid"]:
            print("Lizenz ist gültig!")
```

## Client-Integration Beispiel (C#)

```csharp
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.Management;

public class LicenseClient
{
    private readonly HttpClient httpClient;
    private readonly string apiKey;
    private readonly string serverUrl;

    public LicenseClient(string apiKey, string serverUrl = "https://api-software-undso.z5m7q9dk3ah2v1plx6ju.com")
    {
        this.apiKey = apiKey;
        this.serverUrl = serverUrl;
        
        httpClient = new HttpClient();
        httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
    }

    private string GetMachineId()
    {
        // CPU ID abrufen
        string cpuId = "";
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT ProcessorId FROM Win32_Processor");
        foreach (ManagementObject obj in searcher.Get())
        {
            cpuId = obj["ProcessorId"].ToString();
            break;
        }
        return cpuId;
    }

    private string GetHardwareHash()
    {
        string machineId = GetMachineId();
        string systemInfo = Environment.MachineName + Environment.OSVersion;
        
        using (SHA256 sha256 = SHA256.Create())
        {
            byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(machineId + systemInfo));
            return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
        }
    }

    public async Task<LicenseActivationResponse> ActivateLicenseAsync(string licenseKey)
    {
        var requestData = new
        {
            license_key = licenseKey,
            machine_id = GetMachineId(),
            hardware_hash = GetHardwareHash(),
            os_info = new
            {
                os = "Windows",
                version = Environment.OSVersion.Version.ToString()
            },
            app_version = "1.0.0"
        };

        var json = JsonSerializer.Serialize(requestData);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        var response = await httpClient.PostAsync($"{serverUrl}/api/license/activate", content);
        var responseContent = await response.Content.ReadAsStringAsync();
        
        return JsonSerializer.Deserialize<LicenseActivationResponse>(responseContent);
    }
}

public class LicenseActivationResponse
{
    public bool success { get; set; }
    public string message { get; set; }
    public int? activation_id { get; set; }
    public DateTime? expires_at { get; set; }
}
```

## Wichtige Hinweise

### Sicherheit
- API-Keys niemals im Quellcode hartcodieren
- SSL-Zertifikat immer prüfen (verify=True)
- Hardware-Hash lokal zwischenspeichern

### Rate Limiting
- Max. 100 Anfragen pro Minute pro API-Key
- Heartbeat alle 15 Minuten (nicht öfter)

### Offline-Betrieb
- 7 Tage Grace Period bei Verbindungsproblemen
- Letzte gültige Lizenz lokal cachen
- Bei Hardware-Änderung: Grace Period nutzen

### Fehlerbehandlung
```python
try:
    result = client.verify_license(license_key, activation_id)
except requests.exceptions.ConnectionError:
    # Offline-Modus: Gecachte Lizenz prüfen
    if cached_license_valid():
        continue_execution()
    else:
        show_error("Keine Internetverbindung und Lizenz abgelaufen")
except requests.exceptions.HTTPError as e:
    if e.response.status_code == 401:
        show_error("Ungültiger API-Key")
    elif e.response.status_code == 403:
        show_error("Lizenz ungültig oder abgelaufen")
```

## Test-Zugangsdaten

Für Entwicklungszwecke:
- Test API-Key: `test-api-key-12345`
- Test Lizenz: `TEST-LICENSE-KEY-12345`

**WICHTIG:** Für Produktion eigene API-Keys und Lizenzen erstellen!

## Support

Bei Problemen:
1. Logs prüfen: `docker logs license-server`
2. API-Status: https://api-software-undso.z5m7q9dk3ah2v1plx6ju.com/health
3. Datenbank prüfen: Lizenzen und Aktivierungen