Skip to content

Commit 4569b2e

Browse files
committed
[NDGL-104] feat: 여행 도구 - 환율 정보 조회
1 parent 3f5f7ec commit 4569b2e

14 files changed

Lines changed: 771 additions & 142 deletions

File tree

data/core/src/main/java/com/yapp/ndgl/data/core/di/NetworkModule.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,15 @@ object NetworkModule {
136136
.addInterceptor(androidCredentialInterceptor)
137137
.addInterceptor(httpLoggingInterceptor)
138138
.build()
139+
140+
@ExchangeRateClient
141+
@Singleton
142+
@Provides
143+
fun provideExchangeRateOkHttpClient(
144+
httpLoggingInterceptor: HttpLoggingInterceptor,
145+
): OkHttpClient = OkHttpClient.Builder()
146+
.addInterceptor(httpLoggingInterceptor)
147+
.build()
139148
}
140149

141150
@Qualifier
@@ -173,3 +182,11 @@ annotation class WeatherClient
173182
@Qualifier
174183
@Retention(AnnotationRetention.BINARY)
175184
annotation class GeocodingClient
185+
186+
@Qualifier
187+
@Retention(AnnotationRetention.BINARY)
188+
annotation class ExchangeRateApiKey
189+
190+
@Qualifier
191+
@Retention(AnnotationRetention.BINARY)
192+
annotation class ExchangeRateClient

data/travel/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ android {
1414
buildConfigField("String", "PLACE_API_KEY", "\"${localProperties.getProperty("PLACE_API_KEY", "")}\"")
1515
buildConfigField("String", "ROUTE_API_KEY", "\"${localProperties.getProperty("ROUTE_API_KEY", "")}\"")
1616
buildConfigField("String", "WEATHER_API_KEY", "\"${localProperties.getProperty("WEATHER_API_KEY", "")}\"")
17+
buildConfigField("String", "EXCHANGE_RATE_API_KEY", "\"${localProperties.getProperty("EXCHANGE_RATE_API_KEY", "")}\"")
1718
}
1819

