20230202 TIL RestTemplate으로 아임포트 API 호출하기
아임포트 API호출 시 access token이 필요한 경우가 있다.
따라서 access token을 먼저 받아올 수 있는 issueAccessToken이라는 메서드를 만들었다.
(api key와 api secret은 https://classic-admin.iamport.kr/settings에서 확인할 수 있다.)
private static final String HOST = "https://api.iamport.kr";
private IamPort iamPort;
private String accessToken;
private IamPortAccessToken iamPortAccessToken;
private String apiKey;
private String apiSecret;
public IamPort(String apiKey, String apiSecret) {
this.apiKey = apiKey;
this.apiSecret = apiSecret;
}
public String issueAccessToken() {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("imp_key", apiKey);
params.add("imp_secret", apiSecret);
HttpEntity<MultiValueMap<String, String>> body = new HttpEntity<>(params, headers);
try {
IamPortAccessToken iamPortAccessToken = restTemplate.postForObject(new URI(HOST + "/users/getToken"), body, IamPortAccessToken.class);
return iamPortAccessToken.getResponse().getAccess_token();
} catch (RestClientException e) {
throw new IamPortAccessTokenException(e);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
이 때 IamPortAccessToken은 아래와 같고,
public class IamPortAccessToken {
private Integer code;
private String message;
private IamPortAccessTokenResponse response;
public Integer getCode() {
return code;
}
public String getMessage() {
return message;
}
public IamPortAccessTokenResponse getResponse() {
return response;
}
}
IamPortAccessTokenResponse는 아래와 같다.
public class IamPortAccessTokenResponse {
private String access_token;
private Integer now;
private Integer expired_at;
public String getAccess_token() {
return access_token;
}
public Integer getNow() {
return now;
}
public Integer getExpired_at() {
return expired_at;
}
}
RestTemplate에서 ResponseType의 field명들은 JSON 반환 값의 key값과 동일해야 된다.
만약 다르게 쓰고 싶다면 @JsonProperty를 이용하면 된다.
에를 들면,
{
"property1": "value1",
"property2": 42,
"property3": ["item1", "item2", "item3"]
}
위와 같은 JSON에 해당하는 ResponseType은
public class ResponseClass {
@JsonProperty("property1")
private String someOtherName;
@JsonProperty("property2")
private int someNumber;
@JsonProperty("property3")
private List<String> items;
...
}
와 같이 작성해줄 수 있다.
그리고 이제 필요한 계좌 소유주를 확인을 해야하는데, get메서드로 header에 토큰을 보내야 한다.
그런데 getForObject 메서드는 헤더를 설정해줄 수 없기 때문에 exchange를 쓸 수 밖에 없었다.
public String getBankHolder(String bankName, String accountNumber) {
RestTemplate restTemplate = new RestTemplate();
String accessToken = issueAccessToken();
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + accessToken);
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(headers);
String bankCode = bankCodes.get(bankName);
try {
ResponseEntity<IamPortAccountHolder> response = restTemplate.exchange(
HOST + "/vbanks/holder?bank_code=" + bankCode + "&bank_num=" + accountNumber,
HttpMethod.GET,
entity,
IamPortAccountHolder.class);
return response.getBody().getResponse().getBank_holder();
} catch (RestClientException e) {
throw new IamPortBankHolderException(e);
}
}
위와 같은 코드를 통해 아임포트 API를 통해 계좌 소유주를 확인할 수 있게 되었다!
외부 API를 사용할 때는 API문서를 확인해보고, network 탭을 열어서 실제로 어떻게 주고 받는지 확인을 하고,
httpie등의 도구로 실제로 요청을 해본 뒤에 코드를 작성하는 것이 가장 확실하고 빠르게 작업할 수 있는 방법인 것 같다.
API 문서만 보고 RestTemplate을 쓰면 안될 때 어디서부터 문제인지 파악하기가 어렵다.
RestTemplate을 쓰기 전에 먼저 요청 방식을 꼭 완벽히 확인하자!