Updated checkout to wait for backend confirmation before advancing, added a “Processing payment…” state with retry/ refresh fallback, and now use Paddle totals/currency for purchase records + confirmation emails (with new email translations).

This commit is contained in:
Codex Agent
2025-12-22 09:06:48 +01:00
parent 41d29eb7d3
commit 84234bfb8e
36 changed files with 1742 additions and 187 deletions

209
lang/de/emails.php Normal file
View File

@@ -0,0 +1,209 @@
<?php
return [
'welcome' => [
'subject' => 'Willkommen bei Fotospiel, :name',
'greeting' => 'Hallo :name,',
'body' => 'Danke fuer deine Registrierung bei Fotospiel. Dein Konto ist bereit.',
'username' => 'Benutzername: :username',
'email' => 'E-Mail: :email',
'verification' => 'Bitte bestaetige deine E-Mail-Adresse, um alle Funktionen freizuschalten.',
'footer' => 'Brauchst du Hilfe? Antworte einfach auf diese E-Mail.',
],
'purchase' => [
'subject' => 'Deine Fotospiel-Bestellung: :package',
'greeting' => 'Hallo :name,',
'package' => 'Paket: :package',
'price' => 'Gesamt: :price',
'activation' => 'Dein Paket ist jetzt aktiv. Du kannst dein Event einrichten.',
'footer' => 'Fragen? Antworte auf diese E-Mail oder oeffne dein Dashboard.',
],
'gift_voucher' => [
'recipient' => [
'subject' => 'Du hast einen Fotospiel-Gutschein erhalten (:amount :currency)',
'greeting' => 'Ein Gutschein fuer dich!',
'body' => 'Du hast einen Fotospiel-Gutschein im Wert von :amount :currency von :purchaser erhalten.',
],
'purchaser' => [
'subject' => 'Dein Fotospiel-Gutschein (:amount :currency)',
'greeting' => 'Danke fuer dein Fotospiel-Geschenk!',
'body' => 'Wir haben einen Gutschein im Wert von :amount :currency fuer :recipient erstellt.',
'recipient_fallback' => 'deinen Empfaenger',
],
'message_title' => 'Persoenliche Nachricht',
'code_label' => 'Gutscheincode',
'redeem_hint' => 'Loese den Gutschein waehrend des Checkouts ein, um dein Event-Paket zu aktivieren.',
'printable' => 'Gutschein drucken',
'expiry' => 'Gueltig bis :date.',
'withdrawal' => 'Widerrufsbelehrung: <a href=":url">Hier lesen</a>.',
'footer' => 'Viel Freude beim Event und den besten Momenten.',
],
'contact_confirmation' => [
'subject' => 'Wir haben deine Nachricht erhalten, :name',
'greeting' => 'Hallo :name,',
'body' => 'Danke fuer deine Nachricht. Wir melden uns in Kuerze.',
'footer' => 'Dein Fotospiel-Team',
],
'contact' => [
'subject' => 'Neue Kontaktanfrage',
'body' => "Name: :name\nE-Mail: :email\nNachricht:\n:message",
],
'abandoned_checkout' => [
'subject_1h' => 'Noch Interesse an :package?',
'subject_24h' => 'Dein :package Checkout wartet',
'subject_1w' => 'Letzte Chance fuer deinen :package Checkout',
'greeting' => 'Hallo :name,',
'body_1h' => 'Du hast den Checkout fuer :package gestartet, aber nicht abgeschlossen. Du kannst jederzeit fortfahren.',
'body_24h' => 'Dein :package Checkout ist noch offen. Schließe ihn jetzt ab, um dein Paket zu aktivieren.',
'body_1w' => 'Wir haben deinen :package Checkout gespeichert. Schliesse ihn jetzt ab, um die Event-App freizuschalten.',
'cta_button' => 'Checkout fortsetzen',
'cta_link' => 'Falls der Button nicht funktioniert, nutze diesen Link: :url',
'benefits_title' => 'Warum jetzt abschliessen?',
'benefit1' => 'Sofortige Aktivierung nach Zahlung',
'benefit2' => 'Sicherer Checkout mit Paddle',
'benefit3' => 'Automatische Rechnungen und Steuerabwicklung',
'benefit4' => 'Unterstuetzung, wenn du sie brauchst',
'footer' => 'Brauchst du Hilfe? Antworte einfach auf diese E-Mail.',
],
'package_limits' => [
'package_fallback' => 'Paket',
'team_fallback' => 'dein Team',
'event_fallback' => 'dein Event',
'footer' => 'Fragen? Antworte auf diese E-Mail und wir helfen gern.',
'package_expiring' => [
'subject' => '{1} Dein :package Paket laeuft in :days Tag aus|[2,*] Dein :package Paket laeuft in :days Tagen aus',
'greeting' => 'Hallo :name,',
'body' => '{1} Dein :package Paket laeuft in :days Tag am :date aus.|[2,*] Dein :package Paket laeuft in :days Tagen am :date aus.',
'action' => 'Abrechnung verwalten',
],
'package_expired' => [
'subject' => ':package Paket abgelaufen',
'greeting' => 'Hallo :name,',
'body' => 'Dein :package Paket ist am :date abgelaufen. Erneuere es, um den Zugriff zu behalten.',
'action' => 'Paket erneuern',
],
'event_threshold' => [
'subject' => 'Du hast :percentage% deines Event-Limits genutzt',
'greeting' => 'Hallo :name,',
'body' => 'Du hast :used von :limit Events im :package Paket genutzt. :remaining verbleibend.',
'action' => 'Paket upgraden',
],
'event_limit' => [
'subject' => 'Event-Limit fuer :package erreicht',
'greeting' => 'Hallo :name,',
'body' => 'Du hast das Event-Limit (:limit) deines :package Pakets erreicht.',
'action' => 'Paket upgraden',
],
'photo_threshold' => [
'subject' => 'Du hast :percentage% deines Foto-Limits genutzt',
'greeting' => 'Hallo :name,',
'body' => 'Dein Event :event hat :used von :limit Fotos im :package Paket genutzt. :remaining verbleibend.',
'action' => 'Mehr Fotos hinzufuegen',
],
'photo_limit' => [
'subject' => 'Foto-Limit fuer :event erreicht',
'greeting' => 'Hallo :name,',
'body' => 'Dein Event :event hat das Foto-Limit des :package Pakets erreicht.',
'cta_addon' => 'Du kannst zusaetzliche Foto-Kapazitaet hinzufuegen.',
'addon_action' => 'Foto-Add-on kaufen',
'action' => 'Event verwalten',
],
'guest_threshold' => [
'subject' => 'Du hast :percentage% deines Gaestelimits genutzt',
'greeting' => 'Hallo :name,',
'body' => 'Dein Event :event hat :used von :limit Gaesten im :package Paket genutzt. :remaining verbleibend.',
'action' => 'Mehr Gaeste hinzufuegen',
],
'guest_limit' => [
'subject' => 'Gaestelimit fuer :event erreicht',
'greeting' => 'Hallo :name,',
'body' => 'Dein Event :event hat das Gaestelimit des :package Pakets erreicht.',
'cta_addon' => 'Du kannst zusaetzliche Gaeste hinzufuegen.',
'addon_action' => 'Gaeste-Add-on kaufen',
'action' => 'Event verwalten',
],
'gallery_warning' => [
'subject' => '{1} Galerie fuer :event laeuft in :days Tag ab|[2,*] Galerie fuer :event laeuft in :days Tagen ab',
'greeting' => 'Hallo :name,',
'body' => '{1} Die Galerie fuer :event (Paket :package) laeuft in :days Tag am :date ab.|[2,*] Die Galerie fuer :event (Paket :package) laeuft in :days Tagen am :date ab.',
'action' => 'Event oeffnen',
],
'gallery_expired' => [
'subject' => 'Galerie fuer :event abgelaufen',
'greeting' => 'Hallo :name,',
'body' => 'Die Galerie fuer :event (Paket :package) ist am :date abgelaufen.',
'action' => 'Event oeffnen',
],
],
'tenant_feedback' => [
'unknown_tenant' => 'Unbekannter Mandant',
'unknown' => 'Unbekannt',
'subject' => 'Neues Feedback von :tenant (:sentiment)',
'tenant' => 'Mandant: :tenant',
'category' => 'Kategorie: :category',
'sentiment' => 'Stimmung: :sentiment',
'event' => 'Event: :event',
'rating' => 'Bewertung: :rating',
'title' => 'Titel: :subject',
'message' => 'Nachricht:',
'open' => 'Feedback oeffnen',
'received_at' => 'Erhalten am: :date',
],
'refund' => [
'subject' => 'Rueckerstattung fuer :package',
'greeting' => 'Hallo :name,',
'body' => 'Wir haben eine Rueckerstattung von :amount :currency fuer deinen Kauf verarbeitet (Referenz: :provider_id).',
'reason' => 'Grund: :reason',
'footer' => 'Wenn du Fragen hast, antworte auf diese E-Mail.',
],
'ops' => [
'purchase' => [
'subject' => 'Neuer Kauf: :package',
'greeting' => 'Neuer Kauf eingegangen.',
'tenant' => 'Mandant: :tenant',
'package' => 'Paket: :package',
'amount' => 'Betrag: :amount :currency',
'provider' => 'Provider: :provider (ID: :id)',
'consents' => 'Einwilligungen: legal=:legal, terms=:terms, waiver=:waiver',
'footer' => 'Details im Admin-Panel pruefen.',
],
'refund' => [
'subject' => 'Rueckerstattung: :package',
'greeting' => 'Rueckerstattung-Update.',
'tenant' => 'Mandant: :tenant',
'package' => 'Paket: :package',
'amount' => 'Betrag: :amount :currency',
'provider' => 'Provider: :provider (ID: :id)',
'status_success' => 'Rueckerstattung erfolgreich.',
'status_failed' => 'Rueckerstattung fehlgeschlagen.',
'reason' => 'Grund: :reason',
'error' => 'Fehler: :error',
'footer' => 'Bitte Zahlungslogs pruefen.',
],
'addon' => [
'subject' => 'Add-on gekauft: :addon',
'greeting' => 'Add-on Kauf eingegangen.',
'tenant' => 'Mandant: :tenant',
'event' => 'Event: :event',
'addon' => 'Add-on: :addon (Menge: :quantity)',
'amount' => 'Betrag: :amount :currency',
'provider' => 'Provider: :provider (ID: :id)',
'footer' => 'Details im Admin-Panel pruefen.',
],
],
'addons' => [
'receipt' => [
'subject' => 'Add-on Beleg: :addon',
'greeting' => 'Hallo :name,',
'body' => 'Du hast das Add-on :addon fuer das Event :event gekauft. Betrag: :amount.',
'summary_title' => 'Enthalten:',
'summary' => [
'photos' => ':count zusaetzliche Fotos',
'guests' => ':count zusaetzliche Gaeste',
'gallery' => ':count zusaetzliche Galerietage',
],
'unknown_amount' => 'Unbekannter Betrag',
'action' => 'Event oeffnen',
],
],
];

