블로그
테라코타색 탁자 위, 모래시계와 동전 옆에 휘어진 영수증 띠.

2026년 8월 5일4분 분량Администратор

주문, 결제, 지급: 하나의 구매에 담긴 세 가지 이야기

취소 후 늦게 도착한 결제 확인, 오래된 화면, 부분 환불을 살펴봅니다. 실무 화면에 필요한 상태와 제약 조건을 정리했습니다.

결제완료 주문을 출고했는데 은행 지급은 아직 받지 못했을 수 있습니다. 돈의 일부를 환불하면서도 최초 결제 사실은 남겨 둘 수 있습니다. 문제는 이 모든 것을 초록색 표시 하나에 담으려 할 때 시작됩니다. 실무 화면에는 서로 연결된 세 개의 이력과, 한 이력이 다른 이력을 슬그머니 덮어쓰지 못하게 하는 규칙이 필요합니다.

운영 관리에는 연결된 세 가지 이력을 두는 것이 편리합니다. 상거래 주문, 결제 시도, 그리고 은행 계좌로 가는 자금 이동입니다. 한 화면에 함께 보여 줄 수는 있지만 "결제됨 / 미결제"라는 스위치 하나로 줄여서는 안 됩니다.

하나의 구매, 세 개의 시점

가상의 예시입니다. 한 쇼핑몰이 80유로짜리 세트를 판매합니다. 월요일 10:00에 주문이 생성됩니다. 10:02에 PG사가 결제를 확인하지만, 이벤트는 10:04에 쇼핑몰 시스템에 도착합니다. 화요일에 상품이 출고됩니다. 가상의 계약 조건에 따라 자금은 수요일에 지급 가능해지고, 목요일의 정기 지급에 포함됩니다.

화요일에 주문은 "결제됨"과 "발송됨" 상태를 동시에 갖지만, 연결된 지급은 아직 실행되지 않았습니다. 모순은 없습니다. 오류는 팀이 은행 입금이 없다는 이유로 80유로를 다시 청구하거나 구매자에게 새 결제를 요구할 때 생깁니다.

이제 출고 후 20유로의 부분 환불을 더해 봅시다. 학습용 모델에서 결제 금액은 80유로로 남고, 환불 금액은 20유로, 환불 후 잔액은 수수료 전 60유로입니다. 최초 결제를 60이라는 숫자로 덮어쓰면 곤란합니다. PG사 리포트와 대사할 때 필요한 이력이 사라지기 때문입니다.

주문에는 고유한 생애 주기가 있다

주문은 상품과 판매자의 의무에 대한 질문에 답합니다. 생성됨, 접수됨, 준비 중, 발송됨, 완료됨, 취소됨입니다. 명칭은 사업자가 직접 정합니다. 주문은 결제 후 취소되거나, 일부만 이행되거나, 여러 번에 나눠 결제될 수 있습니다. 따라서 주문 취소는 작업 목록에서 행을 숨기는 데 그치지 말고, 결제에 미치는 영향을 점검하는 절차를 시작해야 합니다.

결제는 다른 질문에 답합니다. 돈을 내려는 특정 시도에 무슨 일이 있었는가입니다. 카드 결제에서는 승인과 청구가 별도 단계일 수 있습니다. 예를 들어 Adyen 문서는 승인, capture, settlement를 구분합니다. 다른 PG사에서는 명칭과 상태 구성이 다를 수 있습니다.

PG사에는 결제 과정 전체를 위한 별도 객체가 있을 수도 있습니다. Stripe PaymentIntent는 그런 과정의 상태를 저장하고 결제 시도들을 연결합니다. 자체 시스템을 설계할 때는 어떤 식별자가 주문을, 어떤 식별자가 시도를, 어떤 식별자가 최종 금융 거래를 나타내는지 파악하는 것이 중요합니다.

자동으로 검증되는 제약 조건을 정하라

몇 가지 내부 무결성 조건부터 시작하는 것이 편리합니다. 하나의 이벤트 식별자가 이행을 두 번 실행해서는 안 됩니다. 확인된 환불은 원 결제와의 연결을 유지합니다. 모든 출고에는 유효한 결제 확인이나 명시적으로 승인된 상업적 예외가 있어야 합니다. 금액과 통화는 정해진 규칙으로 비교하고, 불일치는 별도 대기열로 보냅니다.

