sayren Docs

배송비와 출고지·반품지

배송 묶음, 무료배송 기준, 제주·도서산간 추가 배송비, 출고지·반품지 주소록

배송비 규칙을 정하고 출고지·반품지를 등록해 상품마다 지정합니다. 배송비는 배송 묶음마다 한 번 붙고, 제주·도서산간 추가 배송비는 배송지를 받은 뒤 확정됩니다.

준비

  • 배송비 규칙: 소유자·관리자 또는 store:rw
  • 출고지·반품지 주소록 조회: 소유자·관리자 또는 store:r(액세스 토큰·연동 앱·AI 에이전트 포함)
  • 출고지·반품지 주소록 등록·수정·삭제·기본 지정: 상점 플랫폼으로 로그인한 소유자·관리자만(액세스 토큰·연동 앱·AI 에이전트 불가)
  • 상품에 배송 정책·주소 지정: 소유자·관리자·스태프 또는 product:rw

1. 상점 배송비 규칙

상점 플랫폼에서 설정 › 배송으로 이동합니다(소유자·관리자).

  1. 배송비 규칙 카드에 아래 네 값을 입력합니다. 전체 무료배송은 스위치를 켜고 기준액을 넣습니다.
  2. **[저장]**을 누릅니다. 바꾼 값은 새 주문서부터 적용됩니다.
항목 (API 필드)뜻기본값
기본 배송비 (baseDeliveryFee)상품 등록에서 배송비를 비우면 쓰는 값3000
전체 무료배송 기준액 (freeThreshold)주문 상품 금액 합이 이 값 이상이면 모든 묶음의 기본 배송비가 0. null이면 끔null
제주 추가 배송비 (jejuSurcharge)묶음마다 더함0
도서산간 추가 배송비 (isolatedSurcharge)묶음마다 더함0

API: PATCH /v1/store의 shippingPolicy(준 항목만 바뀜, 모르는 항목은 400). 현재 값은 GET /v1/store로 전부 옵니다.

{ "shippingPolicy": { "baseDeliveryFee": 3500, "freeThreshold": 50000, "jejuSurcharge": 3000, "isolatedSurcharge": 5000 } }

2. 배송 묶음

같은 출고지 + 같은 배송 정책(배송비 유형·배송비·무료배송 기준금액)인 상품은 한 묶음이고 배송비가 한 번 붙습니다.

  • 출고지가 다르거나 배송비가 다르면 다른 묶음입니다.
  • 출고지를 비운 상품은 상점 기본 출고지로 봅니다. 기본 출고지를 지정한 상품과 한 묶음입니다.
  • 무료배송 상품끼리는 한 묶음이고 배송비는 0입니다.
  • 주문서의 delivery.bundleCount가 배송비를 부과한 횟수입니다. 묶음은 주문 시점에 고정됩니다.
  • 배송 없는 상품(MANUAL)은 묶음에 들지 않고 배송비가 없습니다(비실물 상품 판매하기).

3. 무료배송 기준 두 가지

기준정하는 곳비교 금액
상품별 조건부 무료상품의 CONDITIONAL_FREE + conditionalFreeAmount그 묶음의 상품 금액 합
상점 전체 무료shippingPolicy.freeThreshold배송 상품 금액 합(배송이 없는 상품 제외)

계산 순서입니다.

  1. 묶음마다 소계를 조건부 무료 기준과 비교합니다.
  2. 배송 상품 금액 합이 전체 기준을 넘으면 모든 묶음의 기본 배송비를 0으로 만듭니다(delivery.freeByThreshold: true).
  3. 제주·도서산간 추가 배송비를 묶음마다 더합니다.

4. 제주·도서산간 추가 배송비

배송지 우편번호가 아래 범위면 추가 배송비가 묶음마다 붙습니다. 무료배송이어도 부과합니다. 범위는 플랫폼이 고정하고 금액만 상점이 정합니다. 설정 › 배송의 추가 배송비 지역 카드에서도 봅니다.

5. 배송지를 받아 금액을 확정하기

주문서를 만들 때는 배송지를 몰라 추가 배송비가 빠져 있습니다(delivery.zipCode: null, remoteSurcharge: 0). 장바구니 요약도 같습니다.

  1. 주문서 생성 — sdk.checkout.create(). 묶음별 기본 배송비까지 반영됩니다.
  2. 미리보기 — 배송지를 입력하거나 고칠 때 sdk.checkout.quoteDelivery(). 주문서를 바꾸지 않습니다.
  3. 결제 시작 — POST /storefront/v1/checkout/{checkoutId}/payment가 배송지로 다시 계산해 그 금액으로 결제합니다. 응답 amounts가 확정 금액입니다.
