Zahlungsarten überarbeitet: echtes PayPal, Klarna & eigene Kartenmaske raus
Auf ausdrücklichen Wunsch, mit Fokus auf rechtliche Absicherung: - Klarna komplett entfernt (hätte eigene Händlerprüfung + Bonitätsprüfungs- Pflichten nach der neuen EU-Verbraucherkreditrichtlinie vorausgesetzt). - Eigene Kreditkarten-Eingabemaske komplett entfernt (wäre PCI-DSS-pflichtig gewesen — für einen kleinen Shop praktisch nicht stemmbar). Kartenzahlung bleibt möglich: PayPals eigener, PCI-zertifizierter Gast-Checkout bietet Kredit-/Debitkarte an, ohne dass Kartendaten je unsere Seite berühren. - PayPal ist jetzt ECHT server-seitig verifiziert statt dem Browser blind zu vertrauen: eigener Cloudflare-Function-Flow (functions/_shared/paypal.js + functions/api/paypal/) legt die PayPal-Bestellung server-seitig an, zieht die Zahlung nach Bestätigung server-seitig ein und prüft den eingezogenen Betrag gegen die Bestellsumme — die Bestellung wird ausschließlich bei bestätigter, betragsgleicher Zahlung angelegt. /api/orders lehnt direkte PayPal-Bestellungen jetzt ausdrücklich ab (verhindert vorgetäuschte "bezahlte" Bestellungen ohne echte Zahlung). - Neuer, ehrlicherer Bestellstatus "zahlungOffen": Überweisungs-Bestellungen starten jetzt so (Geld noch nicht da) statt fälschlich sofort "bezahlt" zu heißen — Schutz vor Warenversand, bevor das Geld wirklich angekommen ist. Eigene Kachel/Filter/Badge-Farbe in der Verwaltung, Umsatz-/Auswertungs- Zahlen zählen "zahlungOffen" bewusst nicht mit. - Rechtstexte (AGB, Datenschutzerklärung, FAQ, Versand & Zahlung) auf allen 4 Sprachen aktualisiert: nur noch PayPal + Überweisung erwähnt, inkl. DSGVO- Hinweis zur internationalen Datenübertragung an PayPal (Data Privacy Framework-Zertifizierung). - D1-Migration 0003: neue Spalte paypal_order_id (Zahlungsbeleg) + erweiterter Status-Wertebereich, auf Live-Datenbank angewendet, bestehende Daten intakt. Mit echten Testbestellungen lokal verifiziert: Überweisung legt korrekt "zahlungOffen" an, direkter PayPal-Bypass-Versuch an /api/orders wird abgelehnt, PayPal-Route meldet sauber "noch nicht eingerichtet" ohne Zugangsdaten. Checkout-UI zeigt nur noch 2 Zahlungsarten, Bestellknopf ist bei PayPal ausgeblendet (Zahlung läuft exklusiv über den echten PayPal-Button). Für den echten Zahlungseingang fehlt noch VanVans eigenes PayPal-Business- Konto (Client-ID + Secret) — Details in der Vault-Dokumentation. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
98028df4ea
commit
81c175d03c
@@ -0,0 +1,63 @@
|
||||
-- Migration 0003: echte PayPal-Zahlungsabwicklung + realistischer Status "zahlungOffen".
|
||||
--
|
||||
-- Zwei Dinge ändern sich:
|
||||
-- 1. Neue Spalte "paypal_order_id" — speichert die echte, von PayPal bestätigte Bestell-ID als
|
||||
-- Zahlungsbeleg (siehe functions/api/paypal/capture-order.js).
|
||||
-- 2. Der Status-Wertebereich bekommt "zahlungOffen" dazu (für Überweisung/Vorkasse, bevor das
|
||||
-- Geld wirklich da ist) — vorher wurde JEDE Bestellung sofort als "bezahlt" markiert, auch
|
||||
-- wenn noch gar nichts überwiesen war. Das war in der Phase-1-Testphase okay, ist aber ein
|
||||
-- echtes Geschäftsrisiko (Ware könnte vor Zahlungseingang verschickt werden).
|
||||
--
|
||||
-- SQLite kann CHECK-Constraints nicht per ALTER TABLE ändern — deshalb wird die Tabelle nach dem
|
||||
-- Standard-SQLite-Vorgehen neu aufgebaut: neue Tabelle mit korrektem Constraint anlegen, alle
|
||||
-- bestehenden Zeilen 1:1 rüberkopieren (bestehende "bezahlt"-Bestellungen bleiben "bezahlt" —
|
||||
-- die waren ja im alten Phase-1-System tatsächlich abgeschlossen), alte Tabelle löschen, neue
|
||||
-- umbenennen.
|
||||
|
||||
PRAGMA foreign_keys=OFF;
|
||||
|
||||
CREATE TABLE orders_new (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
bestellnummer TEXT UNIQUE,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'zahlungOffen'
|
||||
CHECK (status IN ('zahlungOffen', 'bezahlt', 'bearbeitung', 'versandVorbereitet', 'versendet', 'abgeschlossen', 'storniert')),
|
||||
kunde_name TEXT NOT NULL,
|
||||
kunde_email TEXT NOT NULL,
|
||||
land TEXT NOT NULL CHECK (land IN ('de', 'at', 'ch', 'lu')),
|
||||
strasse TEXT,
|
||||
plz TEXT,
|
||||
ort TEXT,
|
||||
zahlungsart TEXT,
|
||||
tracking TEXT,
|
||||
gutschein_code TEXT,
|
||||
paypal_order_id TEXT,
|
||||
zwischensumme REAL NOT NULL DEFAULT 0,
|
||||
versandkosten REAL NOT NULL DEFAULT 0,
|
||||
rabatt_gesamt REAL NOT NULL DEFAULT 0,
|
||||
summe REAL NOT NULL DEFAULT 0,
|
||||
treuebonus_verwendet INTEGER NOT NULL DEFAULT 0,
|
||||
abo_rabatt_verwendet INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
INSERT INTO orders_new (
|
||||
id, bestellnummer, created_at, updated_at, status, kunde_name, kunde_email, land, strasse, plz,
|
||||
ort, zahlungsart, tracking, gutschein_code, paypal_order_id, zwischensumme, versandkosten,
|
||||
rabatt_gesamt, summe, treuebonus_verwendet, abo_rabatt_verwendet
|
||||
)
|
||||
SELECT
|
||||
id, bestellnummer, created_at, updated_at, status, kunde_name, kunde_email, land, strasse, plz,
|
||||
ort, zahlungsart, tracking, gutschein_code, NULL, zwischensumme, versandkosten,
|
||||
rabatt_gesamt, summe, treuebonus_verwendet, abo_rabatt_verwendet
|
||||
FROM orders;
|
||||
|
||||
DROP TABLE orders;
|
||||
ALTER TABLE orders_new RENAME TO orders;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_orders_land ON orders(land);
|
||||
CREATE INDEX IF NOT EXISTS idx_orders_created_at ON orders(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_orders_gutschein_email ON orders(gutschein_code, kunde_email);
|
||||
|
||||
PRAGMA foreign_keys=ON;
|
||||
Reference in New Issue
Block a user