Skip to content

Split View: 결제 시스템 설계 입문: 결제 플로우·PG·카드망·정산

|

결제 시스템 설계 입문: 결제 플로우·PG·카드망·정산

들어가며 — 결제 버튼 뒤의 세계

사용자가 "결제하기" 버튼을 누르는 순간은 겉보기에는 1초도 안 걸립니다. 하지만 그 1초 안에서, 카드 번호는 대여섯 개의 회사와 최소 두 개의 결제 네트워크를 지나 발급 은행까지 다녀옵니다. 그리고 진짜로 돈이 계좌에서 계좌로 옮겨지는 것은 그 순간이 아니라 며칠 뒤입니다.

결제는 다른 어떤 시스템보다도 "틀리면 안 되는" 시스템입니다. 검색 결과가 한 건 틀리면 사용자는 불편할 뿐이지만, 결제가 한 건 틀리면 누군가는 돈을 잃습니다. 그래서 결제 시스템에는 정합성(consistency), 멱등성(idempotency), 감사 가능성(auditability)이 다른 무엇보다 앞섭니다.

이 글은 결제 시스템을 처음 설계하거나 이해하려는 엔지니어를 위한 지도입니다. 승인과 매입과 정산이 어떻게 다른지, 그 사이에 어떤 주체들이 끼어 있는지, 3-D Secure와 차지백은 무엇인지, 그리고 대사와 멱등성과 PCI-DSS가 왜 결제의 상수인지를 짚겠습니다. 결제에는 보안이 필수이므로, 인증과 토큰의 기초가 궁금하다면 이 사이트의 인증·보안 실습실을, 아래에서 자주 등장하는 응답 코드의 의미가 헷갈린다면 HTTP 상태 코드 도감을 함께 참고하세요.

다섯 명의 등장인물

카드 결제를 이해하는 첫걸음은 "누가 무엇을 하는가"를 아는 것입니다. 한 번의 카드 결제에는 최소 다섯 주체가 등장합니다.

  • 가맹점(merchant): 물건이나 서비스를 파는 쪽입니다. 우리가 만드는 서비스가 여기에 해당합니다.
  • PG / PSP(payment gateway / payment service provider): 가맹점과 복잡한 금융망 사이를 이어 주는 중개자입니다. Stripe, 토스페이먼츠, Adyen 같은 회사입니다. 카드 정보를 안전하게 받고, 아래의 여러 주체와 통신하는 일을 대신해 줍니다. 한국에서는 흔히 "PG사"라 부릅니다.
  • 매입사(acquirer / acquiring bank): 가맹점을 대신해 카드 대금을 "매입"하는 은행입니다. 가맹점의 정산 계좌에 돈이 들어오게 하는 쪽입니다.
  • 카드 네트워크(card network / scheme): Visa, Mastercard, 국내 카드사 망처럼 매입사와 발급사 사이에서 거래를 라우팅하는 네트워크입니다. 규칙(rule)과 수수료(interchange)를 정하는 주체이기도 합니다.
  • 발급사(issuer / issuing bank): 카드를 발급한 은행입니다. 실제로 "이 거래를 승인할지"를 결정하는 최종 권한을 가집니다. 한도, 잔액, 사기 여부를 판단하는 곳입니다.

이 다섯이 어떻게 연결되는지 그림으로 보면 이렇습니다.

  [가맹점] --카드정보--> [PG/PSP] --> [매입사]
                                  [카드 네트워크]
                                   [발급사] --승인/거절--> (역방향으로 응답이 돌아옴)

핵심 직관은 이렇습니다. 카드 네트워크는 "라우터"이고, 발급사는 "결정권자"이며, 매입사는 "가맹점의 은행", PG는 "이 모든 복잡함을 감춰 주는 어댑터"입니다. 우리가 코드에서 마주하는 것은 대개 PG의 API 하나뿐이지만, 그 뒤에는 이 사슬 전체가 매번 움직입니다.

승인 vs 매입 vs 정산 — 결제의 세 단계

결제 시스템을 이해할 때 가장 흔한 오해가 "결제 = 돈이 옮겨지는 것"이라는 생각입니다. 실제로는 세 단계가 시간을 두고 나뉩니다. 이 셋을 구분하지 못하면 결제 상태 관리가 반드시 꼬입니다.

