# 빠른 시작

point3 결제는 결제 세션 생성, 결제창 열기, 결제 승인의 세 단계로 진행돼요. 가맹점 서버에서 결제 세션을 생성하고, 환경에 따라 [연동 방식을 선택하여](/integration-methods) 결제창을 열고, 결제를 승인하여 완료합니다.

1. **결제 세션 생성** (가맹점 서버) — 주문 금액으로 결제 세션을 만들고 sessionId를 화면에 전달합니다. `POST /payment/v3/session`
2. **결제창 열기** (가맹점 화면) — sessionId로 결제창을 열고, 구매자가 결제 의사를 확정하면 받은 값을 서버에 전달합니다.
3. **결제 승인** (가맹점 서버) — 결제 승인 API를 호출하고 응답의 status로 결과를 확정합니다. `POST /capture/v2/{sessionId}`

## 준비하기

1. 담당자 안내에 따라 <a href="https://dashboard.point3.io/app/home">대시보드</a> 가입을 완료해주세요. 아직 도입을 결정하지 않았다면 <a href="https://point3.io">홈페이지</a>에 문의를 남겨주세요.
2. 대시보드의 <a href="https://docs.point3.io/dashboard/contracts-operations/tax-invoice">현금영수증 정보</a> 페이지에서 현금영수증 자동 발급을 활성화 하세요.
3. 대시보드의 개발정보 관리 페이지에서 <a href="https://docs.point3.io/dashboard/development/tokens#결제-모듈-활성화">결제 모듈을 활성화</a> 하세요.
4. 같은 페이지에서 <a href="https://docs.point3.io/dashboard/development/tokens#api-자격증명">API 키를 발급받고</a> 가맹점 아이디를 확인하세요.

| 값 | 형식 | 사용하는 곳 |
| --- | --- | --- |
| 가맹점 아이디 | `client-...` | 가맹점 화면: 결제창을 열 때 `client_id`로 전달 |
| API 키 | `s2scred-...` | 가맹점 서버: API를 호출할 때 `Authorization` 헤더로 전달 |

API 키는 가맹점 서버에만 보관하고 브라우저 코드에 넣지 마세요.

에이전트로 연동한다면 다음 프롬프트를 붙여 넣으세요. 자세한 내용은 [AI로 시작하기](/ai-tools)를 참고하세요.

```text
Retrieve and follow the instructions at: https://docs.point3.io/agent-integration.md
```

## 1. 결제 세션 생성 (서버)

결제 세션은 결제 금액, 상품명 등 결제 한 건을 처리할 때 필요한 정보를 담는 point3의 결제 처리 단위입니다. 가맹점 서버가 결제창을 열기 전에 생성하고, 결제 세션의 아이디인 `sessionId`로 이후 결제창 열기부터 승인, 조회, 취소를 진행하게 됩니다.

```bash
curl -X POST https://api.point3.io/payment/v3/session \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "amount": 10000, "productName": "아메리카노 외 1건" }'
```

가맹점에서 결제 금액과 상품명을 지정하여 결제 세션 생성을 요청하면 응답으로 세션 아이디를 받습니다. 해당 세션 아이디를 가맹점의 주문과 연결하여 저장해두세요.

자세한 요청 값과 세금 처리는 [결제 생성](/payment-creation)에서 확인하세요.

## 2. 결제창 열기 (화면)

이전 단계에서 생성한 결제 세션의 `sessionId`를 서버에서 화면으로 전달하고, 결제창을 열어야합니다. 결제창을 열면 구매자가 결제 내용을 확인하고 결제 의사를 확정할 수 있습니다. 결제창은 JavaScript SDK로 엽니다. React Native, Flutter, 네이티브 앱은 SDK를 연동한 HTML을 WebView로 띄웁니다.

### JavaScript SDK

[SDK를 설치](/sdk-environment)하고 `client_id`로 초기화한 뒤 `requestPayment()`를 호출합니다. `orderId`에는 가맹점 주문번호가 아닌 결제 세션의 `sessionId`를 넣습니다.