"생성 → 성공 → 종료"라는 상태 순서만으로 모든 로직을 표현하려 하지 마세요. 주문이 10:03에 취소됐는데, 10:02에 발생한 결제 확인을 10:04에 받았다고 해 봅시다. 결제는 실제로 이루어졌고, 상거래 주문도 실제로 취소됐습니다. 제안하는 처리 결과는 두 사실을 모두 보존하고, 자동 출고를 막고, 합의에 따른 정리 작업을 여는 것입니다. 여기서 환불은 아직 승인하고 실행해야 하는 일이며, 주문이 취소됐다고 해서 이미 이루어진 것으로 볼 수 없습니다.

직원 화면에는 대기 사유를 보여 주세요. "결제 확인됨, 취소 후 이행 중지." 이것이 단순한 "오류"보다 많은 정보를 줍니다. 그다음에는 담당자와 허용된 조치가 필요합니다. 구매자에게는 더 짧은 설명을 보여 줄 수 있지만, 같은 기록에 근거해야 합니다.

조사를 살리는 필드

  • 내부 주문 번호와 연결된 모든 결제의 식별자.
  • 최초 금액과 통화, 확인된 청구액과 환불액.
  • PG사의 원래 상태와 함께, 운영자가 이해하기 쉬운 자체 상태.
  • 출처에서 이벤트가 발생한 시각과 우리 시스템이 받은 시각.
  • 지급 번호, 그 구성, 예상 일자, 그리고 나중에 생길 은행 입금 확인.

자금 사용 가능일과 지급 발송일도 구분하는 것이 좋습니다. Stripe의 지급 문서에서는 송금 일정과 돈이 사용 가능해지기까지의 기간이 분리되어 있습니다. 다른 상품이라면 주말, 마감 시각, 초기 지연을 포함한 그 상품의 규칙을 확인하세요.

오래된 데이터 스냅숏으로 점검하기

화면은 항상 어느 시점의 데이터를 보여 줍니다. 그래서 상태 옆에 마지막 확인 시각과 출처를 함께 두는 것이 유용합니다. 운영자가 20분 전에 카드를 열었다면, 금전과 관련된 조치는 현재 상태를 다시 확인해야 합니다. 그렇지 않으면 두 직원이 같은 오래된 화면을 보고 각자 옳은 결정을 차례로 내릴 수 있습니다.

테스트에 이런 학습용 시나리오를 추가하세요. 첫 번째 교대조가 환불을 만들고, 두 번째 교대조는 아직 예전 화면을 보며 같은 환불을 만들려고 합니다. 시스템의 기대 동작은 미리 정해 두어야 합니다. 조용히 추가 거래를 만들지 말고, 이미 시작된 조치와 그 식별자, 상태를 보여 주는 것입니다.

수정 이력은 원래 이벤트와 따로 보관하세요. 그러면 내일 실제 순서와, 결정 당시 직원이 알고 있던 내용을 모두 복원할 수 있습니다. 늦게 도착한 확인을 분석할 때 특히 유용합니다. 오늘 알게 된 결과가 어제 내린 조치의 평가를 왜곡해서는 안 됩니다.

수동 결정도 이력을 남긴다

반복된 알림이 출고를 하나 더 만들어서는 안 됩니다. 늦게 도착한 알림이 더 최신 데이터를 흔적 없이 덮어써서도 안 됩니다. Adyen은 중복 가능성과 이벤트의 시간 순서를 고려해야 할 필요성을 설명합니다. 사용하는 API의 규칙에 따라 이런 시나리오를 점검하세요.

마지막으로, 운영자가 수동으로 할 수 있는 전환을 정하세요. "결제됨으로 변경" 버튼보다는 확인 근거의 참조를 필수로 하는 별도의 검토 절차가 더 유용합니다. 이 절차는 결정 사유, 작성자, 시각을 보존합니다. 그래야 예외가 눈에 보이고 검증 가능한 상태로 남습니다.

별도 대기열에는 주문 없는 결제, 확인 없는 주문, 처리되지 않은 환불, 은행 매칭이 없는 지급을 두세요. 각 항목에는 대기 기간, 담당자, 다음 단계가 필요합니다.

결제 확인을 받기 전에 취소된 주문 하나로 모델을 점검하세요. 시스템은 두 사실을 모두 보존하고, 정리 작업을 보여 주며, 재청구도 자동 출고도 실행하지 않아야 합니다. 이런 테스트는 화면의 색상 변경보다 상태의 의미를 더 잘 검증합니다.

출처

  1. 1.docs.adyen.com/account/payments-lifecycle
  2. 2.docs.stripe.com/api/payment_intents
  3. 3.docs.stripe.com/payouts
  4. 4.docs.adyen.com/development-resources/webhooks/handle-webhook-events

댓글 · 0

아직 댓글이 없습니다 — 첫 댓글을 남겨 보세요.

로그인 · 댓글을 남기려면 로그인하세요.