Flutter integrates Jiguang one-click login

1. Open Jiguang certification

After creating the application on the Jiguang official website, fill in the information in the [Integration Settings] of the [Authentication Settings], the Android application signature needs to download the signature tool to obtain it, and the iOS fills in the Bundle ID, and submit it for review after completion

Fill in the RSA encrypted public key in [One-click login] in [Authentication Settings]

 The encrypted public key is obtained from the online generation of public key-private key pair, RSA public-private key generation-ME2 online tool , and the platform that needs to be integrated is opened

Note: The number of RSA encrypted public keys is 1024 bits, and the key format is PKCS#8

2. Introduce plug-ins and related configurations

dependencies:
  jverify: 2.2.8

Make the following configurations in the android/app/build.gradle file:

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

3. Jiguang authentication initialization

Initialize in initState on the login interface:

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. Click the one-click login button to pull up the authorization page

On the login page, we need a one-click login button. After clicking, the authorization page of Jiguang will be pulled up.

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']);
}

 At this point, the Jiguang one-click login function has been realized

There are also some problems encountered in the process:

1. Login prefetch number jverify.preLogin() failed

It may be a problem with connecting to the WiFi network. After turning off WiFi and using mobile data traffic, it succeeded.

2. The token cannot be obtained when calling addLoginAuthCallBackListener, and the return code: 6001, message: fetch loginToken failed

For this problem, after sending the log to Jiguang, it was reported that the prefetch number expired. After trying to run Jiguang's demo and then running its own project, it was fine again... a line of code has not been changed.

This problem occurred again later, the authorization page could not be opened, and the code sometimes returned 6001 and sometimes returned 2005. After sending the log to Jiguang, the feedback was an error returned by the operator.

In short, I feel that Jiguang's one-click login is not very stable, and it is not 100% usable.

Guess you like

Origin blog.csdn.net/YML_426/article/details/128915708
Recommended