flutter 集成极光一键登录

1.开通极光认证

极光官网创建应用后,在【认证设置】的【集成设置】中填写信息,Android的应用签名需要下载签名工具获取,ios填写Bundle ID,填写完毕后提交审核

在【认证设置】的【一键登录】中填写RSA 加密公钥

 加密公钥在在线生成公钥私钥对,RSA公私钥生成-ME2在线工具中获取,开通需要集成的平台

注意:RSA加密公钥位数1024位,密钥格式PKCS#8

2.引入插件及相关配置

dependencies:
  jverify: 2.2.8

在android/app/build.gradle文件中进行以下配置:

android: {
    ...
    manifestPlaceholders = [
        JPUSH_PKGNAME : applicationId, //填写信息时的应用包名
        JPUSH_APPKEY : "appkey", // 极光后台该应用对应的Appkey
		JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可.
    ]
    ...
}

3. 极光认证初始化

在登录界面initState进行初始化:

import 'package:jverify/jverify.dart';

final Jverify jverify = new Jverify();

/// 统一 key
final String f_result_key = "result";

/// 错误码
final String f_code_key = "code";

/// 回调的提示信息,统一返回 flutter 为 message
final String f_msg_key = "message";

/// 运营商信息
final String f_opr_key = "operator";

@override
void initState() {
    await initPlatformState();
    await isInitSuccess();
    await preLogin();
}


void initPlatformState() {
    // 初始化 SDK 之前添加监听
    jverify.addSDKSetupCallBackListener((JVSDKSetupEvent event) {
        print("receive sdk setup call back event :${event.toMap()}");
    });

    // 是否打开调试模式
    jverify.setDebugMode(true);

    // 初始化sdk
    jverify.setup(
      appKey: "填写应用的AppKey",
      channel: "devloper-default"
    );

    // 授权页面点击事件监听
    jverify.addAuthPageEventListener((JVAuthPageEvent event) {
        print("receive auth page event :${event.toMap()}");
    });
}

/// sdk 初始化是否完成
void isInitSuccess() {
    jverify.isInitSuccess().then((map) {
        bool result = map[f_result_key];
        if (result) {
            print("极光一键登录sdk 初始化成功");
        } else {
            print("极光一键登录sdk 初始化失败");
        }
    });
}

// 登录预取号
void preLogin() {
    // 判断当前的手机网络环境是否可以使用认证。
    jverify.checkVerifyEnable().then((map) {
        bool result = map[f_result_key];
        if (result) {
            jverify.preLogin().then((map) {
                print("预取号接口回调:${map.toString()}");
                int code = map[f_code_key];
                String message = map[f_msg_key];
                print("[$code] message = $message");
            });
        } else {
            print("[2016],msg = 当前网络环境不支持认证");
        }
    });
}

 4.点击一键登录按钮拉起授权页

在登录页我们需要一个一键登录的按钮,点击后拉起极光的授权页