1. 승인(authorization). "이 카드로 이 금액을 결제해도 되는가?"를 발급사에 묻고 답을 받는 단계입니다. 발급사는 한도와 잔액, 사기 신호를 확인하고 승인 또는 거절을 응답합니다. 승인이 나면 그 금액만큼 카드의 가용 한도가 **홀드(hold)**됩니다. 하지만 이 순간 돈이 실제로 빠져나간 것은 아닙니다. "예약"에 가깝습니다.

2. 매입(capture). 승인된 금액을 실제로 청구하겠다고 확정하는 단계입니다. 온라인 커머스에서는 보통 상품이 발송될 때 매입합니다. 승인과 매입을 분리하면, 재고가 없어 주문을 취소해야 할 때 매입 전에 승인만 취소(void)하면 되므로 깔끔합니다. 승인 금액보다 적게 매입(부분 매입)하는 것도 가능합니다.

3. 정산(settlement). 실제로 자금이 발급사에서 매입사로, 그리고 가맹점의 계좌로 이동하는 단계입니다. 이것은 보통 배치(batch)로, 하루 단위로 일어납니다. 그래서 사용자가 결제한 날과 가맹점이 돈을 실제로 받는 날 사이에는 며칠의 시차가 있습니다.

이 셋의 관계를 타임라인으로 보면 명확합니다.

  T+0초    승인(authorization)   -> 한도 홀드, 돈은 아직 안 움직임
  T+수시간~일  매입(capture)         -> "이 금액을 청구한다"고 확정
  T+1~3일  정산(settlement)      -> 실제 자금 이동, 가맹점 계좌 입금

간편결제나 즉시결제 상품에서는 승인과 매입이 사실상 한 번에 일어나는 것처럼 보이기도 합니다(sale/purchase 방식). 하지만 내부적으로는 여전히 이 단계들이 존재하며, 정산은 언제나 나중에 배치로 일어난다는 점은 변하지 않습니다. 결제 시스템의 상태 기계(state machine)는 바로 이 세 단계를 반영해서 설계해야 합니다.

승인 플로우를 따라가기

승인 한 건이 어떻게 흐르는지 단계별로 따라가 봅시다. 사용자가 카드 정보를 입력하고 결제를 누른 순간부터입니다.

  1) 사용자가 카드 정보 입력 -> 가맹점 프론트엔드
  2) 가맹점(또는 PG SDK)이 카드 정보를 PG로 전송 (토큰화됨)
  3) PG -> 매입사로 승인 요청
  4) 매입사 -> 카드 네트워크로 라우팅
  5) 카드 네트워크 -> 해당 발급사로 전달
  6) 발급사가 한도/잔액/사기 판단 -> 승인 또는 거절
  7) 응답이 같은 경로를 역순으로 되돌아옴
  8) 가맹점이 결과를 받아 주문 상태를 갱신

여기서 엔지니어가 특히 신경 써야 할 지점이 몇 가지 있습니다.

첫째, 이 왕복은 여러 네트워크 홉(hop)을 지나므로 느리고 실패할 수 있습니다. 타임아웃, 네트워크 단절, PG 장애가 언제든 일어납니다. 그래서 "응답을 못 받았다"는 상황을 항상 가정해야 합니다. 이것이 뒤에서 다룰 멱등성이 필요한 이유입니다.

둘째, 거절(decline)에는 여러 종류가 있습니다. 잔액 부족, 한도 초과, 카드 분실 신고, 사기 의심, 발급사 일시 장애 등입니다. 어떤 거절은 재시도하면 될 수도 있지만(soft decline), 어떤 거절은 재시도해도 소용없고 오히려 카드사의 사기 점수를 악화시킵니다(hard decline). 이 둘을 구분해 처리하는 것이 결제 성공률(conversion)에 직접 영향을 줍니다.

셋째, 응답은 대개 **승인 코드(authorization code)**와 함께 옵니다. 이 코드는 나중에 매입, 취소, 환불, 대사에서 이 거래를 식별하는 열쇠가 되므로 반드시 저장해야 합니다.

3-D Secure — 책임을 옮기는 인증

