개발 slecs

결제 수수료 정산을 지연 차감 방식으로 전환해 환불 흐름 단순화

목차

배경

결제 플랫폼에서 파트너에게 부과되는 수수료를 결제 즉시 차감하는 기존 로직이 있었음. 문제는 이커머스 특성상 결제 후에도 환불/취소가 빈번하게 일어난다는 점. 즉시 차감해버리면 환불이 들어왔을 때 수수료를 다시 환원해야 하는데, 이 역방향 흐름이 곳곳에서 깨지고 있었음.

흐름 재설계

결제대행사에서 정산 데이터가 넘어오는 시점을 기준으로 상태를 다시 잡았음.

단계 상태 시점
결제 발생 PENDING 즉시 3건 생성
가상계좌 확정 COMPLETED 결제 +2시간
카드 확정 COMPLETED 결제 +3일
홀딩 중 환불 CANCELLED 잔액 변동 0

핵심은 PENDING 단계에서 잔액에 손대지 않는다는 것. COMPLETED로 넘어가는 순간에만 파트너 잔액이 움직임. 환불이 홀딩 중 들어오면 그냥 CANCELLED로 마킹하고 끝.

구현하면서 막힌 지점

  • 3건 동시 생성: 충전수수료, 결제수수료, 판매대금이 한 트랜잭션에서 같이 PENDING으로 박혀야 했음. 하나라도 빠지면 정산 검수 때 차이남.
  • 상태 전환 단일 진입점: 곳곳에서 상태를 바꾸지 못하게 단일 메서드로 막아두고, 잔액 차감/지급도 그 안에서만 호출되도록 묶었음.
  • 마진 계산: 가맹점이 1.0% 부담, 총판이 0.8%면 차액 0.2%가 총판 수익. 위로 갈수록 요율이 낮아지고 차액이 각 상위 계층의 수익으로 떨어지는 구조라, COMPLETED 시점에 계층별로 분배 레코드를 같이 박았음.

핵심 쿼리 한 토막

UPDATE charge_history
   SET status = 'COMPLETED',
       confirmed_at = NOW()
 WHERE order_id = #{orderId}
   AND status = 'PENDING'

AND status = 'PENDING' 이 진짜 핵심. 이미 CANCELLED로 넘어간 건은 절대 COMPLETED로 못 가게 막았음. 동시성 들어와도 한 번만 차감되도록.

회고

  • 즉시 차감 → 지연 차감으로 바꿨더니 환불 흐름이 단순해짐. 역방향 보정 코드를 통째로 들어냈음.
  • PENDING/COMPLETED/CANCELLED 3상태로 줄이니 정산 보고서가 깔끔해짐. 검수 담당자가 한 번에 이해함.
  • 가장 위험했던 건 기존 데이터 마이그레이션. 운영 중인 미정산 건들이 PENDING으로 잡혀야 했는데, 일부가 이미 차감된 상태라 백필 스크립트를 별도로 짰음.
  • 즉시 차감의 유혹은 코드량이 적어서 생기는 듯함. 시간축이 들어가는 도메인은 결국 상태머신으로 가는 게 답.
  • 홀딩 기간을 결제 수단별로 동적 설정하는 화면 붙이는 건 다음 작업으로 미뤄둠.

다음

댓글 0

첫 댓글 달아줘.