fix(checkout): return the customer to the merchant when payment is detected

A merchant that supplies `redirectURL` and `redirectAutomatically` is asking for its
customer back, and the moment to do that is detection rather than final depth. The
payment is already irreversible from the payer's side, and the merchant's own page is
where an order status belongs. Waiting for the confirmation target instead parks the
customer on a payment page for as long as the coin takes.

Only the classic style acted on those fields, and it held its own copy of the rule. The
standard style had no automatic return at all, and its way back appeared only once the
invoice was confirmed. Both styles now render one shared component, so the rule lives in
one place, and the return appears as soon as the payment is seen. The receipt still
waits for confirmation, because that is when there is a settled payment to describe.

Also ignores the tsbuildinfo a typecheck leaves behind.
This commit is contained in:
jwinterm
2026-09-05 10:50:02 -04:00
parent ad6121582e
commit 4fdac75ba3
4 changed files with 80 additions and 23 deletions
+6 -16
View File
@@ -5,6 +5,7 @@ import { useEffect, useMemo, useState } from "react";
import QRCode from "qrcode";
import { formatXmrAmount } from "../lib/formatting";
import BtcpayAutoReturn from "./btcpay-auto-return";
type InvoiceStatus =
| "pending"
@@ -129,22 +130,6 @@ export default function BtcpayClassicCheckout({
? `1 WOW = ${formatFiatAmount(quote.rate, quote.fiat_currency)}`
: null;
useEffect(() => {
if ((status !== "confirmed" && status !== "payment_detected") || !redirectUrl || !redirectAutomatically) {
return;
}
const timer = window.setTimeout(() => {
try {
window.top?.location.assign(redirectUrl);
} catch {
window.location.assign(redirectUrl);
}
}, 3000);
return () => {
window.clearTimeout(timer);
};
}, [redirectAutomatically, redirectUrl, status]);
const handleCopy = async (value: string, field: string) => {
try {
await navigator.clipboard.writeText(value);
@@ -285,6 +270,11 @@ export default function BtcpayClassicCheckout({
return (
<div className="rounded-[28px] border border-stroke bg-white px-6 py-8 shadow-card">
<BtcpayAutoReturn
status={status}
redirectUrl={redirectUrl}
redirectAutomatically={redirectAutomatically}
/>
<div className="text-center">
<p className="text-sm font-semibold uppercase tracking-[0.2em] text-ink-soft">
Payment request