```js title="JavaScript"
const point3 = Point3(clientId)
const widgets = point3.widgets({ customerKey: Point3.ANONYMOUS })

await widgets.setAmount({ currency: 'KRW', value: 10000 })
await widgets.requestPayment({
  orderId: sessionId,
  orderName: '아메리카노 외 1건',
  successUrl: 'https://merchant.example.com/payments/success', // 결제 요청이 성공하면 이동할 URL
  failUrl: 'https://merchant.example.com/payments/fail' // 결제 요청이 실패하면 이동할 URL
})
```

```ts title="TypeScript"
const clientId: string = 'client-...'
const sessionId: string = paymentSession.id
const point3 = Point3(clientId)
const widgets = point3.widgets({ customerKey: Point3.ANONYMOUS })

await widgets.setAmount({ currency: 'KRW', value: 10000 })
await widgets.requestPayment({
  orderId: sessionId,
  orderName: '아메리카노 외 1건',
  successUrl: 'https://merchant.example.com/payments/success', // 결제 요청이 성공하면 이동할 URL
  failUrl: 'https://merchant.example.com/payments/fail' // 결제 요청이 실패하면 이동할 URL
})
```

구매자가 결제를 확정하면 SDK가 `successUrl`로 이동하며 `orderId`와 `payerId`를 전달합니다. 두 값은 가맹점 서버가 결제를 최종으로 처리하기 위해 필요합니다. 화면이 값을 받으면 서버에 데이터를 전달하도록 구현해주세요.

SDK에 대한 자세한 내용은 [JavaScript SDK 결제 연동](/sdk-payment-window)을 참고하세요.

### 앱

결제하기 화면이 네이티브 앱 화면이라면 결제창을 연동한 HTML 단일 페이지를 앱의 정적 에셋에 포함하고 WebView로 띄우세요. 하이브리드 앱이나 웹 앱이라면, 별도의 HTML 없이 JavaScript SDK를 연동한 결제하기 페이지를 그대로 띄우면 됩니다. 자세한 내용은 [연동 방식 선택](/integration-methods)을 참고하세요.

<Callout type="caution" title="결제창 성공은 결제 성공이 아닙니다">
  `successUrl`로 이동했다고 해서 결제가 완료된 것이 아닙니다. 상품을 지급하거나 성공 화면을 표시하지 마세요.
</Callout>

## 3. 결제 승인 (서버)

화면에서 받은 값이 주문에 저장한 `sessionId`와 같은지 확인한 뒤 결제 승인 API를 호출합니다.

```bash
curl -X POST https://api.point3.io/capture/v2/$SESSION_ID \
  -H "Authorization: Bearer $API_KEY"
```

결과는 HTTP 상태 코드가 아니라 응답 본문의 `status`로 판단합니다. 실패가 확정된 경우에도 HTTP `200`이 반환됩니다.

- `captured`: 결제 완료
- `failed`: 결제 실패. 잔액 부족, 이체한도 초과 같은 사유는 `outcome.code`로 구분합니다. 처음 받은 `outcome.code`를 주문에 저장해 두세요.
- `processing`(HTTP `202`): 아직 처리 중이며 실패가 아닙니다. 응답을 받지 못했을 때와 같이 `sessionId`로 결제 세션을 조회합니다.

이미 실패한 결제를 다시 승인 요청하면 원래 사유 대신 `PAYMENT_CAPTURE_ALREADY_FAILED`가 반환됩니다. 실패 사유를 확인하려고 승인 API를 다시 호출하지 마세요.

결제 승인 요청은 구매자가 결제 의사를 확정한 당일 자정까지 유효합니다.

실패 코드별 처리 방법은 [문제 해결](/troubleshooting#결제-승인-실패-코드)에서 확인하세요.

자세한 처리 방법은 [결제 승인](/payment-capture)에서 확인하세요.

## 다음 단계

- 승인된 결제의 취소는 [결제 취소](/payment-cancellation)를 참고하세요.
- 결제창을 열기 전에 구매자에게 [EOB 점검 시간](/operations#eob-점검-시간)을 안내해주세요.
- 구매자에게 결제 수단을 미리 등록받으려면 [등록 전용 위젯](/integration-methods#등록-전용-위젯)을 참고하세요.
- 로그인한 회원의 결제에서 문자 인증을 생략하려면 [위임 인증](/delegated-authentication)을 참고하세요.
