토스페이먼츠를 활용하여 카드, 가상계좌, 계좌이체로 결제하는 코드를 기록해 보려 한다.
먼저 결제에 있어서 필요한 페이지는 3개가 있다.
- 결제 요청 페이지 (프론트-토스)
- 결제 요청 성공 페이지 (프론트-백)
- 결제 요청 실패 페이지 (프론트-백)
먼저 토스페이먼츠에 로그인한 후 클라이언트키(프론트)와 시크릿키(백) 이 필요하다.
결제 요청 페이지
const Payment = () => {
const [name, setName] = React.useState("");
const clientKey = process.env.REACT_APP_CLIENT_KEY;
const tossPay = () => {
//orderId가 필요해서 만든 랜덤 아이디값
const random = new Date().getTime() + Math.random()
const randomId = btoa(random)
if (radio === '가상계좌') {
loadTossPayments(clientKey).then(tossPayments => {
// 카드 결제 메서드 실행
tossPayments.requestPayment(`${radio}`, {
amount: 1, // 가격
orderId: `${randomId}`, // 주문 id
orderName: `gagyeong`, // 결제 이름
customerName: `${name}`, // 판매자, 판매처 이름
successUrl: 'http://localhost:3000/success', // 성공시 리다이렉트 주소
failUrl: 'http://localhost:3000/failed', // 실패시 리다이렉트 주소
validHours: 24, // 유효시간
cashReceipt: {
type: '소득공제',
},
})
})
} else {
loadTossPayments(clientKey).then(tossPayments => {
// 카드 결제 메서드 실행
tossPayments.requestPayment(`${radio}`, {
amount: 1, // 가격
orderId: `${randomId}`, // 주문 id
orderName: `gagyeong`, // 결제 이름
customerName: `${name}`, // 판매자, 판매처 이름
successUrl: 'http://localhost:3000/success', // 성공시 리다이렉트 주소
failUrl: 'http://localhost:3000/failed', // 실패시 리다이렉트 주소
})
})
}
}
결제 요청이 토스페이먼츠로 전송되고 성공했을 때 url로 orderId, paymentKey, amount가 나오는데 그 값들을 백엔드에게 넘겨줘야한다.
결제 성공 페이지
let orderId = new URL(window.location.href).searchParams.get("orderId");
let paymentKey = new URL(window.location.href).searchParams.get("paymentKey");
let amount = new URL(window.location.href).searchParams.get("amount");
useEffect(() => {
axios
.get(process.env.REACT_APP_BASE_URL + `/success?paymentKey=${paymentKey}&amount=${amount}&orderId=${orderId}`)
.then((res) => {
if (res.status == 200 && res.data.method === '가상계좌') {
sessionStorage.setItem("accountNumber", res.data.virtualAccount.accountNumber);
sessionStorage.setItem("bank", res.data.virtualAccount.bank);
sessionStorage.setItem("dueDate", res.data.virtualAccount.dueDate);
navigate('/deposit')
} else if (res.status == 200 && (res.data.method === '카드' || res.data.method === '게좌이체')) {
window.alert({
position: 'center',
icon: 'success',
text: '결제가 완료되었습니다!',
showConfirmButton: false,
timer: 1500
})
navigate('/')
}
})
.catch((err) => {
navigate('/failed')
})
}, [])
백엔드와 method 그리고 데이터를 바디에 담을건지 쿼리스트링으로 담을건지 약속하고 실험을 해보면 될 것이다.
또한, 우린 페이지를 닫으면 결제 정보를 날라가게 할 예정이므로 sessionStorage에 담아 뒀다.
결제 요청 실패 페이지
실패 페이지에서는 이정도면 적당할 듯 하다!
<span>※ 만약 같은 문제가 지속적으로 발생한다면 문의 부탁드립니다.</span>