4399一键登录SDK接入文档

文档版本 变更时间 变更内容
v2.0.0 2020-03-19 变更接口,增加一个手机号绑定多个账号的处理方式
v2.1.0 2020-04-29 扩展接口,登录model支持额外参数
v2.5.0 2022-06-20 提升 minSdkVersion 到16
升级Volley依赖
改善aar接入方式
  • 不需要手动添加混淆规则,由依赖自动传递
  • 在线仓库地址升级为https
自定义页面增强,具体参考LoginUiModel类接口:
  • 扩展自定义View, 新增ct_account_extend_view_container容器
  • 扩展隐私协议,支持更多协议设置
  • 新增隐私协议默认是否勾选接口
部分外部渠道自定义受限,页面和主题与旧版略有差异
v2.8.0 2023-09-06 - (接口不变)

一、关于 SDK

4399一键登录SDK,可以让用户不需输入密码,一键确认即可登录。

为使一键登录合理合法正常使用,需要特别注意以下事项:

另外,若应用还有短信登录、账号密码登录等其他登录方式,建议

Android应用支持的最低minSdkVersion16,SDK 内容:

二、概念与流程

1、client id与client secret

分别是接入方应用在 4399 平台的标识和接口密钥,是许多接口的基础参数。 client idclientIdclient_id等效,client secret同理。

2、access token与refresh token

接入方调用 SDK 登录接口后,直接得到的不是完整的用户信息,主要是access tokenrefresh token

3、完整接入流程示意

image

简要说明:

另外,应用还可以请求服务端token刷新接口,时序图中不再单独画出

三、准备阶段

应用注册

首次申请

为了获得“一键登录”能力,接入方需要提交应用的以下基本信息给对接人员,没有特殊说明各项均为必需信息

// java 版本不能高于8,执行前需要在环境变量中添加 keytool 路径,或使用绝对路径
// app/xxxxxx.keystore 为apk签名文件
$ keytool -v -list -keystore app/xxxxxx.keystore
输入密钥库口令:  ******
证书指纹:
         MD5: 76:B4:CC:46:64:55:C7:4D:BD:BB:AA:94:74:BF:A4:DD
         SHA1: C0:CB:7F:19:FB:93:C5:F1:87:E6:67:94:4E:8C:14:AF:36:51:69:3A
         SHA256: CC:EF:6F:14:D1:AC:09:5E:56:60:EB:7F:FB:37:80:AE:21:F3:C1:A3:A2:99:86:DB:B8:B4:29:66:93:4C:EE:C9
         签名算法名称: SHA256withRSA
         版本: 3
// 若只有签名过的apk文件,则可以使用命令: keytool -printcert -jarfile xxx.apk

本例中获取的签名证书指纹md5为:76B4CC466455C74DBDBBAA9474BFA4DD。正常提交后,接入方将得到client idclient secret

重用已有 client 信息

若接入方已经申请过client信息, 且希望与另一个应用绑定,可以将应用基本信息和client idclient secret一并提交给 SDK 对接者。

四、接入流程

引入 SDK

根据接入方需要,以下两种种方式可选其一

repositories {
    // 正式仓库
    maven {
        url 'https://mvn.4399doc.com/repository/maven-releases/'
    }
    
    // 快照仓库,对接调试用,正式环境可以去掉
    maven {
        url 'https://mvn.4399doc.com/repository/maven-snapshots/'
    }
}

dependencies {
    // 一键登录 SDK:建议使用最新版本,可通过浏览仓库地址或向运营咨询版本
    implementation 'cn.m4399.sdk:login-union:2.10.9'
     // volley 是 SDK 使用的外部依赖之一,若接入方已有,可忽略
    implementation 'com.android.volley:volley:1.2.1'
}

注意:若使用7.0+版本的 gradle 及 android build 插件,仓库地址应配置在settings.gradle

operate/libs/volley-v1.2.1.aar

Gradle 文件中注意添加本地依赖

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
}

AndroidManifest 配置

<application android:networkSecurityConfig="@xml/demo_network_compatibility">

res/xml/demo_network_compatibility内容如下

<?xml version="1.0" encoding="utf-8"?>

<network-security-config>
    <base-config cleartextTrafficPermitted="true"/>
</network-security-config>

