After payement success via Stripe the user is redirected to this route:
// path: src/app/client/payment/payment-success/page.tsx
'use client';
import React, {useEffect, useState} from 'react';
import RequireAuth from "@/components/auth/RequireAuth";
import {getSimulationFromCookie} from "@/lib/simulationCookie";
import {toast} from "react-toastify";
import {getEnvoiById, updateEnvoiDatas} from '@/services/frontend-services/envoi/EnvoiService';
import {$Enums} from "@prisma/client";
import {checkAuthStatus} from "@/lib/auth";
import {useRouter} from "next/navigation";
import {deleteSimulationCookie} from '@/services/frontend-services/simulation/SimulationService';
import {DOMAIN} from "@/utils/constants";
import SimulationStatus = $Enums.SimulationStatus;
const PaymentSuccessPage = () => {
const router = useRouter();
const [isLoading, setIsLoading] = useState(false);
const [didUpdate, setDidUpdate] = useState(false);
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [userId, setUserId] = useState<string | null>(null);
useEffect(() => {
const checkAuth = async () => {
setIsLoading(true);
const authResult = await checkAuthStatus(false);
setIsAuthenticated(authResult.isAuthenticated);
if (authResult.isAuthenticated) {
setUserId(authResult.userId || null);
}
setIsLoading(false);
};
checkAuth();
}, [router]);
useEffect(() => {
const finalizePayment = async () => {
const simulation = await getSimulationFromCookie();
if (!simulation) {
toast.error("Erreur lors de la suppression de la simulation.");
return;
}
// get envoi by id
const envoi = await getEnvoiById(Number(simulation.id));
if (!envoi) {
console.log("log ====> envoi not found from getEnvoiById in PaymentSuccessPage in path: src/app/client/payment/payment-success/page.tsx is : ", envoi);
toast.error("Erreur lors de la suppression de l'envoi.");
return;
}
console.log("log ====> envoi from getEnvoiById successful in PaymentSuccessPage with id:", envoi);
if (envoi.trackingNumber &&
envoi.qrCodeUrl &&
envoi.paid &&
(envoi.simulationStatus === SimulationStatus.COMPLETED)) {
// Delete cookies and redirect
console.log("log ====> deleting simulation cookie...");
try {
await deleteSimulationCookie();
console.log("log ====> Cookie deleted, redirecting...");
router.push(`${DOMAIN}/client/profile`);
setDidUpdate(true);
} catch (error) {
console.error("Failed to delete cookie:", error);
toast.error("Erreur lors de la suppression des cookies.");
}
return;
}
// 1. Update envoi data (generates tracking, QR code, etc.)
const updatedEnvoi = await updateEnvoiDatas(Number(simulation.id));
if (!updatedEnvoi) {
toast.error("Erreur lors de la mise à jour de l'envoi.");
return;
}
if (!envoi.arrivalAgency?.id || !envoi.userId) {
toast.error("Erreur lors de la mise à jour de l'agence.");
return;
}
// delete cookies of the simulation and redirect to the profile page
toast.success("Envoi mis à jour avec succès.");
router.push(`${DOMAIN}/client/profile`);
};
finalizePayment();
}, [router]);
return (
<RequireAuth>
<div className="flex flex-col items-center justify-center min-h-screen">
<h1 className="text-3xl font-bold text-green-600">Paiement Réussi !</h1>
<p className="mt-4">Merci pour votre paiement. Votre transaction a été complétée avec succès.</p>
</div>
</RequireAuth>
);
};
export default PaymentSuccessPage;
where after i chek if the envoi has the required datas as :
if (envoi.trackingNumber &&
envoi.qrCodeUrl &&
envoi.paid &&
(envoi.simulationStatus === SimulationStatus.COMPLETED)) {
// Delete cookies and redirect
console.log("log ====> deleting simulation cookie...");
try {
await deleteSimulationCookie();
console.log("log ====> Cookie deleted, redirecting...");
router.push(`${DOMAIN}/client/profile`);
setDidUpdate(true);
} catch (error) {
console.error("Failed to delete cookie:", error);
toast.error("Erreur lors de la suppression des cookies.");
}
return;
}
i call the function await deleteSimulationCookie()
which is :
/**
* Delete the simulation cookie
* @returns {Promise<void | null>} A Promise that resolves when the status is updated
*/
// path: src/services/frontend-services/simulation/SimulationService.ts
export async function deleteSimulationCookie(): Promise<void | null> {
try {
await axios.get(`${API_DOMAIN}/simulations/delete-cookies`, { withCredentials: true });
} catch (error) {
throw error;
}
}
This function works fine when I click to logout the user. That is, I was able to delete this cookie, but the problem comes after the redirection from Stripe upon payment success.
Here is the API route to delete the cookie:
// path: src/app/api/v1/simulations/delete-cookies/route.ts
import {NextResponse} from "next/server";
import {errorHandler} from "@/utils/handelErrors";
import {cookies} from "next/headers";
import {DOMAIN} from "@/utils/constants";
export async function GET() {
console.log("log ====> GET request reached at: /api/v1/simulations/delete-cookies");
try {
const cookieName = process.env.SIMULATION_COOKIE_NAME;
if (!cookieName) {
return NextResponse.json(
{message: "Server configuration error"},
{status: 500}
);
}
// Delete the simulation cookie with a correct path
if (cookies().has(cookieName)) {
cookies().delete(cookieName);
}
// Create response with CORS headers
const response = NextResponse.json(
{message: "Simulation cookies deleted successfully"},
{status: 200}
);
response.headers.set('Access-Control-Allow-Origin', `${DOMAIN}`);
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
response.headers.set('Access-Control-Allow-Credentials', 'true');
return response;
} catch (error) {
return errorHandler("Internal server error", 500);
}
}
```
thank you.
After payement success via Stripe the user is redirected to this route:
// path: src/app/client/payment/payment-success/page.tsx
'use client';
import React, {useEffect, useState} from 'react';
import RequireAuth from "@/components/auth/RequireAuth";
import {getSimulationFromCookie} from "@/lib/simulationCookie";
import {toast} from "react-toastify";
import {getEnvoiById, updateEnvoiDatas} from '@/services/frontend-services/envoi/EnvoiService';
import {$Enums} from "@prisma/client";
import {checkAuthStatus} from "@/lib/auth";
import {useRouter} from "next/navigation";
import {deleteSimulationCookie} from '@/services/frontend-services/simulation/SimulationService';
import {DOMAIN} from "@/utils/constants";
import SimulationStatus = $Enums.SimulationStatus;
const PaymentSuccessPage = () => {
const router = useRouter();
const [isLoading, setIsLoading] = useState(false);
const [didUpdate, setDidUpdate] = useState(false);
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [userId, setUserId] = useState<string | null>(null);
useEffect(() => {
const checkAuth = async () => {
setIsLoading(true);
const authResult = await checkAuthStatus(false);
setIsAuthenticated(authResult.isAuthenticated);
if (authResult.isAuthenticated) {
setUserId(authResult.userId || null);
}
setIsLoading(false);
};
checkAuth();
}, [router]);
useEffect(() => {
const finalizePayment = async () => {
const simulation = await getSimulationFromCookie();
if (!simulation) {
toast.error("Erreur lors de la suppression de la simulation.");
return;
}
// get envoi by id
const envoi = await getEnvoiById(Number(simulation.id));
if (!envoi) {
console.log("log ====> envoi not found from getEnvoiById in PaymentSuccessPage in path: src/app/client/payment/payment-success/page.tsx is : ", envoi);
toast.error("Erreur lors de la suppression de l'envoi.");
return;
}
console.log("log ====> envoi from getEnvoiById successful in PaymentSuccessPage with id:", envoi);
if (envoi.trackingNumber &&
envoi.qrCodeUrl &&
envoi.paid &&
(envoi.simulationStatus === SimulationStatus.COMPLETED)) {
// Delete cookies and redirect
console.log("log ====> deleting simulation cookie...");
try {
await deleteSimulationCookie();
console.log("log ====> Cookie deleted, redirecting...");
router.push(`${DOMAIN}/client/profile`);
setDidUpdate(true);
} catch (error) {
console.error("Failed to delete cookie:", error);
toast.error("Erreur lors de la suppression des cookies.");
}
return;
}
// 1. Update envoi data (generates tracking, QR code, etc.)
const updatedEnvoi = await updateEnvoiDatas(Number(simulation.id));
if (!updatedEnvoi) {
toast.error("Erreur lors de la mise à jour de l'envoi.");
return;
}
if (!envoi.arrivalAgency?.id || !envoi.userId) {
toast.error("Erreur lors de la mise à jour de l'agence.");
return;
}
// delete cookies of the simulation and redirect to the profile page
toast.success("Envoi mis à jour avec succès.");
router.push(`${DOMAIN}/client/profile`);
};
finalizePayment();
}, [router]);
return (
<RequireAuth>
<div className="flex flex-col items-center justify-center min-h-screen">
<h1 className="text-3xl font-bold text-green-600">Paiement Réussi !</h1>
<p className="mt-4">Merci pour votre paiement. Votre transaction a été complétée avec succès.</p>
</div>
</RequireAuth>
);
};
export default PaymentSuccessPage;
where after i chek if the envoi has the required datas as :
if (envoi.trackingNumber &&
envoi.qrCodeUrl &&
envoi.paid &&
(envoi.simulationStatus === SimulationStatus.COMPLETED)) {
// Delete cookies and redirect
console.log("log ====> deleting simulation cookie...");
try {
await deleteSimulationCookie();
console.log("log ====> Cookie deleted, redirecting...");
router.push(`${DOMAIN}/client/profile`);
setDidUpdate(true);
} catch (error) {
console.error("Failed to delete cookie:", error);
toast.error("Erreur lors de la suppression des cookies.");
}
return;
}
i call the function await deleteSimulationCookie()
which is :
/**
* Delete the simulation cookie
* @returns {Promise<void | null>} A Promise that resolves when the status is updated
*/
// path: src/services/frontend-services/simulation/SimulationService.ts
export async function deleteSimulationCookie(): Promise<void | null> {
try {
await axios.get(`${API_DOMAIN}/simulations/delete-cookies`, { withCredentials: true });
} catch (error) {
throw error;
}
}
This function works fine when I click to logout the user. That is, I was able to delete this cookie, but the problem comes after the redirection from Stripe upon payment success.
Here is the API route to delete the cookie:
// path: src/app/api/v1/simulations/delete-cookies/route.ts
import {NextResponse} from "next/server";
import {errorHandler} from "@/utils/handelErrors";
import {cookies} from "next/headers";
import {DOMAIN} from "@/utils/constants";
export async function GET() {
console.log("log ====> GET request reached at: /api/v1/simulations/delete-cookies");
try {
const cookieName = process.env.SIMULATION_COOKIE_NAME;
if (!cookieName) {
return NextResponse.json(
{message: "Server configuration error"},
{status: 500}
);
}
// Delete the simulation cookie with a correct path
if (cookies().has(cookieName)) {
cookies().delete(cookieName);
}
// Create response with CORS headers
const response = NextResponse.json(
{message: "Simulation cookies deleted successfully"},
{status: 200}
);
response.headers.set('Access-Control-Allow-Origin', `${DOMAIN}`);
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
response.headers.set('Access-Control-Allow-Credentials', 'true');
return response;
} catch (error) {
return errorHandler("Internal server error", 500);
}
}
```
thank you.
Share
Improve this question
edited yesterday
Hamed Jimoh
8298 silver badges19 bronze badges
asked yesterday
Just Relax قناة هدوءJust Relax قناة هدوء
234 bronze badges
1 Answer
Reset to default 0the problem was that my if statement:
if (envoi?.paid && envoi?.trackingNumber && envoi?.qrCodeUrl && envoi?.simulationStatus === SimulationStatus.COMPLETED)
which doesn't run because my api backend return an object that contains another object, the soulution i should change my if statement for exemple to be: if(envoi?.envoi.paid)
instead of:
if(envoi?.paid)
Or, update the api response to return directly the 'envoi' object instead of returning it in another object like i had before :
return NextResponse.json({envoi: envoi}, {status: 200});