# JavaScript SDK 등록 연동

point3 JavaScript SDK로 등록 전용 위젯을 연동합니다. 먼저 [JavaScript SDK 설정 및 초기화](/sdk-environment)을 완료하세요. 등록에는 결제 세션이나 금액 설정이 필요하지 않습니다.

**등록 전용 위젯은 필수가 아닌 선택적 기능**으로, 결제 위젯만 연동해도 구매자가 결제 수단을 등록하는 데에 문제가 없습니다.

다만, 사용자 경험을 위하여 선택적으로 등록 전용 위젯을 연동하여 결제 퍼널을 개선할 수 있습니다. 등록 전용 위젯은 결제 위젯과 달리 세션이나 금액 설정이 필요하지 않으며, 구매자가 등록만 진행할 수 있는 별도의 등록창입니다.

앱에서는 [결제창과 같은 방법](/integration-methods#react-native-flutter-네이티브-앱)으로 등록창을 연동한 HTML을 WebView로 띄웁니다.

## 등록 연동

### point3.widgets()

`widgets()` 메서드로 등록 서비스를 초기화합니다.

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

```ts title="TypeScript"
const widgets = point3.widgets({
  customerKey: Point3.ANONYMOUS
})
```

`point3`는 [SDK 설정 및 초기화](/sdk-environment)에서 초기화한 객체입니다.

#### 파라미터

| 이름 | 필수 여부 | 타입 | 설명 |
| --- | --- | --- | --- |
| `customerKey` | 필수 | `string` | `Point3.ANONYMOUS` 고정 |

#### 응답

등록창을 열 수 있는 `widgets` 객체를 반환합니다.

### widgets.requestPayment()

`requestPayment()`에 `orderId: ''`를 전달하면 등록창을 엽니다. 등록에는 `setAmount()` 호출이나
결제 세션 생성이 필요하지 않습니다.

```js title="JavaScript"
await widgets.requestPayment({
  orderId: '',
  orderName: '등록',
  successUrl: 'https://merchant.example/registration/success',
  failUrl: 'https://merchant.example/registration/fail'
})
```

```ts title="TypeScript"
await widgets.requestPayment({
  orderId: '',
  orderName: '등록',
  successUrl: 'https://merchant.example/registration/success',
  failUrl: 'https://merchant.example/registration/fail'
})
```

#### 파라미터

| 이름 | 필수 여부 | 타입 | 설명 |
| --- | --- | --- | --- |
| `orderId` | 필수 | `string` | 빈 문자열 `''`을 고정 사용합니다. |
| `orderName` | 필수 | `string` | `'등록'` 문자열을 고정 사용합니다. |
| `successUrl` | 필수 | `string` | 등록 성공 후 이동할 가맹점의 HTTPS 절대 URL입니다. |
| `failUrl` | 필수 | `string` | 등록을 완료하지 못했을 때 이동할 가맹점의 HTTPS 절대 URL입니다. |

로컬 개발에서는 `localhost`, `127.0.0.1`, `[::1]`에 한해 HTTP 결과 URL을 사용할 수 있습니다. 운영 환경에서는 HTTPS 주소를 사용하세요.

#### 응답

사용자가 등록창에서 등록을 마치면 SDK가 `successUrl`에 `payerId`를 추가해 이동합니다.
예를 들어 다음과 같이 이동합니다.

```text
https://merchant.example/registration/success?payerId=payer:00000000000000000000000000
```

결과 페이지에서는 다음과 같이 값을 읽을 수 있습니다.

```js title="JavaScript"
const params = new URLSearchParams(window.location.search)
const payerId = params.get('payerId')
```

```ts title="TypeScript"
const params = new URLSearchParams(window.location.search)
const payerId: string | null = params.get('payerId')
```

받은 `payerId`를 가맹점 회원 정보에 저장하고, 다음 결제의 `customerKey`로 사용하세요. 이미 결제 세션 조회를 통해 저장된 값이 있다면, 해당 값을 신뢰하고 화면에서 받은 값으로 덮어쓰지 마세요. 자세한 내용은 [구매자 아이디](/payer-id#등록-전용-위젯)를 참고하세요.

## 취소와 오류 처리

취소하거나 등록을 완료하지 못하면 SDK가 `failUrl`에 `code`와 `message`를 추가해 이동합니다.
가맹점 화면은 `message`가 아닌 `code`를 기준으로 처리하고, 다음과 같은 안내를 표시하세요.

| 코드 | 안내 문구 예시 |
| --- | --- |
| `REGISTRATION_CANCELLED` | 등록이 취소됐습니다. |
| `AUTHENTICATION_EXPIRED` | 인증이 만료됐습니다. 등록을 다시 시작하세요. |
| `REGISTRATION_FAILED` | 등록을 완료하지 못했습니다. 안내를 확인한 뒤 다시 시도하세요. |
| `REGISTRATION_RESULT_UNAVAILABLE` | 등록 결과를 확인할 수 없습니다. |

위 표에 없는 `code`는 "등록을 완료하지 못했습니다."로 안내하세요.

### SDK 초기화·시작 전 오류

다음 오류는 `failUrl`로 전달되지 않습니다. SDK 초기화와 등록 요청을 `try/catch`로 감싸고 오류 객체의 `code`를 확인하세요.

| 오류 코드 | 처리 |
| --- | --- |
| `INVALID_CLIENT_KEY` | 발급받은 `client_id`와 `client-...` 형식을 확인하세요. |
| `INVALID_PAYMENT_REQUEST` | 빈 `orderId`, `orderName`, 결과 URL을 확인하세요. |
| `PAYMENT_REQUEST_IN_PROGRESS` | 이미 열린 등록창의 진행을 마무리하세요. |
| `BROWSER_NOT_READY` | 문서 준비 상태, 보안 컨텍스트와 `crypto.randomUUID()` 지원을 확인하세요. |

등록창은 SDK가 닫으므로 가맹점에서 직접 제거하지 마세요. 취소·오류로 종료된 뒤에는 사용자가
버튼을 눌러 다시 시작할 수 있게 하세요. 인증이 만료됐다면 본인인증부터 다시 진행합니다.

## 등록 후 결제

등록 후 결제하려면 가맹점 서버에서 별도의 결제 세션을 생성하세요.
[결제 생성](/payment-creation), [SDK 결제 연동](/sdk-payment-window), [결제 승인](/payment-capture)을 참고하세요.