const quote = await sdk.checkout.quoteDelivery(checkout.checkoutId, { zipCode: "63000" });
// quote.amounts: { productAmount: 40000, deliveryFee: 6000, totalAmount: 46000 }
const start = await sdk.checkout.startPayment(checkout.checkoutId, { option, returnUrl, shippingAddress });
// start.amounts.totalAmount === 46000

미리보기를 건너뛰면 결제창 금액이 갑자기 늘 수 있습니다. payments.start()로 결제창까지 한 번에 열면 확정 금액이 반환되지 않으니 미리보기로 금액을 보여 주십시오(결제 연동).

delivery 필드뜻
baseFee묶음별 기본 배송비의 합
remoteSurcharge지역 추가 배송비 합. 배송지를 모르면 0
remoteArea · remoteAreaLabelNONE·JEJU·ISOLATED와 안내 이름(해당 없으면 null)
bundleCount묶음 수(배송비 부과 횟수)
freeByThreshold전체 무료배송 기준으로 면제했는지
zipCode반영한 우편번호. null이면 배송지 미반영
미리보기 오류의미
400 VALIDATION_FAILED우편번호가 숫자 5자리가 아님
404 CHECKOUT_NOT_FOUND주문서 없음
409 CHECKOUT_EXPIRED주문서 만료(30분). 다시 만듭니다
409 ALREADY_PAID이미 결제된 주문서

6. 상품의 배송 정책

배송 상품 등록·수정의 배송 정책 섹션입니다(상품 등록). API에서는 상품의 fulfillment.shipping입니다 (fulfillment.type이 SHIPPING).

필드뜻
deliveryTypeFREE · PAID · CONDITIONAL_FREE. 등록에서 생략하면 PAID
deliveryFee등록에서 생략하면 그 시점의 상점 기본 배송비를 숫자로 저장합니다. 나중에 기본값을 바꿔도 움직이지 않습니다. FREE면 0이거나 생략합니다
conditionalFreeAmount조건부 무료의 묶음 기준금액. CONDITIONAL_FREE면 필수이고 그 밖에는 null입니다
shippingAddressId · returnAddressId등록에서 생략하면 기본 출고지·반품지를 저장하고, null이면 비워 두고 상점 기본을 따릅니다
{ "fulfillment": { "type": "SHIPPING", "shipping": { "deliveryType": "CONDITIONAL_FREE", "deliveryFee": 3000, "conditionalFreeAmount": 50000 } } }
  • 수정(PUT·PATCH)에서 fulfillment를 보내면 shipping의 다섯 필드를 모두 보냅니다. 빠뜨리면 400입니다. 바꾸지 않으려면 fulfillment를 생략합니다.
  • FREE인데 배송비가 0이 아니거나, CONDITIONAL_FREE가 아닌데 기준금액을 주면 400입니다. 값을 조용히 바꿔 저장하지 않습니다.
  • 반품·교환 배송비는 이 필드가 아니라 상품의 refundPolicy입니다(환불 정책 덮어쓰기).
  • 반품 안내에 쓰는 반품지는 주문 시점의 값입니다. 주문 뒤 상품의 반품지를 바꿔도 이미 들어온 주문의 안내는 바뀌지 않습니다.

이행 방식

상품의 fulfillment.methods로 구매자가 고를 수 있는 이행 방식을 둡니다. 첫 값이 기본입니다.

방식뜻받는 유형배송지·배송비
CARRIER택배SHIPPING있음
DIRECT직접 배달SHIPPING있음
PICKUP방문 수령SHIPPING · MANUAL없음
PROVIDED제공 처리MANUAL없음
{ "fulfillment": { "type": "SHIPPING", "shipping": { "deliveryType": "PAID", "deliveryFee": 3000, "conditionalFreeAmount": null, "shippingAddressId": null, "returnAddressId": null }, "methods": ["CARRIER", "PICKUP"] } }
  • 생략하면 등록은 유형 기본(SHIPPING은 CARRIER, MANUAL은 PROVIDED)이고, 수정은 지금 값을 유지합니다. 유형을 바꾸면 유형 기본으로 돌아갑니다.
  • 구매자는 주문서를 만들 때 fulfillmentMethod로 고릅니다. 모든 줄에 같은 방식을 적용하고, 허용하지 않는 상품이 있으면 400 FULFILLMENT_METHOD_NOT_ALLOWED입니다(error.details.productIds). 다른 방식으로 바꾸려면 주문서를 새로 만듭니다.
  • 방문 수령은 배송 묶음에 들어가지 않아 배송비가 없고, 결제 시작에 배송지를 보내지 않아도 됩니다.
  • 주문상품의 fulfillmentSnapshot.method에 고른 방식이 남습니다.

