개발 기술 · 더 알아보기 · 직접 체험형

앱에서 결제한 주문, 서버는 어떻게 결제 완료로 확정할까요?

서버가 주문번호·금액과 결제 승인 결과를 확인해 주문에 저장한 뒤, 앱이 저장된 주문을 다시 조회해 결제 완료를 표시합니다.

인증 결과와 승인 구분서버의 주문·금액 검증저장 후 독립 조회
앱의 인증 결과, 상점 서버의 검증과 저장, 결제 시스템의 승인을 나눈 세 영역.

결제 완료가 되는 기준을 직접 확인하세요

앱 → 우리 서버 ↔ 결제 시스템 → 주문 재조회

시연만 크게 보기 ↗

앱과 서버를 연결하는 구현 과정

앱의 인증 결과부터 주문 저장·조회까지

결제창에서 앱으로 돌아왔다고 주문을 바로 ‘결제 완료’로 바꾸지는 않습니다. 이 글의 결제 흐름에서는 서버가 주문번호와 금액을 대조하고, 결제 시스템의 승인 결과를 확인한 뒤 결제 기록과 주문을 저장합니다. 앱은 저장된 주문을 다시 읽어 완료를 표시합니다.

아래에서 같은 18,000원 주문을 정상 승인, 돌아온 금액 불일치, 승인 응답 지연으로 비교해보세요. 어떤 정보를 믿고 저장하는지, 결과를 모를 때 왜 다시 결제시키지 않는지 앱 화면·우리 서버·결제 시스템의 세 영역에서 확인할 수 있습니다. 결제 시스템은 별도 시연용 서버로 재현하며 실제 카드 결제나 금전 이동은 없습니다.

구현 과정 01

결제창을 열기 전에 서버에 주문과 금액을 남깁니다

시연의 주문은 원두 1개, 결제할 금액은 18,000원입니다. 서버가 상품 정보로 계산한 금액과 고유한 주문번호를 먼저 저장합니다. 화면에 적힌 금액과 나중에 돌아오는 금액을 비교할 기준을 마련하는 것입니다. 실서비스에서는 할인·배송비·재고와 주문의 유효 조건도 서버에서 계산하고 확인합니다.

앱은 이 주문번호와 금액으로 결제창을 엽니다. 화면에서 상품명이나 금액을 고쳤다고 서버의 주문 금액까지 바뀌어서는 안 됩니다. 결제를 승인할 수 있는 서버 전용 인증 정보도 앱 화면이나 앱에 포함된 코드에 넣지 않습니다. 이 시연은 실제 결제 키를 사용하지 않습니다.

앱에서 연결하는 일

서버가 준비한 주문과 금액을 보여주고 결제창을 엽니다.

서버에서 구현하는 일

상품에서 계산한 금액과 주문번호를 저장해 이후 대조 기준으로 씁니다.

요청 값과 구현 기준 자세히 보기
주문: 서버에서 새 번호 생성
상품: 데일리 블렌드 1개
서버가 계산한 결제 금액: 18,000원
시작 상태: 결제 대기

구현 과정 02

결제 인증 결과와 최종 승인을 나눕니다

여기서는 결제창에서 인증을 마친 뒤 상점 서버가 승인을 요청하는 연동 방식을 다룹니다. 토스페이먼츠의 이 방식에서는 인증 후 돌아오는 주문번호·금액·결제 식별값을 사용해 서버가 승인 요청을 이어갑니다. ‘성공 주소로 이동했다’는 사실과 ‘승인된 결제 내역이 확인됐다’는 사실을 나누는 이유입니다.

시연의 ‘인증 결과만 받기’를 누르면 앱은 인증 후 돌아온 주문 정보를 받지만, 주문은 여전히 결제 대기입니다. ‘결제 승인·주문 저장’을 누르면 그다음 확인이 시작됩니다. 앱 하단의 ‘18,000원 결제하기’는 이 두 동작을 순서대로 이어서 보여줍니다. 결제 시스템 영역에는 인증 준비, 우리 서버가 보낸 승인 요청, 승인 기록과 응답을 따로 표시합니다. 결제창의 카드 정보 입력 단계는 생략합니다. 좁은 화면에서는 위쪽 상태 카드를 눌러 앱·우리 서버·결제 시스템의 상세 화면을 선택할 수 있습니다.

앱에서 연결하는 일

