=== Widerrufsbutton ===
Contributors: wbwiderrufbutton
Tags: woocommerce, widerruf, widerrufsbutton, elektronischer widerruf, widerruf-formular
Requires at least: 6.7
Tested up to: 6.9
Requires PHP: 8.0
Stable tag: 1.3.25
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Rechtskonformer Widerrufsbutton mit zweistufigem Formular für WooCommerce – mit Bestellprüfung, Protokollierung und E-Mail-Bestätigung.


== Beschreibung ==

Der Widerrufsbutton stellt einen strukturierten, zweistufigen elektronischen Widerrufsprozess für WooCommerce-Shops bereit – konform mit § 356a BGB und der EU-Richtlinie 2023/2673 (2011/83/EU). Alle Vorgänge werden im WordPress-Backend vollständig protokolliert.

**Funktionen der kostenlosen Version:**

* Widerrufsbutton per Shortcode
* Widerrufsformular per Shortcode (beliebig platzierbar)
* Optionaler Modal-Modus oder eigene Formularseite
* Zweistufiger Prozess: Einreichung und Bestätigung
* WooCommerce-Bestellprüfung (Bestell-ID + E-Mail + Widerrufsfrist)
* E-Mail-Bestätigung für Kunden und Händler
* Eigene Datenbanktabelle zur Protokollierung
* Admin-Übersicht und Detailansicht aller Widerrufe
* Vollständig konfigurierbare Texte, Labels, Fehlermeldungen und E-Mail-Inhalte
* Theme-neutrales Basis-Styling

**Erweiterungen in der Pro-Version:**

* Teilwiderruf (einzelne Artikel und Mengen auswählbar)
* Elementor- & Gutenberg-Block-Widgets
* PDF-Nachweis mit Integritäts-Hash
* CSV-Export (Gesamt- und Einzel-Download)
* HTML-E-Mail-Vorlagen
* Shortcode für WooCommerce-E-Mail-Templates (Bestellbestätigung etc.)
* Erweiterte Backend-Funktionen

**Sicherheit & Missbrauchsschutz:**

* Honeypot-Feld (Bots laufen ins Leere)
* Rate-Limiting pro IP (Transients, IP nur als Hash gespeichert)
* IP-Adressen werden nicht im Klartext gespeichert
* Zweistufige Bestätigung mit zeitlich begrenztem kryptografischem Token

**Datenschutz:**

Das Plugin speichert ausschließlich die für die Bearbeitung und Dokumentation eines Widerrufs notwendigen Daten: Name, E-Mail-Adresse, Bestell- oder Vertragsreferenz, optional Widerrufsgrund und Bemerkungstext sowie Zeitstempel. Es werden keine Daten an externe Server übertragen. E-Mails werden über das WordPress/WooCommerce-Mailsystem versendet.

**Datenhaltung & Deinstallation:**

Widerrufsdaten bleiben im Backend gespeichert, bis sie vom Shopbetreiber gelöscht werden. Standardmäßig werden Plugin-Daten bei einer Deinstallation nicht entfernt. Optional kann in den Einstellungen aktiviert werden, dass alle Plugin-Optionen und die Widerruf-Tabelle beim Deinstallieren gelöscht werden.

**Rechtlicher Hinweis:**

Dieses Plugin stellt eine technische Lösung zur Verfügung und ersetzt keine individuelle Rechtsberatung.


== Shortcodes ==

Widerrufsbutton:
  [widerrufsbutton url="/widerruf"]

Optional als Modal:
  [widerrufsbutton target="modal" layout="multi"]

Widerrufsformular:
  [widerrufsformular]

Layout-Option (mehrstufig):
  [widerrufsformular layout="multi"]


== Einstellungen ==

Im Backend unter: Widerrufsbutton → Einstellungen

Tab „Formular":

* Widerrufsfrist in Tagen
* Händler-E-Mail (optional)
* Ziel-URL für den Widerrufsbutton (mit Seiten-Suche)
* Widerrufsgründe (optionale Auswahlliste)
* Daten bei Deinstallation löschen (opt-in)

Tab „Texte":

* Überschriften und Hilfetexte
* Formular-Labels
* Buttontexte
* Validierungs- und Fehlermeldungen
* E-Mail-Betreff und -Inhalte (inkl. Platzhalter)

Tab „Design":

* Primärfarbe für Button und Formular
* Rahmen, Hover, Radius


== E-Mail-Platzhalter ==

* {customer_name}
* {customer_email}
* {contract_ref}
* {remark_line}
* {confirmed_at}
* {withdrawal_id}
* {admin_link}
* {statement}


== Häufige Fragen ==

= Benötigt das Plugin WooCommerce? =
Ja. Die Bestellprüfung in der Free-Version erfolgt über WooCommerce.

= Können Kunden den Widerruf ohne Login durchführen? =
Ja.

= Welche Bestellnummer muss der Kunde eingeben? =
In der Free-Version wird die Standard-WooCommerce-Bestell-ID geprüft (numerisch, z. B. 1234).

= Welche personenbezogenen Daten werden gespeichert? =
Ausschließlich die für den Widerruf notwendigen Daten: Name, E-Mail-Adresse, Bestellreferenz sowie Zeitstempel. IP-Adressen werden nicht im Klartext gespeichert, keine Daten werden an Dritte übertragen.

