본문 바로가기

문제 해결, 기술 비교/실무 업무 회고

NICE API 일시불 취소 개발하기

728x90
반응형

개요


 기존에 NICE API로 일시불 결제는 구현되어 있지만 모든 취소는 상담원을 통해서만 가능했습니다. 업무시간(8:30~19:00) 이외에 상담원이 부재하여 바로 취소를 할 수 없어서 NICE API 일시불 취소를 개발했습니다. 

 

 

NICE API 일시불 취소 순서도


취소 요청부터 취소 완료 후 알림톡 발송까지의 과정입니다.

 

일시불 취소 순서도

 

 

순서도 설명


  • 본인이 요청한 주문인가?

 취소의 조건으로 본인이 요청한 주문인지, 취소가 가능한 상황인지 확인합니다. 추소 요청 주문번호에 따른 결제자 아이디가 현재 로그인 한 아이디인지 확인합니다. 또한 상품 준비 중(배송 준비 중) 상태를 기준으로 이전은 즉시 취소가 가능하며 그렇지 않다면 취소 접수를 통해 상담원에 안내합니다.

 

 

  • 취소 가능한 상태인가?

 중복 취소를 방지하기 위해서 취소 가능한 상황에는 락을 겁니다. 결제 정보에서 주문 건을 기준으로 락을 걸기 때문에, 대기가 길지 않습니다. 결제 정보 전체 조회 및 상세 결제 정보 조회가 된 상태에서 취소를 시도하기 때문입니다. 다른 기기에서 중복 로그인해서 결제 정보를 보는 경우에만 영향을 미치며, 심지어 취소 로직은 수초 내로 이루어지기 때문에 대기의 위험이 적습니다. Oracle의 SELECT ~ FOR UPDATE를 활용했습니다.

 

SELECT ~ FOR UPDATE

 

 

  • 취소 로직 실행

주문상태 변경, 배송상태 변경, 환불정보 등록, 입금내역 변경, 재고 증가를 먼저 처리하고 PG 결제 취소가 되도록 합니다. PG 결제 취소가 먼저 된다면 이후 트랜잭션 작업이 실패하는 경우 PG 결제 취소 로직이 예상하는대로 롤백되지 않습니다. 외부 API를 호출하여 작업하기 때문입니다. 심지어 일시불 결제의 경우에는 보상 트랜잭션으로 금액 환불이 바로 가능하지만 일시불 취소는 보상 트랜잭션이 존재하지 않습니다. 따라서, PG 결제 호출을 마지막에 두어 앞 비지니스 로직이 모두 정상적으로 처리되고 나서 외부 API를 호출하여야 안전합니다.

 

 결제 취소와 DB 저장 및 수정 로직을 하나의 트랜잭션으로 묶습니다. 하나의 물리 트랜잭션 안에 5개의 논리 트랜잭션이 있습니다. 참고로 PG 결제에서 통신 실패나 환불 완료 건은 상태코드로 응답받아 예외나 롤백 작업이 없으므로 강제로 롤백할 수 있는 수단을 만들어야 합니다.

 

6개의 논리트랜잭션으로 이루어진 무리트랜잭션

 

 

트랜잭션 내에서 변경 사항은 다음과 같습니다.

  • 주문상태 변경 - 결제완료 상태에서 취소로 변경합니다.
  • 배송상태 변경 - 배송 준비중 상태에서 취소로 변경합니다.
  • 환불정보 등록 - 환불 테이블에 주문번호, 온라인 결제 번호, 입금 번호, 결제자 번호 등을 넣습니다.
  • 입금내역 변경 - 승인정보(승인취소) 및 청구 입금을 생성하여 입금내역 갱신합니다.
  • 재고 증가- 해당 상품의 재고를 1개 증가시킵니다.

 

 트랜잭션 전파를 사용해 위의 과정 중에 하나라도 롤백이 결제 취소 요청의 모든 작업이 롤백되도록 합니다. 기본 전략인 REQUIRED를 사용하면 내부 논리 트랜잭션에서 롤백이 발생하는 경우 다른 논리 트랜잭션의 커밋 여부와 상관없이 물리 트랜잭션이 모두 롤백이 됩니다. 기본 PG 결제 취소 요청은 통신 실패나 환불 완료 건에 아래와 같이 롤백이 발생하지 않습니다.

 

NICE 취소 API 일부

 

 따라서 try ~ catch에서 별도로 throw new RuntimeException(e)을 발생시켜 롤백을 강제합니다. 5개의 논리 트랜잭션이 모두 정상 처리되더라도 PG 결제 취소 요청이 실패하는 경우 5개의 논리 트랜잭션이 모두 롤백되어야 하기 때문입니다.

 

 

  • 취소 알림톡 발송

 알림톡의 경우에는 트랜잭션으로 묶지 않고 후처리 합니다. 알림톡에 문제가 발생한 것은 내부 비지니스에서 발생한 예외가 아닙니다. 즉, 별도의 트랜잭션을 만들어 결제 취소 로직이 알림톡 전송 실패 롤백에 영향을 받지 않도록 합니다. 또한 알림톡은 전송 실패 시 재전송하도록 하고 그래도 실패하면 로그를 남깁니다.

 

 

  • 기타

 배송비는 항상 0원이고 포인트가 따로 없으므로 해당 처리는 없습니다.

 

NICE API는 공식문서에 사용 방법이 잘 나와 있습니다.

JSP, Spring을 이용하여 코드를 짰으며 취소 API 관련 자료 링크는 아래에 있습니다.

https://developers.nicepay.co.kr/manual-cancel.php

728x90
반응형