돌아온 정보를 서버에 보내고, 확인 중에는 완료 화면을 먼저 띄우지 않습니다.

서버에서 구현하는 일

돌아온 값이 실제로 준비한 주문의 것인지 확인한 뒤 승인 단계로 넘깁니다.

요청 값과 구현 기준 자세히 보기
인증 결과 수신 ≠ 주문 결제 완료
앱 → 상점 서버: 주문번호 / 결제 식별값 / 돌아온 금액
상점 서버 → 결제 시스템: 검증 후 승인 요청
앱에서 받은 인증 정보와 서버가 검증하는 주문·금액·승인 결과, 저장 후 재조회를 구분한 비교.
앱에서 받은 인증 정보와 서버가 검증하는 주문·금액·승인 결과, 저장 후 재조회를 구분한 비교. 이미지를 눌러 크게 볼 수 있습니다.

구현 과정 03

주문과 일치하는 승인 결과만 함께 저장합니다

서버는 현재 회원의 주문을 찾고, 돌아온 금액이 저장된 18,000원과 같은지 확인합니다. ‘돌아온 금액 불일치’를 선택하면 앱이 9,000원을 보내도록 바뀝니다. 서버는 금액을 거절하며 결제 시스템에 승인 요청을 보내지 않습니다. 앱이 보낸 금액으로 기존 주문 금액을 덮어쓰지도 않습니다.

정상 값이라면 서버가 별도의 결제 시스템에 승인을 요청합니다. 응답에서도 주문번호·결제 식별값·금액과 승인 상태를 대조한 뒤, 같은 데이터베이스 작업 안에서 결제 기록을 남기고 주문을 결제 완료로 바꿉니다. 그다음 앱은 저장된 주문을 별도 조회합니다. 한 번의 서버 응답을 보고 끝내지 않고 저장 결과까지 확인하는 구조입니다.

앱에서 연결하는 일

승인 요청이 끝나면 주문을 다시 조회해 저장된 결제 상태와 금액을 표시합니다.

서버에서 구현하는 일

주문 대조 → 결제 시스템 승인 → 승인 응답 대조 → 결제·주문 저장을 순서대로 처리합니다.

요청 값과 구현 기준 자세히 보기
돌아온 18,000원 = 서버 주문 18,000원
승인 응답: 같은 주문 / 같은 결제 / 18,000원 / DONE
결제 기록 1건 + 주문 결제 완료: 같은 DB 작업으로 저장
앱: GET 주문 상세로 독립 재조회

구현 과정 04

승인 응답이 늦으면 실패 대신 확인 중으로 남깁니다

결제 시스템은 승인했지만 상점 서버가 응답을 제때 받지 못할 수 있습니다. ‘승인 응답 지연’에서는 별도 결제 서버에 승인 기록을 남긴 뒤 응답을 지연시킵니다. 상점 서버는 결과를 아직 확인하지 못했으므로 주문을 결제 완료나 실패로 단정하지 않고 ‘결제 확인 중’으로 둡니다.

이때 ‘기존 결제 다시 확인’을 누르면 새 결제를 만들지 않고 기존 주문의 결제 결과를 조회합니다. 같은 주문·금액·승인 결과가 확인되면 주문을 반영합니다. 실제 시스템에서는 자동 재확인, 결제사 알림과 운영자 확인 등 복구 경로를 결제 방식에 맞춰 설계합니다. 확인 중인 거래를 새 결제로 바꾸는 버튼만 추가해서는 이 간격을 해결할 수 없습니다.

앱에서 연결하는 일

결제 결과 확인 중이라고 안내하고 기존 거래 확인 동작을 제공합니다.

서버에서 구현하는 일

응답을 못 받았다는 이유로 실패를 확정하지 않고 기존 승인 결과를 다시 조회합니다.

요청 값과 구현 기준 자세히 보기
결제 시스템: 승인 기록 있음
상점 서버: 응답 미확인 → 결제 확인 중
기존 결제 조회 → 주문·금액·승인 대조 → 저장
새 결제 생성: 하지 않음
결제 시스템의 승인 기록, 서버의 결과 확인 중 상태와 새 결제 없는 기존 승인 조회를 구분한 과정.
결제 시스템의 승인 기록, 서버의 결과 확인 중 상태와 새 결제 없는 기존 승인 조회를 구분한 과정. 이미지를 눌러 크게 볼 수 있습니다.

구현 과정 05