온라인 결제(카드 비대면, card-not-present)는 카드 실물이 없으므로 사기에 취약합니다. 이를 보완하기 위해 카드 네트워크가 만든 인증 프로토콜이 **3-D Secure(3DS)**입니다. Visa의 "Verified by Visa", Mastercard의 "Identity Check" 같은 브랜드로 알려져 있고, 현재 널리 쓰이는 것은 2.x 버전입니다.

3DS의 동작을 요약하면 이렇습니다. 결제 도중, 사용자를 발급사가 제어하는 인증 단계로 보냅니다. 발급사는 여기서 추가 인증(예: 앱 푸시 승인, 일회용 비밀번호, 생체인증)을 요구할 수 있습니다. 인증이 끝나면 결제 플로우로 돌아와 승인을 진행합니다.

  결제 요청
  3DS 인증 개시 -> 발급사 인증 화면(필요 시)
     │  (앱 승인 / OTP / 생체 등)
  인증 결과를 승인 요청에 실어 발급사로
  승인 또는 거절

3DS의 핵심은 기술이 아니라 **책임 전가(liability shift)**라는 상업적 개념입니다. 3DS로 인증된 거래에서 사기가 발생하면, 그 손실 책임이 가맹점에서 발급사로 넘어갑니다. 즉 3DS는 사기를 100% 막는 도구가 아니라, 사기 손실의 책임 소재를 바꾸는 장치에 가깝습니다.

3DS 2.x는 이전 버전보다 똑똑해졌습니다. 위험도가 낮아 보이는 거래는 사용자에게 아무것도 묻지 않고 통과시키고(frictionless flow), 위험해 보일 때만 추가 인증을 요구합니다(challenge flow). 유럽의 PSD2/SCA(강력한 고객 인증) 규제는 사실상 이런 인증을 의무화했습니다. 결제 시스템을 설계할 때는 3DS 인증 단계에서 사용자가 이탈하거나, 인증이 실패하거나, 콜백이 지연되는 경우를 모두 상태로 다뤄야 합니다.

차지백 — 사용자가 이의를 제기할 때

결제가 성공했다고 끝이 아닙니다. 사용자는 나중에 그 결제에 이의를 제기할 수 있습니다. 이것이 **차지백(chargeback)**입니다.

차지백은 사용자가 자신의 카드사(발급사)에 "이 거래는 잘못됐다"고 이의를 제기하는 것에서 시작합니다. 사유는 다양합니다. 물건을 안 받았다, 설명과 다르다, 내가 하지 않은 결제다(사기), 중복 청구다 등입니다. 발급사가 이의를 받아들이면, 이미 가맹점에 갔던 돈을 되돌려(reverse) 사용자에게 환급합니다.

  사용자 -> 발급사에 이의 제기
  발급사가 매입사를 통해 차지백 개시 -> 가맹점에서 대금 회수
  가맹점이 증빙 제출로 반박(representment) 가능
  카드 네트워크의 중재로 최종 판정

차지백은 환불(refund)과 다릅니다. 환불은 가맹점이 자발적으로 돈을 돌려주는 것이고, 차지백은 카드사를 통해 강제로 회수되는 것입니다. 차지백은 가맹점에게 여러 면에서 불리합니다. 대금을 잃을 뿐 아니라 별도의 차지백 수수료가 붙고, 차지백 비율이 높아지면 카드 네트워크로부터 제재를 받거나 심하면 가맹점 자격을 잃을 수 있습니다.

그래서 결제 시스템에는 차지백을 다루는 흐름이 필요합니다. 차지백 통지를 수신해 주문 상태를 갱신하고, 증빙을 모아 반박(representment)을 제출하고, 차지백 비율을 모니터링하는 것입니다. 사기로 인한 차지백을 줄이기 위해 앞서 본 3DS의 책임 전가나 사기 탐지 규칙을 함께 씁니다.

멱등성 — 이중 결제를 막는 상수

결제 플로우는 네트워크를 여러 번 왕복하므로 실패가 잦고, 실패하면 재시도하게 됩니다. 여기서 결제 특유의 무서운 문제가 생깁니다. 재시도가 이중 결제를 만들 수 있다는 것입니다.

