# 라이브 전환 체크리스트

point3는 별도의 테스트 환경을 제공하지 않습니다. 운영 배포 전에 아래 항목을 모두 확인하고, 필수 시나리오가 기대 결과대로 동작하는지 점검하세요.

## 소액 결제로 테스트하기

모든 결제는 실제로 처리되므로 연동 테스트는 운영 환경에서 소액 결제로 진행합니다.

1. 적용 수수료보다 큰 소액(예: 100원)으로 결제 세션을 생성합니다. 수수료 이하의 금액은 결제가 거절됩니다.
2. 결제창에서 결제를 마치고 결제 승인까지 확인합니다.
3. 확인이 끝나면 [결제 취소](/payment-cancellation)로 결제를 취소합니다.

최소 수수료와 적용 요율은 대시보드의 계약사항에서 확인할 수 있습니다.

## 배포 전 확인하기

### 가맹점 서버

- [ ] API 키를 서버에만 보관했습니다.
- [ ] 서버에 저장된 주문 금액으로 결제 세션을 생성합니다.
- [ ] 주문과 `sessionId`를 연결하고, 해당 `sessionId`로 결제 승인 API를 호출합니다.
- [ ] EOB 점검 시간과 시간대를 결제창을 열기 전에 구매자에게 안내합니다.
- [ ] 승인 요청 후 응답 결과가 불확실하면 같은 `sessionId`로 결제 세션을 조회하여 최종 결과를 확인합니다.
- [ ] 성공·실패·결과 확인 필요 상태를 구분합니다.
- [ ] 결제 후 결제 세션 조회 응답의 `payerId`로 화면에서 받은 값을 확인하고 회원 정보에 저장합니다.
- [ ] 위임 인증을 사용한다면 로그인한 회원의 회원 정보에 저장된 `payerId`로만 생성하고, 생성에 실패하면 위임 인증 없이 결제창을 엽니다.

### JavaScript SDK

- [ ] SDK를 `https://widget.point3.io/v2/standard`에서 불러오고, 대시보드에서 확인한 가맹점 아이디를 `clientId`로 사용합니다.
- [ ] `requestPayment()`의 `orderId`에 주문의 `sessionId`를 전달합니다.
- [ ] `setAmount()`에 결제 금액을 전달합니다.
- [ ] 저장된 `payerId`가 있으면 `customerKey`로, 없으면 `ANONYMOUS`를 전달합니다.
- [ ] 위임 인증을 사용한다면 `authorization_url`을 가공하지 않고 `brandpay.redirectUrl`로 전달하며, `customerKey`에도 같은 `payerId`를 전달합니다.
- [ ] `successUrl`과 `failUrl`에는 HTTPS 절대 URL을 사용합니다. 결제 시도를 구분할 값이 필요하면 가맹점이 URL에 직접 추가합니다.
- [ ] 성공 URL의 `orderId`가 현재 주문의 `sessionId`와 같은지 확인합니다.
- [ ] `failUrl`에서는 `code`에 맞는 안내를 표시하고 결제 승인 API를 호출하지 않습니다.
- [ ] 결제창은 SDK가 닫으므로 가맹점이 직접 제거하지 않습니다.

### 앱

- [ ] SDK를 연동한 HTML을 가맹점 HTTPS 도메인을 base URL로 지정해 불러옵니다.
- [ ] WebView를 safe area 안에 띄우고, 결제창 위에 네이티브 버튼을 두지 않습니다.
- [ ] 결제창이 떠 있는 동안 시스템 뒤로가기를 막습니다.
- [ ] `successUrl`, `failUrl`로의 이동을 받아 WebView를 닫고 결과를 처리합니다.

### 운영 환경

- [ ] 대시보드에서 확인한 가맹점 아이디와 API 키를 사용합니다.
- [ ] CSP를 사용한다면 SDK는 `script-src`에 `https://widget.point3.io`를, 결제창은 `frame-src`에 `https://auth.point3.io`와 `https://widget.point3.io`를 허용했습니다.
- [ ] API 키, PIN, 계좌정보, 인증번호를 로그에 남기지 않습니다.

## 필수 테스트

| 시나리오 | 기대 결과 |
| --- | --- |
| 신규 구매자 | `customerKey`에 `ANONYMOUS`를 전달해 결제창을 열고 결제 완료 |
| 기존 구매자 | 저장된 `payerId`를 전달해 결제창을 열고 결제 완료 |
| 결제 완료 후 `payerId` 저장 | 결제 세션 조회 응답의 `payerId`와 화면 값이 같은지 확인하고 회원 정보에 저장 |
| 등록 전용 위젯으로 등록 완료 | 저장된 `payerId`가 없을 때만 받은 값을 저장하고, 결제 세션 조회로 확인한 값은 덮어쓰지 않음 |
| 위임 인증 (사용하는 경우) | 로그인한 회원의 `payerId`로 위임 인증을 생성해 문자 인증 없이 결제 완료 |
| 위임 인증 생성 실패 (사용하는 경우) | `brandpay` 옵션 없이 결제창을 열고 결제 완료 |
| 성공 URL의 `orderId`가 주문의 `sessionId`와 다름 | 결제 승인 API를 호출하지 않음 |
| 같은 성공 URL을 다시 받음 | 결제 승인 한 번만 요청 |
| 앱: 결제창에서 뒤로가기를 눌러 결제 취소 | `failUrl`의 `PAYMENT_WINDOW_CLOSED`를 받아 WebView를 닫고 안내 |
| 앱: 결제창이 떠 있을 때 시스템 뒤로가기 | 결제창이 그대로 유지됨 |
| SDK가 `failUrl`로 이동 | 승인 API 호출 없이 `code`에 맞는 안내 표시 |
| 결제창이 `SESSION_EXPIRED`로 종료 | 새 결제 세션을 생성해 다시 시작 |
| EOB 점검 시간에 결제 세션 생성 | `503`과 `error.eob`를 받고, `endsAt`으로 이용 재개 시각을 안내 |
| EOB 점검 시간에 결제창에서 결제 확정 | 결제창이 점검 안내를 표시하고, 가맹점 화면에 승인 준비 신호가 오지 않음 |
| EOB 점검 시간에 결제 취소 요청 | `409 EOB_WINDOW_BLOCKED`를 받고 00:30(KST) 이후 다시 요청 |
| 결제 의사 확정 당일 자정(KST)이 지난 뒤 승인 요청 | `422` `paymentCaptureExpired`를 확인하고 새 결제 세션으로 다시 시작 |
| 조회 응답 `status: created`, `identified`, `initiated`, `committed` | 아직 결제가 끝나지 않은 상태이므로 상품을 지급하지 않음 |
| 조회 응답 `status: processing` | 잠시 기다렸다가 같은 `sessionId`로 다시 조회 |
| 조회 응답 `status: captured` | 결제 성공으로 처리하고 결과 확인을 마침 |
| 조회 응답 `status: failed` | 결제 실패로 처리하고 결과 확인을 마침 |
| 조회 응답 `5xx`, 응답 대기 시간 초과 또는 네트워크 오류 | 성공·실패로 추정하거나 결제 요청을 무조건 반복하지 않고, 식별값을 보존한 뒤 상태 조회 재시도 |
| 결제 취소 `REFUND_TEMPORARY_UNAVAILABLE`, 중복 키 또는 응답 유실 | 원래 키와 식별값을 보존하고 상태 조회 API로 확인한 뒤, 처리 중인 취소만 재개 |

문제가 생기면 [문제 해결](/troubleshooting)과 [에러 코드](/error-codes)를 참고하세요.
