지난 편에서는 API를 활용하기 위해 필요한 Authorization 값을 인증하는 과정을 적어보았다.
이번엔 그 Authorization값을 기반으로 주문 정보를 전달하는 과정을 적어보도록 하겠다.
[API_ENDPOINT]/api/v2/orders으로 POST 요청한다.
| Parameter | Description |
|---|---|
| Authorization | 시작하기에서 생성한 Authorization 파라미터 값 |
| vendor | kakaoT 퀵∙도보 배송 API Sandbox에서 발급받은 Vendor 아이디 |
| Content-Type | application/json |
헤더는 이전에 만들고 인증받은 Authorization과 vendor ID, Content-Type을 포함한다.
| Name | Type | Description | Required |
|---|---|---|---|
orderType | Enum(String) | 주문 유형다음 중 하나:QUICK: 퀵QUICK_ECONOMY: 퀵 이코노미QUICK_EXPRESS: 퀵 급송DOBO: 도보 배송 | 필수 |
partnerOrderId | String | 연동사 주문 아이디(내부에서 사용하시는 주문 아이디) | 필수 |
fleetOption | Object | 차량 선택 | 선택 |
productInfo | Object | 배송 유의사항 | 필수 |
pickup | Object | 출발지 정보 | 필수 |
dropoff | Object | 목적지 정보 | 필수 |
extraOption | Object | 기타 옵션 | 선택 |
ordererContact | Object | 의뢰인 정보 | 선택 |
요청 body는 다음과 같이 다양하게 존재한다
그마저도 세부 사항을 빼고 넣은 것이다
curl -X 'POST' \
'https://open-api-logistics.kakaomobility.com/goa-sandbox-service/api/v2/orders' \
-H 'accept: application/json' \
-H 'vendor:${vendor_id}' \
-H 'Content-Type: application/json' \
-H 'Authorization: XXX' \
-d '{
"partnerOrderId": "{연동사 주문 ID - 유니크 해야합니다}",
"orderType": "QUICK",
"pickup": {
"location": {
"basicAddress": "서울특별시 강남구 역삼동 xxx",
"detailAddress": "1층",
"latitude": 37.4354059,
"longitude": 126.74551
},
"contact": {
"name": "전달하는 사람 이름",
"phone": "010-1000-0001"
}
},
"dropoff": {
"location": {
"basicAddress": "서울특별시 강남구 일원동 xxx",
"detailAddress": "2층",
"latitude": 37.569691,
"longitude": 126.825791
},
"contact": {
"name": "받는 사람 이름",
"phone": "010-1000-0002"
}
}
"productInfo": {
"trayCount": 1,
"size": "XS",
"totalPrice": 29800,
"products": [
{
"name": "양념게장 (대)",
"quantity": "1",
"price": 29800,
"detail": "터지면 큰일남"
}
]
}
}'
예시 코드와 같이 jsp에서 받은 파라미터를 JSON으로 변환해서 보내야 할 것 같다.
응답은 다음과 같은 형식으로 온다.
{
"requestId": ${requestId},
"partnerOrderId": ${partnerOrderId},
"receipt": {
"orderId": ${orderId},
"orderType": "QUICK",
"priceInfo": {
"totalPrice":10000
},
"status": "matching"
}
}
| Name | Type | Description | Required |
|---|---|---|---|
requestId | String | 요청 아이디 | 선택 |
partnerOrderId | String | 연동사 주문 아이디 | 선택 |
receipt | Object | 주문 정보 | 선택 |
이제 주문 정보 전달하기를 적용해보자.
Authorization, VendorID를 준비한다.호출하기 위해 필요한 URL과 헤더 값들을 준비한다.
try {
final String API_ENDPOINT = apiConfig.getHostURL();
final String VENDOR_ID = apiConfig.getVendorID();
// Authorization 동적으로 생성
final String timestamp = String.valueOf(System.currentTimeMillis());
final String nonce = "121212"; // 고유값 (임의로 지정)
final String apiKey = apiConfig.getKeyValue();
String sign = kakaoAuthComponent.generateSignature(timestamp, nonce, apiKey);
final String authorization = kakaoAuthComponent.generateAuthorization(timestamp, nonce, sign);
요청 파라미터를 form으로 보낼 jsp파일을 만든다.
<body>
<h1>Create a New Order</h1>
<form id="orderForm" method="get" action="/hello.do">
<label for="partnerOrderId">연동사 주문 ID:</label><br>
<input type="text" id="partnerOrderId" name="partnerOrderId" required><br><br>
<label for="orderType">주문 유형:</label><br>
<select id="orderType" name="orderType" required>
<option value="QUICK">퀵</option>
<option value="QUICK_ECONOMY">퀵 이코노미</option>
<option value="QUICK_EXPRESS">퀵 급송</option>
<option value="DOBO">도보 배송</option>
</select><br><br>
...
<label for="productName">상품명:</label><br>
<input type="text" id="productName" name="productName" required><br>
<label for="productQuantity">상품 수량:</label><br>
<input type="number" id="productQuantity" name="productQuantity" required><br>
<label for="productPrice">상품 금액:</label><br>
<input type="number" id="productPrice" name="productPrice" required><br>
<label for="productDetail">상품 상세 정보:</label><br>
<textarea id="productDetail" name="productDetail"></textarea><br><br>
<button type="submit">Submit Order</button>
</form>
</body>
jsp에서 form으로 보내는 수많은 값들을 받아온다.
이 값들을 Content-Type인 application/json 으로 변환하기 위해 JSONObject를 활용한다.
@RequestMapping(value = "/order.do", method = RequestMethod.POST)
public String submitOrder(@ModelAttribute OrderVO orderVO, Model model) {
// 헤더값 설정 코드
...
// JSON 데이터 생성
JSONObject json = new JSONObject();
JSONObject pickupLocation = new JSONObject();
pickupLocation.put("basicAddress", orderVO.getPickupBasicAddress());
pickupLocation.put("detailAddress", orderVO.getPickupDetailAddress());
pickupLocation.put("latitude", orderVO.getPickupLatitude());
pickupLocation.put("longitude", orderVO.getPickupLongitude());
...
JSONObject productInfo = new JSONObject();
productInfo.put("trayCount", orderVO.getTrayCount());
productInfo.put("size", orderVO.getSize());
productInfo.put("totalPrice", orderVO.getProductPrice() * orderVO.getProductQuantity());
productInfo.put("products", productsArray);
// 최종 JSON 객체에 데이터 삽입
json.put("partnerOrderId", orderVO.getPartnerOrderId());
json.put("orderType", orderVO.getOrderType());
json.put("pickup", pickup);
json.put("dropoff", dropoff);
json.put("productInfo", productInfo);
}
파라미터에 값들이 너무 많아져서 따로 OrderVO를 만들어 @ModelAttribute를 사용해 처리하였다.
(JSON으로 변환하는 부분도 따로 함수로 만들어서 쓰면 코드가 깔끔해질 것 같다.)
POST 요청을 보내기 위해 Header 값과 body 값(JSON)을 HttpEntity로 캡슐화 한다.
// HTTP Header 설정
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
headers.set("Authorization", authorization);
headers.set("vendor", VENDOR_ID);
// HTTP 요청 생성
HttpEntity<String> requestEntity = new HttpEntity<>(json.toString(), headers);
이후 restTemplate로 API 호출 후 model에 담고 따로 만들어둔 result.jsp에 출력해보기로 했다.
// API 호출
ResponseEntity<String> response = restTemplate.postForEntity(API_ENDPOINT, requestEntity, String.class);
// 응답 처리
model.addAttribute("responseCode", response.getStatusCodeValue());
model.addAttribute("responseBody", response.getBody());
return "result";
} catch (Exception e) {
e.printStackTrace();
System.out.println("Error: " + e.getMessage());
return "result";
}
아래는 테스트용으로 만든 result.jsp이다.
<body>
<h1>Order Result</h1>
<p>Response Code: ${responseCode}</p>
<p>Response Body: ${responseBody}</p>
</body>
이 과정에서 500 Server Error가 떠서 확인해본 결과
두 가지 문제점을 파악할 수 있었다.
또한 반복해서 요청을 보내면 partnerOrderId 가 중복되어 409 Conflict Error가 뜨기 때문에 테스트할 때는 신경 쓸 필요가 있는 것 같다.

여러가지 에러가 나와서 골치아프긴 했지만 어찌저찌 Response를 받아오는데에 성공했다.
다만 인코딩 문제로 한글이 ?로 나오는 것은 따로 해결해야 할 것 같다.
분명 외부 API를 가져오고 쓰는거 자체는 간단할 거라 생각했는데 막상 구현해보니 예상치 못한 에러들이 많이 나와 구현하는데 생각보다 시간이 오래걸렸다.
다음엔 다른 기능과 함께 RestController를 통한 RESTAPI 구축을 해보도록 하겠다.
https://logistics-developers.kakaomobility.com/document/post-orders