시나리오는 이렇습니다. 가맹점이 PG에 승인 요청을 보냈습니다. PG는 정상적으로 발급사까지 다녀와 승인에 성공했습니다. 그런데 그 성공 응답이 가맹점에게 돌아오는 도중에 네트워크가 끊겼습니다. 가맹점 입장에서는 "응답을 못 받았다"뿐이라, 성공했는지 실패했는지 알 수 없습니다. 그래서 안전하게 재시도합니다. 하지만 첫 요청은 이미 성공했으므로, 재시도가 두 번째 결제를 만들어 버립니다. 사용자는 두 번 청구됩니다.

이 문제의 표준 해법이 **멱등성 키(idempotency key)**입니다. 클라이언트가 결제 요청마다 고유한 키를 생성해 함께 보내면, 서버는 같은 키의 요청을 두 번째로 받았을 때 새로 처리하는 대신 첫 번째 결과를 그대로 돌려줍니다. 그러면 몇 번을 재시도해도 결제는 한 번만 일어납니다.

  요청 1: POST /charges  Idempotency-Key: abc-123  -> 결제 실행, 결과 저장
  (응답이 유실됨)
  요청 2: POST /charges  Idempotency-Key: abc-123  -> 저장된 결과를 그대로 반환
                                                       (결제는 다시 일어나지 않음)

이 글에서는 개념만 짚고 넘어가지만, 멱등성은 결제 시스템의 핵심 중의 핵심이라 별도의 글에서 키의 수명, 중복 제거 윈도우, 유니크 제약, 결제 상태 기계까지 깊이 다룹니다. 지금은 "결제 요청은 항상 멱등해야 한다"는 원칙만 확실히 새기면 됩니다.

대사(reconciliation) — 장부를 맞추는 일

결제 시스템에서 겉으로 잘 드러나지 않지만 결정적으로 중요한 작업이 **대사(reconciliation)**입니다. 대사란 "우리 시스템이 기록한 거래"와 "PG나 카드사가 기록한 거래", 그리고 "실제로 은행 계좌에 들어온 돈"이 서로 일치하는지 맞춰 보는 일입니다.

왜 이것이 필요할까요? 결제는 여러 주체와 여러 단계를 거치므로, 어느 지점에서든 불일치가 생길 수 있기 때문입니다.

  • 우리 시스템은 승인 성공으로 기록했는데, PG 정산 내역에는 그 거래가 빠져 있을 수 있습니다.
  • 매입은 100건인데 정산 입금은 98건분만 들어올 수 있습니다(수수료, 차지백, 환불 차감 때문).
  • 앞서 본 이중 결제나 부분 매입, 환불이 얽히면 금액이 미묘하게 어긋납니다.

대사의 기본 아이디어는 이렇습니다. 우리 내부 원장의 거래 목록과 PG가 매일 제공하는 정산 파일을 서로 대조해서, 양쪽에 다 있는 것, 우리에게만 있는 것, PG에만 있는 것으로 분류합니다.

  내부 원장의 거래   vs   PG 정산 파일의 거래
        │                      │
        ▼                      ▼
     대조(match by 거래ID / 승인코드 / 금액)
        ├─ 양쪽 일치           -> OK
        ├─ 우리에만 있음       -> 정산 누락? 조사 필요
        └─ PG에만 있음         -> 우리가 놓친 거래? 조사 필요

불일치가 나오면 그것을 예외(exception)로 분류해 사람이 조사하거나 자동 규칙으로 해소합니다. 잘 만든 결제 시스템은 매일 자동으로 대사를 돌리고, 불일치 건수와 금액을 지표로 관측합니다. 대사가 깨끗하게 맞는다는 것은 "돈을 잃지 않고 있다"는 가장 직접적인 증거입니다. 그리고 대사를 가능하게 하려면, 애초에 모든 거래가 변경 불가능한(immutable) 기록으로 남아 있어야 합니다. 이 지점에서 결제는 자연스럽게 회계 원장 설계와 만납니다.

PCI-DSS — 카드 정보를 다루는 규칙

카드 번호는 극도로 민감한 정보입니다. 유출되면 곧바로 금전 피해로 이어지기 때문입니다. 그래서 카드 업계는 **PCI-DSS(Payment Card Industry Data Security Standard)**라는 보안 표준을 만들어, 카드 정보를 저장·처리·전송하는 모든 곳이 이를 따르도록 요구합니다.

