문제 해결
증상별 확인
결제창
| 현상 | 확인할 내용 |
|---|---|
| SDK가 로드되지 않음 | SDK 주소 https://widget.point3.io/v2/standard의 응답, npm 로더의 loader=toss, CSP의 script-src |
| SDK가 결제창을 열지 않음 | SDK 오류 코드, client_id, customerKey, setAmount() 호출 여부와 결과 URL |
| 본인인증 화면이 열리지 않음 | CSP의 frame-src, 앱이면 WebView의 JavaScript 설정 |
| 인증 후 결제 화면이 열리지 않음 | Referrer-Policy, 결제 세션 상태와 금액 |
| 앱에서 결제창의 뒤로가기·메뉴가 눌리지 않음 | WebView가 safe area 안에 있는지, 결제창 위에 네이티브 버튼이 겹치지 않는지 |
| 앱에서 결제 후 결과를 받지 못함 | 앱이 비교하는 successUrl·failUrl 주소 |
| 앱에서 결제창이 열리지 않음 | HTML을 HTTPS base URL로 불러왔는지, WebView의 JavaScript 설정 |
| 위임 인증을 전달했는데 문자 인증 화면이 열림 | 위임 인증 만료(5분)나 재사용 여부. 정상적인 전환이므로 결제는 계속 진행 |
| 위임 인증 실패 후 결제가 종료됨 | customerKey에 ANONYMOUS를 전달했는지 확인. 같은 payerId를 전달해야 문자 인증으로 전환 |
가맹점 서버
| 현상 | 확인할 내용 |
|---|---|
| 결제 세션을 생성하지 못함 | API 주소, API 키와 HTTP 상태 코드 |
결제 세션 API가 503 temporarilyUnavailable | error.eob가 있을 때만 EOB로 처리하고 endsAt 확인 |
위임 인증 생성이 404 PAYER_NOT_FOUND | 회원 정보에 저장된 payerId를 지금은 사용할 수 없음(탈퇴, 다른 가맹점 값 등). 위임 인증 없이 결제창을 열고, 결제 후 새로 받은 payerId로 회원 정보 갱신 |
| 결제 승인 API가 호출되지 않음 | event.source, event.origin, 메시지 필드, 현재 sessionId, 중복 처리 상태 |
| 결제 결과를 확인할 수 없음 | 승인 요청에 사용한 sessionId와 결제 세션 조회 응답의 status |
| 결제 세션이 만료됨 | 기존 세션을 재사용하지 않고 새 결제 세션 생성 |
| 승인 또는 취소 결과를 확인할 수 없음 | 성공·실패로 추정하지 않고 식별값과 주문 상태를 보존하며 각각의 상태 조회 API로 확인 |
응답 코드별 의미는 에러 코드에서 확인하세요.
결과를 확인할 수 없을 때
응답 대기 시간 초과, 네트워크 오류, 응답 유실, 승인 응답의 세션 불일치 또는 결제 취소의 REFUND_TEMPORARY_UNAVAILABLE·REFUND_DUPLICATE_REQUEST는 결과가 확정되지 않은 상황입니다. 다른 409는 에러 코드의 처리 기준을 따르세요. 결과가 불확실한 승인이나 취소 요청을 무조건 다시 보내거나 상품 지급·환불 완료 처리를 하지 마세요.
확인되지 않은 결과를 실패로 처리하지 마세요
결제 결과를 확인할 수 없다면 같은 주문을 바로 다시 결제하거나 상품을 지급하지 마세요. 주문 상태와 결제 내역을 먼저 확인하세요.
결제 승인 결과가 불확실하면 같은 sessionId로 GET /payment/v3/session/{sessionId}를 호출해 status를 확인합니다. captured 또는 failed가 확인될 때까지 주문을 확정하지 마세요.
취소 요청의 결과가 불확실하면 GET /refunds/v1/{sessionId}로 결제 세션의 취소 상태를 조회합니다. refunds에 요청한 항목이 completed로 확인되면 완료 처리하고, failed면 실패 정보를 기록합니다. processing인 활성 항목이 하나 있으면 POST /refunds/v1/{sessionId}/resume으로 처리를 재개할 수 있습니다. 조회 결과만으로 원래 요청을 식별할 수 없거나 조회·재개도 실패하면 요청 식별값과 Idempotency-Key를 보존한 채 point3 담당자에게 문의하세요.
결제 승인 실패 코드
결제 승인 API는 실패가 확정된 경우에도 HTTP 200과 status: "failed"를 반환합니다. 사유는 outcome.code로 구분하세요. outcome.message 문구는 바뀔 수 있어 분기 조건으로 적합하지 않습니다.
outcome.code | outcome.type | 의미 | 처리 |
|---|---|---|---|
PAYMENT_METHOD_DECLINED | declined | 결제수단 승인 거절. 잔액 부족, 출금 가능 잔액 부족 등이 해당하며 잔액 부족만 뜻하지는 않음 | 구매자에게 잔액 확인 또는 다른 계좌 선택 안내 |
PAYMENT_METHOD_LIMIT_EXCEEDED | failed | 이체한도 초과 | 구매자에게 이체한도 확인 또는 다른 계좌 선택 안내 |
PAYMENT_CAPTURE_REJECTED | rejected | 세부 사유가 분류되지 않은 이체 실패 | 주문·결제 상태 확인, 필요하면 문의 |
PAYMENT_CAPTURE_ALREADY_FAILED | failed | 이미 실패한 결제를 다시 승인 요청함. 원래 사유는 포함되지 않음 | 처음 받은 실패 응답의 기록 확인 |
잔액 부족으로 승인이 거절된 경우:
코드
이체한도를 초과한 경우:
코드
첫 실패 사유 저장
실패한 결제를 다시 승인 요청하면 원래 사유 대신 PAYMENT_CAPTURE_ALREADY_FAILED가 반환되고, 결제 세션 조회 응답에 원래 사유가 남아 있다고 보장할 수도 없습니다. 그래서 처음 받은 실패 응답의 outcome.code를 주문과 sessionId 기준으로 저장해 두어야 합니다.
- 저장한 코드는 이후 받은
processing이나PAYMENT_CAPTURE_ALREADY_FAILED응답으로 덮어쓰지 않습니다. - 같은 주문에서 새 결제 세션을 만들면 실패 기록도 세션별로 따로 둡니다. 이전 세션의 사유를 새 세션에 적용하지 마세요.
- 사유를 다시 확인하려고 승인 API를 반복 호출하지 마세요.
TypeScript
PAYMENT_CAPTURE_ALREADY_FAILED를 받았는데 해당 sessionId의 기록이 없다면 이 코드만으로 원인을 판단하지 말고 point3 담당자에게 문의하세요.
문의하기
시스템 상태에서 장애 여부를 먼저 확인한 뒤, point3 담당자에게 연락해주세요. 어떤 문제가 언제 발생했는지 정리하고, 아래 항목 중 확인할 수 있는 정보를 함께 전달하면 원인을 더 빠르게 파악할 수 있습니다.
- 발생 시각
- 문제가 발생한 단계 (결제 세션 생성, 결제창, 결제 승인, 결제 취소 등)
sessionId- 호출한 API와 받은 HTTP 상태 코드, 오류 코드
- 브라우저 또는 WebView·OS 정보
민감 정보는 보내지 마세요
API 키, PIN, 계좌번호, 주민등록번호, 인증번호를 문의 내용에 포함하지 마세요.