iamport 공식 홈페이지에 가서 가맹점 식별코드를 발급받는다. 그 후 useEffect로 사용하기 위한 라이브러리를 추가한다.
useEffect(() => {
const jquery = document.createElement('script');
jquery.src = 'https://code.jquery.com/jquery-1.12.4.min.js';
const iamport = document.createElement('script');
iamport.src = 'https://cdn.iamport.kr/v1/iamport.js';
document.head.appendChild(jquery);
document.head.appendChild(iamport);
return () => {
document.head.removeChild(jquery);
document.head.removeChild(iamport);
};
}, []);
그 후 TS를 위해 타입을 선언한다.
// /types
// payment type
export interface RequestPayAdditionalParams {
digital?: boolean;
vbank_due?: string;
m_redirect_url?: string;
app_scheme?: string;
biz_num?: string;
}
export interface Display {
card_quota?: number[];
}
export interface RequestPayParams extends RequestPayAdditionalParams {
pg?: string;
pay_method: string;
escrow?: boolean;
merchant_uid: string;
name?: string;
amount: number;
custom_data?: any;
tax_free?: number;
currency?: string;
language?: string;
buyer_name?: string;
buyer_tel: string;
buyer_email?: string;
buyer_addr?: string;
buyer_postcode?: string;
notice_url?: string | string[];
display?: Display;
}
// payment callback func type
export interface RequestPayAdditionalResponse {
apply_num?: string;
vbank_num?: string;
vbank_name?: string;
vbank_holder?: string | null;
vbank_date?: number;
}
export interface RequestPayResponse extends RequestPayAdditionalResponse {
success: boolean;
error_code: string;
error_msg: string;
imp_uid: string | null;
merchant_uid: string;
pay_method?: string;
paid_amount?: number;
status?: string;
name?: string;
pg_provider?: string;
pg_tid?: string;
buyer_name?: string;
buyer_email?: string;
buyer_tel?: string;
buyer_addr?: string;
buyer_postcode?: string;
custom_data?: any;
paid_at?: number;
receipt_url?: string;
}
// 컴포넌트
export type RequestPayResponseCallback = (response: RequestPayResponse) => void;
export interface Iamport {
init: (accountID: string) => void;
request_pay: (
params: RequestPayParams,
callback?: RequestPayResponseCallback,
) => void;
}
declare global {
interface Window {
IMP?: Iamport;
}
}
import { RequestPayParams, RequestPayResponse } from '@/lib/type';
import {
Button,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
} from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React, { useEffect } from 'react';
export type RequestPayResponseCallback = (response: RequestPayResponse) => void;
export interface Iamport {
init: (accountID: string) => void;
request_pay: (
params: RequestPayParams,
callback?: RequestPayResponseCallback,
) => void;
}
declare global {
interface Window {
IMP?: Iamport;
}
}
interface IProps {
isOpen: boolean;
price: number
}
function PurchaseModal({ isOpen, price }: IProps) {
const router = useRouter();
const { IMP } = window;
useEffect(() => {
const jquery = document.createElement('script');
jquery.src = 'https://code.jquery.com/jquery-1.12.4.min.js';
const iamport = document.createElement('script');
iamport.src = 'https://cdn.iamport.kr/v1/iamport.js';
document.head.appendChild(jquery);
document.head.appendChild(iamport);
return () => {
document.head.removeChild(jquery);
document.head.removeChild(iamport);
};
}, []);
const handlePayment = (pgType: 'tosspay' | 'kakaopay' | 'html5_inicis') => {
IMP?.init('impxxxxxxx'); // 발급받은 가맹점 식별코드 넣기
IMP?.request_pay(
{
pg: pgType, // PG사
pay_method: 'card', // 결제수단
merchant_uid: 'merchant_' + new Date().getTime(), // 주문번호
name: '결제테스트', // 주문명
amount: price, // 가격
buyer_email: user.email, // 구매자 이메일
buyer_name: user.name, // 구매자 이름
buyer_tel: '010-1234-5678', // 구매자 전화번호
buyer_addr: '서울특별시 강남구 삼성동', // 구매자 주소
buyer_postcode: '123-456', // 구매자 우편번호
},
// 결제 완료 후 실행될 콜백함수
(res: RequestPayResponse) => {
const { success, error_msg } = res;
if (success) {
if (confirm('결제 성공')) {
router.push('/');
}
} else {
alert(`결제 실패, ${error_msg}`);
}
},
);
};
return (
<>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<form>
<ModalContent>
<ModalHeader>결제 페이지</ModalHeader>
<ModalCloseButton />
<ModalFooter justifyContent="space-evenly">
<Button
colorScheme="red"
onClick={() => {
handlePayment('html5_inicis');
}}
>
결제하기
</Button>
<Button
backgroundColor="#fae100"
_hover={{
bgColor: 'yellow.400',
}}
onClick={() => {
handlePayment('kakaopay');
}}
>
카카오페이
</Button>
<Button
bgColor="#0c61eb"
color="white"
_hover={{
bgColor: '#063a8f',
}}
onClick={() => {
handlePayment('tosspay');
}}
>
토스페이
</Button>
</ModalFooter>
</ModalContent>
</form>
</Modal>
</>
);
}
export default PurchaseModal;
실제 결제를 해도 다음날 취소가 되니까 걱정할 필요는 없다.
카카오페이는 test 결제 기능을 제공해서 가상의 돈으로 결제를 테스트할 수 있다!
-끗-