接口调用

初始化

// 尽早初始化SDK,建议在Application类的onCreate里面
LoginNonPassword.init(
    new Options()
        .debuggable(false) // 可选,是否开启调试模式,开启true,否则false,默认不开启
        .appContext(getApplicationContext()),
    new Client()
        .withId("client_id_of_your_app"), // 必须,client id,即应用在4399平台的标识
    new OnResultListener() {
        @Override
        public void onResult(long code, String message) {
            // SDK 初始化结束,若初始化失败将会在登录前再初始化一次
        }
    }
);

登录

// 检查设备当前状态是否支持一键登录
LoginNonPassword.canSupport(new OnResultListener() {
    @Override
    public void onResult(long code, String message) {
        if (code != Code.OK) {
            Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
            return;
        }

        LoginUiModel uiModel = new LoginUiModel()
                // 可选,设置登录Activity上显示的app logo
                .appLogo(R.mipmap.ic_launcher)
                // 可选,设置登录Activity上显示的app 名称
                .appName(R.string.demo_app_name)
                // 可选,设置打开登录Activity时的切换动画
                .startActivityAnimation(R.anim.demo_slide_in_right, R.anim.demo_slide_out_left)
                // 可选,设置关闭登录Activity时的切换动画
                .finishActivityAnimation(R.anim.demo_slide_in_left, R.anim.demo_slide_out_right)
                // 可选,设置登录Activity布局id
                .loginActivityLayout(R.layout.demo_activity_ct_account_auth)
                // 可选,设置隐私协议是否默认勾选,默认不勾选,SDK 不记忆此状态
                .privacyChecked(true)
                // 可选,设置额外的隐私链接,及其他富文本,至少应有运营商隐私协议
                .privacySpans(new PrivacySpannableHolder(
                    R.string.demo_account_privacy_formatter,
                    new PrivacySpannableHolder.OperatorPrivacy(R.color.demo_color_d81b60),
                    new PrivacySpannableHolder.Privacy(R.string.demo_account_privacy_name_1,
                        R.color.demo_color_d81b60,
                        R.string.demo_account_privacy_url_1),
                    new PrivacySpannableHolder.Privacy(R.string.demo_account_privacy_name_2,
                        R.color.demo_color_d81b60,
                        R.string.demo_account_privacy_url_2),
                    new PrivacySpannableHolder.Content(R.string.demo_app_name, R.color.demo_color_primary)
                ))
                // 可选,设置“用户隐私政策”确认对话框布局id
                .privacyConfirmDialogLayout(R.layout.demo_dialog_ct_account_privacy)
                // 可选,设置”用户隐私政策“内容Activity布局
                .privacyContentActivityLayout(R.layout.demo_activity_ct_account_privacy);
                // 可选,若自定义了登录Activity布局,同时在布局中添加了元素,可以通过此方式添加点击回调
                //.extendView(new LoginUiModel.ExtendViewHolder(viewId, View.OnClickListener), ...);
        
        // 登录,使用自定义UI
        LoginNonPassword.login(MainActivity.this, new OnLoginFinishedListener() {
            @Override
            public void onLoginFinished(long code, String message, User user) {
                if (code == Code.SUCCESS) {
                    // 登录成功,使用token进一步获取用户详细信息
                } else {
                    // 登录失败,提示用户
                }
            }
        }, new AccountNegotiation() {
                @Override
                public void onMultiAccount(String desensitizedPhone, List<AccountCandidate> candidates) {
                    // 展示候选账号列表
                    AccountCandidate ac;
                    // ac = ... 当用户选择其中一个时
                    // SDK 将以选定用户名的账号进行登录
                    ac.onSelected();     
                }
        }, uiModel);
        
        // 登录,使用默认UI,假设MainActivity实现了OnLoginFinishedListener, AccountNegotiation接口
        //LoginNonPassword.login(MainActivity.this, MainActivity.this, MainActivity.this);
    }
});

自定义登录UI

2.5.0 版本引入的新授权渠道,由于渠道 SDK 限制,其主题、页面样式与旧版本略有差别

接入方可以自定义登录相关UI,但以下元素不可变更

除此,接入方可以

Activity 主题定制

