90 lines
2.6 KiB
TypeScript
90 lines
2.6 KiB
TypeScript
"use client";
|
||
|
||
import { useCallback, useMemo, useState } from "react";
|
||
|
||
import { performSingleCheckout } from "@/entities/payment/actions";
|
||
import { PaymentInfo, SingleCheckoutRequest } from "@/entities/payment/types";
|
||
|
||
interface UseSingleCheckoutOptions {
|
||
returnUrl?: string;
|
||
onSuccess?: () => void;
|
||
onError?: (error: string) => void;
|
||
}
|
||
|
||
export function useSingleCheckout(options: UseSingleCheckoutOptions = {}) {
|
||
const [isLoading, setIsLoading] = useState(false);
|
||
|
||
const { returnUrl, onSuccess, onError } = options;
|
||
|
||
const handleSingleCheckout = useCallback(
|
||
async (paymentInfo: PaymentInfo) => {
|
||
if (isLoading) return;
|
||
|
||
setIsLoading(true);
|
||
let shouldResetLoading = true;
|
||
|
||
try {
|
||
const payload: SingleCheckoutRequest = {
|
||
paymentInfo,
|
||
pageUrl: typeof window !== "undefined" ? window.location.href : "",
|
||
return_url: returnUrl,
|
||
};
|
||
|
||
const response = await performSingleCheckout(payload);
|
||
|
||
if (response.error) {
|
||
onError?.(response.error);
|
||
return;
|
||
}
|
||
|
||
if (!response.data) {
|
||
onError?.("Payment failed");
|
||
return;
|
||
}
|
||
|
||
if ("payment" in response.data) {
|
||
const { status, paymentUrl } = response.data.payment;
|
||
|
||
if (paymentUrl) {
|
||
// При редиректе на внешний платеж не сбрасываем isLoading
|
||
shouldResetLoading = false;
|
||
window.location.replace(paymentUrl);
|
||
return;
|
||
}
|
||
|
||
if (status === "paid") {
|
||
// При успешной покупке НЕ сбрасываем isLoading
|
||
// onSuccess callback сам будет управлять состоянием через isNavigating
|
||
shouldResetLoading = false;
|
||
await onSuccess?.();
|
||
return;
|
||
} else {
|
||
onError?.("Payment status is not paid");
|
||
}
|
||
} else {
|
||
const errorMessage = response.data.message || "Payment failed";
|
||
onError?.(errorMessage);
|
||
}
|
||
} catch (error) {
|
||
const errorMessage =
|
||
error instanceof Error ? error.message : "Payment failed";
|
||
onError?.(errorMessage);
|
||
} finally {
|
||
// Сбрасываем isLoading только если не было успешного платежа или редиректа
|
||
if (shouldResetLoading) {
|
||
setIsLoading(false);
|
||
}
|
||
}
|
||
},
|
||
[isLoading, returnUrl, onError, onSuccess]
|
||
);
|
||
|
||
return useMemo(
|
||
() => ({
|
||
handleSingleCheckout,
|
||
isLoading,
|
||
}),
|
||
[handleSingleCheckout, isLoading]
|
||
);
|
||
}
|