import { useState, useEffect } from "react"; import { useStripe, useElements, PaymentElement } from '@stripe/react-stripe-js'; import { Button } from "@/components/ui/button"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { useCheckoutWizard } from "../WizardContext"; interface PaymentStepProps { stripePublishableKey: string; } export const PaymentStep: React.FC = ({ stripePublishableKey }) => { const stripe = useStripe(); const elements = useElements(); const { selectedPackage, authUser, paymentProvider, setPaymentProvider, resetPaymentState, nextStep } = useCheckoutWizard(); const [clientSecret, setClientSecret] = useState(''); const [isProcessing, setIsProcessing] = useState(false); const [error, setError] = useState(''); const [paymentStatus, setPaymentStatus] = useState<'idle' | 'processing' | 'succeeded' | 'failed'>('idle'); useEffect(() => { resetPaymentState(); }, [selectedPackage.id, resetPaymentState]); const isFree = selectedPackage.price <= 0; // Payment Intent für kostenpflichtige Pakete laden useEffect(() => { if (isFree || !authUser) return; const loadPaymentIntent = async () => { try { const response = await fetch('/stripe/create-payment-intent', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || '', }, body: JSON.stringify({ package_id: selectedPackage.id, }), }); const data = await response.json(); if (response.ok && data.clientSecret) { setClientSecret(data.clientSecret); setError(''); } else { setError(data.error || 'Fehler beim Laden der Zahlungsdaten'); } } catch (err) { setError('Netzwerkfehler beim Laden der Zahlungsdaten'); } }; loadPaymentIntent(); }, [selectedPackage.id, authUser, isFree]); const handleSubmit = async (event: React.FormEvent) => { event.preventDefault(); if (!stripe || !elements) { setError('Stripe ist nicht initialisiert. Bitte Seite neu laden.'); return; } if (!clientSecret) { setError('Zahlungsdaten konnten nicht geladen werden. Bitte erneut versuchen.'); return; } setIsProcessing(true); setError(''); setPaymentStatus('processing'); try { const { error: stripeError, paymentIntent } = await stripe.confirmPayment({ elements, confirmParams: { return_url: `${window.location.origin}/checkout/success`, }, redirect: 'if_required', // Wichtig für SCA }); if (stripeError) { console.error('Stripe Payment Error:', stripeError); let errorMessage = 'Zahlung fehlgeschlagen. '; switch (stripeError.type) { case 'card_error': errorMessage += stripeError.message || 'Kartenfehler aufgetreten.'; break; case 'validation_error': errorMessage += 'Eingabedaten sind ungültig.'; break; case 'api_connection_error': errorMessage += 'Verbindungsfehler. Bitte Internetverbindung prüfen.'; break; case 'api_error': errorMessage += 'Serverfehler. Bitte später erneut versuchen.'; break; case 'authentication_error': errorMessage += 'Authentifizierungsfehler. Bitte Seite neu laden.'; break; default: errorMessage += stripeError.message || 'Unbekannter Fehler aufgetreten.'; } setError(errorMessage); setPaymentStatus('failed'); } else if (paymentIntent) { switch (paymentIntent.status) { case 'succeeded': setPaymentStatus('succeeded'); // Kleiner Delay für bessere UX setTimeout(() => nextStep(), 1000); break; case 'processing': setError('Zahlung wird verarbeitet. Bitte warten...'); setPaymentStatus('processing'); break; case 'requires_payment_method': setError('Zahlungsmethode wird benötigt. Bitte Kartendaten überprüfen.'); setPaymentStatus('failed'); break; case 'requires_confirmation': setError('Zahlung muss bestätigt werden.'); setPaymentStatus('failed'); break; default: setError(`Unerwarteter Zahlungsstatus: ${paymentIntent.status}`); setPaymentStatus('failed'); } } } catch (err) { console.error('Unexpected payment error:', err); setError('Unerwarteter Fehler aufgetreten. Bitte später erneut versuchen.'); setPaymentStatus('failed'); } finally { setIsProcessing(false); } }; if (isFree) { return (
Kostenloses Paket Dieses Paket ist kostenlos. Wir aktivieren es direkt nach der Bestätigung.
); } return (
setPaymentProvider(value as 'stripe' | 'paypal')}> Stripe PayPal
{error && ( {error} )} {clientSecret ? (

Sichere Zahlung mit Kreditkarte, Debitkarte oder SEPA-Lastschrift.

) : (
Lade Zahlungsdaten... Bitte warten Sie, während wir die Zahlungsdaten vorbereiten.
)}

PayPal Express Checkout mit Rückleitung zur Bestätigung.

PayPal Integration PayPal wird in einem späteren Schritt implementiert. Aktuell nur Stripe verfügbar.
); };