手机号码一键登录接入

概述

一键登录:用户无需输入手机号码,一键点击即可快速完成注册/登录流程,提高转化率优化用户体验。

申请资源

发起请求前,需要极光后台获取配置:

应用设置-应用信息

AppKey:xxxx
Master Secret:xxxx

应用设置-认证设置

iOS-Bundle ID:com.lx.xxx
一键登录-RSA加密公钥:xxx

密钥生成:https://xuanxuanblingbling.github.io/ctf/web/2019/05/10/rsa/

RSA公钥会在极光返回手机号的时候加密,服务端用对应的私钥去解密,获取手机号

认证流程和时序图

认证流程:

  • 客户端调用极光认证SDK,启动认证流程,需要向极光发起请求
  • 极光返回用户的token
  • 客户端将token发送给服务端,接口 user/account/shanyan_login
  • 服务端将客户端请求中的token,向极光请求返回手机号,接口:https://api.verification.jpush.cn/v1/web/loginTokenVerify
  • 极光验证token是否有效
  • 极光返回用户的手机号
  • 服务端返回用户的UID和Session ID

代码

  String _token;
  _reqOneLogin() async {
    if (_token == null) {
      return;
    }
    var data = await NetUtil.futurePost('/user/account/shanyan_login',
        bodyParams: {
          "token": _token
        });
    var dd = data;
    if (dd['dm_error'] == 0) {
      bool login = await UserManager.instance.isLogin();
      if (login) {
        await UserManager.instance.logout();
      }
      UserManager.instance.updateLoginUser(dd);
    } else {
      TToast.show(dd['error_msg'] ?? '网络不给力');
    }
  }

  /// 统一 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";
  final Jverify jverify = new Jverify();

  ///初始化平台极光SDK
  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initJverifyState() async {

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

    jverify.setDebugMode(true); // 打开调试模式
    jverify.setup(
        appKey: "xxx",//"你自己应用的 AppKey",
        channel: "AppStore"); // 初始化sdk,  appKey 和 channel 只对ios设置有效
    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    /// 授权页面点击时间监听
    jverify.addAuthPageEventListener((JVAuthPageEvent event) {
      print("#one login# receive auth page event :${event.toMap()}");
    });

    preLogin();
  }

  /// 登录预取号
  void preLogin(){
    jverify.checkVerifyEnable().then((map) {
      if (!mounted) return;

      bool result = map[f_result_key];
      if (result) {
        jverify.preLogin().then((map) {
          if (!mounted) return;
          print("#one login# 预取号接口回调:${map.toString()}");
          int code = map[f_code_key];
          String message = map[f_msg_key];
          if (code == 7000) {
            ///预取号成功弹窗登录界面
            loginAuth();
          }
          else {
            print("#one login#" + message);
          }
        });
      }
      else {
        print("#one login# [2016],msg = 当前网络环境不支持认证");
      }
    });
  }

  /// SDK 请求授权一键登录
  void loginAuth() {
    jverify.checkVerifyEnable().then((map) {
      bool result = map[f_result_key];
      if (result) {
        /// 自定义授权的 UI 界面,以下设置的图片必须添加到资源文件里,
        /// android项目将图片存放至drawable文件夹下,可使用图片选择器的文件名,例如:btn_login.xml,入参为"btn_login"。
        /// ios项目存放在 Assets.xcassets。
        ///
        JVUIConfig uiConfig = JVUIConfig();

        //nav
        uiConfig.navHidden = false;
        uiConfig.navReturnImgPath = 'nav_back_black';
        uiConfig.navColor = Colors.white.value;
        uiConfig.navText = '';

        //logo
        uiConfig.logoWidth = 90;
        uiConfig.logoHeight = 90;
        uiConfig.logoOffsetY = 76;
        uiConfig.logoVerticalLayoutItem = JVIOSLayoutItem.ItemSuper;
        uiConfig.logoHidden = false;
        uiConfig.logoImgPath = "icon-180";

        //phone
        uiConfig.numberFieldWidth = 200;
        uiConfig.numberFieldHeight = 40;
        uiConfig.numFieldOffsetY = 58;
        uiConfig.numberVerticalLayoutItem = JVIOSLayoutItem.ItemLogo;
        uiConfig.numberColor = Colors.black.value;
        uiConfig.numberSize = 20;

        //slogan
        uiConfig.sloganOffsetY = 10;
        uiConfig.sloganVerticalLayoutItem = JVIOSLayoutItem.ItemNumber;
        uiConfig.sloganTextColor = CJColor.grayColor.value;
        uiConfig.sloganTextSize = 12;

        //login
        uiConfig.logBtnWidth = 260;
        uiConfig.logBtnHeight = 50;
        uiConfig.logBtnOffsetY = 20;
        uiConfig.logBtnVerticalLayoutItem = JVIOSLayoutItem.ItemSlogan;
        uiConfig.logBtnText = "本机号码一键登录";
        uiConfig.logBtnTextColor = Colors.white.value;
        uiConfig.logBtnTextSize = 14;
        uiConfig.loginBtnNormalImage = "icon-login-bg";//图片必须存在
        uiConfig.loginBtnPressedImage = "icon-login-bg";//图片必须存在
        uiConfig.loginBtnUnableImage = "icon-login-bg";//图片必须存在

        //privacy
        uiConfig.privacyHintToast = true;//only android 设置隐私条款不选中时点击登录按钮默认显示toast。
        uiConfig.privacyState = true;//设置默认勾选
        uiConfig.privacyCheckboxHidden = false;
        uiConfig.privacyOffsetY = 35+MediaQuery.of(context).padding.bottom.toInt();// 距离底部距离
        uiConfig.privacyVerticalLayoutItem = JVIOSLayoutItem.ItemSuper;
        uiConfig.clauseName = "用户服务协议";
        uiConfig.clauseUrl = UserManager.instance.h5Host()+'/about/index.html#/userAgreement';
        uiConfig.clauseBaseColor = Colors.black.value;
        uiConfig.clauseNameTwo = "隐私政策";
        uiConfig.clauseUrlTwo = UserManager.instance.h5Host()+'/about/index.html#/privacyAgreement';
        uiConfig.clauseColor = Color(0xFFFAC409).value;
        uiConfig.privacyText = ["登录即同意","和",",","并授权陌亲获得本机号码"];
        uiConfig.privacyTextSize = 12;
        //uiConfig.privacyWithBookTitleMark = true;
        //uiConfig.privacyTextCenterGravity = false;
        uiConfig.authStatusBarStyle =  JVIOSBarStyle.StatusBarStyleDarkContent;
        uiConfig.privacyStatusBarStyle = JVIOSBarStyle.StatusBarStyleDefault;

        //only android
        uiConfig.statusBarColorWithNav = true;
        uiConfig.virtualButtonTransparent = true;
        uiConfig.privacyStatusBarColorWithNav = true;
        uiConfig.privacyVirtualButtonTransparent = true;

        //animation
        uiConfig.needStartAnim = true;
        uiConfig.needCloseAnim = true;

        //privacy web
        uiConfig.privacyNavColor =  Colors.white.value;
        uiConfig.privacyNavTitleTextColor = Colors.black.value;
        uiConfig.privacyNavTitleTextSize = 16;

        uiConfig.privacyNavTitleTitle  ="认证服务协议";//only ios
        uiConfig.privacyNavTitleTitle1 = "用户服务协议";
        uiConfig.privacyNavTitleTitle2 = "隐私协议";
        uiConfig.privacyNavReturnBtnImage = "nav_back_black";//图片必须存在;

        /// 添加自定义的 控件 到授权界面
        List<JVCustomWidget> widgetList = [];
        /// 步骤 1:调用接口设置 UI
        jverify.setCustomAuthorizationView(true, uiConfig, landscapeConfig: uiConfig,widgets: widgetList);

        /// 步骤 2:调用一键登录接口

        /// 方式一:使用同步接口 (如果想使用异步接口,则忽略此步骤,看方式二)
        /// 先,添加 loginAuthSyncApi 接口回调的监听
        jverify.addLoginAuthCallBackListener((event){
          print("#one login# 通过添加监听,获取到 loginAuthSyncApi 接口返回数据,code=${event.code},message = ${event.message},operator = ${event.operator}");

          if (event.code == 6000) {
            _token = event.message;
            _reqOneLogin();
          }
        });
        /// 再,执行同步的一键登录接口
        jverify.loginAuthSyncApi(autoDismiss: true);
      }
    });
  }

参考资料

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容