* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file lib/qrcode.class.php * \ingroup epcqr * \brief QR-Code Generator mit lokalem Caching */ /** * QRCode Generator Klasse * Generiert QR-Codes und cached sie lokal für Wiederverwendung */ class QRCodeGenerator { private $db; private $cacheDir; /** * Constructor * * @param DoliDB $db Database handler */ public function __construct($db) { global $conf; $this->db = $db; // Cache-Verzeichnis für QR-Codes $this->cacheDir = $conf->epcqr->dir_output.'/qrcodes'; // Verzeichnis erstellen falls nicht vorhanden if (!is_dir($this->cacheDir)) { dol_mkdir($this->cacheDir); } } /** * Generiert einen EPC-QR-Code für SEPA-Überweisungen * * @param string $accountHolder Kontoinhaber Name * @param string $iban IBAN * @param string $bic BIC (optional) * @param float $amount Betrag * @param string $reference Verwendungszweck * @return string|false Pfad zur generierten QR-Code-Datei oder false bei Fehler */ public function generateEPCQRCode($accountHolder, $iban, $bic, $amount, $reference) { // Eindeutigen Dateinamen generieren basierend auf Parametern $hash = md5($accountHolder.$iban.$bic.$amount.$reference); $filename = 'epc_'.$hash.'.png'; $filepath = $this->cacheDir.'/'.$filename; // Prüfen ob QR-Code bereits cached ist if (file_exists($filepath)) { dol_syslog("QRCodeGenerator: QR-Code aus Cache geladen: ".$filepath, LOG_DEBUG); return $filepath; } // QR-Code generieren $qrData = $this->generateEPCData($accountHolder, $iban, $bic, $amount, $reference); $result = $this->generateQRImage($qrData, $filepath); if ($result) { dol_syslog("QRCodeGenerator: QR-Code generiert: ".$filepath, LOG_DEBUG); return $filepath; } dol_syslog("QRCodeGenerator: Fehler beim Generieren des QR-Codes", LOG_ERR); return false; } /** * Generiert einen generischen QR-Code aus beliebigem Text * * @param string $data Daten für QR-Code * @param string $prefix Präfix für Dateinamen (default: 'qr') * @return string|false Pfad zur generierten QR-Code-Datei oder false bei Fehler */ public function generateQRCode($data, $prefix = 'qr') { // Eindeutigen Dateinamen generieren $hash = md5($data); $filename = $prefix.'_'.$hash.'.png'; $filepath = $this->cacheDir.'/'.$filename; // Prüfen ob QR-Code bereits cached ist if (file_exists($filepath)) { dol_syslog("QRCodeGenerator: QR-Code aus Cache geladen: ".$filepath, LOG_DEBUG); return $filepath; } // QR-Code generieren $result = $this->generateQRImage($data, $filepath); if ($result) { dol_syslog("QRCodeGenerator: QR-Code generiert: ".$filepath, LOG_DEBUG); return $filepath; } dol_syslog("QRCodeGenerator: Fehler beim Generieren des QR-Codes", LOG_ERR); return false; } /** * Generiert EPC-Datenstring für SEPA-QR-Codes * * @param string $accountHolder Kontoinhaber Name * @param string $iban IBAN * @param string $bic BIC * @param float $amount Betrag * @param string $reference Verwendungszweck * @return string EPC-Datenstring */ private function generateEPCData($accountHolder, $iban, $bic, $amount, $reference) { // EPC QR-Code Format (GiroCode Standard) $epcData = array( 'BCD', // Service Tag '002', // Version '1', // Character set (1 = UTF-8) 'SCT', // Identification (SEPA Credit Transfer) $bic, // BIC $accountHolder, // Empfänger Name $iban, // Empfänger IBAN 'EUR'.number_format($amount, 2, '.', ''), // Betrag '', // Purpose (optional) $reference, // Verwendungszweck '' // Beneficiary to originator information (optional) ); return implode("\n", $epcData); } /** * Generiert QR-Code-Bild aus Daten * * Nutzt zunächst den externen Service, später kann dies durch * eine native PHP-Implementierung ersetzt werden * * @param string $data Daten für QR-Code * @param string $filepath Zielpfad für PNG-Datei * @return bool true bei Erfolg, false bei Fehler */ private function generateQRImage($data, $filepath) { // Methode 1: Externe API (aktuell) // TODO: Später durch native PHP-Generierung ersetzen $url = 'https://qr.data-it-solution.de/generate?data='.urlencode($data).'&size=300'; // Bild von URL holen $imageData = @file_get_contents($url); if ($imageData === false) { // Fallback: Versuche mit cURL if (function_exists('curl_init')) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $imageData = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200 || $imageData === false) { return false; } } else { return false; } } // Bild speichern $result = file_put_contents($filepath, $imageData); return ($result !== false); } /** * Löscht gecachte QR-Codes die älter als X Tage sind * * @param int $days Anzahl Tage (default: 30) * @return int Anzahl gelöschter Dateien */ public function cleanCache($days = 30) { $deleted = 0; $threshold = time() - ($days * 86400); if (!is_dir($this->cacheDir)) { return 0; } $files = scandir($this->cacheDir); foreach ($files as $file) { if ($file === '.' || $file === '..') { continue; } $filepath = $this->cacheDir.'/'.$file; if (is_file($filepath) && filemtime($filepath) < $threshold) { if (unlink($filepath)) { $deleted++; } } } dol_syslog("QRCodeGenerator: ".$deleted." alte QR-Codes gelöscht", LOG_INFO); return $deleted; } }