<!-- 覆盖Activity主题、方向,注意tools:replace标签-->
<activity
    android:name="cn.com.chinatelecom.account.sdk.ui.AuthActivity"
    android:exported="false"
    android:screenOrientation="portrait"
    android:theme="@style/AppTheme.NoActionBar"
    tools:replace="android:theme"/>
    
<activity
    android:name="cn.com.chinatelecom.account.sdk.ui.PrivacyWebviewActivity"
    android:exported="false"
    android:screenOrientation="portrait"
    android:theme="@style/AppTheme.NoActionBar"
    tools:replace="android:theme" />

<activity
    android:name="cn.m4399.login.union.wo.WoLoginActivity"
    android:exported="false"
    android:screenOrientation="portrait"
    android:theme="@style/AppTheme.NoActionBar"
    tools:replace="android:theme" />

<activity
    android:name="cn.m4399.login.union.wo.WoPrivacyContentActivity"
    android:exported="false"
    android:screenOrientation="portrait"
    android:theme="@style/AppTheme.NoActionBar"
    tools:replace="android:theme" />

<activity
    android:name="com.cmic.gen.sdk.view.GenLoginAuthActivity"
    android:configChanges="orientation|keyboardHidden|screenSize"
    android:launchMode="singleTop"
    android:screenOrientation="portrait"
    android:theme="@style/AppTheme.NoActionBar"
    tools:replace="android:theme,android:screenOrientation" />

布局样式及内容定制

具体方式可以参考demo中的布局文件及其他相关样式文件:

以下对登录Activity做简要说明

元素 用途 可定制方式
1 返回按钮 可定制
2 标题栏 可定制
3 品牌 可定制
4 脱敏手机号 可定制
5 服务提供商标识 必须包含,内容不可定制
6 登录按钮 可定制
7 其他登录方式 可定制
8 用户隐私政策链接 必须,内容中的“登录即同意《天翼账号服务与隐私协议》”部分不可定制

五、服务端接入

SDK 客户端最终可以取到手机号等少量可以标识用户的信息,更多信息仍然需要从账号系统获取。参考服务端接入文档

六、附录

FAQ

A:为什么有时候出现的一键登录界面略有差?
Q: 由于 SDK 集成了不止一个一键登录服务,部分服务商的登录页面定制受限

A: 若不能正常登录,如何调试?
Q: 可以尝试打开调试开关,观察日志信息,开启方式见各平台初始化相关部分

状态码

含义
0 请求成功
-64 permission-denied(无权限访问)
-65 API-request-rates-Exceed-Limitations(调用接口超限)
-10001 取号失败
-10002 参数错误
-10003 解密失败
-10004 ip受限
-10005 异网取号回调参数异常
-10006 Mdn取号失败,且属于电信网络
-10007 重定向到异网取号
-10008 over-limit, 未检测到移动网络,或当前手机网络不支持一键登录
-10009 时间戳过期
-10016 auth-fail(使用了热点)
-20005 sign-invalid(签名错误)
-20006 应用不存在
-20007 公钥数据不存在
-20100 内部解析错误
-20102 加密参数解析失败
-30001 时间戳非法
-30003 topClass失效
99 签名错误
100 成功
101 登录失败(请求到天翼服务端失败)
102 登录失败(生成 access token 失败,可能是请求运营商接口或者账号系统的接口出错)
180 应用配置不全
181 访问未授权
182 客户端错误
183 网络错误
184 无网络连接
185 数据解析错误
186 服务端错误
187 请求超时
188 运营商变更
51002 参数为空
51114 无法获取手机号数据
80000 请求超时
80001 请求网络异常
80002 响应码错误
80003 无网络连接
80004 移动网络未开启
80005 Socket超时异常
80006 域名解析异常
80007 IO异常
80008 No route to host
80009 nodename nor servname provided, or not known
80010 Socket closed by remote peer
80100 登录结果为空
80101 登录结果异常
80102 预登录异常
80103 SDK未初始化
80104 未调用预登录接口
80105 加载nib文件异常
80200 点击返回按钮
80201 点击其他登录方式按钮
80800 Wifi切换异常,可能是应用没有注册或系统没有授权
80801 Wifi切换超时,可能是应用没有注册或系统没有授权
100001 手机号绑定多个候选账号(2.0.0新增,此时开发者应完成候选账号选择交互)