Skip to content

Commit

Permalink
Merge pull request #51 from dayoung20/dayoung@api
Browse files Browse the repository at this point in the history
feat: 카카오 로그인 구현
  • Loading branch information
siiion authored Jan 23, 2025
2 parents e245af4 + f70f3d3 commit 2acc2fc
Show file tree
Hide file tree
Showing 11 changed files with 329 additions and 6 deletions.
12 changes: 12 additions & 0 deletions economic_fe/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
import java.util.Properties

// def getEnvValue(String key, String defaultValue) {
// def properties = new Properties()
// def envFile = rootProject.file('.env')
// if (envFile.exists()) {
// properties.load(new FileInputStream(envFile))
// }
// return properties.getProperty(key, defaultValue)
// }

plugins {
id "com.android.application"
id "kotlin-android"
Expand Down Expand Up @@ -28,6 +39,7 @@ android {
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
manifestPlaceholders += [KAKAO_NATIVE_APP_KEY: project.env.get("NATIVE_APP_KEY")]
}

buildTypes {
Expand Down
2 changes: 2 additions & 0 deletions economic_fe/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<!-- Redirect URI, "kakao${YOUR_NATIVE_APP_KEY}://oauth" 형식 -->
<data android:scheme="kakao${KAKAO_NATIVE_APP_KEY}" android:host="oauth"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
Expand Down
4 changes: 4 additions & 0 deletions economic_fe/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter/material.dart';
import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart';

Future<void> main() async {
//await dotenv.load(fileName: ".env");

WidgetsFlutterBinding.ensureInitialized();
await dotenv.load(fileName: '.env');
String nativeAppKey = dotenv.env['NATIVE_APP_KEY']!;
KakaoSdk.init(nativeAppKey: nativeAppKey);
runApp(const RippleApp());
}

Expand Down
137 changes: 134 additions & 3 deletions economic_fe/lib/view_model/login/login_exist_controller.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,139 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:get/get.dart';
import 'package:kakao_flutter_sdk_user/kakao_flutter_sdk_user.dart';
import 'package:http/http.dart' as http;
import 'package:url_launcher/url_launcher.dart';
import 'package:webview_flutter/webview_flutter.dart';

class LoginExistController extends GetxController {
// 홈 화면으로 이동 (로그인 로직 추가 필요)
void login() {
Get.toNamed('/home');
// 카카오 앱 클라이언트 ID
// String nativeAppKey = dotenv.env['NATIVE_APP_KEY']!;
final String clientId = dotenv.env['CLIENT_ID']!;
final String redirectUri = dotenv.env['REDIRECT_URI']!;

// 1. 카카오 로그인 페이지로 리디렉션
Future<void> openKakaoLogin() async {
final url =
'https://kauth.kakao.com/oauth/authorize?client_id=$clientId&redirect_uri=$redirectUri&response_type=code';

if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}

// 2. 인증 코드로 액세스 토큰 요청
Future<void> fetchAccessToken(String code) async {
const tokenUrl = 'https://kauth.kakao.com/oauth/token';

final response = await http.post(
Uri.parse(tokenUrl),
body: {
'grant_type': 'authorization_code',
'client_id': clientId,
'redirect_uri': redirectUri,
'code': code,
},
);

if (response.statusCode == 200) {
print('Access Token: ${response.body}');
// 추가: 토큰 저장 및 활용 로직
} else {
print('Failed to fetch access token: ${response.body}');
}
}

// 3. 로그인 플로우 실행
// void login() async {
// // 카카오 로그인 요청
// await openKakaoLogin();

// print("리디렉션 전");
// // 리디렉션 처리: Flutter WebView 또는 외부 브라우저에서 인증 코드 추출 필요
// String? code = await _getAuthorizationCodeFromRedirectUri();
// print("code : $code");
// if (code != null) {
// // 액세스 토큰 요청
// await fetchAccessToken(code);
// } else {
// print("Authorization Code not found.");
// }
// }
void login() async {
if (await isKakaoTalkInstalled()) {
try {
await UserApi.instance.loginWithKakaoTalk();
print('카카오톡으로 로그인 성공');
User user = await UserApi.instance.me();
print(
'사용자 정보 요청 성공${user.id} ${user.kakaoAccount?.profile?.nickname} ${user.kakaoAccount?.email}');
OAuthToken token = await UserApi.instance.loginWithKakaoTalk();
print(token);
} catch (error) {
print('카카오톡으로 로그인 실패 $error');

// 사용자가 카카오톡 설치 후 디바이스 권한 요청 화면에서 로그인을 취소한 경우,
// 의도적인 로그인 취소로 보고 카카오계정으로 로그인 시도 없이 로그인 취소로 처리 (예: 뒤로 가기)
if (error is PlatformException && error.code == 'CANCELED') {
return;
}
// 카카오톡에 연결된 카카오계정이 없는 경우, 카카오계정으로 로그인
try {
await UserApi.instance.loginWithKakaoAccount();
print('카카오계정으로 로그인 성공');
} catch (error) {
print('카카오계정으로 로그인 실패 $error');
}
}
} else {
try {
await UserApi.instance.loginWithKakaoAccount();
print('카카오계정으로 로그인 성공');
} catch (error) {
print('카카오계정으로 로그인 실패 $error');
}
}
}

// 4. 리디렉션된 URL에서 인증 코드 추출
Future<String?> _getAuthorizationCodeFromRedirectUri() async {
String? authorizationCode;

// WebViewController 초기화
final webViewController = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted) // 자바스크립트 허용
..setNavigationDelegate(
NavigationDelegate(
onNavigationRequest: (NavigationRequest request) {
if (request.url.contains('code=')) {
final Uri uri = Uri.parse(request.url);
authorizationCode = uri.queryParameters['code'];
Get.back(); // WebView 닫기
return NavigationDecision.prevent; // 탐색 중단
}
return NavigationDecision.navigate; // 계속 탐색
},
),
)
..loadRequest(
Uri.parse('http://localhost:3030/kakao/callback')); // 리디렉션 URL 로드

// WebView 표시
await Get.dialog(
Scaffold(
appBar: AppBar(
title: const Text('카카오 로그인'),
),
body: WebViewWidget(controller: webViewController),
),
);

return authorizationCode; // 추출된 인증 코드 반환
}
}

// class WebView {}
4 changes: 4 additions & 0 deletions economic_fe/linux/flutter/generated_plugin_registrant.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
#include "generated_plugin_registrant.h"

#include <file_selector_linux/file_selector_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>

void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
}
1 change: 1 addition & 0 deletions economic_fe/linux/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

list(APPEND FLUTTER_PLUGIN_LIST
file_selector_linux
url_launcher_linux
)

list(APPEND FLUTTER_FFI_PLUGIN_LIST
Expand Down
2 changes: 2 additions & 0 deletions economic_fe/macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import Foundation

import file_selector_macos
import shared_preferences_foundation
import url_launcher_macos
import webview_flutter_wkwebview

func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
FLTWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "FLTWebViewFlutterPlugin"))
}
Loading

0 comments on commit 2acc2fc

Please sign in to comment.