Rechtstexte und B2C-Vertragsabläufe absichern

This commit is contained in:
2026-08-22 14:31:56 +02:00
parent d320a4fd7a
commit a31a235422
58 changed files with 2502 additions and 316 deletions
+121
View File
@@ -0,0 +1,121 @@
<?php
require_once __DIR__ . '/app/database.php';
require_once __DIR__ . '/app/legal-requests.php';
$pdo = app_db_pdo();
app_start_session();
$h = static fn(mixed $value): string => htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
$stage = (string)($_POST['stage'] ?? 'form');
$values = [
'requester_name' => trim((string)($_POST['requester_name'] ?? '')),
'requester_email' => trim((string)($_POST['requester_email'] ?? '')),
'contract_reference' => strtolower(trim((string)($_POST['contract_reference'] ?? ''))),
'request_reason' => trim((string)($_POST['request_reason'] ?? '')),
];
$errors = [];
$stored = null;
$processing = null;
$mailStatus = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
app_require_csrf();
if ($stage === 'form') {
// Die Werte aus der Prüfseite werden wieder im Formular angezeigt.
} else {
$errors = app_validate_legal_request($values, 'withdrawal');
}
if ($stage !== 'form' && $errors !== []) {
$stage = 'form';
} elseif ($stage === 'submit') {
if (!app_rate_limit_check($pdo, 'legal_request_ip:' . app_client_ip(), 5, 3600)) {
$errors[] = 'Zu viele Erklärungen von diesem Anschluss. Bitte nutze alternativ E-Mail oder das Ticketsystem.';
$stage = 'form';
} else {
$input = $values + ['request_type' => 'withdrawal'];
$stored = app_store_legal_request($pdo, $input);
$processing = app_process_withdrawal_request($pdo, $stored);
$mailStatus = app_send_legal_request_confirmations($input, $stored, $processing);
$stage = 'complete';
}
} elseif ($stage !== 'form') {
$stage = 'review';
}
}
?>
<!DOCTYPE HTML>
<html lang="de">
<head>
<title>Vertrag widerrufen Kaffeeliste</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="assets/css/main.css">
<link rel="stylesheet" href="assets/css/public.css">
</head>
<body class="is-preload public-page">
<div class="public-shell">
<section class="public-section public-legal">
<nav class="public-nav" aria-label="Hauptnavigation"><strong><a href="landing.php">Kaffeeliste</a></strong></nav>
<header class="major"><h1>Vertrag widerrufen</h1></header>
<?php if ($stage === 'complete' && $stored !== null && $processing !== null): ?>
<div class="hint-box success">
<h2>Widerruf eingegangen</h2>
<p>Referenz: <b><?php echo $h($stored['reference_code']); ?></b><br>
Eingang: <?php echo $h($stored['received_at']); ?> Uhr (Europe/Berlin)</p>
<p><?php echo $h($processing['processing_note']); ?></p>
</div>
<?php if (($mailStatus['customer_ok'] ?? false) === true): ?>
<p>Wir haben die Eingangsbestätigung sofort an <?php echo $h($values['requester_email']); ?> gesendet.</p>
<?php else: ?>
<div class="hint-box error">
<p>Der Widerruf wurde gespeichert, aber die E-Mail-Bestätigung konnte nicht versendet werden. Bitte speichere die Bestätigung jetzt über den folgenden Link und kontaktiere uns bei Bedarf über das <a href="<?php echo $h(app_legal_ticket_url()); ?>">Ticketsystem</a>.</p>
</div>
<?php endif; ?>
<ul class="actions">
<li><a class="button primary" href="rechtserklaerung-bestaetigung.php?token=<?php echo $h($stored['access_token']); ?>&amp;download=1">Bestätigung als Textdatei speichern</a></li>
<li><a class="button" href="landing.php">Zur Startseite</a></li>
</ul>
<?php elseif ($stage === 'review'): ?>
<h2>Widerruf prüfen</h2>
<p>Name: <?php echo $h($values['requester_name']); ?><br>
E-Mail: <?php echo $h($values['requester_email']); ?><br>
Kundenkürzel: <?php echo $h($values['contract_reference']); ?></p>
<?php if ($values['request_reason'] !== ''): ?><p>Ergänzung: <?php echo nl2br($h($values['request_reason'])); ?></p><?php endif; ?>
<form method="post" action="widerrufen.php">
<?php echo app_csrf_field(); ?>
<input type="hidden" name="stage" value="submit">
<?php foreach ($values as $name => $value): ?><input type="hidden" name="<?php echo $h($name); ?>" value="<?php echo $h($value); ?>"><?php endforeach; ?>
<ul class="actions">
<li><button type="submit" class="primary">Widerruf bestätigen</button></li>
<li><button type="submit" name="stage" value="form" class="button">Angaben ändern</button></li>
</ul>
</form>
<?php else: ?>
<p>Verbraucher können hier während der Widerrufsfrist ihren Kaffeeliste-Vertrag widerrufen. Eine Begründung und eine Anmeldung sind nicht erforderlich.</p>
<p><a href="widerruf.php">Widerrufsbelehrung und Musterformular anzeigen</a></p>
<?php if ($errors !== []): ?><div class="hint-box error"><?php foreach ($errors as $error): ?><p><?php echo $h($error); ?></p><?php endforeach; ?></div><?php endif; ?>
<form method="post" action="widerrufen.php">
<?php echo app_csrf_field(); ?>
<input type="hidden" name="stage" value="review">
<label for="requester_name">Vollständiger Name</label>
<input type="text" name="requester_name" id="requester_name" maxlength="255" value="<?php echo $h($values['requester_name']); ?>" required>
<label for="requester_email">E-Mail für die sofortige Bestätigung</label>
<input type="email" name="requester_email" id="requester_email" maxlength="255" value="<?php echo $h($values['requester_email']); ?>" required>
<label for="contract_reference">Kundenkürzel / Vertragsreferenz</label>
<input type="text" name="contract_reference" id="contract_reference" maxlength="100" value="<?php echo $h($values['contract_reference']); ?>" required>
<label for="request_reason">Optionale Ergänzung</label>
<textarea name="request_reason" id="request_reason" maxlength="5000" rows="4"><?php echo $h($values['request_reason']); ?></textarea>
<button type="submit" class="primary">Widerruf prüfen</button>
</form>
<?php endif; ?>
</section>
</div>
<?php echo app_public_legal_footer(); ?>
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/browser.min.js"></script>
<script src="assets/js/breakpoints.min.js"></script>
<script src="assets/js/util.js"></script>
<script src="assets/js/main.js"></script>
</body>
</html>