PCI-DSS의 요구사항은 방대하지만, 엔지니어가 먼저 이해할 큰 원칙은 이렇습니다.

  • 저장하지 않을 수 있으면 저장하지 마라. 카드 번호 전체(PAN), 유효기간, CVC를 직접 저장하는 순간, PCI 준수의 범위(scope)가 폭발적으로 커집니다. CVC는 승인 이후에는 절대 저장하면 안 됩니다.
  • 토큰화(tokenization)를 활용하라. 실제 카드 번호 대신, 그것을 대체하는 무의미한 토큰만 우리 시스템에 두는 방식입니다. 진짜 카드 번호는 PCI 인증을 받은 PG나 별도의 볼트(vault)에만 보관됩니다. 대부분의 서비스는 이 방식으로 PCI 범위를 최소화합니다.
  • 범위를 최소화하라. 카드 데이터가 지나가는 시스템이 적을수록 감사와 관리가 쉬워집니다. PG가 제공하는 호스팅 결제창이나 클라이언트 측 토큰화(예: 카드 정보를 브라우저에서 바로 PG로 보내 토큰만 받아 오는 방식)를 쓰면, 카드 번호가 아예 우리 서버를 지나지 않게 만들 수 있습니다.

정리하면, 오늘날 대부분의 서비스에게 최선의 PCI 전략은 "카드 원본 데이터를 직접 만지지 않는 것"입니다. 토큰화와 PG의 결제창을 적극 활용해, 민감 데이터가 우리 시스템에 들어오지 않게 설계하는 것입니다. 인증과 토큰의 기초 개념이 더 궁금하다면 인증·보안 실습실에서 관련 개념을 실습해 볼 수 있습니다.

전체 그림을 다시 보기

지금까지의 조각들을 하나의 그림으로 모아 봅시다. 사용자가 결제를 누른 뒤부터 가맹점이 실제로 돈을 받고, 필요하면 환불하거나 차지백을 처리하기까지의 전체 여정입니다.

단계무슨 일이 일어나는가엔지니어의 관심사
결제 요청카드 정보 입력, 토큰화PCI 범위 최소화
3DS 인증필요 시 발급사 인증이탈/실패/콜백 지연 처리
승인발급사가 한도 확인, 한도 홀드멱등성, soft/hard decline 구분
매입청구 확정(발송 시점 등)부분 매입, 취소(void)
정산배치로 실제 자금 이동수수료/차감 반영
대사내부 기록과 정산 대조불일치 탐지, 예외 처리
환불/차지백사후 대금 반환상태 관리, 증빙, 비율 모니터링

이 표가 결제 시스템 설계의 요약본입니다. 각 행이 하나의 상태이자 하나의 실패 지점이며, 이 모두를 상태 기계로 엮어 관리하는 것이 결제 백엔드의 본질입니다.

마치며

결제 시스템은 "결제 버튼을 누르면 돈이 옮겨진다"는 단순한 겉모습 뒤에, 다섯 주체와 세 단계와 여러 실패 시나리오가 겹겹이 쌓인 세계입니다. 승인은 예약이고, 매입은 확정이며, 정산은 실제 이동입니다. 그 사이를 3DS가 인증으로 지키고, 차지백이 사후 이의를 처리하며, 멱등성이 이중 결제를 막고, 대사가 장부를 맞추고, PCI-DSS가 민감 데이터를 통제합니다.

결제 엔지니어링의 첫 번째 교훈은 "돈이 오가는 시스템은 틀릴 여지를 최소화해야 한다"는 것입니다. 그래서 멱등성과 변경 불가능한 기록, 그리고 매일의 대사가 선택이 아니라 상수가 됩니다. 이 지도를 손에 쥐고 나면, 다음으로 파고들 두 주제가 자연스럽게 보입니다. 이중 결제를 막는 멱등성의 구현, 그리고 돈을 절대 잃지 않는 이중 기입 원장의 설계입니다.

참고 자료

Payment Systems 101: Flow, PSPs, Card Networks, Settlement

Introduction — The World Behind the Pay Button

When a user taps "Pay," it looks like it takes less than a second. But inside that second, the card number travels through half a dozen companies and at least two payment networks all the way to the issuing bank and back. And the money does not actually move from account to account at that moment — it moves days later.

