This commit is contained in:
focp212@naver.com
2025-10-14 16:01:06 +09:00
parent e9758f2240
commit b6d608a6fa
9 changed files with 82 additions and 53 deletions

View File

@@ -5,9 +5,11 @@ import { App } from './app';
import { initAxios } from '@/shared/configs/axios'; import { initAxios } from '@/shared/configs/axios';
import { initSentry } from '@/shared/configs/sentry'; import { initSentry } from '@/shared/configs/sentry';
import { AppProvider } from './providers/app-provider'; import { AppProvider } from './providers/app-provider';
import { useUserInfo } from '@/entities/user/lib/use-user-info';
// import appBridge from '@/shared/lib/appBridge'; // import appBridge from '@/shared/lib/appBridge';
const initApp = async () => { const initApp = async () => {
//const { updateUserData } = useUserInfo();
initAxios(); initAxios();
initSentry(); initSentry();
// appBridge.sendMessage('login') // appBridge.sendMessage('login')

View File

@@ -25,38 +25,14 @@ export const useUserInfo = () => {
logout(); logout();
return; return;
} }
setLocalStorage(StorageKeys.TokenType, result.tokenType); updateUserData(result);
setLocalStorage(StorageKeys.AccessToken, result.accessToken);
setLocalStorage(StorageKeys.RefreshToken, result.refreshToken);
setLocalStorage(StorageKeys.AccessTokenExpiresIn, result.accessTokenExpiresIn);
setLocalStorage(StorageKeys.RefreshTokenExpiresIn, result.refreshTokenExpiresIn);
setLocalStorage(StorageKeys.MenuGrants, result.menuGrants);
setLocalStorage(StorageKeys.ClientAddressIP, result.clientAddressIP);
setLocalStorage(StorageKeys.Requires2FA, result.requires2FA);
setLocalStorage(StorageKeys.Usrid, result.usrid);
useStore.getState().UserStore.setUserInfo({
...result
});
} }
else{ else{
// 개발용 ... // 개발용 ...
if(params){ if(params){
const result = await login(params); const result: LoginResponse = await login(params);
setLocalStorage(StorageKeys.TokenType, result.tokenType); result.usrid = params.id;
setLocalStorage(StorageKeys.AccessToken, result.accessToken); updateUserData(result);
setLocalStorage(StorageKeys.RefreshToken, result.refreshToken);
setLocalStorage(StorageKeys.AccessTokenExpiresIn, result.accessTokenExpiresIn);
setLocalStorage(StorageKeys.RefreshTokenExpiresIn, result.refreshTokenExpiresIn);
setLocalStorage(StorageKeys.MenuGrants, result.menuGrants);
setLocalStorage(StorageKeys.ClientAddressIP, result.clientAddressIP);
setLocalStorage(StorageKeys.Requires2FA, result.requires2FA);
setLocalStorage(StorageKeys.Usrid, params.id);
useStore.getState().UserStore.setUserInfo({
...result,
usrid: params.id
});
} }
} }
} }
@@ -66,7 +42,26 @@ export const useUserInfo = () => {
logout(); logout();
} }
}; };
const updateUserData = (data: LoginResponse) => {
console.log('updateUserData ==> ['+JSON.stringify(data)+']');
setLocalStorage(StorageKeys.TokenType, data.tokenType);
setLocalStorage(StorageKeys.AccessToken, data.accessToken);
setLocalStorage(StorageKeys.RefreshToken, data.refreshToken);
setLocalStorage(StorageKeys.AccessTokenExpiresIn, data.accessTokenExpiresIn);
setLocalStorage(StorageKeys.RefreshTokenExpiresIn, data.refreshTokenExpiresIn);
setLocalStorage(StorageKeys.MenuGrants, data.menuGrants);
setLocalStorage(StorageKeys.ClientAddressIP, data.clientAddressIP);
setLocalStorage(StorageKeys.Requires2FA, data.requires2FA);
setLocalStorage(StorageKeys.Usrid, data.usrid);
useStore.getState().UserStore.setUserInfo({
...data
});
};
return { return {
callLogin, callLogin,
updateUserData
} }
} }

View File

@@ -1,3 +1,4 @@
import { LoginResponse } from '@/entities/user/model/types';
import type { DefaultEvents, EventEmitter } from '@webview-bridge/web'; import type { DefaultEvents, EventEmitter } from '@webview-bridge/web';
export {}; export {};
@@ -41,5 +42,6 @@ declare global {
ReactNativeWebView: { ReactNativeWebView: {
postMessage: (data: string) => void; postMessage: (data: string) => void;
}; };
saveToken: (token: LoginResponse) => void;
} }
} }

