카카오 로그인 기능 추가
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"originHash" : "1f28da3687662a2a9efe60ffc2ca2499be411b5b0a1e07f72559059c40728121",
|
"originHash" : "23fbb8fc47a95510f46840139efb1770d536256f32ac2ba9f74cf03ee90a3979",
|
||||||
"pins" : [
|
"pins" : [
|
||||||
{
|
{
|
||||||
"identity" : "abseil-cpp-binary",
|
"identity" : "abseil-cpp-binary",
|
||||||
@@ -127,6 +127,15 @@
|
|||||||
"version" : "100.0.0"
|
"version" : "100.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"identity" : "kakao-ios-sdk",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/kakao/kakao-ios-sdk",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "5978979157a5a0521c9c56fd0156aec794caa21c",
|
||||||
|
"version" : "2.27.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"identity" : "kingfisher",
|
"identity" : "kingfisher",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>GIDClientID</key>
|
|
||||||
<string>758414412471-3cf403jb4s405eu17qrfrcbs9ofhq369.apps.googleusercontent.com</string>
|
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -21,6 +19,14 @@
|
|||||||
<string>voiceon-test</string>
|
<string>voiceon-test</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Editor</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>kakao20cf19413d63bfdfd30e8e6dff933d33</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>FacebookAppID</key>
|
<key>FacebookAppID</key>
|
||||||
<string>608674328645232</string>
|
<string>608674328645232</string>
|
||||||
@@ -34,6 +40,8 @@
|
|||||||
<false/>
|
<false/>
|
||||||
<key>GADApplicationIdentifier</key>
|
<key>GADApplicationIdentifier</key>
|
||||||
<string>ca-app-pub-1299501215847962~3447556960</string>
|
<string>ca-app-pub-1299501215847962~3447556960</string>
|
||||||
|
<key>GIDClientID</key>
|
||||||
|
<string>758414412471-3cf403jb4s405eu17qrfrcbs9ofhq369.apps.googleusercontent.com</string>
|
||||||
<key>NSAdvertisingAttributionReportEndpoint</key>
|
<key>NSAdvertisingAttributionReportEndpoint</key>
|
||||||
<string>https://appsflyer-skadnetwork.com/</string>
|
<string>https://appsflyer-skadnetwork.com/</string>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
@@ -41,14 +49,6 @@
|
|||||||
<key>NSAllowsArbitraryLoads</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSMicrophoneUsageDescription</key>
|
|
||||||
<string>마이크 접근이 필요합니다.</string>
|
|
||||||
<key>NSCameraUsageDescription</key>
|
|
||||||
<string>사진을 촬영하려면 카메라 접근이 필요합니다.</string>
|
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
|
||||||
<string>사진을 선택하려면 사진 라이브러리 접근이 필요합니다.</string>
|
|
||||||
<key>NSUserTrackingUsageDescription</key>
|
|
||||||
<string>맞춤형 광고 제공을 위해 추적을 허용해 주세요.</string>
|
|
||||||
<key>SKAdNetworkItems</key>
|
<key>SKAdNetworkItems</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -265,5 +265,14 @@
|
|||||||
<string>fetch</string>
|
<string>fetch</string>
|
||||||
<string>remote-notification</string>
|
<string>remote-notification</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>LSApplicationQueriesSchemes</key>
|
||||||
|
<array>
|
||||||
|
<!-- 카카오톡으로 로그인 -->
|
||||||
|
<string>kakaokompassauth</string>
|
||||||
|
<!-- 카카오톡 공유 -->
|
||||||
|
<string>kakaolink</string>
|
||||||
|
<!-- 카카오톡 채널 -->
|
||||||
|
<string>kakaoplus</string>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>GIDClientID</key>
|
|
||||||
<string>983594297130-m6bv7lvc1lsetsvv3rk92etqc98uopqj.apps.googleusercontent.com</string>
|
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -21,6 +19,14 @@
|
|||||||
<string>voiceon</string>
|
<string>voiceon</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Editor</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>kakao231cf78acfa8252fca38b9eedf87c5cb</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>FacebookAppID</key>
|
<key>FacebookAppID</key>
|
||||||
<string>612448298237287</string>
|
<string>612448298237287</string>
|
||||||
@@ -34,6 +40,8 @@
|
|||||||
<false/>
|
<false/>
|
||||||
<key>GADApplicationIdentifier</key>
|
<key>GADApplicationIdentifier</key>
|
||||||
<string>ca-app-pub-1299501215847962~8852459715</string>
|
<string>ca-app-pub-1299501215847962~8852459715</string>
|
||||||
|
<key>GIDClientID</key>
|
||||||
|
<string>983594297130-m6bv7lvc1lsetsvv3rk92etqc98uopqj.apps.googleusercontent.com</string>
|
||||||
<key>NSAdvertisingAttributionReportEndpoint</key>
|
<key>NSAdvertisingAttributionReportEndpoint</key>
|
||||||
<string>https://appsflyer-skadnetwork.com/</string>
|
<string>https://appsflyer-skadnetwork.com/</string>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
@@ -41,14 +49,6 @@
|
|||||||
<key>NSAllowsArbitraryLoads</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSMicrophoneUsageDescription</key>
|
|
||||||
<string>마이크 접근이 필요합니다.</string>
|
|
||||||
<key>NSCameraUsageDescription</key>
|
|
||||||
<string>사진을 촬영하려면 카메라 접근이 필요합니다.</string>
|
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
|
||||||
<string>사진을 선택하려면 사진 라이브러리 접근이 필요합니다.</string>
|
|
||||||
<key>NSUserTrackingUsageDescription</key>
|
|
||||||
<string>맞춤형 광고 제공을 위해 추적을 허용해 주세요.</string>
|
|
||||||
<key>SKAdNetworkItems</key>
|
<key>SKAdNetworkItems</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -265,5 +265,14 @@
|
|||||||
<string>fetch</string>
|
<string>fetch</string>
|
||||||
<string>remote-notification</string>
|
<string>remote-notification</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>LSApplicationQueriesSchemes</key>
|
||||||
|
<array>
|
||||||
|
<!-- 카카오톡으로 로그인 -->
|
||||||
|
<string>kakaokompassauth</string>
|
||||||
|
<!-- 카카오톡 공유 -->
|
||||||
|
<string>kakaolink</string>
|
||||||
|
<!-- 카카오톡 채널 -->
|
||||||
|
<string>kakaoplus</string>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import Kingfisher
|
|||||||
import FBSDKCoreKit
|
import FBSDKCoreKit
|
||||||
import AppsFlyerLib
|
import AppsFlyerLib
|
||||||
import GoogleSignIn
|
import GoogleSignIn
|
||||||
|
import KakaoSDKCommon
|
||||||
|
import KakaoSDKAuth
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct SodaLiveApp: App {
|
struct SodaLiveApp: App {
|
||||||
@@ -26,6 +28,7 @@ struct SodaLiveApp: App {
|
|||||||
configureImageCache()
|
configureImageCache()
|
||||||
// 앱 시작 직후, 초기 네트워크 요청도 올바른 언어 헤더를 갖도록 동기 초기화
|
// 앱 시작 직후, 초기 네트워크 요청도 올바른 언어 헤더를 갖도록 동기 초기화
|
||||||
LanguageHeaderProvider.initialize()
|
LanguageHeaderProvider.initialize()
|
||||||
|
KakaoSDK.initSDK(appKey: KAKAO_APP_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func configureImageCache() {
|
private func configureImageCache() {
|
||||||
@@ -69,6 +72,11 @@ struct SodaLiveApp: App {
|
|||||||
.onOpenURL { url in
|
.onOpenURL { url in
|
||||||
DEBUG_LOG("I have received a URL through a custom scheme! \(url.absoluteString)")
|
DEBUG_LOG("I have received a URL through a custom scheme! \(url.absoluteString)")
|
||||||
|
|
||||||
|
if KakaoSDKAuth.AuthApi.isKakaoTalkLoginUrl(url) {
|
||||||
|
_ = AuthController.handleOpenUrl(url: url)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if let comps = URLComponents(url: url, resolvingAgainstBaseURL: false),
|
if let comps = URLComponents(url: url, resolvingAgainstBaseURL: false),
|
||||||
url.scheme?.lowercased() == APPSCHEME.lowercased(),
|
url.scheme?.lowercased() == APPSCHEME.lowercased(),
|
||||||
comps.host?.lowercased() == "payverse",
|
comps.host?.lowercased() == "payverse",
|
||||||
|
|||||||
@@ -25,3 +25,5 @@ let PAYVERSE_HTML_RESOURCE = "payverse_starter_debug"
|
|||||||
|
|
||||||
let GID_CLIENT_ID = "758414412471-3cf403jb4s405eu17qrfrcbs9ofhq369.apps.googleusercontent.com"
|
let GID_CLIENT_ID = "758414412471-3cf403jb4s405eu17qrfrcbs9ofhq369.apps.googleusercontent.com"
|
||||||
let GID_SERVER_CLIENT_ID = "758414412471-mosodbj2chno7l1j0iihldh6edmk0gk9.apps.googleusercontent.com"
|
let GID_SERVER_CLIENT_ID = "758414412471-mosodbj2chno7l1j0iihldh6edmk0gk9.apps.googleusercontent.com"
|
||||||
|
|
||||||
|
let KAKAO_APP_KEY = "20cf19413d63bfdfd30e8e6dff933d33"
|
||||||
|
|||||||
@@ -1135,6 +1135,24 @@ enum I18n {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Kakao {
|
||||||
|
static var signInFailed: String {
|
||||||
|
pick(
|
||||||
|
ko: "카카오 로그인에 실패했습니다.\n다시 시도해 주세요.",
|
||||||
|
en: "Kakao sign-in failed.\nPlease try again.",
|
||||||
|
ja: "Kakaoログインに失敗しました。\nもう一度お試しください。"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
static var tokenMissing: String {
|
||||||
|
pick(
|
||||||
|
ko: "카카오 인증 토큰을 가져오지 못했습니다.",
|
||||||
|
en: "Failed to retrieve Kakao token.",
|
||||||
|
ja: "Kakao認証トークンを取得できませんでした。"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 문자 메시지(Text Message) 관련 문자열
|
// 문자 메시지(Text Message) 관련 문자열
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ struct LoginView: View {
|
|||||||
Image("ic_login_kakao")
|
Image("ic_login_kakao")
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
hideKeyboard()
|
hideKeyboard()
|
||||||
|
viewModel.loginWithKakao()
|
||||||
}
|
}
|
||||||
|
|
||||||
Image("ic_login_google")
|
Image("ic_login_google")
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import CryptoKit
|
|||||||
import Security
|
import Security
|
||||||
import UIKit
|
import UIKit
|
||||||
import GoogleSignIn
|
import GoogleSignIn
|
||||||
|
import KakaoSDKUser
|
||||||
|
import KakaoSDKAuth
|
||||||
|
|
||||||
final class LoginViewModel: NSObject, ObservableObject {
|
final class LoginViewModel: NSObject, ObservableObject {
|
||||||
private let appViewModel = AppViewModel()
|
private let appViewModel = AppViewModel()
|
||||||
@@ -99,6 +101,33 @@ final class LoginViewModel: NSObject, ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loginWithKakao() {
|
||||||
|
let loginHandler: (OAuthToken?, Error?) -> Void = { token, error in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
if let error = error {
|
||||||
|
ERROR_LOG(error.localizedDescription)
|
||||||
|
self.errorMessage = I18n.Login.Kakao.signInFailed
|
||||||
|
self.isShowPopup = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let accessToken = token?.accessToken, !accessToken.isEmpty else {
|
||||||
|
self.errorMessage = I18n.Login.Kakao.tokenMissing
|
||||||
|
self.isShowPopup = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.loginWithKakao(accessToken: accessToken)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if KakaoSDKUser.UserApi.isKakaoTalkLoginAvailable() {
|
||||||
|
KakaoSDKUser.UserApi.shared.loginWithKakaoTalk(completion: loginHandler)
|
||||||
|
} else {
|
||||||
|
KakaoSDKUser.UserApi.shared.loginWithKakaoAccount(completion: loginHandler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func loginWithApple(identityToken: String, nonce: String) {
|
private func loginWithApple(identityToken: String, nonce: String) {
|
||||||
let pushToken = UserDefaults.string(forKey: .pushToken)
|
let pushToken = UserDefaults.string(forKey: .pushToken)
|
||||||
let marketingPid = UserDefaults.string(forKey: .marketingPid)
|
let marketingPid = UserDefaults.string(forKey: .marketingPid)
|
||||||
@@ -153,6 +182,33 @@ final class LoginViewModel: NSObject, ObservableObject {
|
|||||||
.store(in: &subscription)
|
.store(in: &subscription)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func loginWithKakao(accessToken: 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.loginKakao(request: request, accessToken: accessToken)
|
||||||
|
.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? {
|
private func presentingViewController() -> UIViewController? {
|
||||||
return UIApplication.shared.connectedScenes
|
return UIApplication.shared.connectedScenes
|
||||||
.compactMap { $0 as? UIWindowScene }
|
.compactMap { $0 as? UIWindowScene }
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ enum UserApi {
|
|||||||
case login(request: LoginRequest)
|
case login(request: LoginRequest)
|
||||||
case loginApple(request: SocialLoginRequest)
|
case loginApple(request: SocialLoginRequest)
|
||||||
case loginGoogle(request: SocialLoginRequest, idToken: String)
|
case loginGoogle(request: SocialLoginRequest, idToken: String)
|
||||||
|
case loginKakao(request: SocialLoginRequest, accessToken: String)
|
||||||
case signUp(request: SignUpRequest)
|
case signUp(request: SignUpRequest)
|
||||||
case findPassword(request: ForgotPasswordRequest)
|
case findPassword(request: ForgotPasswordRequest)
|
||||||
case searchUser(nickname: String)
|
case searchUser(nickname: String)
|
||||||
@@ -55,6 +56,9 @@ extension UserApi: TargetType {
|
|||||||
case .loginGoogle:
|
case .loginGoogle:
|
||||||
return "/member/login/google"
|
return "/member/login/google"
|
||||||
|
|
||||||
|
case .loginKakao:
|
||||||
|
return "/member/login/kakao"
|
||||||
|
|
||||||
case .signUp:
|
case .signUp:
|
||||||
return "/member/signup/v2"
|
return "/member/signup/v2"
|
||||||
|
|
||||||
@@ -128,7 +132,7 @@ extension UserApi: TargetType {
|
|||||||
|
|
||||||
var method: Moya.Method {
|
var method: Moya.Method {
|
||||||
switch self {
|
switch self {
|
||||||
case .login, .loginApple, .loginGoogle, .signUp, .findPassword, .notification, .logout, .logoutAllDevice, .signOut, .creatorFollow, .creatorUnFollow, .memberBlock, .memberUnBlock,
|
case .login, .loginApple, .loginGoogle, .loginKakao, .signUp, .findPassword, .notification, .logout, .logoutAllDevice, .signOut, .creatorFollow, .creatorUnFollow, .memberBlock, .memberUnBlock,
|
||||||
.profileImageUpdate:
|
.profileImageUpdate:
|
||||||
return .post
|
return .post
|
||||||
|
|
||||||
@@ -151,6 +155,9 @@ extension UserApi: TargetType {
|
|||||||
case .loginGoogle(let request, _):
|
case .loginGoogle(let request, _):
|
||||||
return .requestJSONEncodable(request)
|
return .requestJSONEncodable(request)
|
||||||
|
|
||||||
|
case .loginKakao(let request, _):
|
||||||
|
return .requestJSONEncodable(request)
|
||||||
|
|
||||||
case .signUp(let request):
|
case .signUp(let request):
|
||||||
return .requestJSONEncodable(request)
|
return .requestJSONEncodable(request)
|
||||||
|
|
||||||
@@ -219,6 +226,9 @@ extension UserApi: TargetType {
|
|||||||
case .loginGoogle(_, let idToken):
|
case .loginGoogle(_, let idToken):
|
||||||
return ["Authorization": "Bearer \(idToken)"]
|
return ["Authorization": "Bearer \(idToken)"]
|
||||||
|
|
||||||
|
case .loginKakao(_, let accessToken):
|
||||||
|
return ["Authorization": "Bearer \(accessToken)"]
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return ["Authorization": "Bearer \(UserDefaults.string(forKey: UserDefaultsKey.token))"]
|
return ["Authorization": "Bearer \(UserDefaults.string(forKey: UserDefaultsKey.token))"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ final class UserRepository {
|
|||||||
return api.requestPublisher(.loginGoogle(request: request, idToken: idToken))
|
return api.requestPublisher(.loginGoogle(request: request, idToken: idToken))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loginKakao(request: SocialLoginRequest, accessToken: String) -> AnyPublisher<Response, MoyaError> {
|
||||||
|
return api.requestPublisher(.loginKakao(request: request, accessToken: accessToken))
|
||||||
|
}
|
||||||
|
|
||||||
func signUp(request: SignUpRequest) -> AnyPublisher<Response, MoyaError> {
|
func signUp(request: SignUpRequest) -> AnyPublisher<Response, MoyaError> {
|
||||||
return api.requestPublisher(.signUp(request: request))
|
return api.requestPublisher(.signUp(request: request))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,3 +25,5 @@ let PAYVERSE_HTML_RESOURCE = "payverse_starter"
|
|||||||
|
|
||||||
let GID_CLIENT_ID = "983594297130-m6bv7lvc1lsetsvv3rk92etqc98uopqj.apps.googleusercontent.com"
|
let GID_CLIENT_ID = "983594297130-m6bv7lvc1lsetsvv3rk92etqc98uopqj.apps.googleusercontent.com"
|
||||||
let GID_SERVER_CLIENT_ID = "983594297130-5hrmkh6vpskeq6v34350kmilf74574h2.apps.googleusercontent.com"
|
let GID_SERVER_CLIENT_ID = "983594297130-5hrmkh6vpskeq6v34350kmilf74574h2.apps.googleusercontent.com"
|
||||||
|
|
||||||
|
let KAKAO_APP_KEY = "231cf78acfa8252fca38b9eedf87c5cb"
|
||||||
|
|||||||
Reference in New Issue
Block a user