# 네이버페이 주문형 설정 방법 — 망보드 쇼핑몰
> 망보드(MangBoard) 기반 쇼핑몰에 네이버페이 주문형(SDK v2)을 연동하는 실전 가이드입니다.
> 실제 검수를 통과하며 발생한 이슈와 해결 방법을 포함합니다.
---
# # 1. 네이버페이 주문형이란?
내 웹사이트에서 네이버페이로 결제할 수 있게 해주는 서비스입니다. 네이버 스토어나 구글 쇼핑과는 **별개**입니다.
```mermaid
flowchart LR
subgraph 내사이트["내 웹사이트 (내가 관리)"]
A["상품 상세 페이지"]
B["장바구니"]
end
subgraph 네이버페이["네이버페이 (결제 처리)"]
C["결제창"]
D["주문/배송 관리"]
end
A -->|"버튼 클릭"| C
B -->|"버튼 클릭"| C
C --> D
style 네이버페이 fill:#03C75A,color:#fff
```
| 구분 | 네이버페이 주문형 | 네이버 스토어 | 구글 쇼핑 |
|------|------------------|-------------|----------|
| 역할 | 내 사이트의 결제 수단 | 네이버 쇼핑 플랫폼 입점 | 구글 검색에 상품 카드 노출 |
| 판매 장소 | **내 웹사이트** | 네이버 플랫폼 | **내 웹사이트** |
| 검색 노출 | 쇼핑 탭 미노출 | 네이버 쇼핑 탭 노출 | 구글 쇼핑 탭 노출 |
| 입점 비용 | 무료 | 수수료 (기본 2.5~3%) | 무료 |
> 네이버페이 주문형은 **결제 수단**일 뿐 **상품 노출 채널**이 아닙니다.
---
# # 2. 전체 연동 흐름
```mermaid
flowchart TD
A["1. 네이버페이센터 가맹점 가입"] --> B["2. 인증키 발급<br/>Button KEY / 상점 ID / 인증키"]
B --> C["3. SDK v2 마이그레이션<br/>PHP + JS 수정"]
C --> D["4. 검수모드 설정<br/>use_naver_pay = 3"]
D --> E["5. 테스트 결제"]
E --> F["6. 검수 신청<br/>테스트 계정 + XML URL 제출"]
F --> G{"검수 피드백"}
G -->|"수정 요청"| C
G -->|"승인"| H["7. 운영 전환<br/>use_naver_pay = 2"]
H --> I["✅ 오픈 완료"]
style A fill:#E8F5E9
style I fill:#C8E6C9
```
---
# # 3. 사전 준비
## # 3.1 필요한 인증값
| 항목 | 발급처 | 용도 |
|------|--------|------|
| Button KEY | 네이버페이센터 | SDK 초기화 |
| 상점 ID (MID) | 네이버페이센터 | 주문등록 API |
| 인증키 (CERTI_KEY) | 네이버페이센터 | 주문등록 API |
| Account ID | 네이버페이센터 > 내 정보 | WCS 애널리틱스 |
## # 3.2 망보드 관리자 설정
> **경로**: 망보드 관리자 → 상점설정 → 네이버 페이 (주문형)
| 설정 항목 | 검수 시 | 운영 시 |
|----------|--------|--------|
| 네이버페이 모드 | 네이버 검수모드(상품내용+장바구니) | 사용함(상품내용+장바구니) |
| Button KEY | 발급받은 값 | 동일 |
| 상점 ID | 발급받은 값 | 동일 |
| 인증키 | 발급받은 값 | 동일 |
| Account ID | 발급받은 값 | 동일 |
---
# # 4. SDK v1 → v2 마이그레이션
## # 4.1 주요 변경사항
```mermaid
flowchart LR
subgraph v1["SDK v1 (기존)"]
A1["별도 PC/모바일 스크립트"]
A2["naver.NaverPayButton.apply()"]
A3["동기 핸들러"]
A4["직접 페이지 이동"]
end
subgraph v2["SDK v2 (변경)"]
B1["통합 SDK (PC/모바일)"]
B2["Npay.order.create()"]
B3["async 핸들러 + Promise"]
B4["{key, merchantId} 반환"]
end
A1 --> B1
A2 --> B2
A3 --> B3
A4 --> B4
```
| 항목 | SDK v1 | SDK v2 |
|------|--------|--------|
| SDK URL | `//pay.naver.com/customer/js/naverPayButton.js` | `https://npay-order.pstatic.net/assets/button/latest/npay.button.js` |
| 모바일 | 별도 URL | 통합 |
| 버튼 API | `naver.NaverPayButton.apply({...})` | `Npay.order.create({...})` |
| 핸들러 | `BUY_BUTTON_HANDLER: buy_nc` (동기) | `onBuyClick: async function()` (Promise) |
| 반환값 | 없음 (직접 이동) | `{ key, merchantId }` 객체 |
## # 4.2 SDK 로딩 (검수/운영 자동 분기)
```mermaid
flowchart TD
A["use_naver_pay 값 확인"] --> B{"== 3 ?"}
B -->|"YES (검수모드)"| C["test-pay.naver.com<br/>샌드박스 SDK 로드"]
B -->|"NO (운영)"| D["npay-order.pstatic.net<br/>프로덕션 SDK 로드"]
C --> E["test- 접두사 계정에게만<br/>버튼 노출"]
D --> F["전체 회원에게 버튼 노출"]
```
> 검수모드에서는 일반 사용자에게 버튼이 보이지 않습니다.
## # 4.3 버튼 렌더링 (functions.php)
```javascript
// SDK v2 버튼 생성
var container_id = 'npay-btn-' + uniqid();
// 컨테이너 div (최소 200px × 150px)
document.write('<div id="' + container_id + '" style="min-width:200px;height:150px;"></div>');
Npay.order.create({
buttonKey: 'BUTTON_KEY',
containerId: container_id,
orderRegistrationVersion: '1.0', // 기존 백엔드 API와 호환
type: 'template',
colorTheme: 'green',
enable: true,
components: {
wishlist: true, // 찜하기
talkTalk: false, // 톡톡
benefitMessage: true, // 혜택 문구
benefitCoachMark: true
},
onBuyClick: async function() {
// 주문등록 API 호출 → 결과 반환
return { key: 'ORDER_ID', merchantId: 'SHOP_ID' };
},
onWishlistClick: async function() {
return { merchantId: 'SHOP_ID', payProductId: 'ITEM_ID' };
}
});
```
## # 4.4 구매 핸들러 (JS)
```mermaid
sequenceDiagram
participant User as 사용자
participant SDK as 네이버페이 SDK
participant JS as buy_nc()
participant WP as WP AJAX
participant NP as 네이버페이 API
User->>SDK: 버튼 클릭
SDK->>JS: onBuyClick() 호출
JS->>JS: 상품 옵션 검증
JS->>WP: AJAX POST (주문등록 데이터)
WP->>NP: 주문등록 API 호출
NP-->>WP: ORDER_ID + SHOP_ID
WP-->>JS: JSON 응답
JS-->>SDK: Promise resolve {key, merchantId}
SDK->>NP: 결제창 이동
```
**핵심**: 핸들러는 `async function`이며, 반드시 `{ key, merchantId }`를 반환해야 합니다.
## # 4.5 AJAX URL 변환 (망보드 호환)
망보드의 `mb_urls["commerce_api"]` 값이 상대경로(`"mb_commerce"`)인데, `jQuery.ajax()`에 직접 전달하면 404가 발생합니다. 망보드 내장 `sendDataRequest()`와 동일하게 변환해야 합니다:
```javascript
var ajaxUrl = mb_urls["commerce_api"];
if (String(ajaxUrl).indexOf('http') !== 0) {
data = data + "&action=" + ajaxUrl + "&admin_page=" + mb_ajax_object.admin_page
+ "&hybrid_app=" + mb_hybrid_app;
ajaxUrl = mb_ajax_object.ajax_url; // → /wp-admin/admin-ajax.php
}
```
---
# # 5. 백엔드 API
## # 5.1 주문등록 API
| 항목 | 내용 |
|------|------|
| 엔드포인트 | `POST /customer/api/order.nhn` |
| 프로토콜 | 쿼리스트링 (`application/x-www-form-urlencoded`) |
| 테스트 환경 | `test-pay.naver.com` (검수모드 시) |
**필수 파라미터**:
| 파라미터 | 설명 |
|----------|------|
| SHOP_ID | 상점 ID |
| CERTI_KEY | 인증키 |
| ITEM_ID | 상품 번호 |
| ITEM_NAME | 상품명 |
| ITEM_COUNT | 수량 |
| ITEM_TPRICE | 총금액 (수량 × 단가) |
| ITEM_UPRICE | 단가 |
| SHIPPING_TYPE | `PAYED` 또는 `FREE` |
| SHIPPING_PRICE | 배송비 |
| TOTAL_PRICE | 결제 총액 (상품 + 배송비) |
## # 5.2 배송비 처리 주의사항
```mermaid
flowchart TD
A["상품 개별 배송비 조회"] --> B{"값이 0?"}
B -->|"YES"| C["전역 배송비 설정 참조<br/>mbw_get_option(shipping_cost)"]
B -->|"NO"| D["상품 개별 배송비 사용"]
C --> E{"주문 금액 ≥ 무료배송 기준?"}
E -->|"YES"| F["SHIPPING_TYPE = FREE<br/>SHIPPING_PRICE = 0"]
E -->|"NO"| G["SHIPPING_TYPE = PAYED<br/>SHIPPING_PRICE = 전역 배송비"]
```
> 망보드에서 상품 개별 배송비를 설정하지 않으면 항상 0이 반환됩니다.
> 0일 때 전역 설정(`shipping_cost`)으로 fallback하는 로직이 필수입니다.
## # 5.3 찜등록 API
| 파라미터 | 설명 |
|----------|------|
| SHOP_ID | 상점 ID |
| CERTI_KEY | 인증키 |
| ITEM_ID | 상품 번호 |
| ITEM_NAME | 상품명 |
| ITEM_UPRICE | 단가 |
| ITEM_IMAGE | 상품 이미지 URL (**https** 여야 함) |
| ITEM_THUMB | 썸네일 URL (**https** 여야 함) |
| ITEM_URL | 상품 페이지 URL |
> 이미지 URL은 반드시 https를 사용하세요. http로 변환하면 검수에서 반려됩니다.
## # 5.4 상품정보 XML 피드
| 항목 | 내용 |
|------|------|
| URL | `https://도메인/?mcp=naver&ITEM_ID=XXX` |
| Content-Type | `application/xml;charset=UTF-8` |
| 필수 항목 | `item@id`, `name`, `url`, `description`, `image`, `thumb`, `price`, `quantity`, `category` |
---
# # 6. 검수 과정에서 발생한 이슈
## # 이슈 요약
```mermaid
flowchart LR
I1["1차<br/>SDK 샌드박스 미사용"] --> I2["2차<br/>AJAX 404 에러"]
I2 --> I3["3차<br/>장바구니 ITEM_ID=0"]
I3 --> I4["4차<br/>장바구니 찜 제거"]
I4 --> I5["5차<br/>이미지 http + NaPm 유실"]
I5 --> I6["✅ 오픈 승인"]
style I6 fill:#C8E6C9
```
## # 6.1 SDK 샌드박스 미사용
**문제**: SDK를 프로덕션 URL로만 로드해서 검수모드에서도 실운영 환경으로 호출됨.
**해결**: `use_naver_pay == 3`일 때 `test-pay.naver.com` SDK를 로드하도록 분기.
## # 6.2 AJAX URL 404 에러
**문제**: `mb_urls["commerce_api"]`가 상대경로(`"mb_commerce"`)인데, `jQuery.ajax()`에 직접 전달하면 `/shop/mb_commerce`로 해석되어 404.
**해결**: `mb_ajax_object.ajax_url`(`wp-admin/admin-ajax.php`)로 변환하는 로직 추가.
## # 6.3 장바구니 ITEM_ID=0
**문제**: 커스텀 상품(추천 조립 PC)을 장바구니에 추가할 때 `product_pid`가 0으로 저장됨.
**해결**:
1. 장바구니 추가 시 올바른 상품 PID 매핑
2. 기존 장바구니 항목에 대한 폴백 로직 (상품명으로 PID 조회)
## # 6.4 장바구니 찜하기 제거
**문제**: 네이버페이 검수팀에서 장바구니 내 찜하기 버튼 제거 요청.
**해결**: `mbw_get_naver_pay_button()`에 `wishlist` 파라미터 추가. 장바구니에서는 `false` 전달.
## # 6.5 이미지 URL http + NaPm 파라미터 유실
**문제**:
1. 찜등록 시 이미지 URL이 https에서 http로 변환됨
2. 네이버페이 찜 목록에서 상품 클릭 시 NaPm 파라미터가 유실됨
**해결**:
1. `str_replace("https://","http://",...)` 제거 → 원본 https 유지
2. 리다이렉트 시 NaPm, NaPm_t, NaPm_bid 파라미터를 보존하는 헬퍼 함수 추가
## # 6.6 배송비 미포함
**문제**: 네이버페이 구매 시 배송비가 0원으로 전송됨.
**해결**: 상품 개별 배송비가 0이면 전역 `shipping_cost` 설정값으로 fallback.
---
# # 7. 찜하기 핸들러 반환값 주의
구매와 찜하기는 **반환값이 다릅니다**:
```mermaid
flowchart LR
subgraph 구매["onBuyClick (구매)"]
A1["{ key: ORDER_ID }"]
A2["{ merchantId: SHOP_ID }"]
end
subgraph 찜["onWishlistClick (찜)"]
B1["{ merchantId: SHOP_ID }"]
B2["{ payProductId: ITEM_ID }"]
end
A1 -.->|"❌ 공유 안 됨"| B1
A2 -.->|"✅ 공유"| B1
```
| 핸들러 | 반환값 | 키 이름 |
|--------|--------|---------|
| 구매 | `{ key, merchantId }` | `key` = 주문 ID |
| 찜 | `{ merchantId, payProductId }` | `payProductId` = 상품 ID |
> 구매와 동일하게 `{ key, merchantId }`를 반환하면 SDK가 찜하기를 처리하지 못합니다.
---
# # 8. 컨테이너 사양
| 항목 | 요구사항 |
|------|----------|
| 최소 너비 | 200px |
| 최대 너비 | 1280px |
| 권장 높이 | 150px |
| 색상 테마 | `green` (기본) 또는 `white` |
---
# # 9. 검수 신청 체크리스트
## # 사전 확인
- [ ] Button KEY, 상점 ID, 인증키, Account ID 입력 완료
- [ ] `use_naver_pay = 3` (검수모드) 설정
- [ ] test- 접두사 테스트 계정 생성
## # SDK v2 마이그레이션
- [ ] PC/모바일 통합 SDK 로드
- [ ] `Npay.order.create()` 적용
- [ ] async 핸들러 + Promise 반환
- [ ] AJAX URL 변환 로직 (망보드 호환)
- [ ] 검수모드 시 샌드박스 SDK 로드
## # 기능 확인
- [ ] 테스트 계정으로만 버튼 노출
- [ ] 일반 사용자에게 버튼 비노출
- [ ] 상품 상세 → 네이버페이 결제창 정상 이동
- [ ] 장바구니 → 네이버페이 결제창 정상 이동
- [ ] 상품정보 XML 정상 응답
- [ ] 배송비 정상 포함
- [ ] 이미지 URL https
- [ ] NaPm 파라미터 보존
## # 검수 신청
- [ ] 테스트 계정 정보 제출
- [ ] 상품정보 XML URL 제출
## # 운영 전환
- [ ] 검수 완료 메일 수신
- [ ] `use_naver_pay = 2` (운영) 변경
- [ ] 프로덕션 SDK 로드 확인
- [ ] 전체 회원에게 버튼 노출 확인
---
# # 10. WCS 유입경로 분석
네이버페이와 별개로, 웹사이트 방문자 유입경로를 분석하는 스크립트입니다:
```mermaid
flowchart TD
A["wp_head"] --> B["wcslog.js 로드"]
B --> C["wcs_add wa = Account ID"]
C --> D["wcs.inflow() 호출<br/>도메인 전달"]
D --> E["wp_footer"]
E --> F["wcs_do() 호출"]
```
> SDK v1/v2와 무관하게 동일하게 동작합니다.
---
# # 11. 다른 사이트에 적용 시 참고
| 항목 | 안내 |
|------|------|
| 동일 계정 사용 가능? | 불가. 별도 신규 가맹점 가입 필요 |
| 기존 인증값 재사용? | 불가. 신규 가입 시 새 인증값 발급 |
| 코드 재사용? | 가능. 동일 마이그레이션 패턴 적용 |
| 망보드가 아닌 경우? | SDK v2 초기화 + async 핸들러 + 주문등록 API만 구현하면 됨 |
---
# # 12. 참고 링크
| 자료 | URL |
|------|-----|
| 네이버페이센터 | https://mkt.naver.com |
| 가맹점 연동 가이드 | 네이버페이센터 > 설정 > 연동 가이드 |
| 네이버 스토어 센터 | https://sell.store.naver.com |
| Google Merchant Center | https://merchants.google.com |
| 이전 | KG 이니시스 관련 기록 | 김재석 | 2026-04-28 |
|---|---|---|---|
| 다음 | 범용 마우스 매크로 프로그램 소개 | 웰컴스 매니저 | 2026-03-25 |