Payments are, more than almost any other system, a domain where being wrong is unacceptable. If a search result is off by one, the user is merely inconvenienced. If a payment is off by one, someone loses money. That is why consistency, idempotency, and auditability come before everything else in a payment system.

This post is a map for engineers who are designing or trying to understand a payment system for the first time. We will look at how authorization, capture, and settlement differ; which players sit between them; what 3-D Secure and chargebacks are; and why reconciliation, idempotency, and PCI-DSS are constants of payments. Since security is mandatory here, if you want the fundamentals of authentication and tokens, see this site's Auth & Security Lab, and if the response codes that show up below are unfamiliar, keep the HTTP Status Code Reference handy.

The Cast of Five

The first step to understanding card payments is knowing who does what. A single card payment involves at least five players.

  • Merchant: the party selling goods or services. This is the service we build.
  • PSP / gateway (payment service provider / payment gateway): the intermediary that connects the merchant to the complex financial rails. Companies like Stripe, Adyen, or Braintree. They receive card details securely and talk to all the players below on the merchant's behalf.
  • Acquirer (acquiring bank): the bank that "acquires" the card funds on behalf of the merchant. It is the party that gets money into the merchant's settlement account.
  • Card network (scheme): networks like Visa and Mastercard that route transactions between acquirers and issuers. They also set the rules and the interchange fees.
  • Issuer (issuing bank): the bank that issued the card. It holds the final authority to decide whether to approve a transaction, checking limits, balance, and fraud.

Here is how the five connect.

  [Merchant] --card data--> [PSP/gateway] --> [Acquirer]
                                          [Card network]
                                            [Issuer] --approve/decline--> (response returns in reverse)

The core intuition: the card network is a "router," the issuer is the "decision maker," the acquirer is the "merchant's bank," and the PSP is the "adapter" that hides all of this complexity. In our code, we usually face just one PSP API, but behind it the whole chain moves on every transaction.

Authorization vs Capture vs Settlement — The Three Phases

The most common misconception when learning payments is thinking "payment = money moving." In reality, three phases are separated in time. If you fail to distinguish them, your payment state management will inevitably tangle.

1. Authorization. The step where you ask the issuer, "May this card pay this amount?" and get an answer. The issuer checks limits, balance, and fraud signals and responds approve or decline. When approved, that amount is placed on hold against the card's available credit. But money has not actually left at this moment. It is closer to a "reservation."

2. Capture. The step where you confirm you actually intend to charge the authorized amount. In online commerce you typically capture when the goods ship. Separating authorization from capture is clean: if you must cancel an order because it is out of stock, you can void the authorization before capture. You can also capture less than the authorized amount (partial capture).

3. Settlement. The step where funds actually move from the issuer to the acquirer and into the merchant's account. This usually happens in a batch, once a day. So there is a gap of several days between the day a user pays and the day the merchant actually receives the money.

The relationship becomes clear on a timeline.

  T+0s      authorization   -> hold on credit, money hasn't moved yet
  T+hours~day  capture       -> confirm "charge this amount"
  T+1~3d    settlement       -> actual money movement, merchant account credited

For instant or one-tap payment products, authorization and capture can appear to happen together (a sale/purchase flow). But internally these phases still exist, and settlement always happens later in a batch — that does not change. A payment system's state machine should be designed to reflect exactly these three phases.

Following the Authorization Flow

Let us trace how a single authorization flows, step by step, from the moment the user enters card details and taps pay.

  1) User enters card details -> merchant frontend
  2) Merchant (or PSP SDK) sends card data to the PSP (tokenized)
  3) PSP -> authorization request to the acquirer
  4) Acquirer -> routes to the card network
  5) Card network -> forwards to the correct issuer
  6) Issuer judges limit/balance/fraud -> approve or decline
  7) The response travels back along the same path in reverse
  8) Merchant receives the result and updates the order state

There are a few points here that engineers must watch carefully.

First, this round trip crosses several network hops, so it is slow and can fail. Timeouts, dropped connections, and PSP outages happen. So you must always assume the case of "I never got a response." This is exactly why the idempotency covered later is necessary.

