diff --git a/src/entities/additional-service/api/link-payment/use-extension-link-pay-request-mutation.ts b/src/entities/additional-service/api/link-payment/use-extension-link-pay-request-mutation.ts new file mode 100644 index 0000000..be99c74 --- /dev/null +++ b/src/entities/additional-service/api/link-payment/use-extension-link-pay-request-mutation.ts @@ -0,0 +1,26 @@ +import axios from 'axios'; +import { API_URL_ADDITIONAL_SERVICE } from '@/shared/api/api-url-additional-service'; +import { resultify } from '@/shared/lib/resultify'; +import { CBDCAxiosError } from '@/shared/@types/error'; +import { + useMutation, + UseMutationOptions +} from '@tanstack/react-query'; +import { ExtensionLinkPayRequestParams, ExtensionLinkPayRequestResponse } from '../../model/types'; + +export const extensionLinkPayRequest = (params: ExtensionLinkPayRequestParams) => { + return resultify( + axios.post(API_URL_ADDITIONAL_SERVICE.extensionLinkPaymentRequest(), params), + ); +}; + +export const useExtensionLinkPayRequestMutation = (options?: UseMutationOptions) => { + const mutation = useMutation({ + ...options, + mutationFn: (params: ExtensionLinkPayRequestParams) => extensionLinkPayRequest(params), + }); + + return { + ...mutation, + }; +}; \ No newline at end of file diff --git a/src/entities/additional-service/api/link-payment/use-extension-link-pay-wait-delete-mutation.ts b/src/entities/additional-service/api/link-payment/use-extension-link-pay-wait-delete-mutation.ts index b55ac87..b2a5b64 100644 --- a/src/entities/additional-service/api/link-payment/use-extension-link-pay-wait-delete-mutation.ts +++ b/src/entities/additional-service/api/link-payment/use-extension-link-pay-wait-delete-mutation.ts @@ -13,7 +13,7 @@ import { ExtensionLinkPayWaitDeleteParams } from '../../model/types'; export const extensionLinkPayWaitDelete = async (params: ExtensionLinkPayWaitDeleteParams)=> { return resultify( - axios.post(API_URL_ADDITIONAL_SERVICE.extensionLinkPayMentWaitDelete(), params) + axios.post(API_URL_ADDITIONAL_SERVICE.extensionLinkPaymentWaitDelete(), params) ); }; diff --git a/src/entities/additional-service/model/types.ts b/src/entities/additional-service/model/types.ts index 506ad99..29de313 100644 --- a/src/entities/additional-service/model/types.ts +++ b/src/entities/additional-service/model/types.ts @@ -215,6 +215,21 @@ export enum LinkPaymentSendingStatus { SEND_CANCEL = "SEND_CANCEL" } +export enum IdentityType { + INDIVIDUAL = "INDIVIDUAL", + CORPORATE = "CORPORATE" +} + +export enum Language { + KR = "KR", + EN = "EN" +} + +export enum LinkContentType { + BASIC = "BASIC", + ADDITIONAL = "ADDITIONAL" +} + export interface LinkPaymentHistoryListItem { tid?: string; // TODO : buyerName 필요 @@ -396,6 +411,45 @@ export interface ExtensionLinkPayHistoryDownloadExcelRespone { status: boolean; } +export interface ExtensionLinkPayRequestParams extends ExtensionRequestParams { + sendMethod: string; + goodsName: string; + amount: number; + moid: string; + paymentExpiryDate: string; + buyerName: string; + email: string; + phoneNumber: string; + isIdentity: boolean; + identityType: IdentityType; + identityValue: string; + language: Language; + linkContentType: LinkContentType; +} + +export interface ExtensionLinkPayRequestResponse { + status: boolean +} + +export interface LinkPaymentFormData { + // Step 1 + mid: string; + sendMethod: LinkPaymentSendMethod; + goodsName: string; + amount: number; + moid: string; + paymentExpiryDate: string; + // Step 2 + buyerName: string; + email: string; + phoneNumber: string; + isIdentity: boolean; + identityType: IdentityType; + identityValue: string; + language: Language; + linkContentType: LinkContentType; +} + export interface ExtensionLinkPayHistoryDetailParams extends ExtensionRequestParams { tid: string; } diff --git a/src/entities/additional-service/ui/link-payment/apply/link-payment-step1.tsx b/src/entities/additional-service/ui/link-payment/apply/link-payment-step1.tsx index efecb06..28374c0 100644 --- a/src/entities/additional-service/ui/link-payment/apply/link-payment-step1.tsx +++ b/src/entities/additional-service/ui/link-payment/apply/link-payment-step1.tsx @@ -1,33 +1,31 @@ -import { useState } from 'react'; import { PATHS } from '@/shared/constants/paths'; import { useNavigate } from '@/shared/lib/hooks/use-navigate'; import { useSetOnBack } from '@/widgets/sub-layout/use-sub-layout'; -import { IMAGE_ROOT } from '@/shared/constants/common'; +import { LinkPaymentFormData, LinkPaymentSendMethod } from '@/entities/additional-service/model/types'; +import { SingleDatePicker } from '@/shared/ui/filter/single-date-picker'; -export const LinkPaymentStep1 = () => { +interface LinkPaymentStep1Props { + formData: LinkPaymentFormData; + setFormData: (formData: LinkPaymentFormData) => void; +} + +export const LinkPaymentStep1 = ({ formData, setFormData }: LinkPaymentStep1Props) => { const { navigate } = useNavigate(); useSetOnBack(() => { navigate(PATHS.additionalService.intro); }); - const [selectedPaymentMethod, setSelectedPaymentMethod] = useState('SMS'); - const [formData, setFormData] = useState({ - merchant: 'nictest001m', - productName: '', - productPrice: '', - orderNumber: '', - validDate: '2025.06.30' - }); - const handlePaymentMethodChange = (method: string) => { - setSelectedPaymentMethod(method); + const handlePaymentMethodChange = (method: LinkPaymentSendMethod) => { + setFormData({ ...formData, sendMethod: method }); }; const handleInputChange = (field: string, value: string) => { - setFormData(prev => ({ - ...prev, - [field]: value - })); + setFormData({ ...formData, [field]: value }); + }; + + const handleDateChange = (date: string) => { + setFormData({ ...formData, paymentExpiryDate: date }); }; return ( @@ -38,8 +36,8 @@ export const LinkPaymentStep1 = () => {
@@ -51,20 +49,20 @@ export const LinkPaymentStep1 = () => {
handlePaymentMethodChange('SMS')} + className={`keyword-tag flex-1 ${formData.sendMethod === 'SMS' ? 'active' : ''}`} + onClick={() => handlePaymentMethodChange(LinkPaymentSendMethod.SMS)} > SMS handlePaymentMethodChange('이메일')} + className={`keyword-tag flex-1 ${formData.sendMethod === 'EMAIL' ? 'active' : ''}`} + onClick={() => handlePaymentMethodChange(LinkPaymentSendMethod.EMAIL)} > 이메일 handlePaymentMethodChange('카카오')} + className={`keyword-tag flex-1 ${formData.sendMethod === 'KAKAO' ? 'active' : ''}`} + onClick={() => handlePaymentMethodChange(LinkPaymentSendMethod.KAKAO)} > 카카오 @@ -78,8 +76,8 @@ export const LinkPaymentStep1 = () => { handleInputChange('productName', e.target.value)} + value={formData.goodsName} + onChange={(e) => handleInputChange('goodsName', e.target.value)} />
@@ -90,8 +88,8 @@ export const LinkPaymentStep1 = () => { handleInputChange('productPrice', e.target.value)} + value={formData.amount} + onChange={(e) => handleInputChange('amount', e.target.value)} />
@@ -102,8 +100,8 @@ export const LinkPaymentStep1 = () => { handleInputChange('orderNumber', e.target.value)} + value={formData.moid} + onChange={(e) => handleInputChange('moid', e.target.value)} /> @@ -112,20 +110,11 @@ export const LinkPaymentStep1 = () => {
결제 유효일
-
- handleInputChange('validDate', e.target.value)} - /> - -
+ 까지
diff --git a/src/entities/additional-service/ui/link-payment/apply/link-payment-step2.tsx b/src/entities/additional-service/ui/link-payment/apply/link-payment-step2.tsx index 3f8207d..f53b8b1 100644 --- a/src/entities/additional-service/ui/link-payment/apply/link-payment-step2.tsx +++ b/src/entities/additional-service/ui/link-payment/apply/link-payment-step2.tsx @@ -1,45 +1,40 @@ import {ProcessStep} from "@/entities/transaction/model/types"; import {useSetOnBack} from "@/widgets/sub-layout/use-sub-layout"; -import {useState} from "react"; +import { LinkPaymentFormData, IdentityType, Language, LinkContentType } from '@/entities/additional-service/model/types' export interface LinkPaymentStep2Props { setProcessStep: ((processStep: ProcessStep) => void); + formData: LinkPaymentFormData; + setFormData: (formData: LinkPaymentFormData) => void; } export const LinkPaymentStep2 = ({ - setProcessStep + setProcessStep, + formData, + setFormData }: LinkPaymentStep2Props) => { useSetOnBack(() => { setProcessStep(ProcessStep.One); }); const handleInputChange = (field: string, value: string) => { - setFormData(prev => ({ - ...prev, - [field]: value - })); + setFormData({ ...formData, [field]: value }); }; - const [selectedPurchaserType, setSelectedPurchaserType] = useState('개인'); - const [selectedLanguage, setSelectedLanguage] = useState('국문') - const [selectedLinkContent, setSelectedLinkContent] = useState('기본'); - const [formData, setFormData] = useState({ - purchaser: '', - purchaserEmail: '', - purchaserPhone: '', - purchaserBirth: '' - }); - - const handlePurchaserTypeChange = (type: string) => { - setSelectedPurchaserType(type) + const handleIdendityTypeChange = (type: IdentityType) => { + setFormData({ ...formData, identityType: type }); } - const handleLanguageType = (type: string) => { - setSelectedLanguage(type) + const handleLanguageType = (type: Language) => { + setFormData({ ...formData, language: type }); } - const handleLinkContent = (content: string) => { - setSelectedLinkContent(content) + const handleLinkContent = (content: LinkContentType) => { + setFormData({ ...formData, linkContentType: content }); + } + + const handleIdentityToggle = (isChecked: boolean) => { + setFormData({ ...formData, isIdentity: isChecked }); } return ( @@ -51,8 +46,8 @@ export const LinkPaymentStep2 = ({ handleInputChange('purchaser', e.target.value)} + value={formData.buyerName} + onChange={(e) => handleInputChange('buyerName', e.target.value)} /> @@ -63,8 +58,8 @@ export const LinkPaymentStep2 = ({ handleInputChange('purchaserEmail', e.target.value)} + value={formData.email} + onChange={(e) => handleInputChange('email', e.target.value)} /> @@ -75,8 +70,8 @@ export const LinkPaymentStep2 = ({ handleInputChange('purchaserPhone', e.target.value)} + value={formData.phoneNumber} + onChange={(e) => handleInputChange('phoneNumber', e.target.value)} /> @@ -84,7 +79,7 @@ export const LinkPaymentStep2 = ({
구매자 정보 대조
@@ -93,14 +88,14 @@ export const LinkPaymentStep2 = ({
handlePurchaserTypeChange('개인')} + className={`keyword-tag flex-1 ${formData.identityType === IdentityType.INDIVIDUAL ? 'active' : ''}`} + onClick={() => handleIdendityTypeChange(IdentityType.INDIVIDUAL)} > 개인 handlePurchaserTypeChange('법인')} + className={`keyword-tag flex-1 ${formData.identityType === IdentityType.CORPORATE ? 'active' : ''}`} + onClick={() => handleIdendityTypeChange(IdentityType.CORPORATE)} > 법인 @@ -112,10 +107,10 @@ export const LinkPaymentStep2 = ({
handleInputChange('purchaserPhone', e.target.value)} + value={formData.identityValue} + onChange={(e) => handleInputChange('identityValue', e.target.value)} />
@@ -125,14 +120,14 @@ export const LinkPaymentStep2 = ({
handleLanguageType('국문')} + className={`keyword-tag flex-1 ${formData.language === Language.KR ? 'active' : ''}`} + onClick={() => handleLanguageType(Language.KR)} > 국문 handleLanguageType('영문')} + className={`keyword-tag flex-1 ${formData.language === Language.EN ? 'active' : ''}`} + onClick={() => handleLanguageType(Language.EN)} > 영문 @@ -144,14 +139,14 @@ export const LinkPaymentStep2 = ({
handleLinkContent('기본')} + className={`keyword-tag flex-1 ${formData.linkContentType === LinkContentType.BASIC ? 'active' : ''}`} + onClick={() => handleLinkContent(LinkContentType.BASIC)} > 기본 handleLinkContent('추가')} + className={`keyword-tag flex-1 ${formData.linkContentType === LinkContentType.ADDITIONAL ? 'active' : ''}`} + onClick={() => handleLinkContent(LinkContentType.ADDITIONAL)} > 추가 diff --git a/src/pages/additional-service/link-payment/apply/link-payment-apply-confirm-page.tsx b/src/pages/additional-service/link-payment/apply/link-payment-apply-confirm-page.tsx index 78edc28..39b8be7 100644 --- a/src/pages/additional-service/link-payment/apply/link-payment-apply-confirm-page.tsx +++ b/src/pages/additional-service/link-payment/apply/link-payment-apply-confirm-page.tsx @@ -1,18 +1,58 @@ import { HeaderType } from '@/entities/common/model/types'; import { useSetFooterMode, useSetHeaderTitle, useSetHeaderType } from '@/widgets/sub-layout/use-sub-layout'; import { useNavigate } from '@/shared/lib/hooks/use-navigate'; +import { useLocation } from 'react-router'; import { IMAGE_ROOT } from "@/shared/constants/common"; import { PATHS } from '@/shared/constants/paths'; +import { LinkPaymentFormData } from '@/entities/additional-service/model/types' +import { useExtensionLinkPayRequestMutation } from '@/entities/additional-service/api/link-payment/use-extension-link-pay-request-mutation'; +import { ExtensionLinkPayRequestParams } from '@/entities/additional-service/model/types'; export const LinkPaymentApplyConfirmPage = () => { const { navigate } = useNavigate(); + const location = useLocation(); + + const formData: LinkPaymentFormData = location.state?.formData; + const { mutateAsync: linkPayRequest } = useExtensionLinkPayRequestMutation(); useSetHeaderTitle('메시지 미리보기'); useSetHeaderType(HeaderType.LeftArrow); useSetFooterMode(false); const onClickToConfirm = () => { - navigate(PATHS.additionalService.linkPayment.confirmSuccess); + if (!formData) { + console.error('Form data is missing'); + return; + } + + const requestParams: ExtensionLinkPayRequestParams = { + mid: formData.mid, + sendMethod: formData.sendMethod, + goodsName: formData.goodsName, + amount: formData.amount, + moid: formData.moid, + paymentExpiryDate: formData.paymentExpiryDate.replace(/\./g, ''), + buyerName: formData.buyerName, + email: formData.email, + phoneNumber: formData.phoneNumber, + isIdentity: formData.isIdentity, + identityType: formData.identityType, + identityValue: formData.identityValue, + language: formData.language, + linkContentType: formData.linkContentType + }; + + console.log("Link Payment 요청 파라미터: ", requestParams); + + linkPayRequest(requestParams) + .then((response) => { + console.log("Link Payment 성공 응답: ", response); + navigate(PATHS.additionalService.linkPayment.confirmSuccess); + }) + .catch((error) => { + console.error("Link Payment 실패: ", error); + // 에러 처리 로직 추가 가능 + }); }; const onClickToBack = () => { @@ -37,8 +77,8 @@ export const LinkPaymentApplyConfirmPage = () => { !${pay_url}

가맹점 상호 : 나이스페이먼츠 주식회사
- 상품명 : TEST
- 금액 : 123,123원 + 상품명 : {formData.goodsName}
+ 금액 : {formData.amount}원

diff --git a/src/pages/additional-service/link-payment/apply/link-payment-apply-page.tsx b/src/pages/additional-service/link-payment/apply/link-payment-apply-page.tsx index a76e857..0addda1 100644 --- a/src/pages/additional-service/link-payment/apply/link-payment-apply-page.tsx +++ b/src/pages/additional-service/link-payment/apply/link-payment-apply-page.tsx @@ -6,22 +6,47 @@ import {ProcessStep} from '@/entities/transaction/model/types'; import {useSetFooterMode, useSetHeaderTitle, useSetHeaderType} from '@/widgets/sub-layout/use-sub-layout'; import {useNavigate} from '@/shared/lib/hooks/use-navigate'; import {PATHS} from "@/shared/constants/paths"; +import { LinkPaymentFormData, IdentityType, Language, LinkContentType, LinkPaymentSendMethod } from '@/entities/additional-service/model/types'; + + export const LinkPaymentApplyPage = () => { const { navigate } = useNavigate(); const [processStep, setProcessStep] = useState(ProcessStep.One); + const [formData, setFormData] = useState({ + mid: 'nictest001m', + sendMethod: LinkPaymentSendMethod.SMS, + goodsName: '', + amount: 0, + moid: '', + paymentExpiryDate: '', + buyerName: '', + email: '', + phoneNumber: '', + isIdentity: false, + identityType: IdentityType.INDIVIDUAL, + identityValue: '', + language: Language.KR, + linkContentType: LinkContentType.BASIC + }); useSetHeaderTitle('링크결제 신청'); useSetHeaderType(HeaderType.LeftArrow); useSetFooterMode(false); + + const onClickToBack = () => { + navigate(-1); + }; const onClickToChangeTab = () => { if(processStep === ProcessStep.One) { setProcessStep(ProcessStep.Two); } else if(processStep === ProcessStep.Two) { - navigate(PATHS.additionalService.linkPayment.requestConfirm) + navigate(PATHS.additionalService.linkPayment.requestConfirm, { + state: { formData } + }); } }; @@ -49,11 +74,16 @@ export const LinkPaymentApplyPage = () => {
{(processStep === ProcessStep.One) && - + } { (processStep === ProcessStep.Two) && } @@ -69,8 +99,9 @@ export const LinkPaymentApplyPage = () => { {(processStep === ProcessStep.Two) &&
+ className="btn-50 btn-darkgray flex-1" + onClick={() => onClickToBack() } + >이전 +
+
+
+ )} + + {!title && ( +
+ + +
+ )} + + + + ); +}; \ No newline at end of file