구글 로그인 기능 추가
This commit is contained in:
@@ -2,12 +2,15 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>GIDClientID</key>
|
||||
<string>758414412471-3cf403jb4s405eu17qrfrcbs9ofhq369.apps.googleusercontent.com</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>fb608674328645232</string>
|
||||
<string>com.googleusercontent.apps.758414412471-3cf403jb4s405eu17qrfrcbs9ofhq369</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>GIDClientID</key>
|
||||
<string>983594297130-m6bv7lvc1lsetsvv3rk92etqc98uopqj.apps.googleusercontent.com</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>fb612448298237287</string>
|
||||
<string>fb612448298237287</string>
|
||||
<string>com.googleusercontent.apps.983594297130-m6bv7lvc1lsetsvv3rk92etqc98uopqj</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
|
||||
@@ -10,6 +10,7 @@ import Kingfisher
|
||||
|
||||
import FBSDKCoreKit
|
||||
import AppsFlyerLib
|
||||
import GoogleSignIn
|
||||
|
||||
@main
|
||||
struct SodaLiveApp: App {
|
||||
@@ -76,6 +77,7 @@ struct SodaLiveApp: App {
|
||||
} else {
|
||||
ApplicationDelegate.shared.application(UIApplication.shared, open: url, options: [:])
|
||||
AppsFlyerLib.shared().handleOpen(url)
|
||||
GIDSignIn.sharedInstance.handle(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,3 +22,6 @@ let NOTIFLY_PASSWORD = "c6c585db0aaa4189be44d0467c7d66b6@A"
|
||||
|
||||
let APPSCHEME = "voiceon-test"
|
||||
let PAYVERSE_HTML_RESOURCE = "payverse_starter_debug"
|
||||
|
||||
let GID_CLIENT_ID = "758414412471-3cf403jb4s405eu17qrfrcbs9ofhq369.apps.googleusercontent.com"
|
||||
let GID_SERVER_CLIENT_ID = "758414412471-mosodbj2chno7l1j0iihldh6edmk0gk9.apps.googleusercontent.com"
|
||||
|
||||
@@ -1101,6 +1101,42 @@ enum I18n {
|
||||
}
|
||||
}
|
||||
|
||||
enum Login {
|
||||
enum Google {
|
||||
static var openFailed: String {
|
||||
pick(
|
||||
ko: "구글 로그인 화면을 열 수 없습니다.\n다시 시도해 주세요.",
|
||||
en: "Unable to open Google sign-in.\nPlease try again.",
|
||||
ja: "Googleログイン画面を開けません。\nもう一度お試しください。"
|
||||
)
|
||||
}
|
||||
|
||||
static var configMissing: String {
|
||||
pick(
|
||||
ko: "구글 로그인 설정을 확인할 수 없습니다.\n다시 시도해 주세요.",
|
||||
en: "Unable to find Google sign-in settings.\nPlease try again.",
|
||||
ja: "Googleログイン設定を確認できません。\nもう一度お試しください。"
|
||||
)
|
||||
}
|
||||
|
||||
static var signInFailed: String {
|
||||
pick(
|
||||
ko: "구글 로그인에 실패했습니다.\n다시 시도해 주세요.",
|
||||
en: "Google sign-in failed.\nPlease try again.",
|
||||
ja: "Googleログインに失敗しました。\nもう一度お試しください。"
|
||||
)
|
||||
}
|
||||
|
||||
static var tokenMissing: String {
|
||||
pick(
|
||||
ko: "구글 인증 토큰을 가져오지 못했습니다.",
|
||||
en: "Failed to retrieve Google token.",
|
||||
ja: "Google認証トークンを取得できませんでした。"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 문자 메시지(Text Message) 관련 문자열
|
||||
enum TextMessage {
|
||||
// 전송 버튼 라벨
|
||||
|
||||
@@ -132,7 +132,12 @@ struct LoginView: View {
|
||||
Image("ic_login_kakao")
|
||||
.onTapGesture {
|
||||
hideKeyboard()
|
||||
AppState.shared.setAppStep(step: .signUp)
|
||||
}
|
||||
|
||||
Image("ic_login_google")
|
||||
.onTapGesture {
|
||||
hideKeyboard()
|
||||
viewModel.loginWithGoogle()
|
||||
}
|
||||
|
||||
Image("ic_login_apple")
|
||||
|
||||
@@ -12,6 +12,7 @@ import AuthenticationServices
|
||||
import CryptoKit
|
||||
import Security
|
||||
import UIKit
|
||||
import GoogleSignIn
|
||||
|
||||
final class LoginViewModel: NSObject, ObservableObject {
|
||||
private let appViewModel = AppViewModel()
|
||||
@@ -68,6 +69,35 @@ final class LoginViewModel: NSObject, ObservableObject {
|
||||
controller.presentationContextProvider = self
|
||||
controller.performRequests()
|
||||
}
|
||||
|
||||
func loginWithGoogle() {
|
||||
guard let presentingViewController = presentingViewController() else {
|
||||
self.errorMessage = I18n.Login.Google.openFailed
|
||||
self.isShowPopup = true
|
||||
return
|
||||
}
|
||||
|
||||
GIDSignIn.sharedInstance.configuration = GIDConfiguration(clientID: GID_CLIENT_ID, serverClientID: GID_SERVER_CLIENT_ID)
|
||||
|
||||
GIDSignIn.sharedInstance.signIn(withPresenting: presentingViewController) { result, error in
|
||||
DispatchQueue.main.async {
|
||||
if let error = error {
|
||||
ERROR_LOG(error.localizedDescription)
|
||||
self.errorMessage = I18n.Login.Google.signInFailed
|
||||
self.isShowPopup = true
|
||||
return
|
||||
}
|
||||
|
||||
guard let idToken = result?.user.idToken?.tokenString else {
|
||||
self.errorMessage = I18n.Login.Google.tokenMissing
|
||||
self.isShowPopup = true
|
||||
return
|
||||
}
|
||||
|
||||
self.loginWithGoogle(idToken: idToken)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func loginWithApple(identityToken: String, nonce: String) {
|
||||
let pushToken = UserDefaults.string(forKey: .pushToken)
|
||||
@@ -95,6 +125,41 @@ final class LoginViewModel: NSObject, ObservableObject {
|
||||
}
|
||||
.store(in: &subscription)
|
||||
}
|
||||
|
||||
private func loginWithGoogle(idToken: String) {
|
||||
let pushToken = UserDefaults.string(forKey: .pushToken)
|
||||
let marketingPid = UserDefaults.string(forKey: .marketingPid)
|
||||
let request = SocialLoginRequest(
|
||||
container: "ios",
|
||||
pushToken: pushToken.isEmpty ? nil : pushToken,
|
||||
marketingPid: marketingPid.isEmpty ? nil : marketingPid,
|
||||
identityToken: nil,
|
||||
nonce: nil
|
||||
)
|
||||
|
||||
isLoading = true
|
||||
repository.loginGoogle(request: request, idToken: idToken)
|
||||
.sink { result in
|
||||
switch result {
|
||||
case .finished:
|
||||
DEBUG_LOG("finish")
|
||||
case .failure(let error):
|
||||
self.isLoading = false
|
||||
ERROR_LOG(error.localizedDescription)
|
||||
}
|
||||
} receiveValue: { response in
|
||||
self.handleLoginResponse(response)
|
||||
}
|
||||
.store(in: &subscription)
|
||||
}
|
||||
|
||||
private func presentingViewController() -> UIViewController? {
|
||||
return UIApplication.shared.connectedScenes
|
||||
.compactMap { $0 as? UIWindowScene }
|
||||
.flatMap { $0.windows }
|
||||
.first { $0.isKeyWindow }?
|
||||
.rootViewController
|
||||
}
|
||||
|
||||
private func handleLoginResponse(_ response: Response) {
|
||||
self.isLoading = false
|
||||
|
||||
@@ -11,6 +11,7 @@ import Moya
|
||||
enum UserApi {
|
||||
case login(request: LoginRequest)
|
||||
case loginApple(request: SocialLoginRequest)
|
||||
case loginGoogle(request: SocialLoginRequest, idToken: String)
|
||||
case signUp(request: SignUpRequest)
|
||||
case findPassword(request: ForgotPasswordRequest)
|
||||
case searchUser(nickname: String)
|
||||
@@ -50,6 +51,9 @@ extension UserApi: TargetType {
|
||||
|
||||
case .loginApple:
|
||||
return "/member/login/apple"
|
||||
|
||||
case .loginGoogle:
|
||||
return "/member/login/google"
|
||||
|
||||
case .signUp:
|
||||
return "/member/signup/v2"
|
||||
@@ -124,7 +128,7 @@ extension UserApi: TargetType {
|
||||
|
||||
var method: Moya.Method {
|
||||
switch self {
|
||||
case .login, .loginApple, .signUp, .findPassword, .notification, .logout, .logoutAllDevice, .signOut, .creatorFollow, .creatorUnFollow, .memberBlock, .memberUnBlock,
|
||||
case .login, .loginApple, .loginGoogle, .signUp, .findPassword, .notification, .logout, .logoutAllDevice, .signOut, .creatorFollow, .creatorUnFollow, .memberBlock, .memberUnBlock,
|
||||
.profileImageUpdate:
|
||||
return .post
|
||||
|
||||
@@ -143,6 +147,9 @@ extension UserApi: TargetType {
|
||||
|
||||
case .loginApple(let request):
|
||||
return .requestJSONEncodable(request)
|
||||
|
||||
case .loginGoogle(let request, _):
|
||||
return .requestJSONEncodable(request)
|
||||
|
||||
case .signUp(let request):
|
||||
return .requestJSONEncodable(request)
|
||||
@@ -208,6 +215,9 @@ extension UserApi: TargetType {
|
||||
switch self {
|
||||
case .login, .loginApple, .signUp, .findPassword:
|
||||
return nil
|
||||
|
||||
case .loginGoogle(_, let idToken):
|
||||
return ["Authorization": "Bearer \(idToken)"]
|
||||
|
||||
default:
|
||||
return ["Authorization": "Bearer \(UserDefaults.string(forKey: UserDefaultsKey.token))"]
|
||||
|
||||
@@ -20,6 +20,10 @@ final class UserRepository {
|
||||
func loginApple(request: SocialLoginRequest) -> AnyPublisher<Response, MoyaError> {
|
||||
return api.requestPublisher(.loginApple(request: request))
|
||||
}
|
||||
|
||||
func loginGoogle(request: SocialLoginRequest, idToken: String) -> AnyPublisher<Response, MoyaError> {
|
||||
return api.requestPublisher(.loginGoogle(request: request, idToken: idToken))
|
||||
}
|
||||
|
||||
func signUp(request: SignUpRequest) -> AnyPublisher<Response, MoyaError> {
|
||||
return api.requestPublisher(.signUp(request: request))
|
||||
|
||||
@@ -22,3 +22,6 @@ let NOTIFLY_PASSWORD = "c6c585db0aaa4189be44d0467c7d66b6@A"
|
||||
|
||||
let APPSCHEME = "voiceon"
|
||||
let PAYVERSE_HTML_RESOURCE = "payverse_starter"
|
||||
|
||||
let GID_CLIENT_ID = "983594297130-m6bv7lvc1lsetsvv3rk92etqc98uopqj.apps.googleusercontent.com"
|
||||
let GID_SERVER_CLIENT_ID = "983594297130-5hrmkh6vpskeq6v34350kmilf74574h2.apps.googleusercontent.com"
|
||||
|
||||
Reference in New Issue
Block a user