Issue
Basically, I wish to call the Stripe api to retrieve the session so that I can check if the payment is done when the user is directed to the success_url. After the payment is confirmed to be paid (this can be confirmed by checking the session retrieved), I want to call the API from my own java server to change the payment status to success and clear up the user's shopping cart. But, the issue I encountered is that the useEffect doesn't run after the user gets redirected to the success_url.
Below is the page:
import Navigationbar from "../../Component/NavBar";
import React, {useEffect, useState} from "react";
import tick from "../../images/check.png";
import instagram from "../../images/instagram.png";
import twitter from "../../images/twitter.png";
import wechat from "../../images/wechat.png";
import tiktok from "../../images/tiktok.png";
import email from "../../images/gmail.png";
import "./style.css";
import {getCheckoutSessionDetails} from "../../../resource/CheckoutSessionResource";
import {changeTransactionStatusToFinished, getTransactionDetailData} from "../../../resource/TransactionDetailResource";
import {TransactionDetailData} from "../../../data/TransactionDetailData";
import {useParams} from "react-router-dom";
import LoadingSpinner from "../../Component/LoadingSpinner";
type params={
tid: string;
}
export default function TransactionCompletedPage(){
const domain=window.location.href;
const sessionId=domain.split("=")[1];
const params=useParams<params>();
const [paymentStatus,setPaymentStatus]=useState<boolean|undefined>(undefined);
const [isRendered,setIsRendered]=useState<boolean>(true);
if(paymentStatus) {
changeTransactionStatusToFinished(parseInt(params.tid as string))
}
//The following API is not called...
useEffect(()=>(
getCheckoutSessionDetails(params.tid as string,sessionId,setPaymentStatus)
) , [] )
return(
<>
<Navigationbar/>
<div className={"transaction-process-container"}>
<div className={"transaction-process-step-one-checkout"}>
<div className={"transaction-process"}>
<div className={"transaction-not-in-process-icon"}>1</div>
</div>
<div className={"transaction-process-step-one-name"}>Checkout</div>
</div>
<div className={"division-line"}></div>
<div className={"transaction-process-step-two-payment"}>
<div className={"transaction-process"}>
<div className={"transaction-not-in-process-icon"}>2</div>
</div>
<div className={"transaction-process-step-three-name"}>Payment</div>
</div>
<div className={"division-line"}></div>
<div className={"transaction-process-step-three-completion"}>
<div className={"transaction-process"}>
<div className={"transaction-in-process-icon"}>3</div>
</div>
<div className={"transaction-process-step-four-name"}>Transaction Completed</div>
</div>
</div>
<img className={"tick-image"} src={tick}/>
<h3 className={"payment-successful-message"}>PAYMENT SUCCESSFUL</h3>
<div className={"email-message"}> Thank you for patronizing our shop!
<br/>A confirmation email has been sent to you via the email address that you used to create this account in our platform
</div>
<div className={"social-media-logos-and-customer-service-container"}>
<div className={"social-media-container"}>
<div className={"social-media"}>
Follow Us on Social Media
</div>
<div className={"social-media-logos-container"}>
<img src={instagram} className={"social-media-logos"}/>
<img src={tiktok} className={"social-media-logos"}/>
<img src={twitter} className={"social-media-logos"}/>
<img src={wechat} className={"social-media-logos"}/>
</div>
</div>
<div className={"customer-service-container"}>
<div className={"social-media"}>Customer Service</div>
<div className={"social-media-logos-container"}>
<img src={email} className={"social-media-logos"}/>
<img src={wechat} className={"social-media-logos"}/>
</div>
</div>
</div>
</>
)
Below is the method to call the APIs to retrieve the Stripe session and clear up the shopping cart:
export const getCheckoutSessionDetails=(tid:string,sessionId:string,setPaymentStatus:(status:boolean)=>void)=> {
firebaseAuthServiceGetAccessToken()?.then((token)=>{
return axios.get(`http://localhost:3001/transaction/success?session_id=${sessionId}`,
)
})
.then(function (response) {
console.log(response);
if(response.data.payment_status==="paid"){
setPaymentStatus(true);
}else if(response.data.payment_status==="unpaid"){
setPaymentStatus(false);
}
}
)
.catch(function (error) {
console.log(error);
})
}
export const changeTransactionStatusToFinished=(tid:number)=>{
firebaseAuthServiceGetAccessToken()?.then((token)=> {
console.log(token);
return axios.patch(
`http://localhost:8080/transaction/${tid}/finish`, {}, {headers: {Authorization: `Bearer ${token}`}})
}).then((response:AxiosResponse<TransactionDetailData>)=>{
console.log(response);
}).catch((response)=>{
console.log(response);
})
}
I tried not putting the methods to call the APIs in useEffect, but outside it, yet no APIs are called all the same.
Solution
I circumvented this problem by creating two pages: one page allows users to click the proceed button and the other page is where users are redirected to after clicking the proceed button as well. In the first page, I put all the APIs that need calling into a handleOnCLick function so after clicking the proceed button, the APIs will be called anyways no matter if the page renders itself and doesn't call the APIs for any weird reason.
Answered By - Ben
Answer Checked By - Mary Flores (JavaFixing Volunteer)