프로그래밍

[SpringBoot] 한국수출입은행 환율 API 가져오기

가시가되어 2023. 3. 29. 16:22

한국수출입은행 현재환율 API

가입하여, 인증키를 발급

https://www.koreaexim.go.kr/ir/HPHKIR020M01?apino=2&viewtype=C&searchselect=&searchword=

 

한국수출입은행

페이지 정보가 없습니다. 요청하신 페이지를 찾을 수 없거나, 서버에서 삭제되었습니다. URL을 확인해주세요.

www.koreaexim.go.kr

 

Java.net URL을 통해 간단히 API 호출해서 저장해보기.

예시
(요청) https://www.koreaexim.go.kr/site/program/financial/exchangeJSON?authkey=AUTHKEY1234567890&searchdate=20180102&data=AP01

종속성 설정(pom.xml)

Swaager(API 문서) , Json-Simple(Json 이용을 위해), ObjectMapper, modelMapper(Entity와 DTO 사이의 매핑을 위해) 추가

 

Swagger를 쓰기 위해선 아직 스프링 3.X 버전을 지원을 안해서 에러가 발생할 수 있음. (스프링 2.X 버전으로 다운)

https://stackoverflow.com/questions/71549614/springfox-type-javax-servlet-http-httpservletrequest-not-present

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.oracle.database.jdbc</groupId>
            <artifactId>ojdbc8</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.googlecode.json-simple</groupId>
            <artifactId>json-simple</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>3.0.0</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>
    </dependencies>

 

API 호출 예시를 바탕으로  키값, 호출 Data 타입, 날짜를 선언

String authKey = "<발급받은 키>";
String searchDate = new SimpleDateFormat("yyyyMMdd").format(new Date());
String dataType = "AP01";

URL 호출

URL url = new URL("https://www.koreaexim.go.kr/site/program/financial/exchangeJSON?authkey=" + authKey + "&searchdate=" + searchDate + "&data=" + dataType);
connection = (HttpURLConnection) url.openConnection();

 

환율 정보 DTO 

swaager Property는 삭제 해도 무방, 현재는 API 호출 시 파라미터로 사용되지 않음.

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.time.LocalDateTime;

@Data
public class ExchangeRateDto {

    int result;
    @ApiModelProperty(value = "통화코드")
    String cur_unit;

    @ApiModelProperty(value = "국가/통화명\t")
    String cur_nm;

    @ApiModelProperty(value = "전신환(송금)\n" +
            "받으실때")
    String ttb;
    @ApiModelProperty(value = "전신환(송금)\n" +
            "보내실때")
    String tts;

    @ApiModelProperty(value = "매매 기준율\t")
    String deal_bas_r;

    @ApiModelProperty(value = "장부가격\t")
    String bkpr;

    @ApiModelProperty(value = "년환가료율")
    String yy_efee_r;

    @ApiModelProperty(value = "10일환가료율")
    String ten_dd_efee_r;

    @ApiModelProperty(value = "서울외국환중개\n" +
            "매매기준율")
    String kftc_deal_bas_r;
    @ApiModelProperty(value = "서울외국환중개\n" +
            "장부가격")
    String kftc_bkpr;
    @ApiModelProperty(value = "API 호출시간")
    LocalDateTime exchangeDate;


}

Controller

@RestController
public class ExchangeRateController {

    private final ExchangeRateService exchangeRateService;

    public ExchangeRateController(ExchangeRateService exchangeRateService) {
        this.exchangeRateService = exchangeRateService;
    }
    @ApiOperation(value="환율 API 동작여부 확인", notes="한국 수출입 은행 api 호출, 11시 이전 혹은 1000번 이상 호출 시 Null")
    @ApiResponses({
            @ApiResponse(code = 200, message = "API 정상 작동"),
            @ApiResponse(code = 500, message = "서버 에러")
    })
    @GetMapping("/getExchangeRate")
    public ResponseEntity getExchangeRate(){
        ExchangeRateDto[] exchangeRateDto = exchangeRateService.getExchangeRate();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(new MediaType("application", "json", Charset.forName("UTF-8")));

        return new ResponseEntity<>(exchangeRateDto, httpHeaders, HttpStatus.OK);
    }
}

 

