Testsystem SpS: Hochladen einer beliebigen Rechnung (openai-php/client v0.10.x)'; echo '

Verbesserte Version mit fehlerresistenter Prüfung von HttpTransporter.

'; /** * Prüfen wir, ob wir die richtige Version von openai-php/client erwischt haben. * Falls nicht, geben wir einen Hinweis aus und definieren einen Fallback-Flag. */ function checkHttpTransporter() { // Globalen Flag setzen, damit wir ihn außerhalb abrufen können global $httpTransporterAvailable; if (class_exists(HttpTransporter::class)) { echo "

HttpTransporter is available. (OK)

"; $httpTransporterAvailable = true; } else { echo "

Warning: 'HttpTransporter' not found. Möglicherweise nutzt du nicht openai-php/client v0.10.x, sondern eine andere Version. Bitte prüfe deine Installation (z. B. composer.json: \"openai-php/client\": \"^0.10\").

"; $httpTransporterAvailable = false; } } /** * Environment-Check: * - PHP-Version * - Composer Dependencies * - PHP-Erweiterungen * - Existenz & Schreibbarkeit von Verzeichnissen * - Kommandos */ function checkEnvironment() { echo "

Environment Check

"; // 1) PHP-Version if (version_compare(PHP_VERSION, '8.2.27', '<')) { echo "

Error: PHP 8.2.27+ erforderlich! Aktuelle Version: " . PHP_VERSION . "

"; return false; } else { echo "

PHP version: " . PHP_VERSION . " (OK)

"; } // 2) openai-php/client-Version per Shell (optional) echo "

Checking openai-php/client version via composer show openai-php/client | grep versions...

"; $verShell = shell_exec("composer show openai-php/client 2>&1 | grep versions"); if ($verShell) { echo "

Detected version info:

"; echo "
" . htmlspecialchars($verShell) . "
"; } else { echo "

Could not retrieve openai-php/client version info via shell. Possibly composer not in PATH?

"; } // 3) PHP-Erweiterungen $requiredExtensions = ['json', 'curl', 'mbstring', 'openssl']; $missingExtensions = []; foreach ($requiredExtensions as $ext) { if (!extension_loaded($ext)) { $missingExtensions[] = $ext; } else { echo "

PHP extension '$ext' is installed. (OK)

"; } } if (!empty($missingExtensions)) { echo "

Error: Missing PHP extensions: " . implode(', ', $missingExtensions) . "

"; return false; } // 4) vendor/autoload? if (!file_exists(__DIR__ . '/vendor/autoload.php')) { echo "

Error: Composer dependencies are not installed. Run 'composer install' in the project directory.

"; return false; } else { echo "

Composer dependencies are installed. (OK)

"; } // 5) HttpTransporter-Klasse? (nicht mehr via die() abgebrochen) checkHttpTransporter(); // 6) Kommandos (z. B. curl) $requiredCommands = ['curl']; $missingCommands = []; foreach ($requiredCommands as $cmd) { $output = null; $returnVar = null; exec("command -v $cmd", $output, $returnVar); if ($returnVar !== 0) { $missingCommands[] = $cmd; } else { echo "

Command '$cmd' is available. (OK)

"; } } if (!empty($missingCommands)) { echo "

Error: Missing required commands: " . implode(', ', $missingCommands) . "

"; return false; } // 7) Verzeichnisrechte $directories = [ __DIR__ . '/uploads', __DIR__ . '/vendor' ]; foreach ($directories as $dir) { if (!is_dir($dir)) { echo "

Warning: Directory $dir does not exist. It will be created if necessary.

"; } elseif (!is_writable($dir)) { echo "

Error: Directory $dir is not writable. Please check permissions.

"; return false; } else { echo "

Directory $dir is writable. (OK)

"; } } return true; } /** * Prüft den API Key (Regex bei Bedarf anpassen). */ function validateApiKey($apiKey) { if (empty($apiKey) || !preg_match('/^sk-(proj|live|test)-[a-zA-Z0-9_\-]+$/', $apiKey)) { echo "

Error: Invalid OpenAI API Key. Please check your API Key.

"; return false; } echo "

OpenAI API Key is valid. (OK)

"; return true; } /** * Initialisiert ggf. den OpenAI-Client * (Nur wenn HttpTransporter tatsächlich verfügbar ist). */ function initializeOpenAIClient($apiKey): ?OpenAIClient { global $httpTransporterAvailable; // Wenn HttpTransporter nicht existiert, brechen wir hier ab – // oder wir könnten versuchen, einen anderen Ansatz zu fahren (Fallback). if (!$httpTransporterAvailable) { echo "

Cannot initialize old version of OpenAI Client (HttpTransporter missing). Please install openai-php/client:^0.10 or adapt the code for v1.x.

"; return null; } try { $transporter = HttpTransporter::create($apiKey); return new OpenAIClient($transporter); } catch (\Exception $e) { echo "

Error initializing OpenAI Client: " . $e->getMessage() . "

"; return null; } } /** * Extrahiert Rechnungsdaten aus einer PDF via Smalot\PdfParser + OpenAI */ function extractInvoiceData($pdfPath, $apiKey) { try { // 1) PDF -> Text $parser = new Parser(); $pdf = $parser->parseFile($pdfPath); $text = $pdf->getText(); // 2) Standardfelder (initial) $invoiceData = [ 'invoice_number' => null, 'invoice_date' => null, 'customer_name' => null, 'total_amount' => null, 'tax_amount' => null, ]; // 3) OpenAI initialisieren $client = initializeOpenAIClient($apiKey); if (!$client) { // Falls Client nicht initialisiert werden konnte (z. B. kein HttpTransporter) return ["error" => "Failed to initialize OpenAI Client or HttpTransporter missing."]; } // 4) Prompt definieren (JSON-Ausgabe) $prompt = <<completions()->create([ "model" => "text-davinci-003", "prompt" => $prompt, "max_tokens" => 300, ]); } catch (\Exception $e) { return ["error" => "Error during AI processing: " . $e->getMessage()]; } // 6) KI-Antwort verarbeiten $aiOutput = $response["choices"][0]["text"] ?? ''; $aiData = json_decode($aiOutput, true); if (json_last_error() === JSON_ERROR_NONE && is_array($aiData)) { $invoiceData = array_merge($invoiceData, $aiData); } else { // Wenn kein valides JSON zurückkommt return [ "error" => "AI response is not valid JSON", "ai_raw_response" => $aiOutput ]; } return $invoiceData; } catch (\Exception $e) { return ["error" => "An error occurred while processing the invoice: " . $e->getMessage()]; } } // --------------------- SCRIPT-ABLABF --------------------- // 1) Environment prüfen $envOk = checkEnvironment(); if (!$envOk) { // Wenn hier Grundanforderungen fehlen, brechen wir ab echo "

Environment check failed. Please fix the above errors.

"; exit; } // 2) API-Key definieren & validieren $apiKey = "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"; $apiKeyOk = validateApiKey($apiKey); if (!$apiKeyOk) { echo "

Invalid API key. Please correct it.

"; exit; } // 3) Upload-Handling if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['pdf_file'])) { echo "

Step 1: Handling File Upload...

"; // a) Sicherstellen, dass uploads/ existiert $uploadDir = __DIR__ . '/uploads/'; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0777, true); echo "

Upload directory created: $uploadDir

"; } $uploadedFile = $_FILES['pdf_file']; // b) MIME-Type checken (nur PDF) $finfo = new finfo(FILEINFO_MIME_TYPE); $mimeType = $finfo->file($uploadedFile['tmp_name']); if ($mimeType !== 'application/pdf') { echo "

Error: Only PDF files are allowed. Detected type: $mimeType

"; exit; } // c) Eindeutigen Dateinamen erzeugen $uniqueName = uniqid('pdf_', true) . '.pdf'; $filePath = $uploadDir . $uniqueName; // d) Datei verschieben if (move_uploaded_file($uploadedFile['tmp_name'], $filePath)) { echo "

File uploaded successfully to: $filePath

"; echo "

Step 2: Extracting Invoice Data via OpenAI...

"; $invoiceData = extractInvoiceData($filePath, $apiKey); echo "

Step 3: Outputting Extracted Data...

"; echo "
" . json_encode($invoiceData, JSON_PRETTY_PRINT) . "
"; } else { echo "

Failed to upload file.

"; } } else { // HTML form for uploading a PDF ?> Upload PDF

Upload a PDF File