픽업 장소

방문 수령을 받는 상점은 /v1/pickup-locations에 수령 장소를 등록합니다(상점당 20개, 이름·주소·연락처·수령 가능 시간). 조회는 store:r, 등록·수정·삭제는 상점 플랫폼의 OWNER·ADMIN입니다.

  • 구매자는 GET /storefront/v1/pickup-locations로 쓰는 장소를 보고, 주문서를 만들 때 pickupLocationId로 고릅니다.
  • 쓰는 장소가 있는데 방문 수령에서 고르지 않으면 400 PICKUP_LOCATION_REQUIRED, 없거나 쓰지 않는 장소면 400 PICKUP_LOCATION_NOT_FOUND, 다른 방식에 주면 400 PICKUP_LOCATION_NOT_APPLICABLE입니다. 등록한 장소가 없으면 장소 없이 받습니다.
  • 주문상품의 fulfillmentSnapshot.pickupLocation에 고른 장소의 그때 값이 남습니다. 장소를 고치거나 지워도 지난 주문의 안내는 바뀌지 않습니다.

7. 출고지·반품지 주소록

상점 플랫폼에서 설정 › 주소록으로 이동합니다(소유자·관리자).

  1. 출고지 또는 반품지 영역에서 **[주소 추가]**를 누릅니다.
  2. 주소 이름·받는 사람·휴대폰·우편번호·주소·상세주소를 입력하고 **[저장]**을 누릅니다.
  3. 기본으로 쓸 주소에 **[기본으로 지정]**을 누릅니다.
  • 유형별 최대 10개, 기본 주소 1개입니다. 첫 주소는 자동으로 기본입니다.
  • 주소를 고치면 그 주소를 쓰는 상품에 바로 반영됩니다. 받은 주문의 묶음은 바뀌지 않습니다.
  • 반품지는 반품·교환 수거 안내에 쓰이고 묶음 판정에는 쓰이지 않습니다.
하는 일APIStore SDK
목록(?type=SHIPPING)GET /v1/seller-addressessellerAddresses.list(type)
등록POST /v1/seller-addressessellerAddresses.create(body)
상세GET /v1/seller-addresses/{addressId}
수정(전체 교체)PUT /v1/seller-addresses/{addressId}sellerAddresses.update(id, body)
삭제DELETE /v1/seller-addresses/{addressId}sellerAddresses.remove(id)
기본 지정POST /v1/seller-addresses/{addressId}/defaultsellerAddresses.setDefault(id)

SDK의 create·update·setDefault는 본문을 돌려주지 않습니다. 저장값은 list()로 다시 읽습니다.

목록·상세 조회는 store:r 스코프만 있으면 됩니다. AI 에이전트가 반품 안내 문구에 반품지를 쓰거나 상품에 출고지를 지정할 때 이 조회로 주소 id를 찾습니다. 등록·수정·삭제·기본 지정은 액세스 토큰·연동 앱으로 부르면 403 INSUFFICIENT_ROLE입니다.

오류의미
400 INVALID_ADDRESS_TYPE출고지 자리에 반품지(또는 반대)를 지정함
403 INSUFFICIENT_ROLE소유자·관리자가 아니거나 액세스 토큰·연동 앱으로 호출함
404 ADDRESS_NOT_FOUND이 상점의 주소가 아님
409 ADDRESS_LIMIT_EXCEEDED유형별 10개 초과
409 DEFAULT_ADDRESS_UNDELETABLE기본 주소. 다른 주소를 기본으로 지정한 뒤 지웁니다
409 ADDRESS_IN_USE상품이 쓰는 주소. 상품의 주소를 다른 값이나 null로 바꾼 뒤 지웁니다

8. 취소·반품과 배송비

묶음의 남은 수량이 0이 될 때만 그 묶음 배송비(추가 배송비 포함)를 한 번 환불하고, 낸 배송비를 넘기지 않습니다. 누가 부담하는지는 환불 정책과 배송비에 있습니다.

자주 막히는 문제

증상해결
배송비가 두 번 붙음출고지나 배송 정책이 다른 상품입니다(delivery.bundleCount)
무료배송인데 배송비가 있음제주·도서산간 추가 배송비입니다
결제 금액이 주문서보다 큼추가 배송비 지역입니다. 배송지 입력 뒤 미리보기를 부릅니다
상품 배송비가 예상과 다름등록 당시 기본 배송비가 저장됐습니다. 상품에서 값을 지정합니다

다음 단계

이 페이지 목차