forked from AcaMate/AcaMate_iOS
135 lines
5.2 KiB
Swift
135 lines
5.2 KiB
Swift
//
|
|
// APIController.swift
|
|
// AcaMate
|
|
//
|
|
// Created by Sean Kim on 11/26/24.
|
|
//
|
|
|
|
|
|
import Foundation
|
|
import Combine
|
|
import Alamofire
|
|
|
|
public class APIManager {
|
|
private var cancellables = Set<AnyCancellable>()
|
|
// public static let shared = APIManager()
|
|
|
|
@UserDefault(key: "refresh", defaultValue: "refreshToken") var refresh
|
|
@UserDefault(key: "token", defaultValue: "accToken") var accToken
|
|
|
|
// private init(cancellables: Set<AnyCancellable> = Set<AnyCancellable>()) {
|
|
// self.cancellables = cancellables
|
|
// }
|
|
|
|
public func loadAPIData<T: APIResponseProtocol>(_ request: APIRequest<T>) -> Future<T, Error> {
|
|
let encoding: ParameterEncoding = (request.method == .get) ? URLEncoding.default : JSONEncoding.default
|
|
|
|
return Future { promise in
|
|
printLog(request.parameters)
|
|
AF.request("\(request.url)\(request.path)",
|
|
method: request.method,
|
|
parameters: request.parameters,
|
|
encoding: encoding,
|
|
headers: request.headers
|
|
)
|
|
.validate(statusCode: 200 ..< 300)
|
|
.responseDecodable(of: request.decoding) { 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<Any, Error> {
|
|
return Future { [weak self] promise in
|
|
guard let self = self else {return}
|
|
|
|
let request = APIRequest.init(path: "/api/v1/in/app/retryAccess",
|
|
parameters: ["refresh": refresh],
|
|
decoding: APIResponse<Access>.self)
|
|
|
|
APIManager().loadAPIData(request)
|
|
.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<Access> 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")))
|
|
}
|
|
}
|
|
.store(in: &self.cancellables)
|
|
}
|
|
}
|
|
|
|
|
|
public func loadUserAPIData<T: APIResponseProtocol & Codable>(request: APIRequest<T>) -> Future<T, Error>{
|
|
return Future { [weak self] promise in
|
|
guard let self = self else {return}
|
|
printLog(request.parameters["token"])
|
|
loadAPIData(request)
|
|
.flatMap { (response: T) -> AnyPublisher<T, Error> in
|
|
switch response.status.code {
|
|
case .inputErr(let code) where code == "101":
|
|
return self.reloadAccessToken()
|
|
.flatMap { response -> AnyPublisher<T, Error> in
|
|
self.accToken = (response as! Access).access
|
|
var updateRequest = request
|
|
updateRequest.parameters["token"] = self.accToken
|
|
printLog("Acc: \(self.accToken)")
|
|
return APIManager().loadAPIData(updateRequest)
|
|
.eraseToAnyPublisher()
|
|
}
|
|
.eraseToAnyPublisher()
|
|
default:
|
|
return Just(response)
|
|
.setFailureType(to: Error.self)
|
|
.eraseToAnyPublisher()
|
|
}
|
|
}
|
|
.sink { completion in
|
|
switch completion {
|
|
case .failure(let error):
|
|
promise(.failure(error))
|
|
case .finished:
|
|
break
|
|
}
|
|
} receiveValue: { finalResponse in
|
|
promise(.success(finalResponse))
|
|
}
|
|
.store(in: &self.cancellables)
|
|
}
|
|
}
|
|
}
|
|
|
|
|