import { useEffect, useCallback, useMemo, useRef } from 'react'; import { useDispatch } from 'react-redux'; import { useAppSelector } from '@akinon/next/redux/hooks'; import { useGetMasterpassRestTokenQuery, useLazyGetMasterpassRestTokenQuery } from '../redux/api'; import { setMasterpassRestToken, setMasterpassRestTokenData, setMasterpassTerminalGroupId, setMasterpassBankIca, setTokenLoading, updatePaymentState } from '../redux/reducer'; import { isTokenExpired } from '../utils/payment-utils'; interface UseMasterpassTokenProps { useThreeD: boolean; token?: string; onTokenReady?: (tokenData: any) => void; } export const useMasterpassToken = ({ useThreeD, token, onTokenReady }: UseMasterpassTokenProps) => { const dispatch = useDispatch(); const skipTokenSyncRef = useRef(false); const onTokenReadyRef = useRef(onTokenReady); onTokenReadyRef.current = onTokenReady; const { token: reduxToken, tokenData, isTokenLoading } = useAppSelector((state) => state.masterpassRest); const stableOnTokenReady = useCallback((tokenData: any) => { onTokenReadyRef.current?.(tokenData); }, []); const shouldSkip = useMemo(() => { const hasToken = !!(token || reduxToken); const isExpired = isTokenExpired(tokenData); return hasToken && !isExpired; }, [token, reduxToken, tokenData]); const { data, refetch, isLoading, error } = useGetMasterpassRestTokenQuery( {}, { skip: shouldSkip } ); const [fetchToken] = useLazyGetMasterpassRestTokenQuery(); useEffect(() => { dispatch(setTokenLoading(isLoading)); }, [isLoading, dispatch]); useEffect(() => { if (skipTokenSyncRef.current) { return; } if (data?.token && data.token !== reduxToken) { dispatch(setMasterpassRestToken(data.token)); dispatch(setMasterpassTerminalGroupId(data.extras.terminal_group_id)); dispatch(setMasterpassBankIca(data.extras.bank_ica)); const decodedToken = window.Utils.decodeJwt(data.token); dispatch(setMasterpassRestTokenData(decodedToken)); if (decodedToken?.AuthenticationMethod?.toLowerCase() === 'none') { dispatch(updatePaymentState({ useThreeD: false })); } stableOnTokenReady(decodedToken); } }, [data?.token, reduxToken, dispatch, stableOnTokenReady]); const refetchToken = useCallback( async (options?: { three_d?: boolean; skipReset?: boolean }) => { skipTokenSyncRef.current = true; const result = await fetchToken(options?.three_d === false ? { three_d: false } : {}); if (result.data?.token) { dispatch(setMasterpassRestToken(result.data.token)); dispatch( setMasterpassTerminalGroupId(result.data.extras.terminal_group_id) ); dispatch(setMasterpassBankIca(result.data.extras.bank_ica)); const decodedToken = window.Utils.decodeJwt(result.data.token); dispatch(setMasterpassRestTokenData(decodedToken)); if (decodedToken?.AuthenticationMethod?.toLowerCase() === 'none') { dispatch(updatePaymentState({ useThreeD: false })); } if (options?.three_d !== false && !options?.skipReset) { stableOnTokenReady(decodedToken); } } return result; }, [fetchToken, dispatch, stableOnTokenReady] ); return { token: reduxToken || token, tokenData, isLoading: isTokenLoading, error, refetch: refetchToken }; };