80 lines
2.8 KiB
TypeScript
80 lines
2.8 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import Link from "next/link";
|
|
import { useRouter } from "next/navigation";
|
|
import { trackEvent } from "@/lib/ebook/analytics";
|
|
import { getFeatures } from "@/lib/ebook/features";
|
|
import { useT } from "@/components/ebook/LocaleProvider";
|
|
import { useAuth } from "@/lib/auth";
|
|
import { api } from "@/lib/api";
|
|
|
|
/** Buy download edition via FastAPI /pay/create (pay_type=ebook). */
|
|
export function BuyEbook({ compact = false }: { compact?: boolean }) {
|
|
const t = useT();
|
|
const { token } = useAuth();
|
|
const router = useRouter();
|
|
const [busy, setBusy] = useState(false);
|
|
const [error, setError] = useState("");
|
|
const [owned, setOwned] = useState(false);
|
|
const features = getFeatures();
|
|
const enabled = features.payment?.checkout?.enabled !== false;
|
|
const productName = features.payment?.checkout?.productName || "Download Edition";
|
|
const buttonText = features.payment?.checkout?.buttonText || "购买下载版";
|
|
|
|
useEffect(() => {
|
|
if (!token) return;
|
|
api.ebookStatus(token).then((s) => setOwned(s.owned)).catch(() => {});
|
|
}, [token]);
|
|
|
|
if (!enabled) return null;
|
|
|
|
const buy = async () => {
|
|
setError("");
|
|
if (!token) {
|
|
router.push("/login?next=/book");
|
|
return;
|
|
}
|
|
if (owned) {
|
|
router.push("/book/thanks");
|
|
return;
|
|
}
|
|
setBusy(true);
|
|
trackEvent("buy_click", { from: compact ? "reader" : "cover" });
|
|
try {
|
|
const returnUrl = `${window.location.origin}/book/thanks`;
|
|
const res = await api.createPayment(token, returnUrl, "ebook");
|
|
if (res.order_id) {
|
|
localStorage.setItem("nomadro-ebook-order", res.order_id);
|
|
}
|
|
// DEV_AUTO_PAY or already-paid: confirm then go to thanks
|
|
if (res.status === "paid" && res.order_id) {
|
|
await api.completePayment(token, res.order_id).catch(() => null);
|
|
router.push(`/book/thanks?order_id=${encodeURIComponent(res.order_id)}`);
|
|
return;
|
|
}
|
|
if (!res.redirect_url) {
|
|
throw new Error(t("payment.checkoutFailed"));
|
|
}
|
|
window.location.href = res.redirect_url;
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : t("payment.checkoutFailed"));
|
|
setBusy(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<section className={`buy-ebook${compact ? " is-compact" : ""}`}>
|
|
<h2 className="buy-ebook-title">{t("payment.buyGet", { name: productName })}</h2>
|
|
<p className="buy-ebook-sub">{t("payment.buySub")}</p>
|
|
<button type="button" className="buy-ebook-btn" disabled={busy} onClick={buy}>
|
|
{busy ? t("payment.openingCheckout") : owned ? "已购买 · 去下载" : buttonText}
|
|
</button>
|
|
{error ? <p className="buy-ebook-error">{error}</p> : null}
|
|
<p className="buy-ebook-hint">
|
|
也可免费 <Link href="/book/read">在线阅读</Link>
|
|
</p>
|
|
</section>
|
|
);
|
|
}
|