跳转到正文
YGJoon 技术博客

Flutter集成社交平台登录

发布于:
·1.6k 字 · 约 4 分钟·作者:
微信、Facebook、Google 三家登录接入:OAuth 授权码换 token、用户信息拉取,第三方登录一次搞定
Flutter集成社交平台登录文章封面
目录

简介

社交平台登录是现代移动应用的重要功能,它可以简化用户的注册和登录流程。本文将详细介绍如何在Flutter应用中集成主流社交平台的登录功能。

微信登录集成

1. 注册开发者账号

  1. 访问微信开放平台
  2. 注册开发者账号并创建应用
  3. 获取AppID和AppSecret

2. 添加依赖

在pubspec.yaml文件中添加依赖:

dependencies:
  fluwx: ^6.0.6

3. 初始化配置

import 'package:fluwx/fluwx.dart';

class WeChatConfig {
  // fluwx 4.x 起所有调用都走 Fluwx 实例,顶层函数 registerWxApi 已移除
  static final fluwx = Fluwx();

  static Future<void> initWxApi() async {
    await fluwx.registerApi(
      appId: "your_app_id",
      universalLink: "your_universal_link", // iOS Universal Links
    );
  }
}

4. 实现登录

class WeChatLogin {
  static Fluwx get _fluwx => WeChatConfig.fluwx;

  static Future<void> login() async {
    // 检查微信是否安装
    final isInstalled = await _fluwx.isWeChatInstalled;
    if (!isInstalled) {
      throw Exception('请先安装微信');
    }

    // 发起登录:返回的只是"是否成功调起微信",code 走下面的回调
    final launched = await _fluwx.authBy(
      which: NormalAuth(
        scope: "snsapi_userinfo",
        state: "wechat_sdk_demo",
      ),
    );
    if (!launched) {
      throw Exception('调起微信失败');
    }
  }

  // 处理登录回调
  static void handleLoginCallback() {
    _fluwx.addSubscriber((res) {
      if (res is WeChatAuthResponse) {
        // 处理登录响应
        print("登录结果:${res.code}");
        // 拿到 code 后发给自己的服务端,用 AppSecret 换 access_token 和用户信息
      }
    });
  }
}

Facebook登录集成

1. 创建Facebook应用

  1. 访问Facebook开发者平台
  2. 创建应用并获取应用ID
  3. 配置OAuth重定向URI

2. 添加依赖

dependencies:
  flutter_facebook_auth: ^7.3.2

3. 平台配置

Android配置

在android/app/res/values/strings.xml中添加:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="facebook_app_id">YOUR_APP_ID</string>
    <string name="fb_login_protocol_scheme">fbYOUR_APP_ID</string>
    <string name="facebook_client_token">YOUR_CLIENT_TOKEN</string>
</resources>

iOS配置

在ios/Runner/Info.plist中添加:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>fbYOUR_APP_ID</string>
    </array>
  </dict>
</array>
<key>FacebookAppID</key>
<string>YOUR_APP_ID</string>
<key>FacebookClientToken</key>
<string>YOUR_CLIENT_TOKEN</string>
<key>FacebookDisplayName</key>
<string>YOUR_APP_NAME</string>

4. 实现登录

class FacebookLogin {
  static final _instance = FacebookAuth.instance;

  static Future<Map<String, dynamic>?> login() async {
    try {
      // 检查登录状态
      final accessToken = await _instance.accessToken;
      if (accessToken != null) {
        return await getUserData();
      }

      // 发起登录
      final result = await _instance.login(
        permissions: ['email', 'public_profile'],
      );

      if (result.status == LoginStatus.success) {
        return await getUserData();
      }

      return null;
    } catch (e) {
      print('Facebook登录错误: $e');
      return null;
    }
  }

  static Future<Map<String, dynamic>?> getUserData() async {
    try {
      return await _instance.getUserData();
    } catch (e) {
      print('获取用户数据错误: $e');
      return null;
    }
  }

  static Future<void> logout() async {
    await _instance.logOut();
  }
}

Google登录集成

1. 配置Firebase项目

  1. 在Firebase控制台启用Google登录
  2. 下载配置文件并添加到项目

2. 添加依赖

dependencies:
  google_sign_in: ^7.2.0
  firebase_auth: ^7.0.1

3. 实现登录

import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

class GoogleLogin {
  static final _auth = FirebaseAuth.instance;

