지난 편에서는 주문 정보를 전달하는 POST 요청을 보내고 응답을 jsp파일에서 띄우는 것까지 진행해보았다. 이번에는 주문 조회와 가격 조회 기능을 추가하는 내용에 대해 적어보도록 하겠다.
[API_ENDPOINT]/api/v2/orders/[partnerOrderId]으로 GET 요청한다.
| Parameter | Description |
|---|---|
| Authorization | 시작하기에서 생성한 Authorization 파라미터 값 |
| vendor | kakaoT 퀵∙도보 배송 API Sandbox에서 발급받은 Vendor 아이디 |
| Content-Type | application/json |
주문 정보 요청과 같은 헤더 값이다.
왠만한 요청에는 Authorization 값이 헤더로 들어가기 때문에 따로 함수를 만들어 관리하기로 했다.
public String getAuthorization() throws InvalidKeyException, NoSuchAlgorithmException {
// 입력값
final String timestamp = String.valueOf(System.currentTimeMillis());
final String nonce = "121212";
final String apiKey = apiConfig.getKeyValue();
System.out.println("tesT");
// 서명 및 Authorization 생성
String sign = kakaoAuthComponent.generateSignature(timestamp, nonce, apiKey);
String authorization = kakaoAuthComponent.generateAuthorization(timestamp, nonce, sign);
return authorization;
}
| Name | Type | Description | Required |
|---|---|---|---|
partnerOrderId | String | 연동사 주문 아이디 | 필수 |
요청 파라미터는 다음과 같이 연동사의 주문 아이디 하나만 필요하다.
그 주문 아이디는 호출 방식에서 API_ENDPOINT에 포함되며 @PathVariable로 쓸 수 있다.
curl -X 'GET'
'https://open-api-logistics.kakaomobility.com/goa-sandbox-service/api/v2/orders/${partnerOrderId}'
-H 'accept: application/json'
-H 'vendor: ${vendor_id}'
-H 'Authorization: XXX'
GET 요청이기 때문에 따로 Body는 없다.
요청응답은 다음과 같이 주문 정보와 같은 JSON 형식으로 받을 수 있다.
{
"requestId": ${requestId},
"partnerOrderId": ${partnerOrderId},
"pickup": {
"location": {
"basicAddress": "서울 강남구 역삼동 xxx",
"detailAddress": "1층",
"latitude": 37.4354059,
"longitude": 126.74551
},
"contact": {
"name": "전달하는 사람 이름",
"phone": "010-1000-0001"
},
"statusUpdatedAt": "2023-02-27T15:40:32+09:00"
},
"dropoff": {
"location": {
"basicAddress": "서울 강남구 일원동 xxx",
"detailAddress": "2층",
"latitude": 37.569691,
"longitude": 126.825791
},
"contact": {
"name": "받는 사람 이름",
"phone": "010-1000-0002"
},
"statusUpdatedAt": "2023-02-27T15:40:32+09:00"
},
"receipt": {
"orderId": ${orderId},
"orderType": ${orderType},
"status": "MATCHING",
"priceInfo": {
"totalPrice": 100000,
},
},
"histories": [
"status": "MATCHING",
"updatedAt": "2023-02-27T15:40:32+09:00"
]
}
Authorization 인증 요청과 비슷하게 GET 요청을 위한 함수를 작성한다.
여기서 미리 만들어 놓은 getAuthorization() 함수를 써 코드를 단축하였다.
@GetMapping("/order/{partnerOrderId}.do")
public String orderCheck(@PathVariable String partnerOrderId, Model model) {
try {
ApiConfig apiconfig = ApiConfig.getApiConfigSingleton();
String authorization = getAuthorization();
String vendorID = apiConfig.getVendorID();
// API 호출을 위한 URL 설정
String apiUrl = apiConfig.getHostURL() + "/api/v2/orders/" + partnerOrderId;
// HttpHeaders 객체 생성
HttpHeaders headers = new HttpHeaders();
headers.set("accept", "application/json");
headers.set("Authorization", authorization); // 동적으로 생성된 Authorization
headers.set("Content-Type", "application/json");
headers.set("vendor", apiConfig.getVendorID()); // vendor_id 설정
// HttpEntity 생성 (헤더 포함)
HttpEntity<String> entity = new HttpEntity<>(headers);
// GET 요청 보내기
ResponseEntity<String> response = restTemplate.exchange(apiUrl, HttpMethod.GET, entity, String.class);
// 응답 처리
model.addAttribute("responseCode", response.getStatusCodeValue());
model.addAttribute("responseBody", response.getBody());
} catch (Exception e) {
e.printStackTrace();
model.addAttribute("responseBody", "API 요청 중 오류 발생: " + e.getMessage());
}
return "result";
}
이걸 통해 받는 result.jsp는 Authorization 인증 때와 똑같이 통일했다.
<body>
<h1>Order Result</h1>
<p>Response Code: ${responseCode}</p>
<p>Response Body: ${responseBody}</p>
</body>
여기서 필요한 것은 partnerOrderId를 입력받고 GET 요청을 보내는 페이지다.
<form id="orderCheck" method="get">
<label for="orderCheck">파트너 ID</label>
<input type="text" id="partnerOrderId" name="partnerOrderId">
<button type="button" onclick="submitForm()">조회</button>
</form>
위와 같이 text로 입력받아 id=”partnerOrderId”로 넘겨주도록 했다.
function submitForm() {
const form = document.getElementById("orderCheck");
const ID = document.getElementById("partnerOrderId").value;
if (ID) {
form.action = '/order/' + ID + '.do';
form.method = 'GET';
form.submit();
} else {
alert("Invaild ID");
}
}
이런식으로 사용자가 입력한 partnerOrderId 를 받고 form.action으로 설정한 뒤 form을 제출한다.
여기서 .do를 넣게 되는데 그 이유는 web.xml에서 filter-mapping을 .do로 설정했기 때문이다.
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
여기서 문제가 생기는데
~~@GetMapping("/order/{partnerOrderId}.do") 여기서 {partnerOrderId}를 하드 코딩 했을 때는 정상적으로 200 응답이 오지만 PathVariable로 받으려고 하면 404가 뜨는 상황이다.~~
문제가 무엇인지 찾았다.
이 프로젝트는 context 경로가 /kakaoTest로 되어있지만 jsp 파일에서는 그걸 포함하지 않고 바로 /order/… 로 보냈기에 주소가 달라서 404 에러가 뜨는 것이었다.
아무튼 이런 식으로 200 요청 코드를 받을 수 있었다.

