wenn checkout.completed kommt, senden wir jetzt transaction_id +

checkout_id direkt an das Backend, damit der Server die Session via Paddle‑API finalisiert (auch wenn der Webhook
  nicht greift). Dadurch sollte “Zahlung wird verarbeitet” nicht mehr hängen bleiben.
This commit is contained in:
Codex Agent
2025-12-22 14:45:51 +01:00
parent 83712b9a3a
commit c0c98abbc7
5 changed files with 189 additions and 0 deletions

View File

@@ -202,6 +202,7 @@ export const PaymentStep: React.FC = () => {
const [confirmationElapsedMs, setConfirmationElapsedMs] = useState(0);
const confirmationTimerRef = useRef<number | null>(null);
const statusCheckRef = useRef<(() => void) | null>(null);
const confirmRequestRef = useRef(false);
const paddleLocale = useMemo(() => {
const sourceLocale = i18n.language || (typeof document !== 'undefined' ? document.documentElement.lang : null);
@@ -210,6 +211,33 @@ export const PaymentStep: React.FC = () => {
const isFree = useMemo(() => (selectedPackage ? Number(selectedPackage.price) <= 0 : false), [selectedPackage]);
const confirmCheckoutSession = useCallback(async (payload: Record<string, unknown>) => {
if (!checkoutSessionId) {
return;
}
const transactionId = typeof payload?.transaction_id === 'string' ? payload.transaction_id : null;
const checkoutId = typeof payload?.id === 'string' ? payload.id : null;
if (!transactionId && !checkoutId) {
return;
}
try {
await fetch(`/checkout/session/${checkoutSessionId}/confirm`, {
method: 'POST',
headers: buildCheckoutHeaders(),
credentials: 'same-origin',
body: JSON.stringify({
transaction_id: transactionId,
checkout_id: checkoutId,
}),
});
} catch (error) {
console.warn('Failed to confirm Paddle session', error);
}
}, [checkoutSessionId]);
const applyCoupon = useCallback(async (code: string) => {
if (!selectedPackage) {
return;
@@ -521,6 +549,10 @@ export const PaymentStep: React.FC = () => {
setInlineActive(false);
setAwaitingConfirmation(true);
setPaymentCompleted(false);
if (!confirmRequestRef.current) {
confirmRequestRef.current = true;
void confirmCheckoutSession(event.data as Record<string, unknown>);
}
toast.success(t('checkout.payment_step.toast_success'));
}
@@ -596,6 +628,7 @@ export const PaymentStep: React.FC = () => {
setInlineActive(false);
setAwaitingConfirmation(false);
setConfirmationElapsedMs(0);
confirmRequestRef.current = false;
}, [selectedPackage?.id, setPaymentCompleted]);
useEffect(() => {