fix payment
This commit is contained in:
parent
e44c64165a
commit
6169e03d9a
@ -71,6 +71,10 @@ const App = () => {
|
||||
const location = useLocation();
|
||||
const userId = useUserStore(state => state.userId);
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Используем обновленный хук useReauthorization для обработки авторизации
|
||||
const { isProcessing } = useReauthorization();
|
||||
|
||||
useUserFetcher({
|
||||
url: process.env.REACT_APP_DOMAIN + `/user/${userId}`,
|
||||
userId,
|
||||
@ -188,6 +192,7 @@ const App = () => {
|
||||
/>
|
||||
|
||||
<Route path={"/image/:srcImage"} element={<ChatImageNewWindow />} />
|
||||
|
||||
<Route element={<PrivateRoute />}>
|
||||
<Route element={<ProtectedLayout />}>
|
||||
<Route path="/tariffs" element={<Tariffs />} />
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
useTheme,
|
||||
CircularProgress,
|
||||
} from "@mui/material";
|
||||
import { activatePromocode } from "@root/api/promocode";
|
||||
import { sendPayment, sendRSPayment } from "@root/api/wallet";
|
||||
@ -31,6 +32,7 @@ import { WarnModal } from "./WarnModal";
|
||||
import { mutate } from "swr";
|
||||
import { allTypesOfPurchases } from "@root/stores/allTypesOfPurchases";
|
||||
import { useAutoPay } from "@root/utils/hooks/useAutoPay";
|
||||
import { useReauthorization } from "@root/utils/hooks/useReauthorization";
|
||||
|
||||
type PaymentMethod = {
|
||||
label: string;
|
||||
@ -61,6 +63,8 @@ export default function Payment() {
|
||||
const navigate = useNavigate();
|
||||
const handleCustomBackNavigation = useHistoryTracker();
|
||||
|
||||
// Используем обновленный хук useReauthorization для обработки авторизации
|
||||
const { isProcessing } = useReauthorization();
|
||||
|
||||
//Логика сбора данных из урла "чё мы ваще пришли на эту страницу"
|
||||
useAutoPay();
|
||||
@ -172,168 +176,192 @@ export default function Payment() {
|
||||
px: isTablet ? (upMd ? "40px" : "18px") : "20px",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
mt: "20px",
|
||||
mb: "40px",
|
||||
display: "flex",
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
{window.history.length > 1 && (
|
||||
<IconButton
|
||||
onClick={handleCustomBackNavigation}
|
||||
sx={{ p: 0, height: "28px", width: "28px", color: "black" }}
|
||||
>
|
||||
<ArrowBackIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
<Typography variant="h4">Способ оплаты</Typography>
|
||||
</Box>
|
||||
{!upMd && (
|
||||
<Typography variant="body2" mb="30px">
|
||||
Выберите способ оплаты
|
||||
</Typography>
|
||||
{/* Показываем состояние загрузки во время авторизации */}
|
||||
{isProcessing && (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
minHeight: "400px",
|
||||
gap: 2,
|
||||
}}
|
||||
>
|
||||
<CircularProgress size={60} />
|
||||
<Typography variant="h6" color="text.secondary">
|
||||
Идёт авторизация...
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: upMd ? "white" : undefined,
|
||||
display: "flex",
|
||||
flexDirection: upMd ? "row" : "column",
|
||||
borderRadius: "12px",
|
||||
boxShadow: upMd ? cardShadow : undefined,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: upMd ? "68.5%" : undefined,
|
||||
p: upMd ? "20px" : undefined,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "start",
|
||||
gap: "40px",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
flexDirection: upSm ? "row" : "column",
|
||||
flexWrap: "wrap",
|
||||
gap: upMd ? "14px" : "20px",
|
||||
alignContent: "start",
|
||||
}}
|
||||
>
|
||||
{paymentMethods.map(({ name, label, image, unpopular = false }) => (
|
||||
<PaymentMethodCard
|
||||
isSelected={selectedPaymentMethod === name}
|
||||
key={name}
|
||||
label={label}
|
||||
image={image}
|
||||
onClick={() => {
|
||||
setSelectedPaymentMethod(name);
|
||||
}}
|
||||
unpopular={false}
|
||||
/>
|
||||
))}
|
||||
<PaymentMethodCard
|
||||
isSelected={selectedPaymentMethod === "rspay"}
|
||||
label={"Расчётный счёт"}
|
||||
image={rsPayLogo}
|
||||
onClick={async () => {
|
||||
setSelectedPaymentMethod("rspay");
|
||||
}}
|
||||
unpopular={false}
|
||||
/>
|
||||
</Box>
|
||||
<CollapsiblePromocodeField
|
||||
fieldValue={promocodeField}
|
||||
onFieldChange={setPromocodeField}
|
||||
onPromocodeApply={handleApplyPromocode}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "start",
|
||||
color: theme.palette.gray.dark,
|
||||
width: upMd ? "31.5%" : undefined,
|
||||
p: upMd ? "20px" : undefined,
|
||||
pl: upMd ? "33px" : undefined,
|
||||
mt: upMd ? undefined : "30px",
|
||||
borderLeft: upMd
|
||||
? `1px solid ${theme.palette.gray.main}`
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
maxWidth: "85%",
|
||||
}}
|
||||
>
|
||||
{upMd && <Typography mb="56px">Выберите способ оплаты</Typography>}
|
||||
<Typography mb="20px">К оплате</Typography>
|
||||
{
|
||||
siteReadyPayCart?.[userId] && notEnoughMoneyAmount > 0 ?
|
||||
<Typography
|
||||
sx={{
|
||||
fontWeight: 500,
|
||||
fontSize: "20px",
|
||||
lineHeight: "48px",
|
||||
mb: "28px",
|
||||
}}
|
||||
>
|
||||
{currencyFormatter.format(
|
||||
Number(bigDecimal.divide(bigDecimal.floor(paymentValue), 100))
|
||||
)}
|
||||
</Typography>
|
||||
:
|
||||
<InputTextfield
|
||||
TextfieldProps={{
|
||||
placeholder: "К оплате",
|
||||
value: paymentValueField,
|
||||
type: "number",
|
||||
}}
|
||||
onChange={(e) => {
|
||||
const value = parseFloat(
|
||||
e.target.value.replace(/^0+(?=\d\.)/, "")
|
||||
);
|
||||
setPaymentValueField(isNaN(value) ? "" : value.toString());
|
||||
}}
|
||||
id="payment-amount"
|
||||
gap={upMd ? "16px" : "10px"}
|
||||
color={"#F2F3F7"}
|
||||
FormInputSx={{ mb: "28px" }}
|
||||
/>
|
||||
}
|
||||
|
||||
</Box>
|
||||
<Button
|
||||
variant="pena-outlined-light"
|
||||
disabled={!isFinite(paymentValue)}
|
||||
onClick={handlePaymentClick}
|
||||
{/* Основной контент страницы */}
|
||||
{!isProcessing && (
|
||||
<>
|
||||
<Box
|
||||
sx={{
|
||||
mt: "auto",
|
||||
color: "black",
|
||||
border: `1px solid ${theme.palette.purple.main}`,
|
||||
"&:hover": {
|
||||
color: "white",
|
||||
},
|
||||
"&:active": {
|
||||
color: "white",
|
||||
},
|
||||
mt: "20px",
|
||||
mb: "40px",
|
||||
display: "flex",
|
||||
gap: "10px",
|
||||
}}
|
||||
>
|
||||
Оплатить
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
<WarnModal open={warnModalOpen} setOpen={setWarnModalOpen} />
|
||||
<SorryModal open={sorryModalOpen} setOpen={setSorryModalOpen} />
|
||||
{window.history.length > 1 && (
|
||||
<IconButton
|
||||
onClick={handleCustomBackNavigation}
|
||||
sx={{ p: 0, height: "28px", width: "28px", color: "black" }}
|
||||
>
|
||||
<ArrowBackIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
<Typography variant="h4">Способ оплаты</Typography>
|
||||
</Box>
|
||||
{!upMd && (
|
||||
<Typography variant="body2" mb="30px">
|
||||
Выберите способ оплаты
|
||||
</Typography>
|
||||
)}
|
||||
<Box
|
||||
sx={{
|
||||
backgroundColor: upMd ? "white" : undefined,
|
||||
display: "flex",
|
||||
flexDirection: upMd ? "row" : "column",
|
||||
borderRadius: "12px",
|
||||
boxShadow: upMd ? cardShadow : undefined,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: upMd ? "68.5%" : undefined,
|
||||
p: upMd ? "20px" : undefined,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "start",
|
||||
gap: "40px",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
flexDirection: upSm ? "row" : "column",
|
||||
flexWrap: "wrap",
|
||||
gap: upMd ? "14px" : "20px",
|
||||
alignContent: "start",
|
||||
}}
|
||||
>
|
||||
{paymentMethods.map(({ name, label, image, unpopular = false }) => (
|
||||
<PaymentMethodCard
|
||||
isSelected={selectedPaymentMethod === name}
|
||||
key={name}
|
||||
label={label}
|
||||
image={image}
|
||||
onClick={() => {
|
||||
setSelectedPaymentMethod(name);
|
||||
}}
|
||||
unpopular={false}
|
||||
/>
|
||||
))}
|
||||
<PaymentMethodCard
|
||||
isSelected={selectedPaymentMethod === "rspay"}
|
||||
label={"Расчётный счёт"}
|
||||
image={rsPayLogo}
|
||||
onClick={async () => {
|
||||
setSelectedPaymentMethod("rspay");
|
||||
}}
|
||||
unpopular={false}
|
||||
/>
|
||||
</Box>
|
||||
<CollapsiblePromocodeField
|
||||
fieldValue={promocodeField}
|
||||
onFieldChange={setPromocodeField}
|
||||
onPromocodeApply={handleApplyPromocode}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "start",
|
||||
color: theme.palette.gray.dark,
|
||||
width: upMd ? "31.5%" : undefined,
|
||||
p: upMd ? "20px" : undefined,
|
||||
pl: upMd ? "33px" : undefined,
|
||||
mt: upMd ? undefined : "30px",
|
||||
borderLeft: upMd
|
||||
? `1px solid ${theme.palette.gray.main}`
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
maxWidth: "85%",
|
||||
}}
|
||||
>
|
||||
{upMd && <Typography mb="56px">Выберите способ оплаты</Typography>}
|
||||
<Typography mb="20px">К оплате</Typography>
|
||||
{
|
||||
siteReadyPayCart?.[userId] && notEnoughMoneyAmount > 0 ?
|
||||
<Typography
|
||||
sx={{
|
||||
fontWeight: 500,
|
||||
fontSize: "20px",
|
||||
lineHeight: "48px",
|
||||
mb: "28px",
|
||||
}}
|
||||
>
|
||||
{currencyFormatter.format(
|
||||
Number(bigDecimal.divide(bigDecimal.floor(paymentValue), 100))
|
||||
)}
|
||||
</Typography>
|
||||
:
|
||||
<InputTextfield
|
||||
TextfieldProps={{
|
||||
placeholder: "К оплате",
|
||||
value: paymentValueField,
|
||||
type: "number",
|
||||
}}
|
||||
onChange={(e) => {
|
||||
const value = parseFloat(
|
||||
e.target.value.replace(/^0+(?=\d\.)/, "")
|
||||
);
|
||||
setPaymentValueField(isNaN(value) ? "" : value.toString());
|
||||
}}
|
||||
id="payment-amount"
|
||||
gap={upMd ? "16px" : "10px"}
|
||||
color={"#F2F3F7"}
|
||||
FormInputSx={{ mb: "28px" }}
|
||||
/>
|
||||
}
|
||||
|
||||
</Box>
|
||||
<Button
|
||||
variant="pena-outlined-light"
|
||||
disabled={!isFinite(paymentValue)}
|
||||
onClick={handlePaymentClick}
|
||||
sx={{
|
||||
mt: "auto",
|
||||
color: "black",
|
||||
border: `1px solid ${theme.palette.purple.main}`,
|
||||
"&:hover": {
|
||||
color: "white",
|
||||
},
|
||||
"&:active": {
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
>
|
||||
Оплатить
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
<WarnModal open={warnModalOpen} setOpen={setWarnModalOpen} />
|
||||
<SorryModal open={sorryModalOpen} setOpen={setSorryModalOpen} />
|
||||
</>
|
||||
)}
|
||||
</SectionWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -3,21 +3,94 @@ import { logout } from '@root/api/auth';
|
||||
import { setNotEnoughMoneyAmount } from '@root/stores/allTypesOfPurchases';
|
||||
import { clearCustomTariffs } from '@root/stores/customTariffs';
|
||||
import { clearTickets } from '@root/stores/tickets';
|
||||
import { clearUserData, useUserStore } from '@root/stores/user';
|
||||
import { useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { clearUserData, setUserId, useUserStore } from '@root/stores/user';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
|
||||
interface QuizAuthParams {
|
||||
action?: string;
|
||||
dif?: string;
|
||||
data?: string;
|
||||
userid?: string;
|
||||
wayback?: string;
|
||||
}
|
||||
|
||||
export const useReauthorization = () => {
|
||||
const userId = useUserStore(store => store.userId)
|
||||
const userId = useUserStore(store => store.userId);
|
||||
const user = useUserStore(store => store.user);
|
||||
const { search } = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const [isProcessing, setIsProcessing] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// Этот эффект сработает при каждом изменении query-параметров
|
||||
const params = new URLSearchParams(search);
|
||||
|
||||
// Обработка старых параметров (userid, sec)
|
||||
const URLuserId = params.get('userid');
|
||||
const URLtoken = params.get('sec');
|
||||
|
||||
// Обработка новых параметров авторизации
|
||||
const quizParams: QuizAuthParams = {
|
||||
action: params.get("action") || undefined,
|
||||
dif: params.get("dif") || undefined,
|
||||
data: params.get("data") || undefined,
|
||||
userid: params.get("userid") || undefined,
|
||||
wayback: params.get("wayback") || undefined,
|
||||
};
|
||||
|
||||
const { action, dif, data: token, userid: quizUserId, wayback } = quizParams;
|
||||
|
||||
// Если есть новые параметры авторизации, обрабатываем их
|
||||
if (action && dif && token && quizUserId) {
|
||||
// Если пользователь уже авторизован и это тот же пользователь, перенаправляем на payment
|
||||
if (user?._id === quizUserId) {
|
||||
let returnUrl = `/payment?action=${action}&dif=${dif}&user=${quizUserId}`;
|
||||
if (wayback) returnUrl += `&wayback=${wayback}`;
|
||||
navigate(returnUrl, { replace: true });
|
||||
return;
|
||||
}
|
||||
|
||||
// Если уже обрабатываем авторизацию, не запускаем повторно
|
||||
if (isProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsProcessing(true);
|
||||
|
||||
const processQuizAuth = async () => {
|
||||
try {
|
||||
// Если есть текущий токен, очищаем данные
|
||||
if (getAuthToken()) {
|
||||
clearAuthToken();
|
||||
clearUserData();
|
||||
clearCustomTariffs();
|
||||
clearTickets();
|
||||
setNotEnoughMoneyAmount(0);
|
||||
await logout();
|
||||
}
|
||||
|
||||
// Устанавливаем новый токен и ID пользователя
|
||||
setAuthToken(token);
|
||||
setUserId(quizUserId);
|
||||
} catch (error) {
|
||||
console.error("Ошибка авторизации:", error);
|
||||
|
||||
// Перенаправляем на внешний сайт в случае ошибки
|
||||
const link = document.createElement("a");
|
||||
link.href = "https://quiz.pena.digital/tariffs";
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
} finally {
|
||||
setIsProcessing(false);
|
||||
}
|
||||
};
|
||||
|
||||
processQuizAuth();
|
||||
return;
|
||||
}
|
||||
|
||||
// Обработка старых параметров (userid, sec)
|
||||
if (URLuserId !== userId && URLtoken) {
|
||||
// Если есть токен в URL, устанавливаем его
|
||||
// Очищаем данные только если токен действительно изменился
|
||||
@ -31,5 +104,9 @@ export const useReauthorization = () => {
|
||||
}
|
||||
setAuthToken(URLtoken);
|
||||
}
|
||||
}, [search]);
|
||||
}, [search, userId, user?._id, navigate, isProcessing]);
|
||||
|
||||
return {
|
||||
isProcessing,
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue
Block a user