payment 이하 구조 변경

This commit is contained in:
focp212@naver.com
2025-10-10 12:45:02 +09:00
parent 18b2f9188a
commit 306629be53
18 changed files with 228 additions and 216 deletions

View File

@@ -77,7 +77,7 @@ export const MenuItems = [
menuIcon: 'payment-icon',
subMenu: [
{menuId: '42', parent: '41', menuName: '결제정보', path: PATHS.payment.info},
{menuId: '43', parent: '41', menuName: '결제데이터통보', path: PATHS.payment.dataNotification},
{menuId: '43', parent: '41', menuName: '결제데이터통보', path: PATHS.payment.notificationData},
]
},
{

View File

@@ -13,6 +13,7 @@ import { useStore } from '@/shared/model/store';
export const InfoWrap = () => {
const userMids = useStore.getState().UserStore.userMids;
const midOptions = useStore.getState().UserStore.selectOptionsMids;
const mid = useStore.getState().UserStore.mid;
const [data, setData] = useState<MerchantMidResponse>();
@@ -34,8 +35,8 @@ export const InfoWrap = () => {
};
useEffect(() => {
if(userMids[0]){
callInfo(userMids[0]);
if(!!mid){
callInfo(mid);
}
}, []);
@@ -50,6 +51,7 @@ export const InfoWrap = () => {
<option
key={ value.value }
value={ value.value }
selected={ (mid === value.value)? true: false }
>{ value.name }</option>
))
}

View File

@@ -17,6 +17,7 @@ import { useStore } from '@/shared/model/store';
export const RegistrationStatusWrap = () => {
const userMids = useStore.getState().UserStore.userMids;
const midOptions = useStore.getState().UserStore.selectOptionsMids;
const mid = useStore.getState().UserStore.mid;
const [onlineInfomation, setOnlineInfomation] = useState<OnlineInfomation>();
const [offlineInfomation, setOfflineInfomation] = useState<OfflineInfomation>();
@@ -43,8 +44,8 @@ export const RegistrationStatusWrap = () => {
};
useEffect(() => {
if(userMids[0]){
callInfo(userMids[0]);
if(!!mid){
callInfo(mid);
}
}, []);
@@ -59,6 +60,7 @@ export const RegistrationStatusWrap = () => {
<option
key={ value.value }
value={ value.value }
selected={ (mid === value.value)? true: false }
>{ value.name }</option>
))
}

View File

@@ -1,6 +1,6 @@
export enum PaymentTabKeys {
Info = 'Info',
DataNotification = 'DataNotification',
NotificationData = 'NotificationData',
};
export enum PaymentInfoItemType {
Comission = 'Comission',
@@ -9,7 +9,7 @@ export enum PaymentInfoItemType {
export interface PaymentTabProps {
activeTab: PaymentTabKeys;
};
export enum DataNotificationNotifyContentKey {
export enum NotifyRowKeys {
CreditCard = 'CreditCard',
AccountTransfer = 'AccountTransfer',
VirtualAccount = 'VirtualAccount',

View File

@@ -1,79 +0,0 @@
import moment from 'moment';
import { useEffect, useState } from 'react';
import { SlideDown } from 'react-slidedown';
import 'react-slidedown/lib/slidedown.css';
import { DataNotificationNotifyContentKey } from '../model/types';
export interface DataNotificationNotifyContentProps {
paymentMethodName: string;
type: DataNotificationNotifyContentKey;
startDate?: string;
adminEmail?: string;
urlIp?: string;
retransmissionInterval?: string;
retransmissionCount?: string;
okCheck?: string;
encryptionStatus?: string;
openChild: DataNotificationNotifyContentKey | null;
setOpenChild: (openChild: DataNotificationNotifyContentKey | null) => void;
};
export const DataNotificationNotifyContent = ({
paymentMethodName,
type,
startDate,
adminEmail,
urlIp,
retransmissionInterval,
retransmissionCount,
okCheck,
encryptionStatus,
openChild,
setOpenChild
}: DataNotificationNotifyContentProps) => {
const [isOpen, setIsOpen] = useState<boolean>(false);
const openNotifyContent = () => {
const staus = !isOpen;
setIsOpen(staus);
if(!!staus){
setOpenChild(type);
}
else {
setOpenChild(null)
}
};
useEffect(() => {
if(!!openChild && openChild !== type){
setIsOpen(false);
}
}, [openChild]);
return (
<>
<div
className="notify-row"
onClick={ () => openNotifyContent() }
>
<span className="notify-name">{ paymentMethodName }</span>
<span className={`ic20 arrow-down ${(isOpen)? 'rot-180': ''}`}></span>
</div>
<SlideDown className={'my-dropdown-slidedown'}>
{ isOpen &&
<div className="notify-content">
<ul className="notify-detail-list">
<li className="notify-detail-item"> : { (!!startDate)? moment(startDate).format('YYYY-MM-DD'): '' }</li>
<li className="notify-detail-item"> : { adminEmail } </li>
<li className="notify-detail-item">URL/IP : { urlIp }</li>
<li className="notify-detail-item"> : { retransmissionInterval }</li>
<li className="notify-detail-item"> : { retransmissionCount }</li>
<li className="notify-detail-item">OK : { okCheck }</li>
<li className="notify-detail-item"> : { encryptionStatus }</li>
</ul>
</div>
}
</SlideDown>
</>
);
};

View File

@@ -162,17 +162,19 @@ export const InfoWrap = () => {
};
const callPaymentIntallmentDetail = () => {
let params: PaymentInstallmentDetailParams = {
mid: mid,
cardCompany: cardCompany
};
paymentInstallmentDetail(params).then((rs: PaymentInstallmentDetailResponse) => {
console.log(rs);
setCardCompany(rs.cardCompany);
setCardCompanyOptions(rs.cardCompanyOptions);
setInstallmentDetails(rs.installmentDetails);
});
if(!!cardCompany){
let params: PaymentInstallmentDetailParams = {
mid: mid,
cardCompany: cardCompany
};
paymentInstallmentDetail(params).then((rs: PaymentInstallmentDetailResponse) => {
console.log(rs);
setCardCompany(rs.cardCompany);
setCardCompanyOptions(rs.cardCompanyOptions);
setInstallmentDetails(rs.installmentDetails);
});
}
};
useEffect(() => {
callPaymentCard();
@@ -185,7 +187,7 @@ export const InfoWrap = () => {
return (
<>
<div className="ing-list pb-70">
<div className="ing-list">
<div className="ing-title"> , </div>
<ul className="ing-card-list">
{ getList(PaymentInfoItemType.Comission) }

View File

@@ -1,23 +1,13 @@
import { useEffect, useState } from 'react';
import { DataNotificationNotifyContent } from './data-notification-notify-content';
import { NotifyRowKeys } from '../model/types';
import { usePaymentNotificationDataMutation } from '../api/use-payment-notification-data-mutation';
import { useStore } from '@/shared/model/store';
import { NotifyRow } from './section/notify-row';
import {
MerchantInfo,
CreditCard,
AccountTransfer,
VirtualAccount,
MobilePayment,
EscrowPayment,
DataNotificationNotifyContentKey,
PaymentNotificationDataResponse
} from '../model/types';
export interface DataNotificationWrapProps {
paymentNotificationData?: PaymentNotificationDataResponse;
};
export const NotificationDataWrap = () => {
const midOptions = useStore.getState().UserStore.selectOptionsMids;
const mid = useStore.getState().UserStore.mid;
export const DataNotificationWrap = ({
paymentNotificationData
}: DataNotificationWrapProps) => {
const [merchantInfo, setMerchantInfo] = useState<Record<string, any>>();
const [creditCard, setCreditCard] = useState<Record<string, any>>();
const [accountTransfer, setAccountTransfer] = useState<Record<string, any>>();
@@ -25,25 +15,50 @@ export const DataNotificationWrap = ({
const [mobilePayment, setMobilePayment] = useState<Record<string, any>>();
const [escrowPayment, setEscrowPayment] = useState<Record<string, any>>();
const [openChild, setOpenChild] = useState<DataNotificationNotifyContentKey | null>(null);
const [openChild, setOpenChild] = useState<NotifyRowKeys | null>(null);
const { mutateAsync: paymentNotificationData } = usePaymentNotificationDataMutation();
const callPaymentNotificationData = (selectedMid: string) => {
let params = {
mid: selectedMid,
gid: selectedMid
};
paymentNotificationData(params).then((rs) => {
console.log(rs);
setMerchantInfo(rs?.merchantInfo);
setCreditCard(rs?.creditCard.detail);
setAccountTransfer(rs?.accountTransfer.detail);
setVirtualAccount(rs?.virtualAccount.detail);
setMobilePayment(rs?.mobilePayment.detail);
setEscrowPayment(rs?.escrowPayment.detail);
});
};
const onChangeMid = (value: string) => {
callPaymentNotificationData(value);
};
useEffect(() => {
setMerchantInfo(paymentNotificationData?.merchantInfo);
setCreditCard(paymentNotificationData?.creditCard.detail);
setAccountTransfer(paymentNotificationData?.accountTransfer.detail);
setVirtualAccount(paymentNotificationData?.virtualAccount.detail);
setMobilePayment(paymentNotificationData?.mobilePayment.detail);
setEscrowPayment(paymentNotificationData?.escrowPayment.detail);
if(!!mid){
callPaymentNotificationData(mid);
}
}, []);
return (
<>
<div className="ing-list">
<div className="input-wrapper top-select mt-16">
<select>
<option value="1">nicetest00g</option>
<option value="2">nicetest00g</option>
<option value="3">nicetest00g</option>
<select
onChange={ (e) => onChangeMid(e.target.value) }
>
{
midOptions.map((value, index) => (
<option
key={ value.value }
value={ value.value }
>{ value.name }</option>
))
}
</select>
</div>
<div className="notify-container">
@@ -52,9 +67,9 @@ export const DataNotificationWrap = ({
</div>
<ul className="notify-list">
<li>
<DataNotificationNotifyContent
<NotifyRow
paymentMethodName={ '신용카드' }
type={ DataNotificationNotifyContentKey.CreditCard }
type={ NotifyRowKeys.CreditCard }
startDate={ creditCard?.startDate }
adminEmail={ creditCard?.adminEmail }
urlIp={ creditCard?.urlIp }
@@ -64,13 +79,13 @@ export const DataNotificationWrap = ({
encryptionStatus={ creditCard?.encryptionStatus }
openChild={ openChild }
setOpenChild={ setOpenChild }
></DataNotificationNotifyContent>
></NotifyRow>
</li>
<li className="notify-divider"></li>
<li>
<DataNotificationNotifyContent
<NotifyRow
paymentMethodName={ '계좌이체' }
type={ DataNotificationNotifyContentKey.AccountTransfer }
type={ NotifyRowKeys.AccountTransfer }
startDate={ accountTransfer?.startDate }
adminEmail={ accountTransfer?.adminEmail }
urlIp={ accountTransfer?.urlIp }
@@ -80,13 +95,13 @@ export const DataNotificationWrap = ({
encryptionStatus={ accountTransfer?.encryptionStatus }
openChild={ openChild }
setOpenChild={ setOpenChild }
></DataNotificationNotifyContent>
></NotifyRow>
</li>
<li className="notify-divider"></li>
<li>
<DataNotificationNotifyContent
<NotifyRow
paymentMethodName={ '가상계좌' }
type={ DataNotificationNotifyContentKey.VirtualAccount }
type={ NotifyRowKeys.VirtualAccount }
startDate={ virtualAccount?.startDate }
adminEmail={ virtualAccount?.adminEmail }
urlIp={ virtualAccount?.urlIp }
@@ -96,13 +111,13 @@ export const DataNotificationWrap = ({
encryptionStatus={ virtualAccount?.encryptionStatus }
openChild={ openChild }
setOpenChild={ setOpenChild }
></DataNotificationNotifyContent>
></NotifyRow>
</li>
<li className="notify-divider"></li>
<li>
<DataNotificationNotifyContent
<NotifyRow
paymentMethodName={ '휴대폰' }
type={ DataNotificationNotifyContentKey.MobilePayment }
type={ NotifyRowKeys.MobilePayment }
startDate={ mobilePayment?.startDate }
adminEmail={ mobilePayment?.adminEmail }
urlIp={ mobilePayment?.urlIp }
@@ -112,13 +127,13 @@ export const DataNotificationWrap = ({
encryptionStatus={ mobilePayment?.encryptionStatus }
openChild={ openChild }
setOpenChild={ setOpenChild }
></DataNotificationNotifyContent>
></NotifyRow>
</li>
<li className="notify-divider"></li>
<li>
<DataNotificationNotifyContent
<NotifyRow
paymentMethodName={ '에스크로 결제' }
type={ DataNotificationNotifyContentKey.EscrowPayment }
type={ NotifyRowKeys.EscrowPayment }
startDate={ escrowPayment?.startDate }
adminEmail={ escrowPayment?.adminEmail }
urlIp={ escrowPayment?.urlIp }
@@ -128,7 +143,7 @@ export const DataNotificationWrap = ({
encryptionStatus={ escrowPayment?.encryptionStatus }
openChild={ openChild }
setOpenChild={ setOpenChild }
></DataNotificationNotifyContent>
></NotifyRow>
</li>
</ul>
</div>

View File

@@ -15,8 +15,8 @@ export const PaymentTab = ({
if(tab === PaymentTabKeys.Info){
navigate(PATHS.payment.info);
}
else if(tab === PaymentTabKeys.DataNotification){
navigate(PATHS.payment.dataNotification);
else if(tab === PaymentTabKeys.NotificationData){
navigate(PATHS.payment.notificationData);
}
}
};
@@ -28,8 +28,8 @@ export const PaymentTab = ({
onClick={ () => onClickToNavigation(PaymentTabKeys.Info) }
> </button>
<button
className={`subtab-btn ${(activeTab === PaymentTabKeys.DataNotification)? 'active': ''}` }
onClick={ () => onClickToNavigation(PaymentTabKeys.DataNotification) }
className={`subtab-btn ${(activeTab === PaymentTabKeys.NotificationData)? 'active': ''}` }
onClick={ () => onClickToNavigation(PaymentTabKeys.NotificationData) }
> </button>
</div>
</>

View File

@@ -0,0 +1,79 @@
import moment from 'moment';
import { useEffect, useState } from 'react';
import { SlideDown } from 'react-slidedown';
import 'react-slidedown/lib/slidedown.css';
import { NotifyRowKeys } from '../../model/types';
export interface NotifyRowProps {
paymentMethodName: string;
type: NotifyRowKeys;
startDate?: string;
adminEmail?: string;
urlIp?: string;
retransmissionInterval?: string;
retransmissionCount?: string;
okCheck?: string;
encryptionStatus?: string;
openChild: NotifyRowKeys | null;
setOpenChild: (openChild: NotifyRowKeys | null) => void;
};
export const NotifyRow = ({
paymentMethodName,
type,
startDate,
adminEmail,
urlIp,
retransmissionInterval,
retransmissionCount,
okCheck,
encryptionStatus,
openChild,
setOpenChild
}: NotifyRowProps) => {
const [isOpen, setIsOpen] = useState<boolean>(false);
const openNotifyRow = () => {
const staus = !isOpen;
setIsOpen(staus);
if(!!staus){
setOpenChild(type);
}
else {
setOpenChild(null)
}
};
useEffect(() => {
if(!!openChild && openChild !== type){
setIsOpen(false);
}
}, [openChild]);
return (
<>
<div
className="notify-row"
onClick={ () => openNotifyRow() }
>
<span className="notify-name">{ paymentMethodName }</span>
<span className={`ic20 arrow-down ${(isOpen)? 'rot-180': ''}`}></span>
</div>
<SlideDown className={'my-dropdown-slidedown'}>
{ isOpen &&
<div className="notify-content">
<ul className="notify-detail-list">
<li className="notify-detail-item"> : { (!!startDate)? moment(startDate).format('YYYY-MM-DD'): '' }</li>
<li className="notify-detail-item"> : { adminEmail } </li>
<li className="notify-detail-item">URL/IP : { urlIp }</li>
<li className="notify-detail-item"> : { retransmissionInterval }</li>
<li className="notify-detail-item"> : { retransmissionCount }</li>
<li className="notify-detail-item">OK : { okCheck }</li>
<li className="notify-detail-item"> : { encryptionStatus }</li>
</ul>
</div>
}
</SlideDown>
</>
);
};

View File

@@ -2,6 +2,7 @@ import { lens } from '@dhmk/zustand-lens';
import { SetStateAction } from 'react';
import { UserFavorite, UserInfo } from './types';
import { StorageKeys } from '@/shared/constants/local-storage';
import { StatementSync } from 'node:sqlite';
export interface UserInfoState {
userInfo: UserInfo;
@@ -13,13 +14,16 @@ export interface UserInfoState {
setUserMids: (update: SetStateAction<Array<string>>) => void;
selectOptionsMids: Array<Record<string, string>>;
setSelectOptionsMids: (update: SetStateAction<Array<Record<string, string>>>) => void;
mid: string;
setMid: (update: SetStateAction<string>) => void;
};
const initialUserInfoState = {
userInfo: {} as UserInfo,
userFavorite: [] as Array<UserFavorite>,
userMids: [] as Array<string>,
selectOptionsMids: [] as Array<Record<string, string>>
selectOptionsMids: [] as Array<Record<string, string>>,
mid: '' as string
} as UserInfoState;
export const createUserInfoStore = lens<UserInfoState>((set, get) => ({
@@ -87,4 +91,14 @@ export const createUserInfoStore = lens<UserInfoState>((set, get) => ({
};
});
},
setMid: (update) => {
set((state: UserInfoState) => {
const newMid = (typeof update === 'function')
? update(state.mid): update;
return {
...state,
mid: newMid
}
});
}
}));

View File

@@ -1,65 +0,0 @@
import { useEffect, useState } from 'react';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { PaymentTab } from '@/entities/payment/ui/payment-tab';
import { DataNotificationWrap } from '@/entities/payment/ui/data-notification-wrap';
import { PaymentNonCardResponse, PaymentNotificationDataResponse, PaymentTabKeys } from '@/entities/payment/model/types';
import { usePaymentNotificationDataMutation } from '@/entities/payment/api/use-payment-notification-data-mutation';
import { HeaderType } from '@/entities/common/model/types';
import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode,
useSetOnBack
} from '@/widgets/sub-layout/use-sub-layout';
export const DataNotificationPage = () => {
const { navigate } = useNavigate();
const { mutateAsync: paymentNotificationData } = usePaymentNotificationDataMutation();
const [activeTab, setActiveTab] = useState<PaymentTabKeys>(PaymentTabKeys.DataNotification);
const [mid, setMid] = useState<string>('nictest00g');
const [gid, setGid] = useState<string>('nictest00g');
const [paymentNotificationDataResult, setPaymentNotificationDataResult] = useState<PaymentNotificationDataResponse>();
useSetHeaderTitle('결제 관리');
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(true);
useSetOnBack(() => {
navigate(PATHS.home);
});
const callPaymentNotificationData = () => {
let params = {
mid: mid,
gid: gid
};
paymentNotificationData(params).then((rs) => {
console.log(rs);
setPaymentNotificationDataResult(rs);
});
};
useEffect(() => {
callPaymentNotificationData();
}, []);
return (
<>
<main>
<div className="tab-content">
<div className="tab-pane pt-46 active">
<PaymentTab activeTab={ activeTab }></PaymentTab>
{ !!paymentNotificationDataResult &&
<DataNotificationWrap
paymentNotificationData={ paymentNotificationDataResult }
></DataNotificationWrap>
}
</div>
</div>
</main>
</>
);
};

View File

@@ -27,7 +27,7 @@ export const InfoPage = () => {
return (
<>
<main>
<div className="tab-content pb-70">
<div className="tab-content">
<div className="tab-pane pt-46 active">
<PaymentTab activeTab={ activeTab }></PaymentTab>
<InfoWrap></InfoWrap>

View File

@@ -0,0 +1,38 @@
import { useState } from 'react';
import { PATHS } from '@/shared/constants/paths';
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
import { PaymentTab } from '@/entities/payment/ui/payment-tab';
import { NotificationDataWrap } from '@/entities/payment/ui/notification-data-wrap';
import { PaymentTabKeys } from '@/entities/payment/model/types';
import { HeaderType } from '@/entities/common/model/types';
import {
useSetHeaderTitle,
useSetHeaderType,
useSetFooterMode,
useSetOnBack
} from '@/widgets/sub-layout/use-sub-layout';
export const NotificationDataPage = () => {
const { navigate } = useNavigate();
const [activeTab, setActiveTab] = useState<PaymentTabKeys>(PaymentTabKeys.NotificationData);
useSetHeaderTitle('결제 관리');
useSetHeaderType(HeaderType.LeftArrow);
useSetFooterMode(true);
useSetOnBack(() => {
navigate(PATHS.home);
});
return (
<>
<main>
<div className="tab-content">
<div className="tab-pane pt-46 active">
<PaymentTab activeTab={ activeTab }></PaymentTab>
<NotificationDataWrap></NotificationDataWrap>
</div>
</div>
</main>
</>
);
};

View File

@@ -2,14 +2,14 @@ import { Route } from 'react-router-dom';
import { SentryRoutes } from '@/shared/configs/sentry';
import { ROUTE_NAMES } from '@/shared/constants/route-names';
import { InfoPage } from './info/info-page';
import { DataNotificationPage } from './data-notification/data-notification-page';
import { NotificationDataPage } from './notification-data/notification-data-page';
export const PaymentPages = () => {
return (
<>
<SentryRoutes>
<Route path={ROUTE_NAMES.payment.info} element={<InfoPage />} />
<Route path={ROUTE_NAMES.payment.dataNotification} element={<DataNotificationPage />} />
<Route path={ROUTE_NAMES.payment.notificationData} element={<NotificationDataPage />} />
</SentryRoutes>
</>
);

View File

@@ -85,7 +85,7 @@ export const PATHS: RouteNamesType = {
payment: {
base: generatePath(ROUTE_NAMES.payment.base),
info: generatePath(ROUTE_NAMES.payment.base, ROUTE_NAMES.payment.info),
dataNotification: generatePath(ROUTE_NAMES.payment.base, ROUTE_NAMES.payment.dataNotification),
notificationData: generatePath(ROUTE_NAMES.payment.base, ROUTE_NAMES.payment.notificationData),
},
account: {
base: generatePath(ROUTE_NAMES.account.base),

View File

@@ -40,7 +40,7 @@ export const ROUTE_NAMES = {
payment: {
base: '/payment/*',
info: 'info',
dataNotification: 'data-notification'
notificationData: 'notification-data'
},
account: {
base: '/account/*',

View File

@@ -18,6 +18,7 @@ export const FilterSelect = ({
<option
key={ `key-filter-select-${i}` }
value={ selectOptions[i]?.value }
selected={ (selectValue === selectOptions[i]?.value)? true: false }
>{ selectOptions[i]?.name }</option>
);
}

View File

@@ -119,6 +119,9 @@ export const SubLayout = () => {
};
});
useStore.getState().UserStore.setSelectOptionsMids(options);
if(!!rs.mids[0]){
useStore.getState().UserStore.setMid(rs.mids[0]);
}
});
};