TIL

20230202 TIL RestTemplate으로 아임포트 API 호출하기

jiwoosmile 2023. 2. 2. 17:45

https://1.bp.blogspot.com/-MlGWLe08yvk/XZQ0w-7dIGI/AAAAAAAAroM/_wqQtsLyiOEpfp7kMZFVXZ6wl-oWKJfGwCLcBGAsYHQ/s1600/rt.PNG

아임포트 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을 쓰기 전에 먼저 요청 방식을 꼭 완벽히 확인하자!