[API_ENDPOINT]/api/v2/orders/price 로 POST 요청한다.
이 헤더는 위 내용과 같습니다.
curl -X 'POST'
'https://open-api-logistics.kakaomobility.com/goa-sandbox-service/api/v2/orders/price'
-H 'accept: application/json'
-H 'vendor:${vendor_id}'
-H 'Content-Type: application/json'
-H 'Authorization: XXX'
-d '{
"orderType": "QUICK",
"pickup": {
"location": {
"basicAddress": "서울특별시 강남구 역삼동 754",
"detailAddress": "1층",
"latitude": 37.498551,
"longitude": 127.0464387
}
},
"dropoff": {
"location": {
"basicAddress": "서울특별시 강남구 일원동 741",
"detailAddress": "2층",
"latitude": 37.490694420048,
"longitude": 127.079607
}
},
"productSize": "XS"
}'
주문 정보 요청 하기의 일부 정보를 받아 POST를 받는다
요청응답은 다음과 같이 물품 가격을 JSON 형식으로 받을 수 있다.
{
"totalPrice": 17800
"maximum": 17800 // 도보 min max
"minimum": 15000 // 퀵은 null
}
가격 조회에 필요한 body를 사용자로부터 받아내는 페이지는 주문정보 전달하기에서 일부만 수정해서 사용했다.
<body>
<h1>가격 조회하기</h1>
<form id="orderForm" method="post" action="/kakaoTest/price.do">
<label for="orderType">주문 유형:</label><br>
...
<button type="submit">Submit Order</button>
</form>
</body>
그리고 price.do 에서 처리하도록 Controller도 구성했으며 대부분 주문 정보 전달하기의 order.do 와 유사하다.
@RequestMapping(value = "/price.do", method = RequestMethod.POST)
public String CheckPrice(OrderVO orderVO, Model model) {
try {
final String API_ENDPOINT = apiConfig.getHostURL() + "/api/v2/orders/price";
final String VENDOR_ID = apiConfig.getVendorID();
final String authorization = getAuthorization();
JSONObject json = new JSONObject();
...
// 최종 JSON 객체에 데이터 삽입
json.put("orderType", orderVO.getOrderType());
json.put("pickup", pickup);
json.put("dropoff", dropoff);
json.put("productSize", orderVO.getSize());
System.out.println("Generated JSON: " + json.toString());
// 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);
System.out.println("Authorization : " + authorization);
// API 호출
ResponseEntity<String> response = null;
try {
response = restTemplate.postForEntity(API_ENDPOINT, requestEntity, String.class);
System.out.println("Response Status Code: " + response.getStatusCode());
System.out.println("Response Body: " + response.getBody());
...
} catch (Exception e) {
System.out.println("기타 예외 발생");
e.printStackTrace();
}
// 응답 처리
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";
}
}
jsp에서 받은 body 정보를 JSONObject화 헤더값과 함께 POST 요청으로 보냈고, 늘 응답받던 result.jsp에서 해당 결과를 받도록 설정했다.

생각보다 어이없는 이유로 생긴 에러때문에 시간을 많이 잡아먹히고 있다.
일단 지금은 간단히 요청을 보내고 받는 부분까지만 하고 있지만 나중엔 UI/UX를 개선하고 RestAPI까지 구성할 계획이다.
https://logistics-developers.kakaomobility.com/document/get-orders