리셀러 계정으로 하위 가맹점(셀러)을 만들고, 셀러의 기본 프로젝트와 첫 결제수단(PG·메서드) 까지 한 트랜잭션 안에서 같이 등록한다. 본사 회원가입 흐름의 마지막 단계에 붙이면 자연스럽다.
핵심 요약
- 셀러를 식별할 외부 키
primary_key가 필수다. 본사 DB 의 회원 ID 와 묶어두면 동일 리셀러 안에서 중복도 자동으로 막힌다. resources배열을 함께 보내면 기본 프로젝트에 PG·결제수단까지 한 번에 붙는다. 비워두면 빈 프로젝트만 만들어진다.- 응답으로 받은
apps[].application_keys와apps[].private_key가 곧 셀러가 결제창에 쓸 키다. 안전한 자리에 저장한다. - 한 트랜잭션이라 중간에 어디가 실패하면 셀러·프로젝트 둘 다 만들어지지 않는다. 같은 키로 다시 호출하면 된다.
API 정보
POST
https://api.bootpay.co.kr/v2/reseller/sellerBasic Auth (리셀러 계정 키)요청 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
primary_key |
String | 필수 | 본사가 관리하는 셀러 식별자. 동일 리셀러 안에서 유일해야 한다 |
company_name |
String | 필수 | 셀러 회사명(사업자 명의) |
email |
String | 필수 | 셀러 대표 이메일. 이 이메일로 부트페이 계정이 함께 생성된다 |
owner_name |
String | 선택 | 대표자명 |
manager_name |
String | 선택 | 담당자명 |
regist_no |
String | 선택 | 사업자등록번호. 하이픈은 무시된다 |
phone |
String | 선택 | 담당자/대표 연락처. 하이픈은 무시된다 |
homepage |
String | 선택 | 서비스 URL |
zip |
String | 선택 | 우편번호 |
address1 |
String | 선택 | 기본 주소 |
address2 |
String | 선택 | 상세 주소 |
send_email |
Boolean | 선택 | true 이면 셀러 이메일로 가입 안내 메일을 발송한다. 기본 false |
resources |
Array | 선택 | 첫 프로젝트에 함께 등록할 PG·결제수단 배열. 형식은 아래 참고 |
resources 배열 형식
각 원소는 PG · 결제수단 · 발급키를 한 묶음으로 갖는다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
pg |
String | 필수 | PG 심볼 (예: nicepay, kcp, inicis, tosspayments). 전체 목록은 PG 코드 참고 |
method |
String | 필수 | 결제수단 심볼 (예: 카드, 계좌이체, 가상계좌, 카드자동). |
sandbox |
Boolean | 선택 | true 면 테스트 모드 키로 설정한다 |
resource |
Object | 필수 | PG 가 발급한 가맹점 키 묶음. 키 이름은 PG·메서드마다 다르다 |
resource 안에 들어가는 키 이름은 PG 사가 정한 그대로다. 나이스페이먼츠 카드라면 mid, merchant_key 같은 식이고, KCP 라면 site_cd, site_key 같은 식이다. 가맹점 발급 통보서에 있는 값을 그대로 넣으면 된다.
코드 예제
import fetch from 'node-fetch'
const RESELLER_AUTH = 'Basic ' + Buffer
.from(`${process.env.BOOTPAY_RESELLER_CLIENT_KEY}:${process.env.BOOTPAY_RESELLER_SECRET_KEY}`)
.toString('base64')
const res = await fetch('https://api.bootpay.co.kr/v2/reseller/seller', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': RESELLER_AUTH
},
body: JSON.stringify({
primary_key: 'host-member-1024',
company_name: '한입가게',
email: 'owner@hanip.shop',
owner_name: '김대표',
manager_name: '박매니저',
regist_no: '1234567890',
phone: '01012345678',
homepage: 'https://hanip.shop',
zip: '06236',
address1: '서울 강남구 테헤란로 123',
address2: '4층',
send_email: true,
resources: [
{
pg: 'nicepay',
method: '카드',
resource: {
mid: 'nicepay00m',
merchant_key: 'EYzu8jGGMfqaDEp76gSckuvnaHHu+...='
}
}
]
})
})
const data = await res.json()
// data.provider_id, data.apps[0].application_keys 저장
console.log(data)javascriptimport base64
import os
import requests
auth_raw = f"{os.environ['BOOTPAY_RESELLER_CLIENT_KEY']}:{os.environ['BOOTPAY_RESELLER_SECRET_KEY']}"
auth = 'Basic ' + base64.b64encode(auth_raw.encode()).decode()
payload = {
'primary_key': 'host-member-1024',
'company_name': '한입가게',
'email': 'owner@hanip.shop',
'owner_name': '김대표',
'manager_name': '박매니저',
'regist_no': '1234567890',
'phone': '01012345678',
'homepage': 'https://hanip.shop',
'zip': '06236',
'address1': '서울 강남구 테헤란로 123',
'address2': '4층',
'send_email': True,
'resources': [
{
'pg': 'nicepay',
'method': '카드',
'resource': {
'mid': 'nicepay00m',
'merchant_key': 'EYzu8jGGMfqaDEp76gSckuvnaHHu+...='
}
}
]
}
res = requests.post(
'https://api.bootpay.co.kr/v2/reseller/seller',
json=payload,
headers={'Authorization': auth}
)
print(res.json())python<?php
$auth = 'Basic ' . base64_encode($_ENV['BOOTPAY_RESELLER_CLIENT_KEY'] . ':' . $_ENV['BOOTPAY_RESELLER_SECRET_KEY']);
$payload = [
'primary_key' => 'host-member-1024',
'company_name' => '한입가게',
'email' => 'owner@hanip.shop',
'owner_name' => '김대표',
'manager_name' => '박매니저',
'regist_no' => '1234567890',
'phone' => '01012345678',
'homepage' => 'https://hanip.shop',
'zip' => '06236',
'address1' => '서울 강남구 테헤란로 123',
'address2' => '4층',
'send_email' => true,
'resources' => [
[
'pg' => 'nicepay',
'method' => '카드',
'resource' => [
'mid' => 'nicepay00m',
'merchant_key' => 'EYzu8jGGMfqaDEp76gSckuvnaHHu+...='
]
]
]
];
$ch = curl_init('https://api.bootpay.co.kr/v2/reseller/seller');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: ' . $auth],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE)
]);
$response = curl_exec($ch);
echo $response;phprequire 'base64'
require 'json'
require 'net/http'
auth = 'Basic ' + Base64.strict_encode64(
"#{ENV['BOOTPAY_RESELLER_CLIENT_KEY']}:#{ENV['BOOTPAY_RESELLER_SECRET_KEY']}"
)
uri = URI('https://api.bootpay.co.kr/v2/reseller/seller')
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json', 'Authorization' => auth)
req.body = {
primary_key: 'host-member-1024',
company_name: '한입가게',
email: 'owner@hanip.shop',
owner_name: '김대표',
manager_name: '박매니저',
regist_no: '1234567890',
phone: '01012345678',
homepage: 'https://hanip.shop',
zip: '06236',
address1: '서울 강남구 테헤란로 123',
address2: '4층',
send_email: true,
resources: [
{ pg: 'nicepay', method: '카드',
resource: { mid: 'nicepay00m', merchant_key: 'EYzu8jGGMfqaDEp76gSckuvnaHHu+...=' } }
]
}.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.bodyrubyRESELLER_AUTH=$(printf '%s' "$BOOTPAY_RESELLER_CLIENT_KEY:$BOOTPAY_RESELLER_SECRET_KEY" | base64)
curl -X POST 'https://api.bootpay.co.kr/v2/reseller/seller' \
-H "Authorization: Basic $RESELLER_AUTH" \
-H 'Content-Type: application/json' \
-d '{
"primary_key": "host-member-1024",
"company_name": "한입가게",
"email": "owner@hanip.shop",
"owner_name": "김대표",
"manager_name": "박매니저",
"regist_no": "1234567890",
"phone": "01012345678",
"homepage": "https://hanip.shop",
"zip": "06236",
"address1": "서울 강남구 테헤란로 123",
"address2": "4층",
"send_email": true,
"resources": [
{ "pg": "nicepay", "method": "카드",
"resource": { "mid": "nicepay00m", "merchant_key": "EYzu8jGGMfqaDEp76gSckuvnaHHu+...=" } }
]
}'bash응답
생성된 셀러 정보와 함께 첫 프로젝트가 apps[] 안에 같이 담겨 온다.
{
"provider_id": "65a1c0aa8f1b5b00367a0001",
"company_alias": null,
"email": "owner@hanip.shop",
"company_name": "한입가게",
"owner_name": "김대표",
"manager_name": "박매니저",
"mail_order_sales_number": null,
"information_manager_name": null,
"biz_tel": null,
"biz_email": null,
"phone": "01012345678",
"homepage": "https://hanip.shop",
"lv": 1,
"regist_no": "1234567890",
"zip": "06236",
"address1": "서울 강남구 테헤란로 123",
"address2": "4층",
"apps": [
{
"app_id": "65a1c0ab8f1b5b00367a0002",
"app_name": "한입가게",
"real": "실물",
"unit": "KRW",
"application_keys": [
{
"kind": "javascript",
"key": "65a1c0ab8f1b5b00367a0003",
"private_key": "..."
}
],
"private_key": "65a1c0ab8f1b5b00367a0004",
"payment_apps": [
{
"pg": "nicepay",
"method": "카드",
"sandbox": false
}
],
"status": 1
}
]
}json응답 파라미터
| 파라미터 | 타입 | 설명 |
|---|---|---|
| provider_id | String | 생성된 셀러의 식별자. 이후 가맹점 조회·프로젝트 추가에 사용 |
| String | 등록된 셀러 이메일 | |
| company_name | String | 셀러 회사명 |
| lv | Number | 가맹점 레벨 (1 = 셀러) |
| apps | Array | 함께 생성된 프로젝트 배열 |
| apps[].app_id | String | 프로젝트(=app) 식별자 |
| apps[].application_keys | Array | 프론트엔드 SDK 가 쓸 결제 연동키 묶음 |
| apps[].application_keys[].key | String | client_key 에 해당. 결제창 호출용 |
| apps[].application_keys[].private_key | String | 백엔드 API 호출용 secret_key |
| apps[].private_key | String | 프로젝트 단위의 백엔드 키 |
| apps[].payment_apps | Array | resources 로 등록한 PG·결제수단 결과 |
키 저장
apps[].application_keys[].key / private_key 는 셀러가 자체적으로 결제창을 띄울 때 쓰는 값이다. 본사 DB 의 셀러 레코드에 묶어 안전하게 저장해두면 된다. 분실 시에는 콘솔에서 재발급해야 한다.
에러 코드
공통 에러
인증·권한 관련 에러는 에러 코드표를 참고한다.
| 코드 | 메시지 | 대처 방법 |
|---|---|---|
API_ONLY_RESELLER |
리셀러만 이용이 가능한 API 다 | 리셀러 권한이 부여된 계정 키로 호출한다 |
PROVIDER_PK_BLANK |
primary_key 가 비어 있다 | primary_key 를 본사 회원 ID 와 묶어 항상 보낸다 |
PROVIDER_PK_EXIST |
동일 primary_key 가 이미 존재한다 | 본사 DB 에서 기존 셀러를 먼저 조회한다. 신규일 때만 호출한다 |
PROVIDER_NAME_INVALID |
회사명이 비어 있다 | company_name 을 채워서 보낸다 |
PROVIDER_EMAIL_INVALID |
이메일이 비어 있거나 형식이 맞지 않다 | RFC 5322 형식의 이메일을 보낸다 |
PG_RESOURCE_NOT_FOUND |
resources[].pg 심볼을 찾지 못했다 |
PG 코드 에서 PG 심볼을 확인한다 |
METHOD_RESOURCE_NOT_FOUND |
resources[].method 심볼을 찾지 못했다 |
PG 가 지원하는 결제수단 심볼인지 확인한다 |
RESOURCE_KEY_BLANK |
resources[].resource 에 PG 가 요구하는 키가 빠져 있다 |
PG 발급 통보서 기준으로 키를 채워서 보낸다 |
PROVIDER_CREATE_FAILED |
셀러 생성이 트랜잭션 도중 실패했다 | 같은 요청을 다시 호출한다. 반복되면 부트페이에 문의 |