Second, declines come in several kinds: insufficient funds, over limit, card reported lost, suspected fraud, temporary issuer outage, and more. Some declines may succeed on retry (soft decline), while others are pointless to retry and only worsen the card's fraud score (hard decline). Distinguishing and handling these two directly affects conversion.

Third, the response usually comes with an authorization code. This code is the key to identifying the transaction later in capture, void, refund, and reconciliation, so you must store it.

3-D Secure — Authentication That Shifts Liability

Online payments (card-not-present) lack a physical card and are therefore vulnerable to fraud. To compensate, the card networks created an authentication protocol called 3-D Secure (3DS). It is known under brands like Visa's "Verified by Visa" and Mastercard's "Identity Check," and the widely used version today is 2.x.

In summary, 3DS works like this. During payment, the user is sent to an authentication step controlled by the issuer. There the issuer may require extra authentication (an app push approval, a one-time password, biometrics). Once authentication finishes, control returns to the payment flow and authorization proceeds.

  payment request
  3DS authentication starts -> issuer authentication screen (if needed)
     │  (app approval / OTP / biometrics)
  authentication result carried into the authorization request
  approve or decline

The core of 3DS is not the technology but the commercial concept of liability shift. When fraud occurs on a 3DS-authenticated transaction, responsibility for the loss moves from the merchant to the issuer. In other words, 3DS is less a tool that stops fraud entirely and more a mechanism that changes who bears the fraud loss.

3DS 2.x is smarter than earlier versions. It lets low-risk-looking transactions pass without asking the user anything (frictionless flow) and only requires extra authentication when things look risky (challenge flow). Europe's PSD2/SCA (Strong Customer Authentication) regulation effectively made such authentication mandatory. When designing a payment system, you must treat every case in the 3DS step as a state: the user abandoning, authentication failing, or the callback being delayed.

Chargebacks — When the User Disputes

A successful payment is not the end. The user can later dispute that payment. This is a chargeback.

A chargeback begins when a user disputes a transaction with their own card issuer, saying "this transaction is wrong." The reasons vary: I never received the item, it differs from the description, I did not make this charge (fraud), it was billed twice. If the issuer accepts the dispute, it reverses the money that already went to the merchant and refunds the user.

  User -> raises a dispute with the issuer
  Issuer starts a chargeback via the acquirer -> funds pulled back from the merchant
  Merchant can push back with evidence (representment)
  Final ruling via the card network's arbitration

A chargeback differs from a refund. A refund is the merchant voluntarily returning money; a chargeback is money forcibly pulled back through the card system. Chargebacks are unfavorable to merchants in several ways. You not only lose the funds but also pay a separate chargeback fee, and if your chargeback ratio gets high, the card networks may impose penalties or even revoke your merchant status.

So a payment system needs a flow for handling chargebacks: receiving the chargeback notice and updating the order state, gathering evidence and submitting a representment, and monitoring the chargeback ratio. To reduce fraud-driven chargebacks, you combine the liability shift of 3DS with fraud detection rules.

Idempotency — The Constant That Prevents Double Charges

Because the payment flow crosses the network several times, failures are frequent, and failures lead to retries. Here a fear peculiar to payments arises: a retry can create a double charge.

The scenario: the merchant sends an authorization request to the PSP. The PSP successfully makes it all the way to the issuer and the authorization succeeds. But on the way back, the network drops the success response. From the merchant's side, all it knows is "I got no response," so it cannot tell whether it succeeded or failed. To be safe, it retries. But the first request already succeeded, so the retry creates a second payment. The user is charged twice.

The standard solution is the idempotency key. If the client generates a unique key for each payment request and sends it along, then when the server receives a request with the same key a second time, instead of processing it anew it returns the first result as-is. No matter how many times you retry, the payment happens only once.

  Request 1: POST /charges  Idempotency-Key: abc-123  -> run payment, store result
  (response lost)
  Request 2: POST /charges  Idempotency-Key: abc-123  -> return the stored result as-is
                                                          (payment does not happen again)

This post only touches the concept, but idempotency is so central to payment systems that a separate post covers key lifetime, dedup windows, unique constraints, and the payment state machine in depth. For now, it is enough to firmly internalize the principle that "a payment request must always be idempotent."

Reconciliation — Making the Books Agree