다시 확인해도 결제 기록을 한 건으로 유지합니다

앱에서 같은 승인 결과를 다시 보내거나 확인 버튼을 다시 눌러도 이미 반영한 결제를 새 기록으로 추가하지 않습니다. 시연은 결제 식별값과 주문의 연결을 고유하게 저장하고, 완료된 주문이면 저장된 결과를 돌려줍니다. 결제 완료 뒤 ‘기존 결제 다시 확인’을 반복해 결제 기록이 1건으로 유지되는지 볼 수 있습니다.

결제사 승인과 상점 데이터베이스 저장을 하나의 데이터베이스 작업으로 묶을 수는 없습니다. 따라서 승인 이후 상점 저장이 실패하는 간격도 복구할 수 있어야 합니다. 같은 DB 안의 결제·주문은 함께 저장하되, 외부 승인과의 불일치는 기존 거래 조회와 재처리 기록으로 연결합니다. 일반적인 요청 번호·재시도의 원리는 관련 글에서 이어서 볼 수 있습니다.

앱에서 연결하는 일

기존 주문의 저장 결과를 다시 읽으며 중복 완료 내역을 만들지 않습니다.

서버에서 구현하는 일

같은 결제 식별값을 한 주문에 한 번만 반영하고, 다시 확인해도 기록 수를 유지합니다.

요청 값과 구현 기준 자세히 보기
외부 결제 승인 + 내부 DB = 서로 다른 처리 경계
내부 DB: 결제 기록과 주문 상태를 함께 저장
같은 결제 재확인: 기존 기록 유지
결제 완료 ≠ 상품 배송 완료

구현 과정 06

화면의 완료 문구와 별도 저장값을 함께 검수합니다

시연은 브라우저의 글자만 바꾸는 방식이 아닙니다. 앱과 상점 서버는 HTTP로 통신하고, 상점 서버도 별도 시연용 결제 서버에 승인·조회를 요청합니다. 주문과 결제 시스템은 서로 다른 저장소를 사용합니다. ‘실제 요청과 저장 결과’를 열면 응답 내용과 마지막 주문 조회 결과를 볼 수 있습니다.

정상 승인에서는 결제 기록 1건과 결제 완료 주문, 금액 불일치에서는 승인 0회와 주문 금액 유지, 응답 지연에서는 결제 확인 중과 기존 승인 복구를 확인합니다. 다시 열어도 같은 주문을 조회하며 다른 검토 세션의 주문과 섞이지 않도록 구분합니다. 상품의 배송 상태는 결제와 별도로 접수 대기를 유지합니다.

실제 서비스에 적용할 때는 사용할 결제사의 연동 규격·계약과 테스트/운영 환경, 결제 수단별 추가 흐름을 확인합니다. 이 글은 인증 후 승인을 요청하는 한 주문의 구현 과정을 다루며, 실제 결제사 연결 완료나 전체 취소·부분 환불·가상계좌·앱 마켓 결제 구현을 뜻하지 않습니다.

앱에서 연결하는 일

조회된 주문의 결제 상태·금액과 별도의 배송 상태를 보여줍니다.

서버에서 구현하는 일

다른 저장소의 승인 결과와 주문 저장값을 대조하고 검수 가능한 이력을 남깁니다.

요청 값과 구현 기준 자세히 보기
정상: 승인 1회 / 결제 기록 1건 / 결제 완료
금액 불일치: 승인 0회 / 결제 기록 0건 / 18,000원 유지
응답 지연: 확인 중 → 기존 승인 조회 → 결제 기록 1건
재확인·재진입: 같은 주문과 결제 기록 유지
처리 원리의 참고 자료

토스페이먼츠 · 결제 흐름 이해하기 · 인증과 승인을 나누고 승인 전 주문번호와 금액을 검증하는 연동 방식

토스페이먼츠 · 주문서형 결제 연동하기 · 앱의 인증 결과를 서버로 전달하고 서버에서 승인 API를 호출하는 경계

토스페이먼츠 · 코어 API · 승인·조회 응답의 주문번호·금액·결제 상태 확인

결제부터 주문 반영까지 연결할 범위를 정리하세요

결제할 상품과 결제 수단, 승인 뒤 이어질 업무를 알려주세요. 주문 준비·승인·저장·결과 확인까지 필요한 개발 범위를 함께 나눕니다.

30분 무료 상담 신청
앱이 만들어지는 방식으로 돌아가기