1920
buildFeatures {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.yapp.ndgl.data.travel.api
2+
3+
import com.yapp.ndgl.data.travel.model.ExchangeRateResponse
4+
import retrofit2.http.GET
5+
import retrofit2.http.Path
6+
7+
interface ExchangeRateApi {
8+
@GET("v6/{apiKey}/latest/{base}")
9+
suspend fun getLatestRate(
10+
@Path("apiKey") apiKey: String,
11+
@Path("base") base: String,
12+
): ExchangeRateResponse
13+
}

data/travel/src/main/java/com/yapp/ndgl/data/travel/di/TravelNetworkModule.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import android.content.Context
44
import com.google.android.libraries.places.api.Places
55
import com.google.android.libraries.places.api.net.PlacesClient
66
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
7+
import com.yapp.ndgl.data.core.di.ExchangeRateApiKey
8+
import com.yapp.ndgl.data.core.di.ExchangeRateClient
79
import com.yapp.ndgl.data.core.di.GeocodingClient
810
import com.yapp.ndgl.data.core.di.RouteApiKey
911
import com.yapp.ndgl.data.core.di.RouteBaseUrl
1012
import com.yapp.ndgl.data.core.di.RouteClient
1113
import com.yapp.ndgl.data.core.di.WeatherApiKey
1214
import com.yapp.ndgl.data.core.di.WeatherClient
1315
import com.yapp.ndgl.data.travel.BuildConfig
16+
import com.yapp.ndgl.data.travel.api.ExchangeRateApi
1417
import com.yapp.ndgl.data.travel.api.GeocodingApi
1518
import com.yapp.ndgl.data.travel.api.PlaceApi
1619
import com.yapp.ndgl.data.travel.api.RouteApi
@@ -35,6 +38,7 @@ object TravelNetworkModule {
3538
private const val ROUTES_BASE_URL = "https://routes.googleapis.com/"
3639
private const val WEATHER_BASE_URL = "https://weather.googleapis.com/"
3740
private const val GEOCODING_BASE_URL = "https://maps.googleapis.com/"
41+
private const val EXCHANGE_RATE_BASE_URL = "https://v6.exchangerate-api.com/"
3842

3943
@Provides
4044
@Singleton
@@ -140,4 +144,27 @@ object TravelNetworkModule {
140144
fun provideRouteApi(
141145
@RouteClient retrofit: Retrofit,
142146
): RouteApi = retrofit.create(RouteApi::class.java)
147+
148+
@ExchangeRateApiKey
149+
@Provides
150+
@Singleton
151+
fun provideExchangeRateApiKey(): String = BuildConfig.EXCHANGE_RATE_API_KEY
152+
153+
@ExchangeRateClient
154+
@Provides
155+
@Singleton
156+
fun provideExchangeRateRetrofit(
157+
@ExchangeRateClient okHttpClient: OkHttpClient,
158+
json: Json,
159+
): Retrofit = Retrofit.Builder()
160+
.baseUrl(EXCHANGE_RATE_BASE_URL)
161+
.client(okHttpClient)
162+
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
163+
.build()
164+
165+
@Provides
166+
@Singleton
167+
fun provideExchangeRateApi(
168+
@ExchangeRateClient retrofit: Retrofit,
169+
): ExchangeRateApi = retrofit.create(ExchangeRateApi::class.java)
143170
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.yapp.ndgl.data.travel.model
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
6+
@Serializable
7+
data class ExchangeRateResponse(
8+
@SerialName("result") val result: String,
9+
@SerialName("base_code") val baseCode: String,
10+
@SerialName("time_last_update_utc") val timeLastUpdateUtc: String,
11+
@SerialName("conversion_rates") val conversionRates: Map<String, Double>,
12+
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.yapp.ndgl.data.travel.repository
2+
3+
import com.yapp.ndgl.data.core.di.ExchangeRateApiKey
4+
import com.yapp.ndgl.data.travel.api.ExchangeRateApi
5+
import javax.inject.Inject
6+
import javax.inject.Singleton
7+
8+
@Singleton
9+
class ExchangeRateRepository @Inject constructor(
10+
private val exchangeRateApi: ExchangeRateApi,
11+
@ExchangeRateApiKey private val apiKey: String,
12+
) {
13+
suspend fun getKrwRate(currencyCode: String): Double? {
14+
return exchangeRateApi.getLatestRate(apiKey, currencyCode)
15+
.conversionRates["KRW"]
16+
}
17+
18+
suspend fun getSupportedCurrencyCodes(): List<String> {
19+
return exchangeRateApi.getLatestRate(apiKey, "USD").conversionRates.keys.toList()
20+
}
21+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.yapp.ndgl.data.travel.util
2+
3+
import java.util.Currency
4+
import java.util.Locale
5+
6+
object CurrencyInfoResolver {
7+
private val countryCodeOverrides = mapOf("EUR" to "EU")
8+
9+
fun getCountryCode(currencyCode: String): String? {
10+
countryCodeOverrides[currencyCode]?.let { return it }
11+
return Locale.getAvailableLocales()
12+
.firstOrNull { locale ->
13+
locale.country.isNotEmpty() &&
14+
runCatching { Currency.getInstance(locale)?.currencyCode == currencyCode }.getOrDefault(false)
15+
}?.country
16+
}
17+
18+
fun getCountryName(currencyCode: String): String {
19+
val code = getCountryCode(currencyCode) ?: return currencyCode
20+
return Locale("", code).getDisplayCountry(Locale.KOREAN)
21+
}
22+
23+
fun getCurrencyCode(countryCode: String): String {
24+
return runCatching {
25+
Currency.getInstance(Locale("", countryCode)).currencyCode
26+
}.getOrDefault("USD")
27+
}
28+
29+
fun getKoreanName(currencyCode: String): String {
30+
return runCatching {
31+
Currency.getInstance(currencyCode).getDisplayName(Locale.KOREAN)
32+
}.getOrDefault(currencyCode)
33+
}
34+
}

0 commit comments

Comments
 (0)