GestureDetector(
    onTap: (){
        loginAuth();
    },
    child: Text(
        '一键登录'
    ),
),
/// SDK 请求授权一键登录
void loginAuth() {
    jverify.checkVerifyEnable().then((map) {
        bool result = map[f_result_key];
        if (result) {
            final screenSize = MediaQuery.of(_context).size;
            final screenWidth = screenSize.width;
            final screenHeight = screenSize.height;
            bool isiOS = Platform.isIOS;

            /// 自定义授权的 UI 界面,以下设置的图片必须添加到资源文件里,
            /// android项目将图片存放至drawable文件夹下,可使用图片选择器的文件名,例如:btn_login.xml,入参为"btn_login"。
            /// ios项目存放在 Assets.xcassets。

            JVUIConfig uiConfig = JVUIConfig();
            uiConfig.authBackgroundImage = 'background_image';

            // 导航栏
            uiConfig.navHidden = isiOS ? true : true;
            uiConfig.navReturnBtnHidden = false;
            uiConfig.navColor = isiOS ? Color(0xFF0C0D16).value : Colors.transparent.value;
            uiConfig.navText = " ";
            uiConfig.navTextColor = Colors.blue.value;
            uiConfig.navReturnImgPath = "return_bg"; //图片必须存在
            
            // logo
            uiConfig.logoWidth = 100;
            uiConfig.logoHeight = 100;
            uiConfig.logoOffsetY = 10;
            uiConfig.logoVerticalLayoutItem = JVIOSLayoutItem.ItemSuper;
            uiConfig.logoHidden = false;
            uiConfig.logoImgPath = "logo";
            uiConfig.logoHidden = true;

            // 号码
            uiConfig.numberFieldWidth = 200;
            uiConfig.numberFieldHeight = 40;
            uiConfig.numFieldOffsetY = isiOS ? 144 : 144;
            uiConfig.numberVerticalLayoutItem = isiOS ? JVIOSLayoutItem.ItemLogo : JVIOSLayoutItem.ItemNone;
            uiConfig.numberColor = Colors.white.value;
            uiConfig.numberSize = 26;

            // slogan
            uiConfig.sloganOffsetY = isiOS ? 20 : 180;
            uiConfig.sloganVerticalLayoutItem = JVIOSLayoutItem.ItemNumber;
            uiConfig.sloganTextColor = Color(0xFF6E6E6E).value;
            uiConfig.sloganTextSize = 14;
            uiConfig.sloganHidden = true;

            // 登录按钮
            uiConfig.logBtnWidth = MediaQuery.of(_context).size.width.toInt() - 100;
            uiConfig.logBtnHeight = 50;
            uiConfig.logBtnOffsetY = isiOS ? 350 : 500;
            uiConfig.logBtnVerticalLayoutItem = isiOS ? JVIOSLayoutItem.ItemSlogan : JVIOSLayoutItem.ItemPrivacy;
            uiConfig.logBtnText = "一键登录";
            uiConfig.logBtnTextColor = Colors.white.value;
            uiConfig.logBtnTextSize = 18;
            uiConfig.logBtnTextBold = true;
            uiConfig.logBtnBackgroundPath = "login_btn"; //图片必须存在
            uiConfig.loginBtnNormalImage = "loginbtn"; //图片必须存在 only ios
            uiConfig.loginBtnPressedImage = "loginbtn"; //图片必须存在 only ios
            uiConfig.loginBtnUnableImage = "loginbtn"; //图片必须存在 only ios

            // 隐私协议栏
            uiConfig.privacyHintToast = true; //设置隐私条款不选中时点击登录按钮默认显示toast。
            uiConfig.privacyState = false; //设置隐私条款默认选中状态,默认不选中
            uiConfig.privacyCheckboxSize = 20;
            uiConfig.privacyCheckboxInCenter = true; //设置隐私条款checkbox是否相对协议文字纵向居中
            uiConfig.privacyCheckboxHidden = false; //设置隐私条款checkbox是否隐藏

            uiConfig.privacyOffsetY = 15; // 隐私条款相对于授权页面底部下边缘 y 偏移
            uiConfig.privacyVerticalLayoutItem = JVIOSLayoutItem.ItemSuper;
            uiConfig.clauseColor = Color(0xFFFEFEFE).value;
            uiConfig.privacyText = ["登录即代表同意"];
            uiConfig.privacyTextSize = 13;
            uiConfig.textVerAlignment = 1; //设置条款文字是否垂直居中对齐(默认居中对齐) 0是top 1是m 2是b
            uiConfig.privacyWithBookTitleMark = true; //设置隐私条款运营商协议名是否加书名号
            uiConfig.privacyTextCenterGravity = true; //隐私条款文字是否居中对齐(默认左对齐)
          
            // 授权页  
            uiConfig.statusBarColorWithNav = true; //授权页状态栏是否跟导航栏同色 only android
            uiConfig.authStatusBarStyle = JVIOSBarStyle.StatusBarStyleDarkContent; //授权页状态栏样式设置 only iOS
            uiConfig.virtualButtonTransparent = true; //授权页虚拟按键背景是否透明 only android
            

            // 隐私协议 web 页 UI 配置
            uiConfig.privacyStatusBarStyle = JVIOSBarStyle.StatusBarStyleDefault; //隐私协议web页 状态栏样式设置 only iOS
            uiConfig.privacyNavColor = Color(0xFF0C0D16).value; // 导航栏颜色
            uiConfig.privacyNavTitleTextColor = Colors.white.value; // 标题颜色
            uiConfig.privacyNavTitleTextSize = 16; // 标题大小
            uiConfig.privacyNavReturnBtnImage = "back"; //图片必须存在;

            
            // 授权页弹窗模式 配置,选填
            uiConfig.modelTransitionStyle = JVIOSUIModalTransitionStyle.CrossDissolve; //弹出方式 only ios

      
            // 隐私页
            uiConfig.privacyStatusBarColorWithNav = true; //隐私页web状态栏是否与导航栏同色 only android
            uiConfig.privacyVirtualButtonTransparent = true; //隐私页web页虚拟按键背景是否透明 only android


            //是否需要动画
            uiConfig.needStartAnim = true; //设置拉起授权页时是否需要显示默认动画
            uiConfig.needCloseAnim = true; //设置关闭授权页时是否需要显示默认动画
            uiConfig.enterAnim = "activity_slide_enter_bottom"; // 拉起授权页时进入动画 only android
            uiConfig.exitAnim = "activity_slide_exit_bottom"; // 退出授权页时动画 only android

            // 添加自定义的 控件 到授权界面
            List<JVCustomWidget> widgetList = [];


            /// 步骤 1:调用接口设置 UI
            jverify.setCustomAuthorizationView(true, uiConfig,landscapeConfig: uiConfig, widgets: widgetList);

            /// 步骤 2:调用一键登录接口,极光提供了两种方式:同步(loginAuthSyncApi)和异步(loginAuth)

            /// 我使用的是同步,需要使用异步的在极光文档查看
            /// 先,添加 loginAuthSyncApi 接口回调的监听
            jverify.addLoginAuthCallBackListener((event) {
                // 当code为6000时,message就是我们需要的token
                print("监听获取返回数据:[${event.code}] message = ${event.message}");
                print("通过添加监听,获取到 loginAuthSyncApi 接口返回数据,code=${event.code},message = ${event.message},operator = ${event.operator}");
                String message = event.message;
                getPhone(message);
            });

            /// 再,执行同步的一键登录接口
            jverify.loginAuthSyncApi(autoDismiss: true);

        } else {
            print("[2016],msg = 当前网络环境不支持认证");
            toast('当前网络环境不支持一键登录');
        }
    });
}

