이미 만들어진 셀러 안에 새 프로젝트(=app)를 추가한다. 본 서비스와 테스트 환경을 분리하거나, 한 셀러가 운영하는 여러 브랜드를 따로 정산·집계하려고 할 때 쓴다.
핵심 요약
- 셀러 생성 시 자동으로 만들어지는 기본 프로젝트 외에 추가가 필요할 때만 호출한다. 신규 셀러용 첫 프로젝트는 가맹점 생성 한 번으로 만들어진다.
provider_id가 리셀러 본인 하위 셀러가 아니면PROVIDER_NOT_FOUND가 떨어진다.- 응답에는 프로젝트 기본 정보 7 개 필드(
app_id,provider_id,app_name,real,desc,unit,status) 가 담긴다. 결제 연동키는 포함되지 않는다. 연동키와 PG 리소스는 PG 리소스 갱신 에서 별도로 받는다. unit기본값은KRW,real기본값은실물이다.timezone은 문서상 선택이 아니라 사실상 필수다 — 생략하면APP_TIMEZONE_INVALID로 떨어진다.
API 정보
POST
https://api.bootpay.co.kr/v2/reseller/seller/appBasic Auth (리셀러 계정 키)요청 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
provider_id |
String | 필수 | 프로젝트를 추가할 셀러의 provider_id |
name |
String | 필수 | 프로젝트명. 콘솔과 영수증 표시에 사용 |
desc |
String | 선택 | 프로젝트 설명 |
unit |
String | 선택 | 결제 통화. KRW 또는 USD 만 허용한다. 기본 KRW. 그 외 값은 APP_UNIT_INVALID 로 거부된다 |
real |
String | 선택 | 거래 상품 유형. 실물 또는 비실물. 기본 실물 |
timezone |
String | 필수 | 프로젝트 타임존 (예: Asia/Seoul). 생략하면 APP_TIMEZONE_INVALID 로 거부된다 |
실물 vs 비실물
물리적 배송이 발생하는 상품(쇼핑몰, 식음료) 은 실물, 디지털 콘텐츠 / 구독 / 충전금은 비실물 로 설정한다. 일부 PG 가 사용 가능한 결제수단 목록을 이 값으로 분기한다. 판별은 실물 문자열 일치로만 이뤄지므로, 실물 이 아닌 값은 모두 비실물로 저장된다.
timezone 은 사실상 필수
timezone 은 요청에서 생략하면 서버 기본값이 채워지지 않고 그대로 검증 단계로 넘어가 APP_TIMEZONE_INVALID (223) 가 떨어진다. 항상 명시해서 보낸다.
코드 예제
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/app', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': RESELLER_AUTH
},
body: JSON.stringify({
provider_id: '65a1c0aa8f1b5b00367a0001',
name: '한입가게 — 정기구독',
desc: '월 정기구독 전용 프로젝트',
unit: 'KRW',
real: '비실물',
timezone: 'Asia/Seoul'
})
})
const data = await res.json()
// data.app_id 저장
console.log(data)javascriptimport base64, os, requests
auth = 'Basic ' + base64.b64encode(
f"{os.environ['BOOTPAY_RESELLER_CLIENT_KEY']}:{os.environ['BOOTPAY_RESELLER_SECRET_KEY']}".encode()
).decode()
payload = {
'provider_id': '65a1c0aa8f1b5b00367a0001',
'name': '한입가게 — 정기구독',
'desc': '월 정기구독 전용 프로젝트',
'unit': 'KRW',
'real': '비실물',
'timezone': 'Asia/Seoul'
}
res = requests.post(
'https://api.bootpay.co.kr/v2/reseller/seller/app',
json=payload,
headers={'Authorization': auth}
)
print(res.json())pythonRESELLER_AUTH=$(printf '%s' "$BOOTPAY_RESELLER_CLIENT_KEY:$BOOTPAY_RESELLER_SECRET_KEY" | base64)
curl -X POST 'https://api.bootpay.co.kr/v2/reseller/seller/app' \
-H "Authorization: Basic $RESELLER_AUTH" \
-H 'Content-Type: application/json' \
-d '{
"provider_id": "65a1c0aa8f1b5b00367a0001",
"name": "한입가게 — 정기구독",
"desc": "월 정기구독 전용 프로젝트",
"unit": "KRW",
"real": "비실물",
"timezone": "Asia/Seoul"
}'bash응답
{
"app_id": "65a1c0ab8f1b5b00367a0010",
"provider_id": "65a1c0aa8f1b5b00367a0001",
"app_name": "한입가게 — 정기구독",
"real": { "name": "비실물", "value": 0, "desc": "" },
"desc": "월 정기구독 전용 프로젝트",
"unit": "KRW",
"status": 20
}json응답 파라미터
| 파라미터 | 타입 | 설명 |
|---|---|---|
| app_id | String | 생성된 프로젝트 식별자 |
| provider_id | String | 소속 셀러 |
| app_name | String | 프로젝트명 |
| real | Object | 거래 상품 유형. { name, value, desc } 구조이고 name 은 실물 / 비실물 / 실물&비실물 중 하나다 |
| desc | String | 프로젝트 설명 |
| unit | String | 결제 통화 |
| status | Number | 프로젝트 상태. 기본값 20 (심사통과) |
결제 연동키
이 응답에는 결제 연동키가 포함되지 않는다. 결제수단까지 붙여야 의미가 있으므로 PG 리소스 갱신 을 이어서 호출하면 application_keys 묶음을 받는다.
에러 코드
| 코드 | 메시지 | 대처 방법 |
|---|---|---|
API_ONLY_RESELLER |
리셀러만 이용이 가능한 API 다 | 리셀러 권한 계정 키로 호출한다 |
PROVIDER_NOT_FOUND (300) |
본인 하위 셀러가 아니다 | provider_id 가 본인 리셀러 소속인지 확인한다 |
APP_REAL_GOOD_INVALID (221) |
판매타입(real) 이 유효하지 않다 |
실물 또는 비실물 로 보낸다 |
APP_UNIT_INVALID (222) |
화폐유형(unit) 이 유효하지 않다 |
KRW 또는 USD 로 보낸다 |
APP_TIMEZONE_INVALID (223) |
타임존이 비었거나 유효하지 않다 | timezone 을 Asia/Seoul 같은 유효한 값으로 항상 명시한다 |
APP_NAME_BLANK (220) |
프로젝트 이름이 비어 있다 | name 을 채워서 보낸다 |