🛒

오픈마켓 API 명세

‼️ 업데이트 내용

  • 계정 검증하기 기능이 추가되었습니다. (22/8/31)
  • 사업자 등록번호 검증하기 기능이 추가되었습니다. (22/9/13) 계정 검증하기 요청 URL이 변경되었습니다. (22/9/13)
  • product list의 seller_store store_name으로 변경되었습니다. (22/9/19)
  • product를 수정할 때 전체 값이 아닌 필요한 값만 보내주시면 됩니다.(23/9/22)
  • 23년 9월 22일부로 데이터베이스가 전체 초기화되었습니다.(23/9/22)
 

0. 접속하기/요청 URL

계정

  • 구매자(buyer)
    • ID : buyer1 PW: hodu0910
    • ID : buyer2 PW: hodu0910
    • ID : buyer3 PW: hodu0910
  • 판매자(seller)
    • ID : seller1 PW : hodu0910
    • ID : seller2 PW : hodu0910
    • ID : seller3 PW : hodu0910
 

figma

  • 피그마 링크는 상단 페이지로 옮겨갔습니다.
 

(Tip)헤더에 토큰넣기

const instance = axios.create({ headers: { Authorization: 'JWT eyJ0eXAiOiJKV1Qi...' } });
key - Authorization value - JWT eyJ0eXAiOiJKV1Qi...(생략)
notion imagenotion image

1. 계정

1.1 계정 만들기(구매자,POST)

  • API
