Skip to content

Commit

Permalink
feat : 환율 정보 제공 API 추가
Browse files Browse the repository at this point in the history
Dayon-Hong committed Jul 13, 2024
1 parent 80eb5f5 commit ffa951a
Showing 5 changed files with 147 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -2,8 +2,10 @@

import com.isp.backend.domain.country.dto.request.LocationRequest;
import com.isp.backend.domain.country.dto.response.DailyWeatherResponse;
import com.isp.backend.domain.country.dto.response.ExchangeRateResponse;
import com.isp.backend.domain.country.dto.response.LocationResponse;
import com.isp.backend.domain.country.dto.response.WeatherResponse;
import com.isp.backend.domain.country.entity.ExchangeRate;
import com.isp.backend.domain.country.service.CountryService;
import com.isp.backend.domain.country.service.ExchangeRateService;
import lombok.RequiredArgsConstructor;
@@ -58,24 +60,23 @@ public ResponseEntity<List<DailyWeatherResponse>> getWeeklyWeather(@RequestBody
}


/** 특정 기준 통화에 대한 모든 환율 정보 API **/
// @GetMapping("/exchange-rates")
// public ResponseEntity<?> getExchangeRates(@RequestParam String baseCurrency) {
// logger.info("Received request for exchange rates with base currency: {}", baseCurrency);
//
// try {
// Map<String, Double> exchangeRates = exchangeRateService.getExchangeRates(baseCurrency);
// return ResponseEntity.ok(exchangeRates);
// } catch (Exception e) {
// logger.error("Error fetching exchange rates", e);
// return ResponseEntity.badRequest().body(Map.of(
// "errorMessage", "환율 정보를 가져오는데 실패했습니다.",
// "httpStatus", "BAD_REQUEST",
// "code", null
// ));
// }
// }
/** 환율 정보 업데이트 API **/
@GetMapping("/exchange-rates/update")
public String updateExchangeRate() {
try {
exchangeRateService.updateExchangeRates();
return "updated Successfully";
} catch (Exception e) {
return "failed to update exchange rates: " + e.getMessage();
}
}

