[React+DRF] 토스 페이먼츠 결제 구현 1. 일반 결제

hapwoo·2022년 12월 13일
5

기존에 결제 시스템은 아임포트를 이용하고 있었다. 예전에 등록해놓고 관련 서비스가 활성화되지 않아서 방치해 놓고 있었는데 최근에 다시 결제 모듈이 필요해서 들어가보니 뭐가 잔뜩 바뀌고 전에 신청해놓은것도 다 사라져서 결국 pg사 연동부터 다시 해야했다...

이번에는 일반결제+정기결제를 해야했는데 어차피 새로 pg사 연동부터 다 새로 해야하는거.. 굳이 아임포트 안쓰고 한 pg사꺼 써서 커스텀을 더 풍부하게 해보자 하는 생각으로 아임포트를 버렸다.

그리고 선택한 pg사는 토스페이먼츠.
큰 이유는 없다. 그냥 결제 모듈 ui가 깔끔해서임.
기존에는 kg이니시스를 사용했는데, 뭔가 내 과거기억/경험상 kg이니시스의 ui가 상당히 촌스럽다는 어떤 편견아닌 편견이 있었다...

주로 쓰는 곳도 약간 업데이트가 느린 정부기관에서 쓰는 느낌적인 느낌....ㅎ

쨌든 상당히 단순한 이유로 토스페이먼츠를 선택했다.

1-1. 토스페이먼츠 가입 및 신청

https://www.tosspayments.com/


실 운영을 위해서는 가입을 하고 결제 서비스 신청하기를 눌러 폼을 제출한다.

1-2. 테스트


이전에 개발단에서 테스트를 할 땐 결제 서비스 신청까지는 할 필요없다.
바로 개발자센터로 들어간다.

https://docs.tosspayments.com/guides/overview
사실 개발자 문서에 이미 너무나 친절하게 잘 올라와있다.

  1. 다음 키들을 환경변수에 등록한다.
//.env.dev
toss_payments_client_key = "클라이언트 키"
toss_payments_secret_key = "시크릿 키"
  1. 패키지를 설치한다.
yarn add @tosspayments/payment-sdk
  1. 결제를 한다.
    일단 결제창을 띄우는 버튼을 만든다.
// PaymentButton.tsx
import React from 'react';
import { loadTossPayments } from '@tosspayments/payment-sdk';

const PaymentButton = () => {
  const clientKey = process.env.toss_payments_client_key;
  const originUrl = process.env.originUrl; //환경변수에 등록해야함. dev의 경우 "http://localhost:3000" 이 되겠고, prod의 경우 도메인이 되겠지
  const payment = () => {
    loadTossPayments(clientKey).then(tossPayments => {
      tossPayments.requestPayment('카드', {
        amount: ${결제할 금액},
        orderId: '${상품 주문번호}', // 대충 날짜를 조합하든가 uuid를 사용하는 방법도..
        orderName: '${상품이름}',
        customerName: '${주문자 이름}',
        successUrl: "https://{originUrl}/success", // ${결제 성공 후 redirect할 url}
        failUrl:"https://{originUrl}/fail", //  ${결제 실패한 경우 redirect할 url}
      })
      .catch(function (error) {
        if (error.code === 'USER_CANCEL') {
          // 결제 고객이 결제창을 닫았을 때 에러 처리
        } else if (error.code === 'INVALID_CARD_COMPANY') {
          // 유효하지 않은 카드 코드에 대한 에러 처리
        }
      })
    })
  }
  
  return <button onClick={payment}>결제하기</button>
}

export default PaymentButton;
  1. 결제 실패/성공한 경우 페이지를 구현한다.
    4-1. 결제를 실패한 경우
    결제에 실패한 경우, 토스페이먼츠는 파라미터를 붙여서 다음과 같은 url로 리다이렉트된다.
https://{originUrl}/fail?code={ERROR_CODE}&message={ERROR_MESSAGE}&orderId={ORDER_ID}
// 결제실패.tsx
import React from 'react;
import { useRouter } from 'next/router'

const PaymentFailContainer = () => {
	const router = useRouter();
    const { code, message } = router.query;
	return (
    	<div>
          <div>결제 실패했으니 다시 시도하슈;</div>
          <div>{code}</div>
          <div>{message}</div>
        </div>
    )
}

대충 요런 느낌으로.. 보여준다.

4-2. 결제에 성공한 경우
결제에 성공한 경우 요런 파라미터를 포함해서 리다이렉트 된다.

https://{ORIGIN}/success?paymentKey={PAYMENT_KEY}&orderId={ORDER_ID}&amount={AMOUNT}
// 결제성공.tsx
import React, { useEffect } from 'react;
import { useRouter } from 'next/router'

const PaymentSuccessContainer = () => {
	const router = useRouter();
    const { paymentKey, orderId, amount } = router.query;
    useEffect(()=>{
    	const init = async() => {
        	// ... 대충 결제에 성공하면 백단에 정보 저장하는 API
        }
    },[])
	return (
    	<div> 
          <div>결제 성공</div>
        </div>
    )
}

일반 결제는 금방 구현할 수 있다.

사실 이전에 아임포트튼 정기결제 api를 제공해서 뭔가 당연하게 정기결제도 api로 쉽사리 받을 수 있을거라 생각했는데..
토스페이먼츠만 사용하는 경우 별도로 서버에서 처리해주는 과정이 필요했고, 일반결제보다는 처리해야할 작업이 많았다..

to be continued...... 2. 정기결제

덧붙임말) 벨로그에서 코드를 작성하고 테스트 별도로 해보지 않아 높은 확률로 잘못쓴 코드가 있을 수 있으니 오류가 있는 경우 알려주시면 감사하겠습니다. (_ _)

profile
프론트 개발자

2개의 댓글

comment-user-thumbnail
2023년 5월 6일

덕분에 좋은 공부가 되고 있습니다.
수고로움을 감수하시고 작성해주신 포스팅 덕분에 저의 삽질이 줄었습니다.
거듭 감사드립니다.

1개의 답글