POST /accounts/signup/
  • Req
{ "username": String, // 아이디 "password": String, "password2": String, "phone_number": String, // 전화번호는 010으로 시작하는 10~11자리 숫자 "name": String, // 이름 }
  1. 모든 필드는 필수로 작성해야 합니다.
  1. 비밀번호는 8자 이상, 영소문자를 포함해야 합니다.
  1. 핸드폰 번호는 010으로 시작하는 10~11자리 숫자로만 이루어져 있습니다.
 
  • Res
// SUCCESS { "name": String, "phone_number": String, "type": String, "username": String, } // FAIL // username, password, password2, name, phone_number 중 하나라도 작성하지 않을 경우 이 필드는 필수 항목입니다. // password를 8자 이상 입력하지 않을 경우 비밀번호는 8자 이상이어야 합니다. // password에 영소문자가 없을 경우 비밀번호는 한개 이상의 영소문자가 필수적으로 들어가야 합니다. // password에 숫자가 없을 경우 비밀번호는 한개 이상의 숫자가 필수적으로 들어가야 합니다. // 가입된 username일 경우 해당 사용자 아이디는 이미 존재합니다. // username에 지정된 문자 이외의 문자가 들어갈 경우 ID는 20자 이내의 영어 소문자, 대문자, 숫자만 가능합니다.' // 가입된 phone_number일 경우 해당 사용자 전화번호는 이미 존재합니다. // 핸드폰번호가 양식에 맞지 않을 경우 핸드폰번호는 01*으로 시작해야 하는 10~11자리 숫자여야 합니다.
 

1.2 계정 만들기(판매자,POST)

  • API
POST /accounts/signup_seller/
  • Req
// SUCCESS { "username": String, // 아이디 "password": String, "password2": String, "phone_number": String, // 전화번호는 010으로 시작하는 10~11자리 숫자 "name": String, // 이름 "company_registration_number": String, "store_name": String, }
  1. 모든 필드는 필수로 작성해야 합니다.
  1. 비밀번호는 8자 이상, 영소문자를 포함해야 합니다.
  1. 핸드폰 번호는 010으로 시작하는 10~11자리 숫자로만 이루어져 있습니다.
  1. 사업자등록번호는 10자리로 이루어진 숫자입니다.
  1. 이름(name)은 중복될 수 있습니다.
  1. 스토어이름(store_name)은 중복될 수 없습니다.
 
  • Res
// SUCCESS { "name": String, "phone_number": String, "type": String, "username": String, "company_registration_number": String, "store_name": String, } // FAIL // username, password, password2, name, phone_number 중 하나라도 작성하지 않을 경우 이 필드는 blank일 수 없습니다. // password를 8자 이상 입력하지 않을 경우 비밀번호는 8자 이상이어야 합니다. // password에 영소문자가 없을 경우 비밀번호는 한개 이상의 영소문자가 필수적으로 들어가야 합니다. // password에 숫자가 없을 경우 비밀번호는 한개 이상의 숫자가 필수적으로 들어가야 합니다. // 가입된 username일 경우 해당 사용자 아이디는 이미 존재합니다. // username에 지정된 문자 이외의 문자가 들어갈 경우 ID는 20자 이내의 영어 소문자, 대문자, 숫자만 가능합니다.' // 가입된 phone_number일 경우 해당 사용자 전화번호는 이미 존재합니다. // 핸드폰번호가 양식에 맞지 않을 경우 핸드폰번호는 01*으로 시작해야 하는 10~11자리 숫자여야 합니다. // 사업자등록번호가 이미 있을 경우 해당 사업자등록번호는 이미 존재합니다. // 스토어 이름이 이미 있을 경우 해당 스토어이름은 이미 존재합니다.
 

1.3 아이디 검증하기

  • API
POST /accounts/signup/valid/username/
  • Req
{ "username": String }
  • Res
// username 필드를 입력하지 않았거나 비어있을 경우 "FAIL_Message": "username 필드를 추가해주세요 :)" // 중복아이디가 없을 경우 "Success": "멋진 아이디네요 :)" // 중복아이디가 있을 경우 "FAIL_Message": "이미 사용 중인 아이디입니다."
 

1.4 사업자등록번호 검증하기

  • API
POST /accounts/signup/valid/company_registration_number/
  • Req
{ "company_registration_number": String }
  • Res
// username 필드를 입력하지 않았거나 비어있을 경우 "FAIL_Message": "company_registration_number 필드를 추가해주세요 :)" // 중복아이디가 없을 경우 "Success": "사용 가능한 사업자등록번호입니다." // 중복아이디가 있을 경우 "FAIL_Message": "이미 등록된 사업자등록번호입니다."

2. 로그인/로그아웃

2.1 로그인

로그인 유형별로 로그인됩니다. 로그인 요청을 보낼 때 login_type도 함께 보내야 합니다.
  • API
POST /accounts/login/
  • Req
{ "username": String, "password": String, "login_type": String // BUYER : 일반 구매자, SELLER : 판매자 }
*username, password은 필수로 작성해야 합니다.
 
  • Res
// SUCCESS { "product_id": Int, "token": String } // FAIL { "username": [ "이 필드는 필수 항목입니다." ], "password": [ "이 필드는 필수 항목입니다." ] "login_type": [ "이 필드는 필수 항목입니다." ] } // 아이디 및 비밀번호가 틀렸을 때 { "message": "로그인 정보가 없습니다." } // 로그인을 요청한 사용자의 정보와 사용자 유형이 다를 경우 { "message": "로그인 정보가 없습니다. 로그인 유형을 학인해주세요." }
*token으로 인증합니다.
 

2.2 로그아웃

 
  • API
POST /accounts/logout/
  • Res
{ "detail": "로그아웃되었습니다." }
 

3. 상품

3.1 상품 전체 불러오기(GET)

3.1.1) 상품 전체 불러오기(GET)

  • API
GET /products/
  • Res
// SUCCESS { "count": Int, "next": String, "previous": String, "results": [ { "product_id": Int, "product_name": String, "seller": Int, "store_name": String, "image": String, "price": Int, "shipping_method": String, //parcel: 택배발송, delivery: 직접전달 중 선택 1 "shipping_fee": Int, "stock": Int, "products_info": String, }] } // product가 없을 경우 { "count": 0, "next": null, "previous": null, "results": [] }

3.1.2) 판매자 상품 불러오기(GET)

  • API
GET /seller/
  • Res
// SUCCESS { "count": Int, "next": String, "previous": String, "results": [ { "product_id": Int, "product_name": String, "seller": Int, "store_name": String, "image": String, "price": Int, "shipping_method": String, //"PARCEL" or "DELIVERY" "shipping_fee": Int, "stock": Int, "products_info": String, }] } // product가 없을 경우 { "count": 0, "next": null, "previous": null, "results": [] }