/** 환율 정보 조회 API **/
@GetMapping("/exchange-rates")
public ResponseEntity<List<ExchangeRateResponse>> getAllExchangeRates() {
List<ExchangeRateResponse> exchangeRates = exchangeRateService.getAllExchangeRates();
return ResponseEntity.ok(exchangeRates);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.isp.backend.domain.country.mapper;

import com.isp.backend.domain.country.dto.response.ExchangeRateResponse;
import com.isp.backend.domain.country.entity.ExchangeRate;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

@Component
@RequiredArgsConstructor
public class ExchangeRateMapper {

public ExchangeRateResponse convertToDto(ExchangeRate exchangeRate) {
ExchangeRateResponse dto = new ExchangeRateResponse();
dto.setBaseCurrency(exchangeRate.getBaseCurrency());
dto.setTargetCurrency(exchangeRate.getTargetCurrency());
dto.setRate(BigDecimal.valueOf(exchangeRate.getRate()));
return dto;
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.isp.backend.domain.country.repository;

import com.isp.backend.domain.country.entity.ExchangeRate;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ExchangeRateRepository extends JpaRepository<ExchangeRate, Long> {
ExchangeRate findByBaseCurrencyAndTargetCurrency(String baseCurrency, String targetCurrency);

}
Original file line number Diff line number Diff line change
@@ -1,56 +1,116 @@
package com.isp.backend.domain.country.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.isp.backend.domain.country.dto.response.ExchangeRateResponse;
import com.isp.backend.domain.country.entity.ExchangeRate;
import com.isp.backend.domain.country.mapper.ExchangeRateMapper;
import com.isp.backend.domain.country.repository.ExchangeRateRepository;
import com.isp.backend.global.exception.openApi.ExchangeRateIsFailedException;
import com.isp.backend.global.exception.openApi.ExchangeRateSearchFailedException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class ExchangeRateService {

private final ExchangeRateRepository exchangeRateRepository;
private final ExchangeRateMapper exchangeRateMapper ;

@Value("${api-key.exchange-rate}")
private String exchangeRateApiKey;

private final String BASE_URL = "https://v6.exchangerate-api.com/v6";

/** 특정 기준 통화에 대한 모든 환율 정보 가져오기 **/
// public Map<String, Double> getExchangeRates(String baseCurrency) {
// String url = BASE_URL + exchangeRateApiKey + "/latest/" + baseCurrency;
// logger.info("Requesting exchange rates for base currency: {}", baseCurrency);
//
// try {
// String jsonResponse = restTemplate.getForObject(url, String.class);
// ObjectMapper objectMapper = new ObjectMapper();
// JsonNode rootNode = objectMapper.readTree(jsonResponse);
// logger.info("Received response: {}", jsonResponse);
//
// String result = rootNode.path("result").asText();
// if (!"success".equals(result)) {
// throw new RuntimeException("API 요청 실패: " + result);
// }
//
// JsonNode conversionRates = rootNode.path("conversion_rates");
// Map<String, Double> rates = new HashMap<>();
// conversionRates.fields().forEachRemaining(entry -> {
// rates.put(entry.getKey(), entry.getValue().asDouble());
// });
//
// return rates;
// } catch (IOException e) {
// logger.error("Error parsing JSON response", e);
// throw new RuntimeException("환율 정보를 가져오는데 실패했습니다.", e);
// }
// }
@Autowired
public ExchangeRateService(ExchangeRateRepository exchangeRateRepository, ExchangeRateMapper exchangeRateMapper) {
this.exchangeRateRepository = exchangeRateRepository;
this.exchangeRateMapper = exchangeRateMapper;
}

/** 환율 데이터 가져와서 업데이트 하는 API 메서드 **/
@Transactional
public void updateExchangeRates() {
// 한국과 미국 통화 환율 비율 저장
updateRatesForBaseCurrency("KRW");
updateRatesForBaseCurrency("USD");
}


/** 환율 데이터 가져와서 업데이트 하는 API 메서드 **/
public List<ExchangeRateResponse> getAllExchangeRates() {
try {
// DB에서 모든 환율 데이터를 가져옴
List<ExchangeRate> exchangeRates = exchangeRateRepository.findAll();

// baseCurrency가 "KRW" 또는 "USD"인 데이터만 필터링하고 DTO로 변환
return exchangeRates.stream()
.filter(rate -> ("KRW".equals(rate.getBaseCurrency()) || "USD".equals(rate.getBaseCurrency()))
&& !rate.getBaseCurrency().equals(rate.getTargetCurrency()))
.map(exchangeRateMapper::convertToDto)
.collect(Collectors.toList());
} catch (Exception e) {
throw new ExchangeRateIsFailedException() ;
}
}


/** 측정 baseCurrency 통화에 대해 업데이트 하는 메서드**/
private void updateRatesForBaseCurrency(String baseCurrency) {
String exchangeRateAPI_URL = "https://v6.exchangerate-api.com/v6/" + exchangeRateApiKey + "/latest/" + baseCurrency;

try {
URL url = new URL(exchangeRateAPI_URL);
HttpURLConnection request = (HttpURLConnection) url.openConnection();
request.connect();

// API 응답 데이터를 JsonObject로 변환
Gson gson = new Gson();
JsonObject jsonobj = gson.fromJson(new InputStreamReader(request.getInputStream()), JsonObject.class);

// API 응답 결과
String req_result = jsonobj.get("result").getAsString();

if ("success".equals(req_result)) {
JsonObject conversionRates = jsonobj.getAsJsonObject("conversion_rates");
for (String targetCurrency : conversionRates.keySet()) {
// 필요한 통화만 가져온다
if (isSupportedCurrency(targetCurrency)) {
double rate = conversionRates.get(targetCurrency).getAsDouble();

// DB에서 환율 데이터 존재 여부 확인
ExchangeRate existingRate = exchangeRateRepository.findByBaseCurrencyAndTargetCurrency(baseCurrency, targetCurrency);

if (existingRate == null) {
ExchangeRate newExchangeRate = new ExchangeRate(baseCurrency, targetCurrency, rate);
exchangeRateRepository.save(newExchangeRate);
} else {
// 기록이 이미 존재하면, rate만 수정한다.
existingRate.setRate(rate);
exchangeRateRepository.save(existingRate);
}
}
}
} else {
throw new ExchangeRateSearchFailedException();
}
} catch (Exception e) {
throw new ExchangeRateIsFailedException() ;
}
}

/** 지원하는 통화만 가져오는 메서드 **/
private boolean isSupportedCurrency(String currencyCode) {
return Set.of("JPY", "GBP", "EURO", "CHF", "CZK", "USD", "SGD", "TWD", "LAK", "MYR", "VND", "THB", "IDR", "PHP", "KRW").contains(currencyCode);
}




0 comments on commit ffa951a

Please sign in to comment.