수익화 ·
결제 완료 화면과 웹훅과 환불 상태를 따로 확인하는 법
먼저 답부터
결제 성공 화면은 사용자의 브라우저가 특정 주소에 도착했다는 표시일 뿐 최종 결제 증거가 아닙니다. 서버는 결제 제공사의 상태와 서명된 웹훅을 확인해 주문을 처리하고 같은 사건을 중복 반영하지 않아야 합니다. 환불도 요청, 처리 중, 성공, 실패 상태를 나누고 실제 완료를 확인해야 합니다.
결제 버튼 뒤에 “완료” 화면이 보이면 주문도 끝났다고 생각하기 쉽습니다. 그러나 사용자가 주소를 직접 열거나, 화면으로 돌아오기 전에 창을 닫거나, 결제 수단이 나중에 결과를 확정하는 경우가 있어 화면만으로 상품을 보내면 안 됩니다.
택배 접수 화면과 물류센터의 인계 확인이 다른 것처럼 결제 화면과 서버 상태도 다릅니다. 환불 역시 버튼을 눌렀다는 사실과 은행이 돈을 돌려준 결과를 나누어 봐야 합니다.
성공 화면은 사용자 안내이지 결제 장부가 아니다
결제 성공 화면은 브라우저가 성공 주소로 이동해 사용자에게 다음 행동을 안내하는 화면입니다. 주문 번호와 처리 중 상태를 보여 줄 수 있지만 상품 제공 여부를 결정하는 유일한 근거가 되어서는 안 됩니다.
Stripe는 고객이 결제 뒤 화면을 떠날 수 있으므로 브라우저 쪽에서 주문 이행을 처리하지 말고 서버가 웹훅으로 상태 변화를 받도록 안내합니다. 화면에는 “확인 중”과 “완료”를 실제 서버 상태에 맞춰 표현합니다.
결제 객체는 여러 상태를 거쳐 바뀐다
결제 의도는 PaymentIntent, 즉 한 번의 결제 흐름을 생성부터 필요한 추가 인증과 성공 또는 실패까지 추적하는 서버 객체입니다. 카드 인증이 더 필요하거나 결제 수단을 다시 받아야 하는 상태가 있을 수 있습니다.
주문 created
결제 pending
결제 paid
제공 fulfilled
환불 refund_pending 또는 refunded
이것은 서비스 내부에서 쓸 수 있는 단순 예시입니다. 제공사의 실제 상태를 그대로 덮어쓰기보다 내부 주문 상태와 연결 규칙을 문서로 정합니다.
웹훅은 서버가 상태 변화를 받는 통로다
웹훅은 외부 서비스가 사건이 생겼을 때 내 서버의 약속된 주소로 보내는 HTTPS 요청입니다. 서버는 전송된 본문과 서명 헤더를 제공사 문서의 방식으로 검증하고, 결제 ID와 주문을 연결한 뒤 처리 결과를 기록합니다.
같은 웹훅은 네트워크 재시도로 여러 번 올 수 있습니다. 사건 ID나 결제 ID와 처리 종류를 고유하게 저장해 이미 끝낸 제공이나 메일을 다시 실행하지 않도록 합니다. 응답이 늦으면 전달이 반복될 수 있으므로 오래 걸리는 작업은 대기열로 넘기고 먼저 안전하게 접수합니다.
환불 요청과 실제 완료를 나눈다
환불은 결제를 원래 결제 수단으로 돌려보내는 별도 작업입니다. 요청 직후 처리 중일 수 있고 결제 수단에 따라 추가 정보가 필요하거나 실패할 수도 있습니다. Stripe 문서도 Refund 객체의 상태와 실패 사건, 원래 결제 수단으로 돌아가는 규칙을 설명합니다.
- 환불 요청자와 주문을 권한으로 확인합니다.
- 환불 가능한 금액과 이미 환불한 금액을 다시 계산합니다.
- 고유한 작업 식별자로 중복 요청을 막습니다.
- 제공사의 환불 객체와 상태를 저장합니다.
- 웹훅이나 상태 조회로 성공과 실패를 갱신합니다.
- 사용자에게 요청 시각과 현재 상태와 문의 경로를 보여 줍니다.
부분 환불은 통화의 최소 단위와 세금, 쿠폰, 배송비 규칙이 얽힐 수 있습니다. 단순히 화면 숫자를 빼는 방식으로 처리하지 않습니다.
비밀키와 금액 변경은 서버 경계 안에 둔다
결제 비밀키는 브라우저 코드, 공개 저장소, AI 채팅, 로그에 넣지 않습니다. 결제 금액과 상품 권한은 사용자가 보낸 화면 값을 그대로 믿지 않고 서버의 상품 자료로 다시 계산합니다. 웹훅 서명 검증도 끄지 않습니다.
모르는 결제 취소나 환불 명령을 운영 계정에서 시험하지 마세요. 테스트 모드 표시, 대상 주문, 통화, 금액, 이미 처리된 상태, 되돌릴 수 있는지부터 확인합니다. 실결제와 환불은 금전 이동이므로 자동화보다 감사 기록과 좁은 권한이 먼저입니다.
주문 조회 화면은 사용자와 운영자에게 같은 정보를 그대로 보여 줄 필요가 없습니다. 사용자는 주문 번호, 현재 상태, 다음 예상 행동, 문의 경로를 보면 되고, 운영자는 제공사 결제 ID, 웹훅 사건 ID, 마지막 처리 시각을 권한 안에서 확인합니다. 내부 오류와 비밀 헤더를 사용자 화면에 노출하지 않습니다.
처리 실패도 끝 상태로 숨기지 않습니다. 결제는 성공했지만 상품 제공이 실패했다면 재처리 가능한 작업으로 남기고, 이미 제공됐는지 먼저 확인합니다. 환불 웹훅이 늦거나 실패했을 때도 새 환불을 즉시 만들기보다 기존 환불 객체를 조회해 중복 금전 이동을 막습니다. 모든 상태 변경에는 누가 언제 무엇을 근거로 바꿨는지 기록합니다.
오늘 바로 해볼 작은 실습
돈을 움직이지 않고 종이에 상태표를 그립니다.
- 주문 생성부터 제공 완료까지 상태를 다섯 칸으로 나눕니다.
- 성공 화면이 닫혀도 서버가 확인할 근거를 적습니다.
- 같은 웹훅이 두 번 왔을 때 한 번만 할 행동을 표시합니다.
- 환불 요청과 환불 성공 사이의 상태를 추가합니다.
- 사용자에게 보여 줄 문장과 내부 로그 문장을 분리합니다.
- 비밀키, 카드 정보, 개인정보가 들어갈 칸을 모두 제거합니다.
완성된 표에서 화면, 서버 결제 상태, 상품 제공, 환불을 각각 가리킬 수 있으면 첫 설계가 된 것입니다. 한 칸을 바꾸면 어떤 다음 행동이 가능한지도 함께 적어야 운영 중 중복 제공과 성급한 완료 안내를 줄일 수 있습니다.
확인한 자료
- Payment status updates — Stripe Docs
- Refund and cancel payments — Stripe Docs
함께 읽기
- 페이지뷰와 완료 이벤트로 제품의 쓸모를 구분하는 법
페이지뷰는 페이지가 열린 횟수를 알려 주지만 사용자가 목적을 끝냈는지는 말해 주지 않습니다. 이벤트는 검색, 저장, 가입 완료처럼 의미 있는 행동이 일어난 순간을 이름과 필요한 정보로 기록합니다. 시작과 완료와 실패를 같은 흐름에서 확인해야 유입 증가와 제품 가치 증가를 구분할 수 있습니다.
- 크롤링과 색인과 표준 URL을 도서관 일처럼 구분하기
크롤링은 검색 시스템이 URL을 찾아 페이지를 읽는 과정이고, 색인은 읽은 내용을 분석해 검색용 목록에 저장하는 과정입니다. 표준 URL은 비슷한 페이지 여러 개 중 대표로 삼길 바라는 주소를 알리는 신호입니다. 세 단계는 서로 다르므로 페이지 접근, 원문 내용, 선택된 대표 주소와 검색 상태를 각각 확인해야 합니다.
- 광고와 구독과 한 번 결제를 작은 가게처럼 비교하는 법
광고는 이용자의 주의를 광고주에게 연결해 수익을 얻고, 구독은 가치가 반복되는 동안 정기 결제를 받으며, 1회 결제는 한 번 완성되는 결과에 값을 받는 방식입니다. 인기만 보고 고르지 말고 사용자가 가치를 얻는 빈도, 서비스의 반복 비용, 가격과 해지·환불을 분명히 설명할 수 있는지를 함께 비교해야 합니다.