A task that does not surface visibly yet is decisively important in a payment system is reconciliation. Reconciliation means checking whether "the transactions our system recorded," "the transactions the PSP or card company recorded," and "the money that actually landed in the bank account" all agree.

Why is this needed? Because payments pass through many players and many phases, a mismatch can arise at any point.

  • Our system recorded an authorization as successful, but the PSP's settlement report may be missing that transaction.
  • There were 100 captures, but the settlement deposit covers only 98 (because of fees, chargebacks, refunds deducted).
  • When the double charges, partial captures, and refunds we saw earlier get entangled, the amounts drift subtly.

The basic idea of reconciliation: compare the list of transactions in our internal ledger against the settlement file the PSP provides daily, and classify each into present in both, present only on our side, and present only on the PSP's side.

  transactions in internal ledger   vs   transactions in PSP settlement file
        │                                     │
        ▼                                     ▼
     match (by transaction ID / auth code / amount)
        ├─ present in both           -> OK
        ├─ ours only                 -> settlement missing? needs investigation
        └─ PSP only                  -> a transaction we missed? needs investigation

When a mismatch appears, you classify it as an exception for a human to investigate or an automated rule to resolve. A well-built payment system runs reconciliation automatically every day and observes the count and amount of mismatches as metrics. Clean reconciliation is the most direct evidence that "we are not losing money." And to make reconciliation possible at all, every transaction must be recorded as an immutable entry in the first place. At this point payments naturally meet the design of an accounting ledger.

PCI-DSS — The Rules for Handling Card Data

A card number is extremely sensitive information, because a leak leads straight to financial harm. So the card industry created a security standard called PCI-DSS (Payment Card Industry Data Security Standard) and requires everyone who stores, processes, or transmits card data to follow it.

PCI-DSS has a vast set of requirements, but the big principles for an engineer to understand first are these.

  • If you can avoid storing it, do not store it. The moment you directly store the full card number (PAN), expiry, or CVC, the scope of PCI compliance explodes. The CVC must never be stored after authorization.
  • Use tokenization. Instead of the real card number, keep only a meaningless token that stands in for it in our system. The real card number is held only in a PCI-certified PSP or a dedicated vault. Most services minimize their PCI scope this way.
  • Minimize scope. The fewer systems that card data passes through, the easier auditing and management become. Using a PSP's hosted payment page or client-side tokenization (for example, sending card details straight from the browser to the PSP and receiving back only a token) can keep the card number from ever passing through our servers.

In short, for most services today the best PCI strategy is "never touch raw card data." Lean heavily on tokenization and the PSP's payment forms so that sensitive data never enters our system. If you want more on the fundamentals of authentication and tokens, you can practice the related concepts in the Auth & Security Lab.

Seeing the Whole Picture Again

Let us gather the pieces into a single picture — the entire journey from the moment a user taps pay, through the merchant actually receiving money, to handling a refund or chargeback if needed.

PhaseWhat happensEngineer's concern
Payment requestCard entry, tokenizationMinimize PCI scope
3DS authIssuer authentication if neededHandle abandon/failure/callback delay
AuthorizationIssuer checks limit, places holdIdempotency, soft/hard decline
CaptureConfirm charge (e.g. at shipping)Partial capture, void
SettlementActual funds move in a batchReflect fees/deductions
ReconciliationCompare internal records vs settlementDetect mismatches, handle exceptions
Refund/chargebackPost-hoc return of fundsState management, evidence, ratio monitoring

This table is a summary of payment system design. Each row is a state and a point of failure, and weaving all of them into a state machine is the essence of a payment backend.

Conclusion

A payment system is a world where, behind the simple surface of "press pay and money moves," five players, three phases, and many failure scenarios are layered on top of one another. Authorization is a reservation, capture is confirmation, settlement is the actual movement. Between them, 3DS guards with authentication, chargebacks handle after-the-fact disputes, idempotency prevents double charges, reconciliation makes the books agree, and PCI-DSS controls sensitive data.

The first lesson of payment engineering is that a system moving money must minimize room for error. That is why idempotency, immutable records, and daily reconciliation become constants rather than choices. With this map in hand, the next two topics come into focus naturally: implementing the idempotency that prevents double charges, and designing the double-entry ledger that never loses money.

References