diff --git a/AcaMate.xcodeproj/project.pbxproj b/AcaMate.xcodeproj/project.pbxproj index 50d9bde..dee89eb 100644 --- a/AcaMate.xcodeproj/project.pbxproj +++ b/AcaMate.xcodeproj/project.pbxproj @@ -328,7 +328,7 @@ SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited) DEV"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited) DEV LOCAL"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = 1; diff --git a/AcaMate.xcodeproj/project.xcworkspace/xcuserdata/tanine.xcuserdatad/UserInterfaceState.xcuserstate b/AcaMate.xcodeproj/project.xcworkspace/xcuserdata/tanine.xcuserdatad/UserInterfaceState.xcuserstate index 50b4d96..973f12e 100644 Binary files a/AcaMate.xcodeproj/project.xcworkspace/xcuserdata/tanine.xcuserdatad/UserInterfaceState.xcuserstate and b/AcaMate.xcodeproj/project.xcworkspace/xcuserdata/tanine.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/AcaMate/1. View/11. Intro & Login/IntroView.swift b/AcaMate/1. View/11. Intro & Login/IntroView.swift index 7d03394..e776bc2 100644 --- a/AcaMate/1. View/11. Intro & Login/IntroView.swift +++ b/AcaMate/1. View/11. Intro & Login/IntroView.swift @@ -99,7 +99,7 @@ struct IntroView: View { private func loadVersion() -> Future { return Future { promise in - loadAPIData(url: "\(API_URL)", + APIManager.shared.loadAPIData(url: "\(API_URL)", path: "/api/v1/in/app/version", parameters: ["type":"I"], decodingType: APIResponse.self) diff --git a/AcaMate/1. View/11. Intro & Login/LoginView.swift b/AcaMate/1. View/11. Intro & Login/LoginView.swift index 0e593d9..8d06828 100644 --- a/AcaMate/1. View/11. Intro & Login/LoginView.swift +++ b/AcaMate/1. View/11. Intro & Login/LoginView.swift @@ -35,8 +35,10 @@ struct LoginView: View { Button { // MARK: - TODO, 애플 계정 로그인 구현 // appVM.naviState.set(act: .ADD, path: .SelectAcademy(bids: ["AA0000", "AA0001"])) - loginVM.toggleLoading = true +// loginVM.toggleLoading = true // loginVM.loginTest(type: .Kakao, id: "TestSNSID1@#") + loginVM.USERPAITEST() + } label: { makeButton(image: Image(.Logo.appleIcon), color: Color(.Text.black), "애플 계정으로 시작하기") diff --git a/AcaMate/3. ViewModel/LoginViewModel.swift b/AcaMate/3. ViewModel/LoginViewModel.swift index 112721f..9ace1dd 100644 --- a/AcaMate/3. ViewModel/LoginViewModel.swift +++ b/AcaMate/3. ViewModel/LoginViewModel.swift @@ -17,16 +17,57 @@ class LoginViewModel: ObservableObject { var bidArray: [String] = [] + func USERPAITEST() { + @UserDefault(key: "refresh", defaultValue: "refreshToken") var refresh + var acc = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJBTVRlc3RFbWFpbDIwMjUwMzE3IiwianRpIjoiYTQzN2Q4YjUtNzQyMi00NWVhLWFiNTktZWI2MTBkNDMwNWRlIiwiZXhwIjoxNzQyMjAwODQ3LCJpc3MiOiJBY2FNYXRlIiwiYXVkIjoiaHR0cHM6L2RldmFjYW1hdGUuaXBzdGVpbi5teWRzLm1lIn0.Y-xxdQWyu3BX_y5hlwWjAdxG5-QRZyHEgJ6T2pDkFRc" + + refresh = "tsLeVEtZTjy8iWDvT9vf7Kv7qQr3WgPjeNkFdMb9Rv4=" + + APIManager.shared.loadAPIData(url: "\(API_URL)", + path: "/api/v1/in/user/cancel", + parameters: ["token": acc], + decodingType: APIResponse.self) + .flatMap { response -> AnyPublisher, Error> in + switch response.status.code { + case .inputErr(let code) where code == "101": + return APIManager.shared.reloadAccessToken() + .flatMap { newAcc -> AnyPublisher, Error> in + APIManager.shared.loadAPIData(url: "\(API_URL)", + path: "/api/v1/in/user/cancel", + parameters: ["token": (newAcc as! Access).access], + decodingType: APIResponse.self) + .eraseToAnyPublisher() + } + .eraseToAnyPublisher() + default: + return Just(response) + .setFailureType(to: Error.self) + .eraseToAnyPublisher() + } + } + .sink { completion in + switch completion { + case .failure(let error): + printLog("최종 \(error)") + case .finished: + break + } + } receiveValue: { response in + printLog("최종: \(response)") + } + .store(in: &cancellables) + } + func loginAction(type: SNSLoginType) { LoginController().login(type) .flatMap{ snsId in - loadAPIData(url: "\(API_URL)", - path: "/api/v1/in/user/login", - parameters: [ - "acctype": "\(type == .Apple ? "ST00": "ST01")", - "sns_id": "\(snsId.snsId)" - ], - decodingType: APIResponse.self) + APIManager.shared.loadAPIData(url: "\(API_URL)", + path: "/api/v1/in/user/login", + parameters: [ + "acctype": "\(type == .Apple ? "ST00": "ST01")", + "sns_id": "\(snsId.snsId)" + ], + decodingType: APIResponse.self) .map { response in return (snsId: snsId.snsId, response: response) } @@ -42,17 +83,17 @@ class LoginViewModel: ObservableObject { } } receiveValue: { [weak self] response in guard let self = self else { return } - guard let userToken = response.response as? APIResponse else {return} - var snsId = response.snsId + // let userToken = response.response // as? APIResponse else {return} + let snsId = response.snsId - switch userToken.status.code { + switch response.response.status.code { case .success(let code): if code == "000" { @UserDefault(key: "token", defaultValue: "accToken") var accToken @UserDefault(key: "refresh", defaultValue: "refreshToken") var refreshToken - if let token = userToken.data.toStringDict()["token"], - let refresh = userToken.data.toStringDict()["refresh"] { + if let token = response.response.data.toStringDict()["token"], + let refresh = response.response.data.toStringDict()["refresh"] { printLog(token) printLog(refresh) accToken = token @@ -69,7 +110,7 @@ class LoginViewModel: ObservableObject { // MARK: TO-DO // 회원가입 로직 printLog("\(apiCode) : 로그인 정보 없음") -// self.pathName = .Register(type, id: "\(id)") + // self.pathName = .Register(type, id: "\(id)") default: // 그외에 서버에서 처리를 하다가 문제가 생겨서 발생하는 에러는 여기로 보낼거임 printLog("ERROR") diff --git a/AcaMate/3. ViewModel/SelectAcademyViewModel.swift b/AcaMate/3. ViewModel/SelectAcademyViewModel.swift index e4c6c46..ac13db9 100644 --- a/AcaMate/3. ViewModel/SelectAcademyViewModel.swift +++ b/AcaMate/3. ViewModel/SelectAcademyViewModel.swift @@ -18,7 +18,7 @@ class SelectAcademyViewModel: ObservableObject { func loadAcademy() { @UserDefault(key: "token", defaultValue: "accToken") var token @UserDefault(key: "refresh", defaultValue: "refreshToken") var refresh - loadAPIData(url: "\(API_URL)", + APIManager.shared.loadAPIData(url: "\(API_URL)", path: "/api/v1/in/user/academy", method: .get, parameters: ["token": token, "refresh": refresh], diff --git a/AcaMate/5. Manager/APIManager.swift b/AcaMate/5. Manager/APIManager.swift index 64ad373..a69b594 100644 --- a/AcaMate/5. Manager/APIManager.swift +++ b/AcaMate/5. Manager/APIManager.swift @@ -10,75 +10,92 @@ import Foundation import Combine import Alamofire - -public func loadAPIData(url: String, path: String, - method: HTTPMethod = .get, - parameters: [String: Any], - headers: HTTPHeaders = [:],//["Accept": "application/json"], - decodingType: T.Type) -> Future { - let encoding: ParameterEncoding = (method == .get) ? URLEncoding.default : JSONEncoding.default - return Future { promise in - printLog(parameters) - AF.request("\(url)\(path)", - method: method, - parameters: parameters, - encoding: encoding, - headers: headers - ) - .validate(statusCode: 200 ..< 300) - .responseString { response in - printLog(response) - } - .responseDecodable(of: decodingType) { response in - switch response.result { - case .success(let value): - promise(.success(value)) - case .failure(let error): - promise(.failure(error)) +public class APIManager { + private var cancellables = Set() + public static let shared = APIManager() + + private init(cancellables: Set = Set()) { + self.cancellables = cancellables + } + + public func loadAPIData(url: String, path: String, + method: HTTPMethod = .get, + parameters: [String: Any], + headers: HTTPHeaders = [:],//["Accept": "application/json"], + decodingType: T.Type) -> Future { + let encoding: ParameterEncoding = (method == .get) ? URLEncoding.default : JSONEncoding.default + return Future { promise in + printLog(parameters) + AF.request("\(url)\(path)", + method: method, + parameters: parameters, + encoding: encoding, + headers: headers + ) + .validate(statusCode: 200 ..< 300) + // .responseString { response in + // printLog(response) + // } + .responseDecodable(of: decodingType) { response in + + switch response.result { + case .success(let value): + printLog("Good: \(value)") + promise(.success(value)) + + case .failure(let error): + printLog("Bad: \(error))") + promise(.failure(error)) + + } } } } -} - -public func reloadAccessToken() -> Future { - @UserDefault(key: "refresh", defaultValue: "refreshToken") var refresh - return Future { promise in - _ = loadAPIData(url: "\(API_URL)", - path: "/api/v1/in/app/retryAccess", - parameters: ["refresh": refresh], - decodingType: APIResponse.self) - .sink { completion in - switch completion { - case .failure(let error): - promise(.failure(error)) - printLog("\(error)") - case .finished: - printLog("엑세스 토큰 재발급 완료") - break - } - } receiveValue: { response in - guard let accToken = response as? APIResponse else { - promise(.failure(ACA_ERROR("Unknown ERROR"))) - return - } - - switch accToken.status.code { - case .success(let code): - if code == "000" { - if let tknData = accToken.data { promise(.success(tknData)) } + + + + public func reloadAccessToken() -> Future { + + @UserDefault(key: "refresh", defaultValue: "refreshToken") var refresh + return Future { [weak self] promise in + guard let self = self else {return} + APIManager.shared.loadAPIData(url: "\(API_URL)", + path: "/api/v1/in/app/retryAccess", + parameters: ["refresh": refresh], + decodingType: APIResponse.self) + .sink { completion in + switch completion { + case .failure(let error): + promise(.failure(error)) + printLog("\(error)") + case .finished: + printLog("엑세스 토큰 재발급 완료") + break + } + } receiveValue: { response in + guard let accToken = response as? APIResponse else { + promise(.failure(ACA_ERROR("Unknown ERROR"))) + return + } + + switch accToken.status.code { + case .success(let code): + if code == "000" { + if let tknData = accToken.data { promise(.success(tknData)) } + } + case .inputErr(let code): + // 로그인 화면으로 전환하기 + promise(.failure(ACA_ERROR("Refresh token ERROR(\(code), \(accToken.status.message)"))) + default: + // 그외에 서버에서 처리를 하다가 문제가 생겨서 발생하는 에러는 여기로 보낼거임 + promise(.failure(ACA_ERROR("Unknown ERROR"))) } - case .inputErr(let code): - // 로그인 화면으로 전환하기 - promise(.failure(ACA_ERROR("Refresh token ERROR(\(code), \(accToken.status.message)"))) - default: - // 그외에 서버에서 처리를 하다가 문제가 생겨서 발생하는 에러는 여기로 보낼거임 - promise(.failure(ACA_ERROR("Unknown ERROR"))) } + .store(in: &self.cancellables) } + } - - }