// // Login.swift // JJUNGTABLE // // Created by Sean Kim on 6/11/24. // import SwiftUI import Combine import AuthenticationServices import KakaoSDKCommon import KakaoSDKAuth import KakaoSDKUser import Firebase import FirebaseAuth /* 2024-06-11 01:26:08184 [ℹ️][Api.swift 136:41] -> response: Optional({ "app_id" = 987284; "expires_in" = 43199; id = 3138117983; }) __________ __________ __________ __________ * LOCATION : [ContentView.swift : 69] - body | TIME : [2024/06/12 14:39:17:856] > NOTE : 001273.49bfcb15b70d440a9666b4434336fc2c.0741  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ */ class Login: NSObject, ObservableObject{ // let appId = "987284" @State private var verificationCode: String = "" @State private var verificationID: String? private var cancellables = Set() private var currentPromise: Future.Promise? func tryKakaoLogin() -> Future { return Future { promise in if UserApi.isKakaoTalkLoginAvailable() { // 카카오 간편로그인이 가능한지 확인 UserApi.shared.loginWithKakaoTalk { (oauthToken, error) in if let error = error { promise(.failure(.init(caseType: .KAKAO_LOGIN, message: "\(error.localizedDescription)"))) } else { printLog("Login success.: \(oauthToken)") self.kakaoAccessUserInfo().sink( receiveCompletion: { completion in if case .failure(let error) = completion { promise(.failure(error)) } }, receiveValue: { id in promise(.success(id)) } ).store(in: &self.cancellables) } } } else { UserApi.shared.loginWithKakaoAccount { (oauthToken, error) in if let error = error { promise(.failure(.init(caseType: .KAKAO_LOGIN, message: "\(error.localizedDescription)"))) } else { print("Login success.") // AccessToken 저장 또는 다른 로그인 후 처리 self.kakaoAccessUserInfo().sink( receiveCompletion: { completion in if case .failure(let error) = completion { promise(.failure(error)) } }, receiveValue: { id in promise(.success(id)) } ).store(in: &self.cancellables) } } } } } func kakaoAccessUserInfo() -> Future { return Future { promise in UserApi.shared.me { user, error in if let error = error { printLog("[ERROR] Kakao me: \(error)") promise(.failure(.init(caseType: .KAKAO_ACC_USER, message: "\(error.localizedDescription)"))) } else if let user = user, let id = user.id { printLog("Access Kakao UserInfo") promise(.success("\(id)")) } else { promise(.failure(.init(caseType: .KAKAO_ACC_USER, message: "undefined ERROR"))) } } } } } extension Login: ASAuthorizationControllerDelegate { func tryAppleLogin() -> Future { return Future { promise in let request = ASAuthorizationAppleIDProvider().createRequest() // request.requestedScopes = [.fullName, .email] let controller = ASAuthorizationController(authorizationRequests: [request]) controller.delegate = self controller.presentationContextProvider = self // 이거를 써야지 로그인 창이 뜹니다 controller.performRequests() self.currentPromise = promise } } func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { printLog("APPLE success") if let credential = authorization.credential as? ASAuthorizationAppleIDCredential { let userId = credential.user currentPromise?(.success(userId)) } else { currentPromise?(.failure(.init(caseType: .APPLE_LOGIN, message: "로그인 실패"))) } currentPromise = nil } func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: any Error) { currentPromise?(.failure(.init(caseType: .APPLE_LOGIN, message: "\(error.localizedDescription)"))) currentPromise = nil } } extension Login: ASAuthorizationControllerPresentationContextProviding{ func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor { guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return ASPresentationAnchor() } // Return the first window of the window scene return windowScene.windows.first { $0.isKeyWindow } ?? ASPresentationAnchor() } } extension Login { func sendCodeToPhone() { PhoneAuthProvider.provider().verifyPhoneNumber("+821034523551", uiDelegate: nil) { verificationID, error in if let error = error { print("Error: \(error.localizedDescription)") return } // self.verificationID = verificationID UserDefaults.standard.set(verificationID, forKey: "authVerifyID") printLog(verificationID) } } func verifyCode(code: String) { printLog(code) // let verificationID = UserDefaults.standard.string(forKey: "authVerifyID") guard let verificationID = UserDefaults.standard.string(forKey: "authVerifyID") else { printLog("Please request verification code first.") return } let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationID, verificationCode: code ) printLog(credential) } }