= Werden Daten automatisch gelöscht? =
Nein. Die Widerrufe dienen der rechtlichen Dokumentation. Optional können in den Einstellungen alle Daten bei der Deinstallation entfernt werden.

= Wie nutze ich den Modal-Modus? =
Den Widerrufsbutton so einbinden, dass sich das Formular als Overlay auf derselben Seite öffnet:
[widerrufsbutton target="modal" layout="multi"]

= Wie setze ich die Ziel-URL für den Widerrufsbutton? =
Im Tab „Formular" kann die Ziel-URL per Seiten-Suche komfortabel ausgewählt werden. Alternativ ist auch eine manuelle Eingabe möglich.

= Was passiert mit den Daten bei Deinstallation? =
Standardmäßig bleiben alle gespeicherten Widerrufe und Einstellungen erhalten. Optional kann im Tab „Formular" aktiviert werden, dass bei Deinstallation alle Plugin-Daten gelöscht werden.

= Gibt es eine Pro-Version? =
Ja. Die Pro-Version erweitert das Plugin um Teilwiderruf, PDF-Nachweis, CSV-Export, HTML-E-Mail-Vorlagen, Elementor- und Gutenberg-Widgets sowie einen Shortcode für WooCommerce-E-Mail-Templates.


== Screenshots ==

1. Elektronischer Widerruf-Button im Frontend
2. Widerrufsformular – Schritt 1: Dateneingabe
3. Widerrufsformular – Schritt 2: Datenprüfung und Bestätigung
4. Erfolgsbestätigung nach dem Absenden
5. Backend-Übersicht aller Widerrufe
6. Backend-Detailansicht eines Widerrufs mit vollständiger Dokumentation
7. Einstellungen – Tab Formular: Frist, Ziel-URL, Händler-E-Mail
8. Einstellungen – Tab Texte: Formular, Prozessschritte und E-Mails
9. Einstellungen – Tab Design: Farbe, Rahmen, Radius
10. Plugin-Übersichtsseite: Status und Kurzanleitung
11. E-Mail-Bestätigung für Endkunde und Shopbetreiber


== Changelog ==

= 1.3.25 =
* Fix: Wizard-Schritt-Markierung (step_texts_touched, step_design_touched) aus dem $_GET[settings-updated]-Check in pre_update_option_-Filter-Hooks verschoben. Die Wizard-Schritte werden jetzt innerhalb des verifizierten Settings-Speichervorgangs als abgeschlossen markiert.

= 1.3.24 =
* Verbesserung: Alle SQL-SELECT-Abfragen in class-wbwiderruf-db.php mit vollständig literalen Spaltennamen umgeschrieben – keine Variableninterpolation mehr in SQL-Templates.

= 1.3.23 =
* Fix: Bestätigungsseite (Erfolgs-Schritt) wird nach dem Absenden des Formulars jetzt korrekt angezeigt. Ursache: Die validate_callback für pending_token hatte ein Längenlimit von 128 Zeichen, das bei realen Tokens (SHA-256-HMAC) regelmäßig überschritten wird. Anfragen wurden stillschweigend abgelehnt.
* Fix: Datenbank-Migration (v2) konvertiert frisch angelegte Pending-Einträge nicht mehr zu „submitted". Eine v3-Migration korrigiert betroffene Einträge automatisch.
* Fix: JavaScript-Funktion confirmStep() verwendet jetzt eine lokal gebundene Fehlervariable statt des außerhalb des Scopes liegenden alert-Bezeichners.
* Fix: Suche in der Admin-Widerrufsliste funktioniert wieder korrekt.
* Fix: Nicht belegte Statusfilter-Tabs (In Prüfung, Fertig, Abgelehnt) aus der Admin-Liste entfernt.
* Fix: ORDER BY-Spalte wird jetzt korrekt von der List-Table an die Datenbankabfrage weitergegeben.
* Verbesserung: Alle Datenbankabfragen in class-wbwiderruf-db.php auf explizite $wpdb->prepare()-Aufrufe umgestellt.
* Verbesserung: Migrations-Abfragen in db-schema.php verwenden $wpdb->prepare() mit %i-Platzhalter für den Tabellennamen.

= 1.3.21 =
* Review-Update: Interne Präfixe auf „wbwiderruf" vereinheitlicht (wp.org-Konformität).
* Review-Update: Sanitization bei register_setting(), Nonce-Handling und Script-Enqueueing verbessert.
* Review-Update: Kompatibilitäts-Layer für migrierte Options-Schlüssel und Hooks ergänzt.

= 1.3.11 =
* Bugfix: Frontend-Formular nutzt wieder die korrekten REST-Routen.

= 1.3.10 =
* Entfernt: manueller load_plugin_textdomain()-Aufruf.

= 1.3.7 =
* REST-Validierung konsolidiert.
* Bugfix: sichere MySQL-Datetime-Konvertierung nach RFC3339.
* Admin-Suche verbessert.

= 1.3.6 =
* Verbesserte Fehlermeldungen im Widerrufsformular (Endkunde-seitig).

= 1.0.0 =
* Erstveröffentlichung.
