概述
一鍵登錄:用戶無需輸入手機號碼,一鍵點擊即可快速完成注冊/登錄流程,提高轉(zhuǎn)化率優(yōu)化用戶體驗。
申請資源
發(fā)起請求前,需要極光后臺獲取配置:
應用設置-應用信息
AppKey:xxxx
Master Secret:xxxx
應用設置-認證設置
iOS-Bundle ID:com.lx.xxx
一鍵登錄-RSA加密公鑰:xxx
密鑰生成:https://xuanxuanblingbling.github.io/ctf/web/2019/05/10/rsa/
RSA公鑰會在極光返回手機號的時候加密,服務端用對應的私鑰去解密,獲取手機號
認證流程和時序圖
認證流程:
- 客戶端調(diào)用極光認證SDK,啟動認證流程,需要向極光發(fā)起請求
- 極光返回用戶的token
- 客戶端將token發(fā)送給服務端,接口 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'] ?? '網(wǎng)絡不給力');
}
}
/// 統(tǒng)一 key
final String f_result_key = "result";
/// 錯誤碼
final String f_code_key = "code";
/// 回調(diào)的提示信息,統(tǒng)一返回 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 之前添加監(jiān)聽
jverify.addSDKSetupCallBackListener((JVSDKSetupEvent event){
print("#one login# receive sdk setup call back event :${event.toMap()}");
});
jverify.setDebugMode(true); // 打開調(diào)試模式
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;
/// 授權(quán)頁面點擊時間監(jiān)聽
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# 預取號接口回調(diào):${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 = 當前網(wǎng)絡環(huán)境不支持認證");
}
});
}
/// SDK 請求授權(quán)一鍵登錄
void loginAuth() {
jverify.checkVerifyEnable().then((map) {
bool result = map[f_result_key];
if (result) {
/// 自定義授權(quán)的 UI 界面,以下設置的圖片必須添加到資源文件里,
/// android項目將圖片存放至drawable文件夾下,可使用圖片選擇器的文件名,例如:btn_login.xml,入?yún)?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 = "用戶服務協(xié)議";
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 = ["登錄即同意","和",",","并授權(quán)陌親獲得本機號碼"];
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 ="認證服務協(xié)議";//only ios
uiConfig.privacyNavTitleTitle1 = "用戶服務協(xié)議";
uiConfig.privacyNavTitleTitle2 = "隱私協(xié)議";
uiConfig.privacyNavReturnBtnImage = "nav_back_black";//圖片必須存在;
/// 添加自定義的 控件 到授權(quán)界面
List<JVCustomWidget> widgetList = [];
/// 步驟 1:調(diào)用接口設置 UI
jverify.setCustomAuthorizationView(true, uiConfig, landscapeConfig: uiConfig,widgets: widgetList);
/// 步驟 2:調(diào)用一鍵登錄接口
/// 方式一:使用同步接口 (如果想使用異步接口,則忽略此步驟,看方式二)
/// 先,添加 loginAuthSyncApi 接口回調(diào)的監(jiān)聽
jverify.addLoginAuthCallBackListener((event){
print("#one login# 通過添加監(jiān)聽,獲取到 loginAuthSyncApi 接口返回數(shù)據(jù),code=${event.code},message = ${event.message},operator = ${event.operator}");
if (event.code == 6000) {
_token = event.message;
_reqOneLogin();
}
});
/// 再,執(zhí)行同步的一鍵登錄接口
jverify.loginAuthSyncApi(autoDismiss: true);
}
});
}