Line, Google, Facebook (Flutter & iOS) 第三方登入

語言: CN / TW / HK

Line

註冊 line 賬號

  • 建立 Providers & channel
  • 配置 bundle ID

注意設定 URL Type

image.png

image

程式碼

iOS

``` /// 註冊渠道 ID func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. LoginManager.shared.setup(channelID: "xxxxxxx", universalLinkURL: nil) return true }

/// 登入 line func lineAction(_ sender: UIButton) { LoginManager.shared.login(permissions: [.profile], in: self) { result in switch result { case .success(let loginResult): if let profile = loginResult.userProfile { print("User ID: (profile.userID)") print("User Display Name: (profile.displayName)") print("User Icon: (String(describing: profile.pictureURL))") } case .failure(let error): print(error) } } }

/// 登出 line func lineLoginOutAction() { LoginManager.shared.logout { (result) in switch result { case .success(let success): print(success) case .failure(let error): print(error) } } } ```

Flutter

``` /// 註冊渠道 ID void main() { WidgetsFlutterBinding.ensureInitialized(); LineSDK.instance.setup("xxxxxx").then((_) {}); runApp(const MyApp()); }

/// 登入 line void lineLoginHandler() async { try { final result = await LineSDK.instance.login(); final userId = result.userProfile?.userId; final name = result.userProfile?.displayName; final avatar = result.userProfile?.pictureUrl; print('userId: $userId name: $name avatar: $avatar'); } on PlatformException catch (e) { print(e.toString()); } }

/// 登出 line void lineLoginOutHandler() async { try { await LineSDK.instance.logout(); } on PlatformException catch (e) { print(e.message); } } ```

Google

建立 OAuth 客戶端 ID

配置 OAuth 同意畫面

注意

設定 URL Type

  • 注意設定 URL Schemes 是憑證 iOS 網址通訊協定

image.png

設定 OAuth

  • 如果沒有設定配置 OAuth 同意畫面如下問題

  • 需要對自己站臺配置 DNS 設定,傳送門

程式碼

iOS

``` func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in if error != nil || user == nil { // Show the app's signed-out state. } else { // Show the app's signed-in state. } } return true }

/// 登入 google func googleAction(_ sender: UIButton) { // 注意客戶端 id 是憑著裡的使用者端編號 let signInConfig = GIDConfiguration(clientID: "xxxxxxx-xxxxxxxxxxxxxx.apps.googleusercontent.com") GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { user, error in guard error == nil else { return } // If sign in succeeded, display the app's main content View. } }

/// 登出 google func googleLoginOutAction() { GIDSignIn.sharedInstance.signOut(); } ```

Flutter

``` final GoogleSignIn _googleSignIn = GoogleSignIn( clientId: 'xxxxxxx-xxxxxxxxxx.apps.googleusercontent.com', scopes: [ 'email', 'https://www.googleapis.com/auth/contacts.readonly', ], );

/// google 登入 void googleLoginHandler() async { try { final result = await _googleSignIn.signIn(); final userId = result?.id; final name = result?.displayName; final email = result?.email; final avatar = result?.photoUrl; print('userId: $userId name: $name email: $email avatar: $avatar'); } catch (error) { print(error); } }

/// google 登出 void googleLoginOutHandler() async { try { await _googleSignIn.signOut(); } catch (error) { print(error); } } ```

Facebook

建立應用,並授權

注意設定 URL Type 等資訊

  • 應用編號 (FacebookAppID)
  • 客戶埠令 (FacebookClientToken)
  • 顯示名稱(FacebookDisplayName)

程式碼

iOS

``` func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
ApplicationDelegate.shared.application( application, didFinishLaunchingWithOptions: launchOptions ) return true }

// AppDelegate.swift func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { var handled: Bool handled = GIDSignIn.sharedInstance.handle(url) if handled { return true } ApplicationDelegate.shared.application( app, open: url, sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String, annotation: options[UIApplication.OpenURLOptionsKey.annotation] ) return LoginManager.shared.application(app, open: url) }

/// facebook 登入 @IBAction func facebookAction(_ sender: UIButton) { let loginManager = LoginManager() loginManager.logIn(permissions: ["public_profile"], from: self) { result, error in if let error = error { print("Encountered Erorr: (error)") } else if let result = result, result.isCancelled { print("Cancelled") } else { print("Logged In") if let userID = result?.token?.userID { print("userID: ===> (userID)") } if let tokenString = result?.token?.tokenString { print("tokenString: ===> (tokenString)") } } } }

/// 登出 facebook func facebookLoginOutAction() { let loginManager = LoginManager() loginManager.logOut() } ```

Flutter

``` /// facebook 登入 void facebookLoginHandler() async { final fb = FacebookLogin();

final res = await fb.logIn(permissions: [ FacebookPermission.publicProfile, FacebookPermission.email, ]);

switch (res.status) { case FacebookLoginStatus.success: // Logged in

  // Send access token to server for validation and auth
  final FacebookAccessToken? accessToken = res.accessToken;
  print('Access token: ${accessToken?.token}');

  // Get profile data
  final profile = await fb.getUserProfile();
  print('Hello, ${profile?.name}! You ID: ${profile?.userId}');

  // Get user profile image url
  final imageUrl = await fb.getProfileImageUrl(width: 100);
  print('Your profile image: $imageUrl');

  // Get email (since we request email permission)
  final email = await fb.getUserEmail();
  // But user can decline permission
  if (email != null) print('And your email is $email');

  break;
case FacebookLoginStatus.cancel:
  // User cancel log in
  break;
case FacebookLoginStatus.error:
  // Log in failed
  print('Error while log in: ${res.error}');
  break;

} }

/// facebook 登出 void facebookLoginOutHandler() async { try { final fb = FacebookLogin(); await fb.logOut(); } catch (error) { print(error); } } ```

Demo

參考

官方文件

Flutter SDK