포스트

결제 로직 설계1

결제 로직 설계1

결제 로직을 어떻게 구현할 수 있을지를 고찰해보고자 합니다.

결제 단계

인터넷에서 상품을 주문하는 과정을 단순화해서 생각해봅시다.

  1. 상품을 고르고, 수량을 입력한 후 [주문하기] 버튼을 누릅니다.
  2. 결제 팝업이 뜬 후, 결제를 진행합니다.
  3. 결제가 완료되면, 완료 창으로 redirect 됩니다.

구매자 입장에서는, 상품 주문하기 버튼을 클릭하고, 결제 창을 통해 결제를 진행하면, 상품 구매가 완료됩니다. 판매자(쇼핑몰 운영자) 입장에서는 어떨까요?

  1. 상품 주문에 대한 결제 요청이 들어오면, PG 사 api 를 호출합니다.
  2. PG 사 api 의 호출 인자에는 어떤 상품을, 얼마의 금액으로, 어떤 결제 수단으로 결제할지 와 같은 정보들을 담아서 요청합니다.
  3. pg 사로부터 결제가 완료됐다는 successurl 이 호출되고, 결제를 요청한 페이지에서 해당 이동을 감지해서 적절한 화면을 띄워줍니다.

pg 사 api 호출은 이런 형태일 것입니다. 토스 페이먼츠를 참고했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tossPayments
.requestPayment('카드', {
  // 결제수단 파라미터 (카드, 계좌이체, 가상계좌, 휴대폰 등)
  // 결제 정보 파라미터
  // 더 많은 결제 정보 파라미터는 결제창 Javascript SDK에서 확인하세요.
  // https://docs.tosspayments.com/reference/js-sdk
  amount: 100, // 결제 금액
  orderId: '4O6TcGH5l8FxyTBhsfTEq', // 주문번호(주문번호는 상점에서 직접 만들어주세요.)
  orderName: '테스트 결제', // 구매상품
  customerName: '김토스', // 구매자 이름
  successUrl: 'https://docs.tosspayments.com/guides/payment/test-success', // 결제 성공 시 이동할 페이지(이 주소는 예시입니다. 상점에서 직접 만들어주세요.)
  failUrl: 'https://docs.tosspayments.com/guides/payment/test-fail', // 결제 실패 시 이동할 페이지(이 주소는 예시입니다. 상점에서 직접 만들어주세요.)
})

결제와 csrf 공격

그렇다면 결제를 구현하기 위해서는 클라이언트에서 pg 사에 적절한 api 를 호출하고, 해당 api 의 결과만 기다리면 될까요? 아닙니다. 해당 방법으로만 구현한다면 CSRF 공격에 취약하기에, 결제 정보를 내 서버와 pg 사 서버 간에 동기화를 할 수 있어야 합니다.

csrf 란 웹 보안 공격의 일종으로, 인증된 사용자의 웹 애플리케이션을 사용하여 악의적인 요청을 보내는 공격 기법입니다. 이 공격은 사용자가 악의적인 웹 사이트를 방문하거나 악성 이메일을 통해 트리거될 수 있습니다.

예를 들어, 사용자가 인증된 상태에서 온라인 상점에서 결제를 진행하는 경우, 해당 결제 요청은 사용자의 세션 정보를 이용하여 서버에 전송됩니다. 이때, 악의적인 웹 페이지나 악성 이메일을 통해 사용자의 브라우저가 CSRF 공격자의 요청을 수행하도록 유도될 수 있습니다. 이러한 공격에서는 사용자가 의도하지 않은 결제를 실행하거나 결제 정보가 탈취될 수 있습니다.

결제 상태 관리

따라서, 우리는 결제 정보를 서버에서 관리해야 합니다. 결제 정보를 서버에서 관리 하기 위해서 서버에서는 주문 엔티티를 생성하고, 해당 주문에는 주문 코드와 csrf 토큰을 발급할 수 있습니다.
주문 발급 api 를 내 서버에서 처리한다면 어떤 로직으로 결제를 처리할 수 있을까요?

  1. 결제 버튼 클릭
  2. 주문 발급 api 호출
  3. 주문 발급 완료
  4. 클라이언트에서 pg 호출
  5. pg 팝업 오픈 및 결제 처리
  6. 결제 결과 redirect


주문 발급 api 를 호출하고, pg api 를 호출할 때 전달해야 하는 정보는 어떤걸까요? 가장 먼저 결제 금액이 들어갈 것이고, csrf 공격을 방지하기 위한 csrf 토큰도 포함될 것입니다. 이 토큰을 통해서 pg 에서 관리한 주문과 우리 서버에서 관리하는 주문의 동등성을 확인할 수 있습니다.
우리는 pg 에서 어떻게 결제가 처리되고 있는지를 모릅니다. 따라서 자체적으로 결제 단계에 따른 주문의 상태 관리를 해야 합니다. 우리가 생성한 주문은 pg 사와의 api 호출에 따라서 다음과 같은 상태를 가질 수 있을 것입니다.

  • prepay : pg api 호출 전
  • inprogress : pg api 호출 후, pg 처리 진행
  • cancel / success / fail : pg api 호출 결과
  • complete : success 이후, pg api 호출 결과에 대한 주문 처리 완료 ack 전송

주문 상태를 관리함으로서 pg api 와의 연동을 비동기적으로 처리하며, pg 의 결제 단계에 덜 의존할 수 있습니다.

재고 관리

그렇다면 주문과 연동된 재고 관리는 어떻게 진행해야 할까요? 다음 포스트에서 이어서 고려해보겠습니다.

다음에 다룰 내용..
재고 관리 - 배치
재고 관리 - Queue
재고 관리 - 코드

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.