  static Future<UserCredential?> signIn() async {
    try {
      // 7.x 起 GoogleSignIn 是单例,且调用前必须先 initialize 一次
      await GoogleSignIn.instance.initialize();

      // 发起登录流程
      final googleUser = await GoogleSignIn.instance.authenticate();

      // 7.x 的 authentication 是同步 getter,且只有 idToken;
      // accessToken 改走 googleUser.authorizationClient 单独申请
      final googleAuth = googleUser.authentication;

      // 创建Firebase凭证
      final credential = GoogleAuthProvider.credential(
        idToken: googleAuth.idToken,
      );

      // 使用Firebase进行身份验证
      return await _auth.signInWithCredential(credential);
    } catch (e) {
      print('Google登录错误: $e');
      return null;
    }
  }

  static Future<void> signOut() async {
    await Future.wait([
      GoogleSignIn.instance.signOut(),
      _auth.signOut(),
    ]);
  }
}

统一登录管理

1. 登录类型枚举

enum LoginType {
  wechat,
  facebook,
  google,
}

2. 统一登录服务

class SocialLoginService {
  static Future<Map<String, dynamic>?> login(LoginType type) async {
    switch (type) {
      case LoginType.wechat:
        return await _handleWeChatLogin();
      case LoginType.facebook:
        return await _handleFacebookLogin();
      case LoginType.google:
        return await _handleGoogleLogin();
    }
  }

  static Future<Map<String, dynamic>?> _handleWeChatLogin() async {
    try {
      await WeChatLogin.login();
      // 处理微信登录结果
      return null;
    } catch (e) {
      print('微信登录错误: $e');
      return null;
    }
  }

  static Future<Map<String, dynamic>?> _handleFacebookLogin() async {
    return await FacebookLogin.login();
  }

  static Future<Map<String, dynamic>?> _handleGoogleLogin() async {
    final credential = await GoogleLogin.signIn();
    if (credential?.user != null) {
      return {
        'id': credential!.user!.uid,
        'email': credential.user!.email,
        'name': credential.user!.displayName,
        'photo': credential.user!.photoURL,
      };
    }
    return null;
  }
}

3. 使用示例

class LoginPage extends StatelessWidget {
  Future<void> _handleLogin(LoginType type) async {
    try {
      final userData = await SocialLoginService.login(type);
      if (userData != null) {
        print('登录成功: $userData');
        // 处理登录成功后的逻辑
      } else {
        print('登录失败');
      }
    } catch (e) {
      print('登录错误: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('社交登录')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => _handleLogin(LoginType.wechat),
              child: Text('微信登录'),
            ),
            ElevatedButton(
              onPressed: () => _handleLogin(LoginType.facebook),
              child: Text('Facebook登录'),
            ),
            ElevatedButton(
              onPressed: () => _handleLogin(LoginType.google),
              child: Text('Google登录'),
            ),
          ],
        ),
      ),
    );
  }
}

注意事项

  1. iOS 强制要求:App 里有任何第三方登录,必须同时提供 Sign in with Apple,否则上架被拒——这是苹果审核铁律,不是”建议”
  2. code 换 token 走服务端:App 拿 code 调服务端,服务端用 AppSecret 换 token;AppSecret 永不进客户端(和支付同一条铁律)
  3. token 存 flutter_secure_storage:别放 SharedPreferences 明文——作者 freight 项目真实坑:登录态明文存 SP,退出登录时 controller 没清干净,切账号直接串数据
  4. 退出登录要清干净:清 token、清用户态 controller、清路由栈(Get.offAllNamed 回登录页)——三件缺一件,切账号就会串数据

实战案例

第三方登录(微信/QQ/Apple)我还没在项目里做过——我的 App 全是”手机号+验证码”或干脆无登录(工具类)。但我踩过相关的坑:在 某物流冷链项目 里,登录态存在 SharedPreferences(明文),退出登录时 GetX 的常驻 controller 没清,导致切账号后还是旧数据——这就是”登录”和”状态管理”搅在一起的典型问题。所以我的体会:第三方登录的难点不在”接 SDK”,在”登录态的生命周期管理”(token 存哪、过期怎么刷、退出怎么清干净)。SDK 按文档半天接完,状态理不清能折腾一周。iOS 上注意:只要有第三方登录,苹果强制要求加”Sign in with Apple”,否则上架被拒。参考:Flutter 官方文档相关章节。

总结

微信、Facebook、Google、Apple 登录,SDK 都是半天能接完的体力活。真正的坑在登录态的生命周期:token 存哪、过期怎么刷、退出登录时常驻的 controller 清没清干净——SDK 接完只是开始,状态理不清能折腾一周。iOS 上注意:只要有第三方登录,苹果强制要求加 Sign in with Apple,否则上架被拒。


分享这篇文章:


相关文章

上一篇
Flutter 使用 Melos 管理多包项目
下一篇
Flutter集成Firebase Analytics