This commit is contained in:
Jay Sheen
2025-11-21 15:57:36 +09:00
27 changed files with 379 additions and 86 deletions

View File

@@ -1,6 +1,4 @@
VITE_APP_ENV=development
# VITE_APP_AUTH_PROXY_HOST='http://3.35.79.250:8090'
# VITE_APP_API_PROXY_HOST='http://3.35.79.250:8080'
VITE_APP_AUTH_PROXY_HOST='https://auth.nicepay.co.kr'
VITE_APP_API_PROXY_HOST='https://rest.nicepay.co.kr'
GENERATE_SOURCEMAP=false

View File

@@ -4,7 +4,7 @@
"version": "1.0.3",
"type": "module",
"scripts": {
"dev": "env-cmd -f .env.local vite --host --open",
"dev": "env-cmd -f .env.development vite --host --open",
"build:development": "env-cmd -f .env.development vite build",
"build": "env-cmd -f .env.production vite build",
"lint": "eslint . --ext js,jsx,ts,tsx --report-unused-disable-directives --max-warnings 0",

View File

@@ -1,8 +1,40 @@
import { TFunction } from 'i18next';
import { LinkPaymentProcessStatus } from "./types";
import { LinkPaymentPaymentMethod, LinkPaymentProcessStatus } from "./types";
export const getProcessStatusBtnGroup = (t: TFunction) => [
{ name: t('transaction.constants.all'), value: LinkPaymentProcessStatus.ALL },
{ name: t('additionalService.linkPay.sendRequest'), value: LinkPaymentProcessStatus.SEND_REQUEST },
{ name: t('additionalService.linkPay.sendCancel'), value: LinkPaymentProcessStatus.SEND_CANCEL }
]
export const getPaymentMethodOptionGroup = (t: TFunction) => [
{ name: t('additionalService.linkPayment.paymentMethod.all'), value: '' },
{ name: t('additionalService.linkPayment.paymentMethod.card'), value: LinkPaymentPaymentMethod.CARD},
{ name: t('additionalService.linkPayment.paymentMethod.bank'), value: LinkPaymentPaymentMethod.BANK},
{ name: t('additionalService.linkPayment.paymentMethod.virtualAccount'), value: LinkPaymentPaymentMethod.VIRTURE_BANK},
{ name: t('additionalService.linkPayment.paymentMethod.phone'), value: LinkPaymentPaymentMethod.PHONE},
{ name: t('additionalService.linkPayment.paymentMethod.cultureland'), value: LinkPaymentPaymentMethod.CULTURELAND},
{ name: t('additionalService.linkPayment.paymentMethod.ssgMoney'), value: LinkPaymentPaymentMethod.SSG_MONEY},
{ name: t('additionalService.linkPayment.paymentMethod.ssgBank'), value: LinkPaymentPaymentMethod.SSG_BANK},
{ name: t('additionalService.linkPayment.paymentMethod.cmsBank'), value: LinkPaymentPaymentMethod.CMS_BANK}, //계좌간편결제
{ name: t('additionalService.linkPayment.paymentMethod.tmoneyPay'), value: LinkPaymentPaymentMethod.TMONEY_PAY},
]
export const getPaymentMethodText = (t: TFunction) => (status?: string): string => {
if (!status) return '';
const paymentMethodMap: Record<LinkPaymentPaymentMethod, string> = {
[LinkPaymentPaymentMethod.ALL]: t('additionalService.linkPayment.paymentMethod.all'),
[LinkPaymentPaymentMethod.CARD]: t('additionalService.linkPayment.paymentMethod.card'),
[LinkPaymentPaymentMethod.BANK]: t('additionalService.linkPayment.paymentMethod.bank'),
[LinkPaymentPaymentMethod.VIRTURE_BANK]: t('additionalService.linkPayment.paymentMethod.virtualAccount'),
[LinkPaymentPaymentMethod.PHONE]: t('additionalService.linkPayment.paymentMethod.phone'),
[LinkPaymentPaymentMethod.CULTURELAND]: t('additionalService.linkPayment.paymentMethod.cultureland'),
[LinkPaymentPaymentMethod.SSG_MONEY]: t('additionalService.linkPayment.paymentMethod.ssgMoney'),
[LinkPaymentPaymentMethod.SSG_BANK]: t('additionalService.linkPayment.paymentMethod.ssgBank'),
[LinkPaymentPaymentMethod.CMS_BANK]: t('additionalService.linkPayment.paymentMethod.cmsBank'),
[LinkPaymentPaymentMethod.TMONEY_PAY]: t('additionalService.linkPayment.paymentMethod.tmoneyPay')
}
return paymentMethodMap[status as LinkPaymentPaymentMethod] || status;
}

View File

@@ -20,6 +20,7 @@ export enum LinkPaymentSearchCl {
}
export enum LinkPaymentPaymentMethod {
ALL = "",
CARD = "CARD",
BANK = "BANK",
VIRTURE_BANK = "VIRTURE_BANK",
@@ -124,6 +125,7 @@ export interface LinkPaymentHistoryFilterProps extends FilterProps {
mid: string;
searchCl: LinkPaymentSearchCl;
searchValue: string;
paymentMethod: LinkPaymentPaymentMethod;
fromDate: string;
toDate: string;
paymentStatus: LinkPaymentPaymentStatus;
@@ -132,6 +134,7 @@ export interface LinkPaymentHistoryFilterProps extends FilterProps {
setMid: (mid: string) => void;
setSearchType: (searchType: LinkPaymentSearchCl) => void;
setSearchKeyword: (searchKeyWorld: string) => void;
setPaymentMethod: (paymentMethod: LinkPaymentPaymentMethod) => void;
setStartDate: (startDate: string) => void;
setEndDate: (endDate: string) => void;
setPaymentStatus: (transactionStatus: LinkPaymentPaymentStatus) => void;
@@ -161,6 +164,7 @@ export interface LinkPaymentWaitFilterProps extends FilterProps {
export interface ExtensionLinkPayHistoryListParams extends ExtensionRequestParams {
searchCl: string;
searchValue: string;
paymentMethod: LinkPaymentPaymentMethod;
fromDate: string;
toDate: string;
paymentStatus: LinkPaymentPaymentStatus;

View File

@@ -131,9 +131,14 @@ export const LinkPaymentStep1 = ({ formData, setFormData }: LinkPaymentStep1Prop
<div className="issue-field">
<input
type="text"
inputMode="text"
placeholder=""
value={formData.moid}
onChange={(e) => handleInputChange('moid', e.target.value)}
onChange={(e) => {
// 영문자와 숫자만 허용 (한글, 특수문자 제거)
const cleanedValue = e.target.value.replace(/[^a-zA-Z0-9]/g, '');
handleInputChange('moid', cleanedValue);
}}
onFocus={handleInputFocus}
/>
</div>

View File

@@ -13,11 +13,12 @@ import { FilterCalendar } from '@/shared/ui/filter/calendar';
import { FilterButtonGroups } from '@/shared/ui/filter/button-groups';
import { FilterMotionDuration, FilterMotionStyle, FilterMotionVariants } from '@/entities/common/model/constant';
import { useStore } from '@/shared/model/store';
import { LinkPaymentHistoryFilterProps, LinkPaymentPaymentStatus, LinkPaymentSearchCl, LinkPaymentSendMethod, LinkPaymentSendStatus } from '@/entities/additional-service/model/link-pay/types';
import { LinkPaymentHistoryFilterProps, LinkPaymentPaymentMethod, LinkPaymentPaymentStatus, LinkPaymentSearchCl, LinkPaymentSendMethod, LinkPaymentSendStatus } from '@/entities/additional-service/model/link-pay/types';
import { FilterSelectMid } from '@/shared/ui/filter/select-mid';
import { useTranslation } from 'react-i18next';
import { FullMenuClose } from '@/entities/common/ui/full-menu-close';
import { useKeyboardAware } from '@/shared/lib/hooks';
import { getPaymentMethodOptionGroup } from '@/entities/additional-service/model/link-pay/constant';
export const LinkPaymentHistoryFilter = ({
filterOn,
@@ -25,6 +26,7 @@ export const LinkPaymentHistoryFilter = ({
mid,
searchCl,
searchValue,
paymentMethod,
fromDate,
toDate,
paymentStatus,
@@ -33,6 +35,7 @@ export const LinkPaymentHistoryFilter = ({
setMid,
setSearchType,
setSearchKeyword,
setPaymentMethod,
setStartDate,
setEndDate,
setPaymentStatus,
@@ -44,6 +47,7 @@ export const LinkPaymentHistoryFilter = ({
const [filterMid, setFilterMid] = useState<string>(mid);
const [filterSearchCl, setFilterSearchCl] = useState<LinkPaymentSearchCl>(searchCl);
const [filterSearchValue, setFilterSearchValue] = useState<string>(searchValue);
const [filterPaymentMethod, setFilterPaymentMethod] = useState<LinkPaymentPaymentMethod>(paymentMethod);
const [filterStartDate, setFilterStartDate] = useState<string>(fromDate);
const [filterEndDate, setFilterEndDate] = useState<string>(toDate);
const [filterTransactionStatus, setFilterTransactionStatus] = useState<LinkPaymentPaymentStatus>(paymentStatus)
@@ -85,6 +89,7 @@ export const LinkPaymentHistoryFilter = ({
setMid(filterMid);
setSearchType(filterSearchCl);
setSearchKeyword(filterSearchValue);
setPaymentMethod(filterPaymentMethod);
setStartDate(filterStartDate);
setEndDate(filterEndDate);
setPaymentStatus(filterTransactionStatus);
@@ -112,7 +117,7 @@ export const LinkPaymentHistoryFilter = ({
<div className="full-menu-actions">
<FullMenuClose
addClass='full-menu-close'
onClickToCallback={ onClickToClose }
onClickToCallback={onClickToClose}
></FullMenuClose>
</div>
</div>
@@ -131,8 +136,14 @@ export const LinkPaymentHistoryFilter = ({
selectOptions={searchTypeOption}
inputValue={filterSearchValue}
inputSetter={setFilterSearchValue}
handleInputFocus={ handleInputFocus }
handleInputFocus={handleInputFocus}
></FilterSelectInput>
<FilterSelect
title={t('filter.paymentMethod')}
selectValue={filterPaymentMethod}
selectSetter={setFilterPaymentMethod}
selectOptions={getPaymentMethodOptionGroup(t)}
></FilterSelect>
<FilterCalendar
startDate={filterStartDate}
endDate={filterEndDate}

View File

@@ -35,7 +35,7 @@ const defaultParams = {
toDate: moment().format('YYYYMMDD'),
searchCl: LinkPaymentSearchCl.PHONE,
searchValue: '',
paymentMethod: LinkPaymentPaymentMethod.CARD,
paymentMethod: LinkPaymentPaymentMethod.ALL,
paymentStatus: LinkPaymentPaymentStatus.ALL,
sendStatus: LinkPaymentSendStatus.ALL,
sendMethod: LinkPaymentSendMethod.ALL
@@ -109,6 +109,7 @@ export const LinkPaymentHistoryWrap = () => {
mid: mid,
searchCl: searchCl,
searchValue: searchValue,
paymentMethod: paymentMethod,
fromDate: fromDate,
toDate: toDate,
paymentStatus: paymentStatus,
@@ -333,6 +334,7 @@ export const LinkPaymentHistoryWrap = () => {
mid={mid}
searchCl={searchCl}
searchValue={searchValue}
paymentMethod={paymentMethod}
fromDate={fromDate}
toDate={toDate}
paymentStatus={paymentStatus}
@@ -341,6 +343,7 @@ export const LinkPaymentHistoryWrap = () => {
setMid={setMid}
setSearchType={setSearchCl}
setSearchKeyword={setSearchValue}
setPaymentMethod={setPaymentMethod}
setStartDate={setFromDate}
setEndDate={setToDate}
setPaymentStatus={setPaymentStatus}

View File

@@ -14,6 +14,7 @@ import { ServiceCode } from '../model/alimtalk/types';
import { getAlimtalkAlimClText, getAlimtalkSendClTypeText, getAlimtalkSendTypeText, getAlimtalkServiceCodeText } from '../model/alimtalk/constant';
import { getAuthResultStatusText, getTransTypeText } from '../model/face-auth/constant';
import { getPayoutStatusText } from '../model/payout/constant';
import { getPaymentMethodText } from '../model/link-pay/constant';
export const ListItem = ({
additionalServiceCategory,
@@ -376,9 +377,9 @@ export const ListItem = ({
}
else if (additionalServiceCategory === AdditionalServiceCategory.LinkPaymentHistory
) {
str = `${getMaskedName(buyerName)}`;
str = receiverInfo ? `${getMaskedName(buyerName)}(${receiverInfo})` : `${getMaskedName(buyerName)}`;
} else if (additionalServiceCategory === AdditionalServiceCategory.LinkPaymentWait) {
str = `${getMaskedName(buyerName)}(${receiverInfo})`;
str = receiverInfo ? `${getMaskedName(buyerName)}(${receiverInfo})` : `${getMaskedName(buyerName)}`;
}
else if (additionalServiceCategory === AdditionalServiceCategory.Payout) {
str = companyName;
@@ -452,7 +453,7 @@ export const ListItem = ({
);
}
else if (additionalServiceCategory === AdditionalServiceCategory.LinkPaymentHistory) {
if (paymentStatus === "0" || paymentStatus === "3" || paymentStatus === "4") {
if (paymentStatus === "2" || paymentStatus === "4") {
rs.push(
<div key="link-payment-history" className="transaction-details">
<span>{getPaymentStatusText(t)(paymentStatus)}</span>
@@ -466,8 +467,12 @@ export const ListItem = ({
<span>{getPaymentStatusText(t)(paymentStatus)}</span>
<span className="separator">|</span>
<span>{getSendMethodText(t)(sendMethod)}</span>
<span className="separator">|</span>
<span>{paymentMethod}</span>
{paymentMethod && (
<>
<span className="separator">|</span>
<span>{getPaymentMethodText(t)(paymentMethod)}</span>
</>
)}
</div>
);
}
@@ -483,7 +488,7 @@ export const ListItem = ({
}
else if (additionalServiceCategory === AdditionalServiceCategory.Payout) {
rs.push(
<div className="transaction-details">
<div key="payout" className="transaction-details">
<span>{getPayoutStatusText(t)(status)}</span>
<span className="separator">|</span>
<span>{submallId}</span>
@@ -519,7 +524,7 @@ export const ListItem = ({
}
else if (additionalServiceCategory === AdditionalServiceCategory.Ars) {
rs.push(
<div className="transaction-details">
<div key="ars" className="transaction-details">
<span>{getTime()}</span>
<span className="separator">|</span>
<span>{getStatus()}</span>
@@ -532,7 +537,7 @@ export const ListItem = ({
}
else if (additionalServiceCategory === AdditionalServiceCategory.Alimtalk) {
rs.push(
<div className="transaction-details">
<div key="alimtalk" className="transaction-details">
<span>{getTime()}</span>
<span className="separator">|</span>
<span>{getAlimtalkServiceCodeText(t)(serviceCode)}</span>
@@ -557,14 +562,14 @@ export const ListItem = ({
let rs: any[] = [];
if (additionalServiceCategory === AdditionalServiceCategory.AccountHolderSearch) {
rs.push(
<div className={`status-label ${resultStatus === 'SUCCESS' ? 'success' : 'fail'}`}>
<div key="account-holder-search-amount" className={`status-label ${resultStatus === 'SUCCESS' ? 'success' : 'fail'}`}>
{resultStatus === 'SUCCESS' ? t('additionalService.common.success') : t('additionalService.common.fail')}
</div>
);
}
else if (additionalServiceCategory === AdditionalServiceCategory.FaceAuth) {
rs.push(
<div className={`status-label ${authResult === 'SUCCESS' ? 'success' : 'fail'}`}>
<div key="face-auth-amount" className={`status-label ${authResult === 'SUCCESS' ? 'success' : 'fail'}`}>
{authResult === 'SUCCESS' ? t('additionalService.common.success') : t('additionalService.common.fail')}
</div>
);
@@ -573,14 +578,14 @@ export const ListItem = ({
const statusText = authStatus === 'REQUEST' ? t('additionalService.common.request') : authStatus === 'SUCCESS' ? t('additionalService.common.success') : t('additionalService.common.fail');
const statusClass = authStatus === 'SUCCESS' || 'REQUEST' ? 'success' : 'fail';
rs.push(
<div className={`status-label ${statusClass}`}>
<div key="account-holder-auth-amount" className={`status-label ${statusClass}`}>
{statusText}
</div>
);
}
else if (additionalServiceCategory === AdditionalServiceCategory.KeyInPayment) {
rs.push(
<div className="transaction-amount">
<div key="key-in-payment-amount" className="transaction-amount">
{t('home.money', { value: new Intl.NumberFormat('en-US').format(amount || 0) })}
</div>
);
@@ -589,7 +594,7 @@ export const ListItem = ({
additionalServiceCategory === AdditionalServiceCategory.LinkPaymentWait
) {
rs.push(
<div className="transaction-amount">
<div key="link-payment-amount" className="transaction-amount">
{t('home.money', { value: new Intl.NumberFormat('en-US').format(amount || 0) })}
</div>
);

View File

@@ -98,7 +98,7 @@ export const ListFilter = ({
<div className="option-list pt-16 pb-86">
<FilterSelectMid
title={t('filter.merchant')}
selectSetter={ setMid }
selectSetter={ setFilterMid }
showType={ 'GID' }
></FilterSelectMid>
<FilterButtonGroups

View File

@@ -84,6 +84,9 @@ export const NoticeDetail = ({
className="notice-detail__body"
dangerouslySetInnerHTML={{ __html: result.contents || '' }}
></div>
{/*
<div className="notice-detail__body">{ result.contents }</div>
*/}
</div>
</div>
</div>

View File

@@ -0,0 +1,39 @@
import axios from 'axios';
import { API_URL_TRANSACTION } from '@/shared/api/api-url-transaction';
import { resultify } from '@/shared/lib/resultify';
import { NiceAxiosError } from '@/shared/@types/error';
import {
AllTransactionIssueSendParams,
AllTransactionIssueSendResponse
} from '../model/types';
import {
useMutation,
UseMutationOptions
} from '@tanstack/react-query';
import { getHeaderUserAgent } from '@/shared/constants/url';
export const allTransactionIssueSend = (params: AllTransactionIssueSendParams) => {
let headerOptions = {
menuId: 31,
apiType: 'SEND'
};
let options = {
headers: {
'X-User-Agent': getHeaderUserAgent(headerOptions)
}
};
return resultify(
axios.post<AllTransactionIssueSendResponse>(API_URL_TRANSACTION.transactionIssueSend(), params, options),
);
};
export const useAllTransactionIssueSendMutation = (options?: UseMutationOptions<AllTransactionIssueSendResponse, NiceAxiosError, AllTransactionIssueSendParams>) => {
const mutation = useMutation<AllTransactionIssueSendResponse, NiceAxiosError, AllTransactionIssueSendParams>({
...options,
mutationFn: (params: AllTransactionIssueSendParams) => allTransactionIssueSend(params),
});
return {
...mutation,
};
};

View File

@@ -454,8 +454,10 @@ export interface ImportantInfo {
approvalDate?: string;
approvalTime?: string;
transactionDate?: string;
transactionTime?: string;
requestDate?: string;
cancelDate?: string;
cancelTime?: string;
goodsName?: string;
orderNumber?: string;
@@ -483,6 +485,7 @@ export interface PaymentInfo {
depositorName?: string;
depositDeadline?: string;
depositDate?: string;
depositTime?: string;
refundScheduleDate?: string;
refundBankName?: string;
refundAccountNumber?: string;
@@ -907,3 +910,34 @@ export interface EscrowMailResendParams {
export interface EscrowMailResendResponse {
};
export interface AllTransactionIssueSendParams {
sendEmail: string;
mid?: string;
tid: string;
buyerName?: string;
approvalDate?: string;
depositDate?: string;
transactionDate?: string;
approvalTime?: string;
depositTime?: string;
transactionTime?: string;
transactionAmount?: number;
goodsName?: string;
buyerTel?: string;
approvalNo?: string;
installmentMonth?: string;
moid?: string;
bankName?: string;
accountNo?: string;
purchaseCompany?: string;
cancelDate?: string;
cancelTime?: string;
serviceCode?: string;
transactionStatus?: string;
};
export interface AllTransactionIssueSendResponse {
code: string;
message: string;
ordNm: string;
};

View File

@@ -191,6 +191,9 @@ export const AllTransactionDetail = ({
<AmountInfoSection
transactionCategory={ TransactionCategory.AllTransaction }
amountInfo={ amountInfo }
importantInfo={ importantInfo }
paymentInfo={ paymentInfo }
transactionInfo={ transactionInfo }
isOpen={ showAmountInfo }
tid={ tid }
serviceCode={ serviceCode }

View File

@@ -234,7 +234,7 @@ export const AllTransactionFilter = ({
<div className="option-list pt-16 pb-86">
<FilterSelectMid
title={t('filter.merchant')}
selectSetter={ setMid }
selectSetter={ setFilterMid }
showType={ 'GID' }
></FilterSelectMid>
<FilterSelectInput

View File

@@ -119,7 +119,7 @@ export const CashReceiptFilter = ({
<div className="option-list pt-16 pb-86">
<FilterSelectMid
title={t('filter.merchant')}
selectSetter={ setMid }
selectSetter={ setFilterMid }
showType={ 'GID' }
></FilterSelectMid>
<FilterCalendar

View File

@@ -118,7 +118,7 @@ export const EscrowFilter = ({
<div className="option-list pt-16 pb-86">
<FilterSelectMid
title={t('filter.merchant')}
selectSetter={ setMid }
selectSetter={ setFilterMid }
showType={ 'GID' }
></FilterSelectMid>
<FilterSelectInput

View File

@@ -1,7 +1,7 @@
import moment from 'moment';
import { useTranslation } from 'react-i18next';
import { SectionTitleArrow } from '@/entities/common/ui/section-title-arrow';
import { AmountInfo, CashReceiptReceiptDownloadParams, CashReceiptReceiptDownloadResponse, CashReceiptReceiptSendEmailParams, CashReceiptReceiptSendEmailResponse, CustomerInfo, InfoSectionKeys, InfoSectionProps, IssueInfo, MerchantInfo, ProductInfo, TransactionCategory, TransactionInfo } from '../../model/types';
import { AllTransactionIssueSendParams, AllTransactionIssueSendResponse, AmountInfo, CashReceiptReceiptDownloadParams, CashReceiptReceiptDownloadResponse, CashReceiptReceiptSendEmailParams, CashReceiptReceiptSendEmailResponse, CustomerInfo, InfoSectionKeys, InfoSectionProps, IssueInfo, MerchantInfo, ProductInfo, TransactionCategory, TransactionInfo } from '../../model/types';
import { SlideDown } from 'react-slidedown';
import 'react-slidedown/lib/slidedown.css';
import { snackBar } from '@/shared/lib';
@@ -10,11 +10,15 @@ import { useState } from 'react';
import { DownloadBottomSheet, DownloadSelectedMode } from '@/entities/common/ui/download-bottom-sheet';
import { CashReceiptSample } from '@/entities/common/ui/cash-receipt-sample';
import { useCashReceiptReceiptSendEmailMutation } from '../../api/use-cash-receipt-receipt-send-email-mutation';
import { useDownloadBottomSheetOnStore } from '@/shared/model/store';
import { useDownloadBottomSheetOn2Store } from '@/shared/model/store';
import { useAllTransactionIssueSendMutation } from '../../api/use-all-transaction-issue-send-mutation';
export const AmountInfoSection = ({
transactionCategory,
amountInfo,
importantInfo,
paymentInfo,
transactionInfo,
isOpen,
tid,
serviceCode,
@@ -23,10 +27,11 @@ export const AmountInfoSection = ({
}: InfoSectionProps) => {
const { t } = useTranslation();
const { mutateAsync: allTransactionIssueSend } = useAllTransactionIssueSendMutation();
const { mutateAsync: cashReceiptReceiptDownload } = useCashReceiptReceiptDownloadMutation();
const { mutateAsync: cashReceiptReceiptSendEamil } = useCashReceiptReceiptSendEmailMutation();
const { downloadBottomSheetOn, setDownloadBottomSheetOn } = useDownloadBottomSheetOnStore();
const { downloadBottomSheetOn2, setDownloadBottomSheetOn2 } = useDownloadBottomSheetOn2Store();
const [cashReceiptSampleOn, setCashReceiptSampleOn] = useState<boolean>(false);
const [receiptIssueInfo, setReceiptIssueInfo] = useState<IssueInfo>({});
@@ -199,7 +204,7 @@ export const AmountInfoSection = ({
};
const onClickToOpenDownloadBottomSheet = () => {
setDownloadBottomSheetOn(true);
setDownloadBottomSheetOn2(true);
};
const onRequestDownload = (
@@ -210,21 +215,63 @@ export const AmountInfoSection = ({
if(selectedMode === DownloadSelectedMode.EMAIL
&& !!userEmail
){
let params: CashReceiptReceiptSendEmailParams = {
tid: tid,
email: userEmail
};
cashReceiptReceiptSendEamil(params).then((rs: CashReceiptReceiptSendEmailResponse) => {
console.log(rs);
if(rs.message){
snackBar(rs.message);
}
}).catch((e: any) => {
if(e.response?.data?.error?.message){
snackBar(e.response?.data?.error?.message);
return;
}
});
if(transactionCategory === TransactionCategory.AllTransaction){
let params: AllTransactionIssueSendParams = {
sendEmail: userEmail,
mid: amountInfo?.mid,
tid: tid,
buyerName: transactionInfo?.buyerName,
approvalDate: importantInfo?.approvalDate,
depositDate: paymentInfo?.depositDate,
transactionDate: importantInfo?.transactionDate,
approvalTime: importantInfo?.approvalTime,
depositTime: paymentInfo?.depositTime,
transactionTime: importantInfo?.transactionTime,
transactionAmount: amountInfo?.transactionAmount,
goodsName: importantInfo?.goodsName,
buyerTel: transactionInfo?.buyerTel,
approvalNo: paymentInfo?.approvalNo,
installmentMonth: paymentInfo?.approvalNo,
moid: importantInfo?.moid,
bankName: paymentInfo?.bankName || paymentInfo?.refundBankName,
accountNo: paymentInfo?.accountNo || paymentInfo?.refundAccountNo,
purchaseCompany: paymentInfo?.purchaseCompany,
cancelDate: importantInfo?.cancelDate,
cancelTime: importantInfo?.cancelTime,
serviceCode: serviceCode,
transactionStatus: importantInfo?.transactionStatus
};
allTransactionIssueSend(params).then((rs: AllTransactionIssueSendResponse) => {
if(rs.message){
snackBar(rs.message);
}
else{
snackBar('메일이 전송 되었습니다.');
}
}).catch((e: any) => {
if(e.response?.data?.error?.message){
snackBar(e.response?.data?.error?.message);
return;
}
});
}
else if(transactionCategory === TransactionCategory.CashReceipt){
let params: CashReceiptReceiptSendEmailParams = {
tid: tid,
email: userEmail
};
cashReceiptReceiptSendEamil(params).then((rs: CashReceiptReceiptSendEmailResponse) => {
console.log(rs);
if(rs.message){
snackBar(rs.message);
}
}).catch((e: any) => {
if(e.response?.data?.error?.message){
snackBar(e.response?.data?.error?.message);
return;
}
});
}
}
else if(selectedMode === DownloadSelectedMode.IMAGE){
let params: CashReceiptReceiptDownloadParams = {
@@ -460,8 +507,9 @@ export const AmountInfoSection = ({
</div>
}
<div className="txn-doc">
{ (transactionCategory === TransactionCategory.CashReceipt) &&
!!canDownloadReceipt &&
{ ((transactionCategory === TransactionCategory.AllTransaction) ||
((transactionCategory === TransactionCategory.CashReceipt) &&
!!canDownloadReceipt)) &&
<button
className="doc-btn"
type="button"
@@ -470,11 +518,11 @@ export const AmountInfoSection = ({
}
</div>
</div>
{ !!downloadBottomSheetOn &&
{ !!downloadBottomSheetOn2 &&
<DownloadBottomSheet
bottomSheetOn={ downloadBottomSheetOn }
setBottomSheetOn={ setDownloadBottomSheetOn }
imageMode={ true }
bottomSheetOn={ downloadBottomSheetOn2 }
setBottomSheetOn={ setDownloadBottomSheetOn2 }
imageMode={ (transactionCategory === TransactionCategory.CashReceipt) }
emailMode={ true }
sendRequest={ onRequestDownload }
></DownloadBottomSheet>

View File

@@ -86,7 +86,7 @@ export const ListFilter = ({
<div className="option-list pt-16 pb-86">
<FilterSelectMid
title={t('merchant.title')}
selectSetter={ setMid }
selectSetter={ setFilterMid }
showType={ 'GID' }
></FilterSelectMid>
<FilterCalendarMonth

View File

@@ -1295,7 +1295,18 @@
"apply": "Apply",
"sendRequest": "Send Request",
"sendCancel": "Send Cancel",
"progressStatus": "Progress Status"
"progressStatus": "Progress Status",
"paymentMethod": {
"card": "Credit Card",
"bank": "Bank Transfer",
"virtualAccount": "Virtual Account",
"phone": "Mobile Phone",
"cultureland": "Cultureland",
"ssgMoney": "SSG Money",
"ssgBank": "SSG Bank",
"cmsBank": "Easy Account Payment",
"tmoneyPay": "T-money Pay"
}
},
"infoWrap": {
"paymentInfo": "Payment Information",

View File

@@ -897,27 +897,27 @@
},
"services": {
"sms": "SMS 결제 통보",
"smsDesc": "입금 요청부터 완료까지 SMS 자동 전송",
"smsDesc": "입금 요청부터 완료까지 \n SMS 자동 전송",
"ars": "신용카드 ARS 결제",
"arsDesc": "전화 한 통으로 결제 성공 편리하고 안전한 서비스",
"arsDesc": "전화 한 통으로 결제 성공 \n 편리하고 안전한 서비스",
"keyIn": "KEY-IN 결제",
"keyInDesc": "카드정보 입력만으로 \n 간편하게 결제 가능",
"accountHolderSearch": "계좌성명조회",
"accountHolderSearchDesc": "예금주 정보 입력으로 즉시 예금주 확인",
"accountHolderSearchDesc": "예금주 정보 입력으로 \n 즉시 예금주 확인",
"payout": "지급대행",
"payoutDesc": "하위 가맹점에 빠른 정산금 지급 지급대행 서비스",
"settlementAgency": "정산대행",
"settlementAgencyDesc": "하위 가맹점 정산금 계산부터 지급까지 자동 해결 서비스",
"linkPayment": "링크 결제",
"linkPaymentDesc": "결제 링크 전송만으로 어디서든 결제 가능 서비스",
"linkPaymentDesc": "결제 링크 전송만으로 \n 어디서든 결제 가능 서비스",
"fundAccount": "자금이체",
"fundAccountDesc": "예치금으로 즉시 송금, 파일 등록만으로 다중 송금 가능",
"accountHolderAuth": "계좌점유인증",
"accountHolderAuthDesc": "1원 송금으로 \n 계좌 점유 인증 가능",
"alimtalk": "알림톡 결제통보",
"alimtalkDesc": "결제 상태를 알림톡으로 쉽고 빠른 안내",
"alimtalkDesc": "결제 상태를 알림톡으로 \n 쉽고 빠른 안내",
"faceAuth": "안면인증",
"faceAuthDesc": "얼굴 인식만으로 본인확인과 \n 결제 가능한 안전 결제 서비스"
"faceAuthDesc": "얼굴 인식만으로 본인확인과 결제 가능한 안전 결제 서비스"
},
"settlementAgency": {
"title": "정산대행",
@@ -1290,13 +1290,25 @@
"kakao": "카카오",
"merchant": "가맹점",
"phoneNumberEmail": "휴대폰번호/이메일",
"transactionStatus": "거래 상태",
"sendResult": "발송 결과",
"transactionStatus": "결제 상태",
"sendResult": "전송결과",
"sendMethod": "발송수단",
"apply": "적용",
"sendRequest": "발송요청",
"sendCancel": "발송취소",
"progressStatus": "진행상태"
"progressStatus": "진행상태",
"paymentMethod": {
"all": "전체",
"card": "신용카드",
"bank": "계좌이체",
"virtualAccount": "가상계좌",
"phone": "휴대폰",
"cultureland": "문화상품권",
"ssgMoney": "SSG머니",
"ssgBank": "SSG뱅크",
"cmsBank": "계좌간편결제",
"tmoneyPay": "티머니페이"
}
},
"infoWrap": {
"paymentInfo": "결제 정보",

View File

@@ -91,7 +91,9 @@ export const LinkPaymentApplyConfirmPage = () => {
};
const onClickToBack = () => {
navigate(-1);
navigate(PATHS.additionalService.linkPayment.request, {
state: { formData, returnToStep: 2 }
});
};
return (

View File

@@ -11,12 +11,14 @@ import { IdentityType, Language } from '@/entities/additional-service/model/type
import { LinkContentType, LinkPaymentFormData, LinkPaymentSendMethod } from '@/entities/additional-service/model/link-pay/types';
import { useStore } from '@/shared/model/store';
import moment from 'moment';
import { useLocation } from 'react-router';
export const LinkPaymentApplyPage = () => {
const { t } = useTranslation();
const { navigate } = useNavigate();
const location = useLocation();
const midOptionsWithoutGids = useStore.getState().UserStore.selectOptionsMidsWithoutGids;
const userMid = useStore.getState().UserStore.mid;
@@ -27,23 +29,31 @@ export const LinkPaymentApplyPage = () => {
});
const initialMid = (midItem.length > 0) ? userMid : (midOptionsWithoutGids.length > 0 ? midOptionsWithoutGids[0]?.value || '' : '');
const [processStep, setProcessStep] = useState<ProcessStep>(ProcessStep.One);
const [formData, setFormData] = useState<LinkPaymentFormData>({
mid: initialMid,
sendMethod: LinkPaymentSendMethod.SMS,
goodsName: '',
amount: 0,
moid: '',
paymentLimitDate: moment().format('YYYY.MM.DD'),
buyerName: '',
email: '',
phoneNumber: '',
isIdentity: false,
identityType: IdentityType.INDIVIDUAL,
identityValue: '',
language: Language.KR,
linkContentType: LinkContentType.BASIC
});
// location.state에서 formData와 returnToStep 받기
const savedFormData = location.state?.formData;
const returnToStep = location.state?.returnToStep;
const [processStep, setProcessStep] = useState<ProcessStep>(
returnToStep === 2 ? ProcessStep.Two : ProcessStep.One
);
const [formData, setFormData] = useState<LinkPaymentFormData>(
savedFormData || {
mid: initialMid,
sendMethod: LinkPaymentSendMethod.SMS,
goodsName: '',
amount: 0,
moid: '',
paymentLimitDate: moment().format('YYYY.MM.DD'),
buyerName: '',
email: '',
phoneNumber: '',
isIdentity: false,
identityType: IdentityType.INDIVIDUAL,
identityValue: '',
language: Language.KR,
linkContentType: LinkContentType.BASIC
}
);
useSetHeaderTitle(t('additionalService.linkPayment.applyTitle'));
useSetHeaderType(HeaderType.LeftArrow);

View File

@@ -31,6 +31,10 @@ export const API_URL_TRANSACTION = {
// POST: 거래취소 정보 조회
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/transaction/cancel-info`;
},
transactionIssueSend: () => {
// POST: 거래확인서 메일 발송
return `${API_BASE_URL}/api/v1/${API_URL_KEY}/transaction/issue/send`;
},
/* Cash Receipt Management - 현금영수증 API */
cashReceiptList: () => {

View File

@@ -10,6 +10,10 @@ export interface DownloadBottomSheetOnStore {
downloadBottomSheetOn: boolean;
setDownloadBottomSheetOn: (downloadBottomSheetOn: boolean) => void;
};
export interface DownloadBottomSheetOn2Store {
downloadBottomSheetOn2: boolean;
setDownloadBottomSheetOn2: (downloadBottomSheetOn2: boolean) => void;
};
export interface FilterOnStore {
filterOn: boolean;
setFilterOn: (filterOn: boolean) => void;
@@ -50,6 +54,14 @@ export const useDownloadBottomSheetOnStore = create<DownloadBottomSheetOnStore>(
}));
}
}));
export const useDownloadBottomSheetOn2Store = create<DownloadBottomSheetOn2Store>((set) => ({
downloadBottomSheetOn2: false,
setDownloadBottomSheetOn2: (downloadBottomSheetOn2: boolean) => {
set((state: {downloadBottomSheetOn2: boolean}) => ({
downloadBottomSheetOn2: (state.downloadBottomSheetOn2 = downloadBottomSheetOn2)
}));
}
}));
export const useFilterlOnStore = create<FilterOnStore>((set) => ({
filterOn: false,

View File

@@ -567,6 +567,46 @@ main.pop{
padding-bottom: 100px;
}
/* 부가서비스 리스트 스타일 조정 */
.ing-list .list-wrap02 {
gap: 50px;
}
.ing-list .list-wrap01 img,
.ing-list .list-wrap02 img {
width: 60px;
height: 60px;
object-fit: contain;
}
/* 링크결제 확인 페이지 */
main.pop {
height: 100vh;
overflow: hidden;
display: flex;
flex-direction: column;
}
main.pop .sub-wrap {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding-bottom: 120px;
-webkit-overflow-scrolling: touch;
}
main.pop .preview-body {
max-width: 338px;
width: 100%;
min-height: auto;
}
main.pop .apply-row {
position: fixed;
bottom: 0;
flex-shrink: 0;
}
.resend-text {
word-break: break-all !important;
}
@@ -591,3 +631,20 @@ main.pop{
.tab36 {
font-size: var(--fs-15);
}
/* 로그인 인증 정보 input-row 레이아웃 수정 */
.settings-login-auth .input-row {
display: flex;
align-items: center;
gap: 16px;
padding-bottom: 16px;
}
.settings-login-auth .input-row input {
flex: 1;
min-width: 0;
}
.settings-login-auth .icon-btn.minus {
flex-shrink: 0;
}

View File

@@ -54,11 +54,11 @@ export const MaskedNameInput = ({
onChange(valueWithoutSpace);
}}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
if(isComposing){
// composition 중에는 스페이스 제거
const valueWithoutSpace = e.target.value.replace(/\s/g, '');
onChange(valueWithoutSpace);
}
}}
onFocus={onFocus}
/>

View File

@@ -260,8 +260,8 @@ export const SubLayout = () => {
let userParmas;
if(!isNativeEnvironment){
userParmas = {
//id: 'nictest00',
id: 'reptest22m',
id: 'nictest00',
//id: 'reptest22m',
password: 'nictest00'
};
// userParmas = {