View File

@@ -5,7 +5,16 @@ import { StorageKeys } from '@/shared/constants/local-storage';
import { checkIsAxiosError, getLocalStorage } from '@/shared/lib'; import { checkIsAxiosError, getLocalStorage } from '@/shared/lib';
import { finalizeConfig, extractAccessToken, extractRequestId } from './utils'; import { finalizeConfig, extractAccessToken, extractRequestId } from './utils';
import { HEADER_USER_AGENT } from '@/shared/constants/url'; import { HEADER_USER_AGENT } from '@/shared/constants/url';
import { useAppBridge } from '@/hooks';
import { useUserInfo } from '@/entities/user/lib/use-user-info';
/*
const {
isNativeEnvironment,
requestRefreshToken
} = useAppBridge();
const { updateUserData } = useUserInfo();
*/
const onRequestFulfilled = (config: InternalAxiosRequestConfig) => { const onRequestFulfilled = (config: InternalAxiosRequestConfig) => {
config.headers['Content-Type'] = 'application/json;charset=UTF-8'; config.headers['Content-Type'] = 'application/json;charset=UTF-8';
config.headers['X-User-Agent'] = HEADER_USER_AGENT; config.headers['X-User-Agent'] = HEADER_USER_AGENT;
@@ -26,6 +35,7 @@ const onRequestFulfilled = (config: InternalAxiosRequestConfig) => {
const onRequestRejected = (error: any) => { const onRequestRejected = (error: any) => {
const { method, url, params, data, headers } = error.config; const { method, url, params, data, headers } = error.config;
/*
Sentry.setContext('API Request Detail', { Sentry.setContext('API Request Detail', {
method, method,
url, url,
@@ -33,7 +43,7 @@ const onRequestRejected = (error: any) => {
data, data,
headers, headers,
}); });
*/
return Promise.reject(error); return Promise.reject(error);
}; };
@@ -47,7 +57,30 @@ const onResponseFulfilled = (response: AxiosResponse) => {
}; };
const onResponseRejected = (error: AxiosError) => { const onResponseRejected = (error: AxiosError) => {
if (error?.response) { /*
const {
isNativeEnvironment,
requestRefreshToken
} = useAppBridge();
const { updateUserData } = useUserInfo();
*/
console.log('onResponseRejected --> ', error)
if(error?.status === 401){
/*
if(isNativeEnvironment){
requestRefreshToken().then((token) => {
updateUserData(token);
});
}
else{
requestRefreshToken().then((token) => {
updateUserData(token);
});
}
*/
}
/*
else if (error?.response) {
const { data, status } = error.response; const { data, status } = error.response;
extractRequestId(error?.response); extractRequestId(error?.response);
Sentry.setContext('API Response Detail', { Sentry.setContext('API Response Detail', {
@@ -55,6 +88,7 @@ const onResponseRejected = (error: AxiosError) => {
data, data,
}); });
} }
*/
return new Promise((_resolve, reject) => { return new Promise((_resolve, reject) => {
if (checkIsAxiosError(error)) { if (checkIsAxiosError(error)) {
// iOS의 경우 window에서 unload event가 일어날때 네트워크 에러가 발생하곤 해서 이런 케이스를 방지하기 위해 지연시킴 // iOS의 경우 window에서 unload event가 일어날때 네트워크 에러가 발생하곤 해서 이런 케이스를 방지하기 위해 지연시킴

View File

@@ -23,6 +23,7 @@ export const extractRequestId = (response: AxiosResponse): void => {
const requestIdHeader = response?.headers?.['x-request-id']; const requestIdHeader = response?.headers?.['x-request-id'];
if (requestIdHeader) { if (requestIdHeader) {
const requestId = requestIdHeader.replaceAll(', *', ''); const requestId = requestIdHeader.replaceAll(', *', '');
console.log('requestId --> ', requestId);
setLocalStorage(StorageKeys.RequestId, requestId); setLocalStorage(StorageKeys.RequestId, requestId);
} }
}; };

View File

@@ -33,7 +33,9 @@ class ApiClient {
this.instance.interceptors.request.use( this.instance.interceptors.request.use(
(config) => { (config) => {
const token = tokenManager.getAccessToken(); const token = tokenManager.getAccessToken();
if (token) { console.log('setupInterceptors request ==> ', token)
if(token){
config.headers.Authorization = `Bearer ${token}`; config.headers.Authorization = `Bearer ${token}`;
} }
return config; return config;
@@ -45,6 +47,7 @@ class ApiClient {
this.instance.interceptors.response.use( this.instance.interceptors.response.use(
(response: AxiosResponse) => response, (response: AxiosResponse) => response,
async (error: AxiosError) => { async (error: AxiosError) => {
console.log(' this.instance.interceptors.response' );
const originalRequest = error.config as AxiosRequestConfig & { _retry?: boolean }; const originalRequest = error.config as AxiosRequestConfig & { _retry?: boolean };
console.log('originalRequest ==> ', JSON.stringify(originalRequest)); console.log('originalRequest ==> ', JSON.stringify(originalRequest));
if (error.response?.status === 401 && !originalRequest._retry) { if (error.response?.status === 401 && !originalRequest._retry) {

View File

@@ -24,6 +24,7 @@ export class TokenManager {
} }
getAccessToken(): string | null { getAccessToken(): string | null {
console.log('getAccessToken')
return localStorage.getItem(ACCESS_TOKEN_KEY); return localStorage.getItem(ACCESS_TOKEN_KEY);
} }

View File

@@ -16,34 +16,16 @@ export const FooterNavigation = ({
const { navigate } = useNavigate(); const { navigate } = useNavigate();
const [isFooterOn, setIsFooterOn] = useState<boolean>(false); const [isFooterOn, setIsFooterOn] = useState<boolean>(false);
const {
isNativeEnvironment,
openBiometricRegistrationPopup,
requestRefreshToken,
logout
} = useAppBridge();
const onClickToNavigate = (path?: string) => { const onClickToNavigate = (path?: string) => {
if(!!path){ if(!!path){
if(path === PATHS.settlement.list){ navigate(path);
callRefresh();
}
else{
navigate(path);
}
} }
}; };
const onClickToOpenMenu = () => { const onClickToOpenMenu = () => {
setFavoriteEdit(false); setFavoriteEdit(false);
setMenuOn(true); setMenuOn(true);
}; };
const callRefresh = () => {
requestRefreshToken().then((token) => {
console.log('requestRefreshToken +[' + JSON.stringify(token) + ']' );
});
}
const buttonItems = [ const buttonItems = [
{ {
activeIcon: IMAGE_ROOT + '/home-active.svg', activeIcon: IMAGE_ROOT + '/home-active.svg',

View File

@@ -18,6 +18,7 @@ import { useStore } from '@/shared/model/store';
import { getLocalStorage, setLocalStorage } from '@/shared/lib'; import { getLocalStorage, setLocalStorage } from '@/shared/lib';
import { StorageKeys } from '@/shared/constants/local-storage'; import { StorageKeys } from '@/shared/constants/local-storage';
import { HomeGroupsParams, HomeGroupsResponse } from '@/entities/home/model/types'; import { HomeGroupsParams, HomeGroupsResponse } from '@/entities/home/model/types';
import { LoginResponse } from '@/entities/user/model/types';
export interface ContextType { export interface ContextType {
setOnBack: (onBack: () => void) => void; setOnBack: (onBack: () => void) => void;
@@ -42,7 +43,10 @@ export const SubLayout = () => {
const [favoriteEdit, setFavoriteEdit] = useState<boolean>(false); const [favoriteEdit, setFavoriteEdit] = useState<boolean>(false);
const [headerNavigationKey, setHeaderNavigationKey] = useState<number>(1); const [headerNavigationKey, setHeaderNavigationKey] = useState<number>(1);
const { callLogin } = useUserInfo(); const {
callLogin,
updateUserData
} = useUserInfo();
const { isNativeEnvironment } = useAppBridge(); const { isNativeEnvironment } = useAppBridge();
const { mutateAsync: homeGroups } = useHomeGroupsMutation(); const { mutateAsync: homeGroups } = useHomeGroupsMutation();
@@ -89,6 +93,11 @@ export const SubLayout = () => {
}); });
}, []); }, []);
const saveToken = (token: LoginResponse) => {
updateUserData(token);
};
window.saveToken = saveToken;
useEffect(() => { useEffect(() => {
handleLogin(); handleLogin();