11package com.jusicool.network.util
22
33import android.content.Context
4+ import android.util.Log
45import com.jusicool.model.koreaInvestment.AccessKeyRequest
56import com.jusicool.model.koreaInvestment.AccessTokenRequest
67import com.jusicool.network.BuildConfig
@@ -18,87 +19,100 @@ class KoreaInvestmentAuthManager @Inject constructor(
1819) {
1920 private val prefs = context.getSharedPreferences(" auth_prefs" , Context .MODE_PRIVATE )
2021
21- // Mutex 객체 생성
2222 private val tokenMutex = Mutex ()
2323 private val approvalKeyMutex = Mutex ()
2424
25- private var accessToken: String? = null
26- private var accessTokenExpiresAt: Long = 0L
27-
28- private var approvalKey: String? = null
29- private var approvalKeyExpiresAt: Long = 0L
30-
3125 suspend fun getValidAccessToken (forceRefresh : Boolean = false): String {
3226 return tokenMutex.withLock {
33- val now = System .currentTimeMillis()
34-
35- if (! forceRefresh && accessToken != null && now < accessTokenExpiresAt) {
36- return accessToken!!
37- }
38-
39- val storedToken = prefs.getString(" access_token" , null )
40- val storedExpires = prefs.getLong(" access_token_expires_at" , 0L )
27+ try {
28+ val now = System .currentTimeMillis()
29+
30+ val storedToken = prefs.getString(" access_token" , null )
31+ val storedExpires = prefs.getLong(" access_token_expires_at" , 0L )
32+
33+ if (! forceRefresh && storedToken != null && now < storedExpires) {
34+ Log .d(" AuthManager" , " ✅ SharedPreferences 캐시된 AccessToken 사용: $storedToken " )
35+ return storedToken
36+ }
37+
38+ Log .d(" AuthManager" , " 🔄 API 요청으로 AccessToken 갱신" )
39+ val response = koreaInvestmentApi.getAccessToken(
40+ AccessTokenRequest (
41+ grantType = " client_credentials" ,
42+ appKey = BuildConfig .KOREAINVESTMENT_API_KEY ,
43+ secretKey = BuildConfig .KOREAINVESTMENT_APP_SECRET ,
44+ )
45+ )
4146
42- if (! forceRefresh && storedToken != null && now < storedExpires) {
43- accessToken = storedToken
44- accessTokenExpiresAt = storedExpires
45- return storedToken
46- }
47+ val newToken = response.accessToken
48+ val expiresAt = (now + (response.expiresIn * 1000L ) - 5 * 60 * 1000L ).toLong()
4749
48- val response = koreaInvestmentApi.getAccessToken(
49- AccessTokenRequest (
50- grantType = " client_credentials" ,
51- appKey = BuildConfig .KOREAINVESTMENT_API_KEY ,
52- secretKey = BuildConfig .KOREAINVESTMENT_APP_SECRET ,
53- )
54- )
50+ prefs.edit().apply {
51+ putString(" access_token" , newToken)
52+ putLong(" access_token_expires_at" , expiresAt)
53+ }.apply ()
5554
56- accessToken = response.accessToken
57- accessTokenExpiresAt = (now + (response.expiresIn * 1000L ) - 5 * 60 * 1000L ).toLong()
55+ Log .d(" AuthManager" , " ✅ 새 AccessToken 저장 및 반환: $newToken , 만료시간: $expiresAt " )
56+ return newToken
57+ } catch (e: Exception ) {
58+ Log .e(" AuthManager" , " ❌ AccessToken 갱신 실패: ${e.message} " , e)
5859
59- prefs.edit().apply {
60- putString(" access_token" , accessToken)
61- putLong(" access_token_expires_at" , accessTokenExpiresAt)
62- }.apply ()
60+ // 기존 저장된 토큰이라도 있으면 반환
61+ val fallbackToken = prefs.getString(" access_token" , null )
62+ if (fallbackToken != null ) {
63+ Log .w(" AuthManager" , " ⚠️ API 실패, 캐시된 AccessToken 반환: $fallbackToken " )
64+ return fallbackToken
65+ }
6366
64- return accessToken!!
67+ throw e // 진짜로 토큰이 없으면 예외 던짐
68+ }
6569 }
6670 }
71+
6772 suspend fun getApprovalKey (forceRefresh : Boolean = false): String {
6873 return approvalKeyMutex.withLock {
69- val now = System .currentTimeMillis()
74+ try {
75+ val now = System .currentTimeMillis()
76+
77+ val storedKey = prefs.getString(" approval_key" , null )
78+ val storedExpires = prefs.getLong(" approval_key_expires_at" , 0L )
79+
80+ if (! forceRefresh && storedKey != null && now < storedExpires) {
81+ Log .d(" AuthManager" , " ✅ SharedPreferences 캐시된 ApprovalKey 사용: $storedKey " )
82+ return storedKey
83+ }
84+
85+ Log .d(" AuthManager" , " 🔄 API 요청으로 ApprovalKey 갱신" )
86+ val response = koreaInvestmentApi.getWebSocketAccessToken(
87+ AccessKeyRequest (
88+ grantType = " client_credentials" ,
89+ appKey = BuildConfig .KOREAINVESTMENT_API_KEY ,
90+ secretKey = BuildConfig .KOREAINVESTMENT_APP_SECRET ,
91+ )
92+ )
7093
71- if (! forceRefresh && approvalKey != null && now < approvalKeyExpiresAt) {
72- return approvalKey!!
73- }
94+ val newKey = response.approvalKey
95+ val expiresAt = now + 24 * 60 * 60 * 1000L
7496
75- val storedKey = prefs.getString(" approval_key" , null )
76- val storedExpires = prefs.getLong(" approval_key_expires_at" , 0L )
97+ prefs.edit().apply {
98+ putString(" approval_key" , newKey)
99+ putLong(" approval_key_expires_at" , expiresAt)
100+ }.apply ()
77101
78- if (! forceRefresh && storedKey != null && now < storedExpires) {
79- approvalKey = storedKey
80- approvalKeyExpiresAt = storedExpires
81- return storedKey
82- }
102+ Log .d(" AuthManager" , " ✅ 새 ApprovalKey 저장 및 반환: $newKey , 만료시간: $expiresAt " )
103+ return newKey
104+ } catch (e: Exception ) {
105+ Log .e(" AuthManager" , " ❌ ApprovalKey 갱신 실패: ${e.message} " , e)
83106
84- val response = koreaInvestmentApi.getWebSocketAccessToken(
85- AccessKeyRequest (
86- grantType = " client_credentials" ,
87- appKey = BuildConfig .KOREAINVESTMENT_API_KEY ,
88- secretKey = BuildConfig .KOREAINVESTMENT_APP_SECRET ,
89- )
90- )
107+ // 기존 저장된 키라도 있으면 반환
108+ val fallbackKey = prefs.getString(" approval_key" , null )
109+ if (fallbackKey != null ) {
110+ Log .w(" AuthManager" , " ⚠️ API 실패, 캐시된 ApprovalKey 반환: $fallbackKey " )
111+ return fallbackKey
112+ }
91113
92- approvalKey = response.approvalKey
93- approvalKeyExpiresAt = now + 24 * 60 * 60 * 1000L
94-
95- prefs.edit().apply {
96- putString(" approval_key" , approvalKey)
97- putLong(" approval_key_expires_at" , approvalKeyExpiresAt)
98- }.apply ()
99-
100- return approvalKey!!
114+ throw e // 진짜로 키가 없으면 예외 던짐
115+ }
101116 }
102117 }
103118}
104-
0 commit comments