3.2 상품 등록하기(POST)

  1. user 중 “seller”만 요청을 보내줄 수 있습니다.
 
  • API
POST /products/
  • Req
{ "product_name": String, "image": 이미지 파일(*.jpg, *.gif, *.png), "price": Int, "shipping_method": String, // PARCEL 또는 DELIVERY 선택 "shipping_fee": Int, "stock": Int, "product_info": String, }
  • Res
// header -> 토큰이 있어야 함 Authorization: JWT 토큰 // SUCCESS { "count": Int, "next": String, "previous": String, "results": [ { "product_id": Int, "created_at": String, "updated_at": String, "product_name": String, "image": String, "price": Int, "shipping_method": String, // PARCEL 또는 DELIVERY 선택 "shipping_fee": Int, "stock": Int, "products_info": String, "seller": Int }] } // FAIL : token이 없을 경우 { "detail": "자격 인증데이터(authentication credentials)가 제공되지 않았습니다." } // FAIL : 필드가 비었을 경우 { "product_name": [ "이 필드는 blank일 수 없습니다." ], // image 파일이 없을 경우 "image": [ "제출된 데이터는 파일이 아닙니다. 제출된 서식의 인코딩 형식을 확인하세요." ], "price": [ "유효한 정수(integer)를 넣어주세요." ], "shipping_fee": [ "유효한 정수(integer)를 넣어주세요." ], "stock": [ "유효한 정수(integer)를 넣어주세요." ], "products_info": [ "이 필드는 blank일 수 없습니다." ] }
 

3.3 상품 디테일(GET)

  • API
GET /products/<int:product_id>/ 예제 : /products/1/
  • Res
// SUCCESS { "product_id": Int, "created_at": String, "updated_at": String, "product_name": String, "image": String, "price": Int, "shipping_method": String, //string, 선택 "shipping_fee": Int, "stock": Int, "products_info": String, "seller": Int, "store_name": String } // FAIL { "detail": "찾을 수 없습니다." }
 

3.4 상품 수정하기(PUT)

  • API
PUT /products/<int:product_id>/
  • Req
    • 수정이 필요한 값들만 넣어주면 됩니다. 값을 넣지 않을경우 이전에 저장된 값들이 그대로 저장됩니다.
// header -> 토큰이 있어야 함 Authorization: JWT 토큰 // Body { "product_name": String, "price": Int, "shipping_method": String, "shipping_fee": Int, "stock": Int, "products_info": String }
 
  • Res
// SUCCESS { "product_id": Int, "created_at": String, "updated_at": String, "product_name": String, "image": String, "price": Int, "shipping_method": String, //string, 선택 "shipping_fee": Int, "stock": Int, "product_info": String, "seller": Int } // FAIL { "product_name": [ "이 필드는 blank일 수 없습니다." ], // image 파일이 없을 경우 "image": [ "제출된 데이터는 파일이 아닙니다. 제출된 서식의 인코딩 형식을 확인하세요." ], "price": [ "유효한 정수(integer)를 넣어주세요." ], "shipping_fee": [ "유효한 정수(integer)를 넣어주세요." ], "stock": [ "유효한 정수(integer)를 넣어주세요." ], "product_info": [ "이 필드는 blank일 수 없습니다." ] }

3.5 상품 삭제하기(DELETE)

  • API
DELETE /products/<int:product_id>/
 
  • Res
// header -> 토큰이 있어야 함 Authorization: JWT 토큰 // body // SUCCESS { "detail": "상품이 삭제되었습니다." }
 

3.6 상품 검색하기(GET)

  • API
GET /products/?search=입력값
입력값 필드에 원하는 값을 넣으면 됩니다.
 

4. 장바구니

  • 아래 설명은 가볍게 읽어주세요. 이해가 가지 않으셔도 됩니다.
notion imagenotion image
  • 장바구니는 buyer만 접근할 수 있습니다.
  • (참고)개인별 장바구니가 있고(Cart), 그 안에 CartItem을 넣어주는 형태. cart는 한번만 생성되지만 cartItem은 요청될 때 마다 생성됨.
  • (참고)장바구니 기본 로직 : user(buyer)에 대한 개인 Cart가 할당되며 이 Cart안에 CartItem(product, 수량, is_active 정보가 담겨있음)을 넣습니다.
  • (참고) my_cart는 CartItem에서 접근할 수 있는 Cart의 pk값입니다. cart_item_id는 상품을 카트에 담을 때 마다 생성되는 pk 값

4.1 장바구니 목록 보기(GET)

  • API
GET /cart/
  • Req
// header -> 토큰이 있어야 함 Authorization: `JWT ${토큰}`
  • Res
// SUCCESS { "count": Int, "next": String, "previous": String, "results": [ { "my_cart": Int, // 카트 고유번호, User가 바뀌지 않는이상 번호가 바뀌지 않음 "cart_item_id": Int, // cartItem의 고유번호, 요청시마다 번호가 바뀜 "product_id": Int, // 상품 아이디 "quantity": Int // 장바구니에 담긴 상품의 개수 "is_active": Bool // 장바구니 내 상품 활성화 버튼, 같이 보내지 않으면 False } ] } // 장바구니에 상품이 없을 경우 { "count": 0, "next": null, "previous": null, "results": [] }

4.2 장바구니에 물건 넣기(POST)

장바구니에 이미 있는경우에도 POST요청을 보내줍니다.(백엔드에서 이미 있으면 재고와 현재 요청 수량을 체크하고, 요청 수량이 재고를 넘을 경우 에러를 보내줍니다.)
 
  • API
POST /cart/
  • Req
// header -> 토큰이 있어야 함 Authorization: JWT 토큰 //body { "product_id": Int, //product의 id 값을 넣어주면 됩니다. "quantity": Int }
  • Res
{ "my_cart": Int, // 내 카트 고유번호 "cart_item_id": Int, // 카트 아이템 번호/ PUT,DELETE 메소드를 사용하기 위해 필요함 "product_id": Int, "quantity": Int }

4.3 장바구니 디테일(개발용,GET)

  • API
GET /cart/<int:cart_item_id>/
  • Res
// SUCCESS { "my_cart": Int, "cart_item_id": Int, "product_id": Int, "quantity": Int } // FAIL : buyer가 아니거나 token이 없을 경우 { "detail": "자격 인증데이터(authentication credentials)가 제공되지 않았습니다." } // FAIL : user가 다를 경우 { "detail": "접근권한이 없습니다." } // FAIL : 해당 pk값이 없을 경우 { "detail": "찾을 수 없습니다." }
 

4.4 장바구니 수량 수정하기(PUT)

  • API
PUT /cart/<int:cart_item_id>/
  • Req
// header -> 토큰이 있어야 함 Authorization: JWT 토큰 //body { "product_id": Int, "quantity": Int, "is_active": Bool // 장바구니 내 상품 활성화 버튼, 같이 보내지 않으면 False }
  • Res
{ "product_id": Int, "quantity": Int, "is_active": Bool } // FAIL // is_active 값이 없을 때 { "detail": "is_active 값이 없습니다." } // is_active 값이 bool이 아닐 때 { "is_active": [ "Must be a valid boolean." ] }
 

4.4 장바구니 전부 삭제하기(DELETE)

  • API
DELETE /cart/
  • Res
// SUCCESS { "detail": "장바구니의 모든 상품이 삭제되었습니다." }
 

4.4 장바구니 개별 삭제하기(DELETE)

  • API
DELETE /cart/<int:cart_item_id>/
  • Res
// SUCCESS { "detail": "장바구니의 상품이 삭제되었습니다." } // FAIL

5. 주문하기

주문하기는 세가지 방법으로 나뉩니다.
  1. 바로 주문하기(product detail 페이지에서 접근)
  1. 카트에서 주문하기(cart에서 is_active = True인 값만 주문)
  1. 카트에서 한가지만 주문하기(장바구니 페이지에서 주문하기 버튼 누를 경우)
 
이 세가지 분기를 처리해주기 위해서 order_kind를 서버에 보내주셔야 합니다.
  1. direct_order
  1. cart_order
  1. cart_one_order
 

1. 주문 목록 가져오기(GET)

  • API
GET /order/
  • Req
// header -> buyer 토큰이 있어야 함 Authorization: JWT 토큰
  • Res
// SUCCESS { "count": Int, "next": null, "previous": null, "results": [ { "buyer": Int, // 구매자(로그인 된 유저) "order_number": Int, // 주문번호 "order_items": [ // 구매 상품들 Int, Int, ], "order_quantity": [ // 구매 상품들의 수량 Int, Int, ], "receiver": String, // 받는사람 "receiver_phone_number": String, // 받는사람의 핸드폰번호 "address": String, // 주소 "address_message": String, // 배송메세지 "payment_method": String, // 배송방법 "total_price": Int // 결제금액 } ] } // 값이 없을 떄 { "count": 0, "next": null, "previous": null, "results": [] }

2. 주문 생성하기(POST)

2-1. 주문 생성하기(POST)

참고
>>> myList = [1,2,3,4,5,'hello'] >>> import simplejson as json >>> myJsonList = json.dumps(myList) >>> myJsonList '[1, 2, 3, 4, 5, "hello"]' >>> myJsonList.__class__ <type 'str'> >>> jsonDec = json.decoder.JSONDecoder() >>> myPythonList = jsonDec.decode(myJsonList) >>> myPythonList [1, 2, 3, 4, 5, u'hello'] >>> myPythonList.__class__ <type 'list'>
 
  • API
POST /order/
  • Req
{ "product_id": Int, "quantity" : Int, "order_kind" : String, // 바로주문하기일 경우에는 direct_order여야 합니다. "reciever": String, "reciever_phone_number": String, "address": String, "address_message": String, "payment_method": String, //CARD, DEPOSIT, PHONE_PAYMENT, NAVERPAY, KAKAOPAY 중 하나 선택 "total_price": Int // 총 금액(total_price)은 자동계산되나, 유효성검사를 위해 받아와야 합니다. }
  • Res
// SUCCESS { "buyer": Int, "order_number": Int, "order_items": [ Int, ], "receiver": String, "receiver_phone_number": String, "address": String, "address_message": String, "payment_method": String, "total_price": Int, "order_quantity": [ Int ], "delivery_status": String } // 값이 없을 떄 { "count": 0, "next": null, "previous": null, "results": [] } // product_id 정보가 없을 때 { "FAIL_message": "product_id 정보가 없습니다." } // quantity 정보가 없을 떄 { "FAIL_message": "quantity 정보가 없습니다." } // 총 금액이 백엔드에서 계산한 것과 다를 때 { "FAIL_message": "total_price 금액이 맞지 않습니다. 백엔드에서 계산한 금액은 __원 입니다." } // 총 금액이 백엔드에서 계산한 것과 다를 때 { "FAIL_message": "total_price 금액이 맞지 않습니다. 백엔드에서 계산한 금액은 __원 입니다." }
 

2-2. 카트에서 주문 생성하기(POST)

참고
>>> myList = [1,2,3,4,5,'hello'] >>> import simplejson as json >>> myJsonList = json.dumps(myList) >>> myJsonList '[1, 2, 3, 4, 5, "hello"]' >>> myJsonList.__class__ <type 'str'> >>> jsonDec = json.decoder.JSONDecoder() >>> myPythonList = jsonDec.decode(myJsonList) >>> myPythonList [1, 2, 3, 4, 5, u'hello'] >>> myPythonList.__class__ <type 'list'>
카트로 보내기 전 카트의 각 quantity가 product의 재고보다 많지 않은지 유효성 검사를 해주셔야 합니다. ex) product 9번의 재고가 10개인데 카트에 담긴 재고는 15개임 → 에러 (카트 수량과 재고 검사가 주기적으로 확인이 가능하다면 이 유효성검사는 무시하셔도 됩니다.)
 
  • API
POST /order/
  • Req
{ "total_price": Int // cart에 담긴 총 금액(수량*가격+배송비)을 보내줘야 합니다. "order_kind" : String // 카트에서 주문할 경우에는 cart_order를 보내줘야 합니다. "receiver": String, "receiver_phone_number": String, // 01012341234 와 같은 형태로 보내야 합니다. "address": String, "address_message": String, "payment_method": String, //CARD, DEPOSIT, PHONE_PAYMENT, NAVERPAY, KAKAOPAY 중 하나 선택 }
  • Res
// SUCCESS { "buyer": Int, "order_number": Int, "order_items": [ Int, Int, ], "receiver": String, "receiverr_phone_number": String, "address": String, "address_message": String, "payment_method": String, "total_price": Int, "order_quantity": [ Int, Int, ], "delivery_status": String } // FAIL // 총 금액이 백엔드에서 계산한 것과 다를 때 { "FAIL_message": "total_price 금액이 맞지 않습니다. 백엔드에서 계산한 금액은 __원 입니다." } // total_price 정보가 없을 때 { "FAIL_message": "total_price 정보가 없습니다." } // 품절된 상품이 있을 때 { "FAIL_message":"품절된 상품이 있습니다. 다시 주문해주세요" } // order_items와 order_quantity의 개수가 맞지 않을 때 { "FAIL_message":"카트내 제품 개수와 수량 개수가 맞지 않습니다. 다시 요청해주세요." }
 

2-3. 카트에서 하나만 주문 생성하기(POST)

참고
>>> myList = [1,2,3,4,5,'hello'] >>> import simplejson as json >>> myJsonList = json.dumps(myList) >>> myJsonList '[1, 2, 3, 4, 5, "hello"]' >>> myJsonList.__class__ <type 'str'> >>> jsonDec = json.decoder.JSONDecoder() >>> myPythonList = jsonDec.decode(myJsonList) >>> myPythonList [1, 2, 3, 4, 5, u'hello'] >>> myPythonList.__class__ <type 'list'>
해당 경우에는 is_active 즉, 선택한 아이템의 상태값이 False일 경우도 생각해야 합니다.
(백엔드에서 is_active값이 False인 제품의 정보를 불러올 수 없도록 구현되어 있어요.) → 만약 주문할 제품의 is_active 값이 False인데 주문하기를 누른다면? : 이 경우를 생각해서 구현해주세요!
 
힌트(스포가 될 수 있으니 ,, 생각해보고 눌러주세요)
is_active 값을 주문하기 버튼을 누르는 순간 True로 PUT..
 
  • API
POST /order/
  • Req
{ "product_id": Int, "quantity" : Int, "order_kind" : String // 카트에서 주문할 경우에는 cart_one_order를 보내줘야 합니다. "total_price": Int // cart에 담긴 총 금액(수량*가격+배송비)을 보내줘야 합니다. "receiver": String, "receiver_phone_number": String, // 01012341234 와 같은 형태로 보내야 합니다. "address": String, "address_message": String, "payment_method": String, //CARD, DEPOSIT, PHONE_PAYMENT, NAVERPAY, KAKAOPAY 중 하나 선택 }
  • Res
// SUCCESS { "buyer": Int, "order_number": Int, "order_items": [ Int, Int, ], "receiver": String, "receiver_phone_number": String, "address": String, "address_message": String, "payment_method": String, "total_price": Int, "order_quantity": [ Int, Int, ], "delivery_status": String } // FAIL // 총 금액이 백엔드에서 계산한 것과 다를 때 { "FAIL_message": "total_price 금액이 맞지 않습니다. 백엔드에서 계산한 금액은 __원 입니다." } // total_price 정보가 없을 때 { "FAIL_message": "total_price 정보가 없습니다." } // product_id 정보가 없을 때 { "FAIL_message": "product_id 정보가 없습니다." } // quantity 정보가 없을 떄 { "FAIL_message": "quantity 정보가 없습니다." } // 품절된 상품이 있을 때 { "FAIL_message":"품절된 상품이 있습니다. 다시 주문해주세요" } // order_items와 order_quantity의 개수가 맞지 않을 때 { "FAIL_message":"카트내 제품 개수와 수량 개수가 맞지 않습니다. 다시 요청해주세요." } // 카트안에 보낸 아이템 정보가 없을 때 { "FAIL_message": "카트안에 해당 아이템 정보가 없습니다." }