// 将token传给后端,获取手机号
void getPhone(String token) async {
    String url = "https://api.verification.jpush.cn/v1/web/loginTokenVerify";
    Dio dio = new Dio();
    dio.options.contentType = "application/json";
    // 注意!!!将appKey和masterSecret以“appKey:masterSecret”的格式转为base64
    dio.options.headers = {
        "Authorization":"Basic 此处为转为base64的字符串",
    };
    Map<String, dynamic> params = {
        "loginToken": token,
        "exID": '',
    };

    print("调用极光接口:$url  参数:$params");
    Response response = await dio.post(url, data: params);

    var data = response.data;
    String result = json.encode(data);
    Map<String, dynamic> user = convert.jsonDecode(result);
    print('极光返回值:$user');

    // 此处调后端一键登录接口,user['phone']是获取到的加密的手机号码,后端需要使用极光后台填写的公钥对应的私钥进行解密,方法内写登录逻辑即可
    oneClickLogin(user['phone']);
}

 到此处极光一键登录的功能实现了

过程中还遇到了一些问题:

扫描二维码关注公众号,回复: 16054719 查看本文章

1.登录预取号jverify.preLogin()失败

可能是连接了WiFi网络的问题,关闭WiFi使用移动数据流量后成功

2.调用addLoginAuthCallBackListener时获取不到token,返回code:6001,message:fetch loginToken failed

这个问题把日志发给极光后反馈预取号过期,尝试运行了极光的demo后又运行了自己的项目又可以了......一行代码都没改。

后续又出现过这个问题,拉不起授权页,code有时返回6001有时返回2005,发日志给极光后反馈是运营商返回的报错,在网络双开或用户网络状况不好的情况下会发生。

总之感觉极光的一键登录不是很稳定,不是100%能使用。

猜你喜欢

转载自blog.csdn.net/YML_426/article/details/128915708