209
lang/en/emails.php Normal file
View File

@@ -0,0 +1,209 @@
<?php
return [
'welcome' => [
'subject' => 'Welcome to Fotospiel, :name',
'greeting' => 'Hi :name,',
'body' => 'Thanks for registering with Fotospiel. Your account is ready.',
'username' => 'Username: :username',
'email' => 'Email: :email',
'verification' => 'Please confirm your email to unlock all features.',
'footer' => 'Need help? Reply to this email and we will be happy to assist.',
],
'purchase' => [
'subject' => 'Your Fotospiel order: :package',
'greeting' => 'Hi :name,',
'package' => 'Package: :package',
'price' => 'Total: :price',
'activation' => 'Your package is now active. You can start setting up your event.',
'footer' => 'Questions? Reply to this email or open your dashboard.',
],
'gift_voucher' => [
'recipient' => [
'subject' => 'You received a Fotospiel gift voucher (:amount :currency)',
'greeting' => 'A gift voucher for you!',
'body' => 'You received a Fotospiel voucher worth :amount :currency from :purchaser.',
],
'purchaser' => [
'subject' => 'Your Fotospiel gift voucher (:amount :currency)',
'greeting' => 'Thanks for gifting Fotospiel!',
'body' => 'We created a voucher worth :amount :currency for :recipient.',
'recipient_fallback' => 'your recipient',
],
'message_title' => 'Personal message',
'code_label' => 'Voucher code',
'redeem_hint' => 'Redeem this voucher during checkout to activate your event package.',
'printable' => 'Printable voucher',
'expiry' => 'Valid until :date.',
'withdrawal' => 'Withdrawal policy: <a href=":url">Read here</a>.',
'footer' => 'Enjoy the event and capture the best moments.',
],
'contact_confirmation' => [
'subject' => 'We received your message, :name',
'greeting' => 'Hi :name,',
'body' => 'Thanks for reaching out. We will get back to you shortly.',
'footer' => 'Your Fotospiel team',
],
'contact' => [
'subject' => 'New contact request',
'body' => "Name: :name\nEmail: :email\nMessage:\n:message",
],
'abandoned_checkout' => [
'subject_1h' => 'Still interested in :package?',
'subject_24h' => 'Your :package checkout is waiting',
'subject_1w' => 'Last chance to finish your :package checkout',
'greeting' => 'Hi :name,',
'body_1h' => 'You started the checkout for :package but did not finish. Continue whenever you are ready.',
'body_24h' => 'Your :package checkout is still open. Complete it now to activate your package.',
'body_1w' => 'We saved your :package checkout. Finish now to unlock your event app.',
'cta_button' => 'Resume checkout',
'cta_link' => 'If the button does not work, use this link: :url',
'benefits_title' => 'Why finish now?',
'benefit1' => 'Instant activation after payment',
'benefit2' => 'Secure checkout with Paddle',
'benefit3' => 'Automatic invoices and tax handling',
'benefit4' => 'Friendly support whenever you need help',
'footer' => 'Need help? Reply to this email.',
],
'package_limits' => [
'package_fallback' => 'package',
'team_fallback' => 'your team',
'event_fallback' => 'your event',
'footer' => 'Questions? Reply to this email and we will help.',
'package_expiring' => [
'subject' => '{1} Your :package package expires in :days day|[2,*] Your :package package expires in :days days',
'greeting' => 'Hi :name,',
'body' => '{1} Your :package package expires in :days day on :date.|[2,*] Your :package package expires in :days days on :date.',
'action' => 'Manage billing',
],
'package_expired' => [
'subject' => ':package package expired',
'greeting' => 'Hi :name,',
'body' => 'Your :package package expired on :date. Renew to keep your access active.',
'action' => 'Renew package',
],
'event_threshold' => [
'subject' => 'You have used :percentage% of your event limit',
'greeting' => 'Hi :name,',
'body' => 'You have used :used of :limit events on your :package package. :remaining remaining.',
'action' => 'Upgrade package',
],
'event_limit' => [
'subject' => 'Event limit reached for :package',
'greeting' => 'Hi :name,',
'body' => 'You have reached the event limit (:limit) for your :package package.',
'action' => 'Upgrade package',
],
'photo_threshold' => [
'subject' => 'You have used :percentage% of your photo limit',
'greeting' => 'Hi :name,',
'body' => 'Your event :event has used :used of :limit photos on :package. :remaining remaining.',
'action' => 'Add more photos',
],
'photo_limit' => [
'subject' => 'Photo limit reached for :event',
'greeting' => 'Hi :name,',
'body' => 'Your event :event reached the photo limit for :package.',
'cta_addon' => 'You can add extra photo capacity.',
'addon_action' => 'Buy photo add-on',
'action' => 'Manage event',
],
'guest_threshold' => [
'subject' => 'You have used :percentage% of your guest limit',
'greeting' => 'Hi :name,',
'body' => 'Your event :event has used :used of :limit guests on :package. :remaining remaining.',
'action' => 'Add more guests',
],
'guest_limit' => [
'subject' => 'Guest limit reached for :event',
'greeting' => 'Hi :name,',
'body' => 'Your event :event reached the guest limit for :package.',
'cta_addon' => 'You can add extra guests.',
'addon_action' => 'Buy guest add-on',
'action' => 'Manage event',
],
'gallery_warning' => [
'subject' => '{1} Gallery for :event expires in :days day|[2,*] Gallery for :event expires in :days days',
'greeting' => 'Hi :name,',
'body' => '{1} The gallery for :event (package :package) expires in :days day on :date.|[2,*] The gallery for :event (package :package) expires in :days days on :date.',
'action' => 'Open event',
],
'gallery_expired' => [
'subject' => 'Gallery expired for :event',
'greeting' => 'Hi :name,',
'body' => 'The gallery for :event (package :package) expired on :date.',
'action' => 'Open event',
],
],
'tenant_feedback' => [
'unknown_tenant' => 'Unknown tenant',
'unknown' => 'Unknown',
'subject' => 'New feedback from :tenant (:sentiment)',
'tenant' => 'Tenant: :tenant',
'category' => 'Category: :category',
'sentiment' => 'Sentiment: :sentiment',
'event' => 'Event: :event',
'rating' => 'Rating: :rating',
'title' => 'Title: :subject',
'message' => 'Message:',
'open' => 'Open feedback',
'received_at' => 'Received at: :date',
],
'refund' => [
'subject' => 'Refund processed for :package',
'greeting' => 'Hi :name,',
'body' => 'We processed a refund of :amount :currency for your purchase (reference: :provider_id).',
'reason' => 'Reason: :reason',
'footer' => 'If you have any questions, reply to this email.',
],
'ops' => [
'purchase' => [
'subject' => 'New purchase: :package',
'greeting' => 'New purchase received.',
'tenant' => 'Tenant: :tenant',
'package' => 'Package: :package',
'amount' => 'Amount: :amount :currency',
'provider' => 'Provider: :provider (ID: :id)',
'consents' => 'Consents: legal=:legal, terms=:terms, waiver=:waiver',
'footer' => 'View the purchase details in the admin panel.',
],
'refund' => [
'subject' => 'Refund processed: :package',
'greeting' => 'Refund update.',
'tenant' => 'Tenant: :tenant',
'package' => 'Package: :package',
'amount' => 'Amount: :amount :currency',
'provider' => 'Provider: :provider (ID: :id)',
'status_success' => 'Refund succeeded.',
'status_failed' => 'Refund failed.',
'reason' => 'Reason: :reason',
'error' => 'Error: :error',
'footer' => 'Check the payment logs for details.',
],
'addon' => [
'subject' => 'Add-on purchased: :addon',
'greeting' => 'Add-on purchase received.',
'tenant' => 'Tenant: :tenant',
'event' => 'Event: :event',
'addon' => 'Add-on: :addon (qty: :quantity)',
'amount' => 'Amount: :amount :currency',
'provider' => 'Provider: :provider (ID: :id)',
'footer' => 'Review the add-on details in the admin panel.',
],
],
'addons' => [
'receipt' => [
'subject' => 'Add-on receipt: :addon',
'greeting' => 'Hi :name,',
'body' => 'You purchased the add-on :addon for event :event. Amount: :amount.',
'summary_title' => 'Included:',
'summary' => [
'photos' => ':count additional photos',
'guests' => ':count additional guests',
'gallery' => ':count additional gallery days',
],
'unknown_amount' => 'Unknown amount',
'action' => 'Open event',
],
],
];