payment = new Payment(); $this->multiShop = new MultiShop(); $this->security = new Security(); $this->config = new Configuration(); // Session-Check if (!isset($_SESSION['admin_logged_in']) || !$_SESSION['admin_logged_in']) { header('Location: /admin/login'); exit; } } /** * Payment-Dashboard anzeigen */ public function index() { $shopId = $this->multiShop->getCurrentShopId(); // Payment-Statistiken abrufen $statistics = $this->payment->getPaymentStatistics($shopId); // Verfügbare Zahlungsmethoden $availableMethods = $this->payment->getAvailablePaymentMethods(); // Provider-Status prüfen $providerStatus = []; foreach (['paypal', 'stripe', 'sepa'] as $provider) { $providerStatus[$provider] = $this->payment->checkPaymentProviderStatus($provider); } $data = [ 'statistics' => $statistics, 'available_methods' => $availableMethods, 'provider_status' => $providerStatus, 'shop_id' => $shopId ]; $this->render('admin/payment/index.html.twig', $data); } /** * PayPal-Konfiguration anzeigen */ public function paypal() { if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->updatePayPalConfig(); } $shopId = $this->multiShop->getCurrentShopId(); $data = [ 'enabled' => $this->multiShop->getShopConfig('PAYMENT_PAYPAL_ENABLED', false), 'sandbox' => $this->multiShop->getShopConfig('PAYMENT_PAYPAL_SANDBOX', true), 'client_id' => $this->multiShop->getShopConfig('PAYMENT_PAYPAL_CLIENT_ID', ''), 'client_secret' => $this->multiShop->getShopConfig('PAYMENT_PAYPAL_CLIENT_SECRET', ''), 'webhook_id' => $this->multiShop->getShopConfig('PAYMENT_PAYPAL_WEBHOOK_ID', ''), 'connection_status' => $this->payment->checkPaymentProviderStatus('paypal'), 'shop_id' => $shopId ]; $this->render('admin/payment/paypal.html.twig', $data); } /** * PayPal-Konfiguration aktualisieren */ private function updatePayPalConfig() { $shopId = $this->multiShop->getCurrentShopId(); // CSRF-Schutz if (!$this->security->validateCSRFToken($_POST['csrf_token'] ?? '')) { $this->addError('Sicherheitsfehler: Ungültiger Token'); return; } $config = [ 'enabled' => isset($_POST['enabled']), 'sandbox' => isset($_POST['sandbox']), 'client_id' => trim($_POST['client_id'] ?? ''), 'client_secret' => trim($_POST['client_secret'] ?? ''), 'webhook_id' => trim($_POST['webhook_id'] ?? '') ]; // Validierung if ($config['enabled']) { if (empty($config['client_id'])) { $this->addError('PayPal Client ID ist erforderlich'); return; } if (empty($config['client_secret'])) { $this->addError('PayPal Client Secret ist erforderlich'); return; } } // Konfiguration speichern foreach ($config as $key => $value) { $this->multiShop->setShopConfig("PAYMENT_PAYPAL_" . strtoupper($key), $value); } $this->addSuccess('PayPal-Konfiguration wurde erfolgreich aktualisiert'); } /** * Stripe-Konfiguration anzeigen */ public function stripe() { if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->updateStripeConfig(); } $shopId = $this->multiShop->getCurrentShopId(); $data = [ 'enabled' => $this->multiShop->getShopConfig('PAYMENT_STRIPE_ENABLED', false), 'test_mode' => $this->multiShop->getShopConfig('PAYMENT_STRIPE_TEST_MODE', true), 'publishable_key' => $this->multiShop->getShopConfig('PAYMENT_STRIPE_PUBLISHABLE_KEY', ''), 'secret_key' => $this->multiShop->getShopConfig('PAYMENT_STRIPE_SECRET_KEY', ''), 'webhook_secret' => $this->multiShop->getShopConfig('PAYMENT_STRIPE_WEBHOOK_SECRET', ''), 'connection_status' => $this->payment->checkPaymentProviderStatus('stripe'), 'shop_id' => $shopId ]; $this->render('admin/payment/stripe.html.twig', $data); } /** * Stripe-Konfiguration aktualisieren */ private function updateStripeConfig() { $shopId = $this->multiShop->getCurrentShopId(); // CSRF-Schutz if (!$this->security->validateCSRFToken($_POST['csrf_token'] ?? '')) { $this->addError('Sicherheitsfehler: Ungültiger Token'); return; } $config = [ 'enabled' => isset($_POST['enabled']), 'test_mode' => isset($_POST['test_mode']), 'publishable_key' => trim($_POST['publishable_key'] ?? ''), 'secret_key' => trim($_POST['secret_key'] ?? ''), 'webhook_secret' => trim($_POST['webhook_secret'] ?? '') ]; // Validierung if ($config['enabled']) { if (empty($config['publishable_key'])) { $this->addError('Stripe Publishable Key ist erforderlich'); return; } if (empty($config['secret_key'])) { $this->addError('Stripe Secret Key ist erforderlich'); return; } } // Konfiguration speichern foreach ($config as $key => $value) { $this->multiShop->setShopConfig("PAYMENT_STRIPE_" . strtoupper($key), $value); } $this->addSuccess('Stripe-Konfiguration wurde erfolgreich aktualisiert'); } /** * SEPA-Konfiguration anzeigen */ public function sepa() { if ($_SERVER['REQUEST_METHOD'] === 'POST') { $this->updateSEPAConfig(); } $shopId = $this->multiShop->getCurrentShopId(); $data = [ 'enabled' => $this->multiShop->getShopConfig('PAYMENT_SEPA_ENABLED', false), 'test_mode' => $this->multiShop->getShopConfig('PAYMENT_SEPA_TEST_MODE', true), 'merchant_id' => $this->multiShop->getShopConfig('PAYMENT_SEPA_MERCHANT_ID', ''), 'iban' => $this->multiShop->getShopConfig('PAYMENT_SEPA_IBAN', ''), 'bic' => $this->multiShop->getShopConfig('PAYMENT_SEPA_BIC', ''), 'connection_status' => $this->payment->checkPaymentProviderStatus('sepa'), 'shop_id' => $shopId ]; $this->render('admin/payment/sepa.html.twig', $data); } /** * SEPA-Konfiguration aktualisieren */ private function updateSEPAConfig() { $shopId = $this->multiShop->getCurrentShopId(); // CSRF-Schutz if (!$this->security->validateCSRFToken($_POST['csrf_token'] ?? '')) { $this->addError('Sicherheitsfehler: Ungültiger Token'); return; } $config = [ 'enabled' => isset($_POST['enabled']), 'test_mode' => isset($_POST['test_mode']), 'merchant_id' => trim($_POST['merchant_id'] ?? ''), 'iban' => trim($_POST['iban'] ?? ''), 'bic' => trim($_POST['bic'] ?? '') ]; // Validierung if ($config['enabled']) { if (empty($config['merchant_id'])) { $this->addError('SEPA Merchant ID ist erforderlich'); return; } if (empty($config['iban'])) { $this->addError('SEPA IBAN ist erforderlich'); return; } if (empty($config['bic'])) { $this->addError('SEPA BIC ist erforderlich'); return; } // IBAN-Validierung if (!$this->validateIBAN($config['iban'])) { $this->addError('Ungültige IBAN'); return; } // BIC-Validierung if (!$this->validateBIC($config['bic'])) { $this->addError('Ungültige BIC'); return; } } // Konfiguration speichern foreach ($config as $key => $value) { $this->multiShop->setShopConfig("PAYMENT_SEPA_" . strtoupper($key), $value); } $this->addSuccess('SEPA-Konfiguration wurde erfolgreich aktualisiert'); } /** * IBAN validieren */ private function validateIBAN($iban) { $iban = str_replace(' ', '', strtoupper($iban)); if (strlen($iban) < 15 || strlen($iban) > 34) { return false; } // IBAN-Prüfziffer berechnen $country = substr($iban, 0, 2); $check = substr($iban, 2, 2); $account = substr($iban, 4); $iban = $account . $country . $check; $iban = str_replace( ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'], ['10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35'], $iban ); return bcmod($iban, '97') == '1'; } /** * BIC validieren */ private function validateBIC($bic) { $bic = strtoupper($bic); // BIC sollte 8 oder 11 Zeichen haben if (strlen($bic) !== 8 && strlen($bic) !== 11) { return false; } // Format: 4 Zeichen Bank-Code + 2 Zeichen Ländercode + 2 Zeichen Ort + 3 Zeichen Filiale (optional) if (!preg_match('/^[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?$/', $bic)) { return false; } return true; } /** * Payment-Transaktionen anzeigen */ public function transactions() { $shopId = $this->multiShop->getCurrentShopId(); $page = (int)($_GET['page'] ?? 1); $limit = 20; $offset = ($page - 1) * $limit; try { $conn = $this->payment->getConnection(); // Transaktionen abrufen $stmt = $conn->prepare(' SELECT pt.*, o.order_number, o.total_amount as order_amount, o.currency as order_currency FROM ws_payment_transaction pt JOIN ws_order o ON pt.order_id = o.id WHERE o.shop_id = ? ORDER BY pt.created_at DESC LIMIT ? OFFSET ? '); $stmt->execute([$shopId, $limit, $offset]); $transactions = $stmt->fetchAllAssociative(); // Gesamtanzahl abrufen $stmt = $conn->prepare(' SELECT COUNT(*) as total FROM ws_payment_transaction pt JOIN ws_order o ON pt.order_id = o.id WHERE o.shop_id = ? '); $stmt->execute([$shopId]); $total = $stmt->fetchAssociative()['total']; $data = [ 'transactions' => $transactions, 'total' => $total, 'page' => $page, 'limit' => $limit, 'total_pages' => ceil($total / $limit), 'shop_id' => $shopId ]; $this->render('admin/payment/transactions.html.twig', $data); } catch (\Exception $e) { $this->addError('Fehler beim Laden der Transaktionen: ' . $e->getMessage()); $this->render('admin/payment/transactions.html.twig', ['transactions' => [], 'total' => 0]); } } /** * Payment-Statistiken als JSON */ public function statistics() { $shopId = $this->multiShop->getCurrentShopId(); $statistics = $this->payment->getPaymentStatistics($shopId); header('Content-Type: application/json'); echo json_encode($statistics); } /** * Payment-Provider testen */ public function testProvider() { $provider = $_POST['provider'] ?? ''; if (!in_array($provider, ['paypal', 'stripe', 'sepa'])) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'Ungültiger Provider']); return; } $status = $this->payment->checkPaymentProviderStatus($provider); echo json_encode([ 'success' => true, 'provider' => $provider, 'status' => $status, 'message' => $status ? 'Verbindung erfolgreich' : 'Verbindung fehlgeschlagen' ]); } /** * Template rendern */ private function render($template, $data = []) { // CSRF-Token generieren $data['csrf_token'] = $this->security->generateCSRFToken(); // Flash-Messages $data['success_messages'] = $_SESSION['success_messages'] ?? []; $data['error_messages'] = $_SESSION['error_messages'] ?? []; // Session-Messages löschen unset($_SESSION['success_messages'], $_SESSION['error_messages']); // Template laden $templatePath = __DIR__ . '/../../templates/' . $template; if (file_exists($templatePath)) { extract($data); include $templatePath; } else { throw new \Exception("Template nicht gefunden: {$template}"); } } /** * Erfolgs-Message hinzufügen */ private function addSuccess($message) { if (!isset($_SESSION['success_messages'])) { $_SESSION['success_messages'] = []; } $_SESSION['success_messages'][] = $message; } /** * Fehler-Message hinzufügen */ private function addError($message) { if (!isset($_SESSION['error_messages'])) { $_SESSION['error_messages'] = []; } $_SESSION['error_messages'][] = $message; } }