Service

 

ObjectMapper 로 Json 데이터를 DTO로 담음.

ModelMapper 를 이용해서 DTO -> Entity로 전환하여 DB Save

PropertyMap  : DTO 와 객체 사이 필드를 매핑하는 설정 Map

@Service
@RequiredArgsConstructor
public class ExchangeRateImpl implements ExchangeRateService {

    @Autowired
    private Environment environment;
    private ExchangeRateDto exchangeRateDto;


    private final ExchangeRepository exchangeRepository;
    @Override
    public ExchangeRateDto[] getExchangeRate() {
        ArrayList<ExchangeRateDto> exchangeRateDtoArrayList = new ArrayList<>();
        BufferedReader reader;
        String line;
        StringBuffer responseContent = new StringBuffer();
        JSONParser parser = new JSONParser();

        String authKey = "<발급받은 키>";
        String searchDate = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String dataType = "AP01";
        BigDecimal exchangeRate = null;
        HttpURLConnection connection = null;
        try {
            // Request URL
            URL url = new URL("https://www.koreaexim.go.kr/site/program/financial/exchangeJSON?authkey=" + authKey + "&searchdate=" + searchDate + "&data=" + dataType);
            connection = (HttpURLConnection) url.openConnection();

            // Request 초기 세팅
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);

            int status = connection.getResponseCode();

            // API 호출
            // 실패했을 경우 Connection Close
            if (status > 299) {
                reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
                while ((line = reader.readLine()) != null) {
                    responseContent.append(line);
                }
                reader.close();
            } else { // 성공했을 경우 환율 정보 추출
                reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                while ((line = reader.readLine()) != null) {

                    JSONArray exchangeRateInfoList = (JSONArray) parser.parse(line);

                    for (Object o : exchangeRateInfoList) {
                        JSONObject exchangeRateInfo = (JSONObject) o;


                        ObjectMapper objectMapper = new ObjectMapper();
                        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                        // Json String 으로 변환
                        String jsonString = objectMapper.writeValueAsString(o);

                        PropertyMap<ExchangeRateDto, ExchangeRate> exchangeRateMap = new PropertyMap<ExchangeRateDto, ExchangeRate>() {
                            protected void configure() {
                                map().setBkpr(source.getBkpr());
                                map().setCurNm(source.getCur_nm());
                                map().setCurUnit(source.getCur_unit());
                                map().setDealBasR(source.getDeal_bas_r());
                                map().setKftcDealBasR(source.getKftc_deal_bas_r());
                                map().setTenDdEfeeR(source.getTen_dd_efee_r());
                                map().setKftcBkpr(source.getKftc_bkpr());
                                map().setYyEfeeR(source.getYy_efee_r());
                            }
                        };

                        // DTO -> Entity 객체로 변환
                        ModelMapper modelMapper = new ModelMapper();
                        modelMapper.addMappings(exchangeRateMap);
                        exchangeRateDto = objectMapper.readValue(jsonString, ExchangeRateDto.class);
                        exchangeRateDto.setExchangeDate(LocalDateTime.now());
                        ExchangeRate exchangeRateVo = modelMapper.map(exchangeRateDto, ExchangeRate.class);


                        exchangeRepository.save(exchangeRateVo);
                        exchangeRateDtoArrayList.add(exchangeRateDto);

                    }
                }
                reader.close();
            }
            System.out.println(responseContent.toString());

        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (org.json.simple.parser.ParseException e) {
            throw new RuntimeException(e);
        } finally {
            connection.disconnect();
        }

        return exchangeRateDtoArrayList.toArray(ExchangeRateDto[]::new);
    }

}

 

Repository

public interface ExchangeRepository extends JpaRepository<ExchangeRate, Long> {
}

 

Swagger