You need to enable JavaScript to run this app.
导航
Android版本
最近更新时间:2024.05.29 15:00:07首次发布时间:2023.04.10 17:45:45

获取SDK包与Demo

请先参照开通服务页流程获得身份认证服务授权,再下载SDK包进行使用。

SDK

BytedCertSDK-Android.zip
未知大小

Demo

BytedCertSdk-release_plus_v2.1.2.apk
未知大小

源码:

BytedCertSdk-Demo_plus_v2.1.2.zip
未知大小

若无火山引擎销售人员与您对接,请点击此处申请试用,咨询问题请注明为身份认证。

在工程中导入SDK

1. 将BytedCertSdk-release.aar 引入您的工程中

  1. 拷贝BytedCertSdk-release.aar 到您工程的libs目录下
  2. 配置gradle, build.gradle中加入flatDir,并在dependencies中加入implementation(name:'BytedCertSdk-release', ext:'aar')
repositories {
    flatDir{
        dirs 'libs'
    }
}

dependencies {
    //本地依赖
    implementation(name:'BytedCertSdk-release', ext:'aar')
    //远程依赖
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.10"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.squareup.okhttp3:okhttp:3.4.1'
    implementation 'com.amazonaws:aws-android-sdk-s3:2.12.7'
}

2. AndroidManifest.xml添加以下权限权

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> 
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

3. 如果开启了混淆(minifyEnabled true),需要在混淆文件中添加以下配置

-keepattributes Signature
-keepattributes Exceptions,InnerClasses
-keep class ms.bz.bd.**{ *; }
-keep class com.bytedance.** {*;}
-keep class com.volcengine.mobsecBiz.**{ *; }

-keep class kotlinx.coroutines.** {*;}

# security sdk for com.volcengine.bizssdk:ml:7.0.1.mlBusiness
-keepattributes Signature
-keepattributes Exceptions,InnerClasses
-keep class ms.bz.bd.**{ *; }
-keep class com.volcengine.mobsecBiz.**{ *; }

-keepnames class com.bytedance.applog.**

#amazonaws s3
-keepnames class com.amazonaws.**
-keepnames class com.amazon.**

# Enums are not obfuscated correctly in combination with Gson
-keepclassmembers enum * { *; }

# Request handlers defined in request.handlers
-keep class com.amazonaws.services.**.*Handler

# The following are referenced but aren't required to run
-dontwarn com.fasterxml.jackson.**


-dontwarn org.apache.http.**
# The SDK has several references of Apache HTTP client
-dontwarn com.amazonaws.http.**
-dontwarn com.amazonaws.metrics.**

4. 其他配置

本 Android SDK 基于 Java8 构建,支持的 minSDK 版本为 API 21。对于 minSDK 版本低于 API 26(不包括26)的 Android 应用,需额外进行如下设置才能正常运行

相关依赖

  • Gradle 6.1.1 或更高版本
  • Android Gradle 插件 4.0.0 或更高版本
  • 在您的安卓应用模块(通常在 app 目录下)的 build.gradle 文件中,添加如下代码
    android {
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    }
    
    

调用流程
  1. 鉴权参数设置,启动风控数据上报。
    setSignAccessKeySecretAccessKey()
  2. 进行身份认证 (setSignAccessKeySecretAccessKey接口回调后才能进行身份认证逻辑)
    1. 全流程启动:OCR+活体检测+身份认证
      beginAuthorizationWithParams()
    2. 启动活体:
      通过SDK的接口获取 bytedToken startBytedToken(),或者业务自行通过服务获取。
      startFaceCert//启动活体+身份认证
      图片

接口说明

1.入口类BytedFaceLiveManager

1.1 获取BytedFaceLiveManager单例

BytedFaceLiveManager为kotlin单例对象

/**
 *  @return  BytedFaceLiveManager对象
 */
 //Java类中使用
BytedFaceLiveManager.INSTANCE;

1.2 设置鉴权参数

/**
 *  @param  context: Android上下文
 *  @param  stsToken: 鉴权配置  使用临时密钥需要传入ststoken, 使用长期密钥时传null,强烈推荐使用临时密钥的方式,安全性更强
 *  @param  accessKey: 密钥ak
 *  @param  secretAccessKey: 密钥sk
 *  @param  callback: 接口回调,返回值为dev_token(设备稳定标识)
 *  @return  void
 *  默认使用正常采集模式进行风控数据采集,如需修改采集模版可以使用下面的方法设置securityMode参数实现。
 */
public void setSignAccessKeySecretAccessKey(Context appContext, String stsToken, String accessKey, String secretAccessKey,
                                            SDKCallBack.StringResultCallback callback)
/**
 *  @param  context: Android上下文
 *  @param  stsToken: 鉴权配置  使用临时密钥需要传入ststoken, 使用长期密钥时传null,强烈推荐使用临时密钥的方式,安全性更强
 *  @param  accessKey: 密钥ak
 *  @param  secretAccessKey: 密钥sk
 *  @param  securityMode: 风控数据采集模版/可选字段开关。MODE_DEFAULT:正常模式,MODE_MINIMIZE:基础模式。基础模版不采集可选字段(不会采集BSSID、IMEI、MEID、Mac地址、MSIN/IMSI),风控识别能力低,建议使用DEFAULT模式。
 *  @param  callback: 接口回调,返回值为dev_token(设备稳定标识)
 *  @return  void
 */
public void setSignAccessKeySecretAccessKey(Context appContext, String stsToken, String accessKey, String secretAccessKey,int securityMode
                                            SDKCallBack.StringResultCallback callback)

1.3 获取设备稳定标识

请求服务端接口时需要带上该参数。

/**
 *  @return  SecurityInfo 风控配置信息
 */
public SecurityInfo getSecurityInfo()

Example:

BytedFaceLiveManager.getInstance().getSecurityInfo().getSecurityToken();

1.4配置视频录制参数

/**
 *  @param  tosInfo:  tos配置,可空,当传空时,默认使用服务端端配置。
 *  @param  callback: 视频上传callback, 注意:返回非主线程
 *  @return  void
 */
public void configRecordeAndUploadParams(BytedCertTosInfo tosInfo, SDKCallBack.UploadVideoCallback callback)

Example:

BytedCertTosInfo bytedTosInfo = BytedCertTosInfo.createTosInfo("ak",
        "sk",
        "sts_token",
        "bucket",
        "tos-cn-beijing.volces.com",
        "cjq-test.tos-cn-beijing.volces.com");
BytedFaceLiveManager.getInstance().configRecordeAndUploadParams(bytedTosInfo, new SDKCallBack.UploadVideoCallback() {
    @Override
    public void onUploadFinsh(String bytedToken, final int errorCode, final String errorMsg, final String filePath) {
        bytedCertManager.executeInMainThread(new Runnable() {
            @Override
            public void run() {
                mUploadLog.setVisibility(View.VISIBLE);
                if (errorCode == 0) {
                    mUploadLog.setText("上传视频成功:" + filePath);
                    FileUtils.deleteFileByPath(filePath);
                }else {
                    mUploadLog.setText(String.format("上传视频失败(%d): %s", errorCode, errorMsg));
                }
            }
        });
    }
});

1.4 ocr识别接口

/**
 *  @param  context:     Android上下文
 *  @param  ocrCallback: ocr识别结果回调,详细参数见2.2 SDKCallBack.OcrCallback介绍
 *  @return  void
 */
public void doOCRH5(Context context, SDKCallBack.OcrCallback ocrCallback)

Example:

BytedFaceLiveManager.getInstance().doOCRH5(mContext, new SDKCallBack.OcrCallback(){
    @Override
    public void onOcrFinish(final int errorCode, final String errorMsg, final String identityCode, final String identityName) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (errorCode == 0) {
                    Toast.makeText(mContext, "ocr识别成功, 姓名:" + identityName, Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(mContext, "ocr识别失败, " + errorMsg, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
});

1.5 获取token接口

/**
 *  @param  refSource: true为有源比对,false为无源比对
 *  @param  params:    活体配置参数,具体取值见3.params 活体配置参数介绍
 *  @param  callback: 返回token结果的callback,详细参数见2.4 SDKCallBack.BytedTokenCallback介绍
 *  @return  void
 */
public void startBytedToken(boolean refSource, Map<String, String> params, SDKCallBack.BytedTokenCallback callback)

Example:

//无源比对
HashMap<String, String> params = new HashMap<>();
params.put("risk_motion_list", ""risk_motion_list":{"free":["0","1","2","3"],"low":["0","1","2","3"], "medium":["0","1","2","3"],"high":["0","1","2","3"]}");
params.put("risk_motion_count", ""risk_motion_count":"free":2,"low":2,"medium":3,"high":4}");
params.put("liveness_timeout", 10);
params.put("risk_fixed_motion_list", ""risk_fixed_motion_list":{"free":["0","1","2","3"],"low":["0","1","2","3"], "medium":["0","1","2","3"],"high":["0","1","2","3"]}");
params.put("max_liveness_trial", mMaxLivenessTrial);
BytedFaceLiveManager.getInstance().startBytedToken(false, params, new SDKCallBack.BytedTokenCallback() {
    @Override
    public void onBytedTokenFinish(int errorCode, String errorMsg, String bytedToken, String clientConfig) {
        if (errorCode == 0 && !bytedToken.isEmpty() && !clientConfig.isEmpty()) {
            mBytedToken = bytedToken;
            mClientConfig = clientConfig
        }
    }
});

1.6 启动活体

/**
 * 认证相关配置
 *  @param  needVerify: 是否需要进行后续服务的有源/无源比对,默认为true。
 *  @param  refSource:  true为有源比对,false为无源比对
 *  @param  textSpeech: 文本播报功能 默认值为false,表示不进行语音播报。
 */
class CertConfig( 
     boolean needVerify,
     boolean refSource,
     boolean textSpeech
     )

/**
 *  @param  context:      Android上下文
 *  @param  certConfig:   认证相关配置
 *  @param  bytedToken:   通过1.5的startBytedToken接口获取,或者通过服务端中TokenPro中获取。一般使用后者方式获取。
 *  @param  clientConfig:  从startBytedToken获取,同时也可以使用服务端中TokenPro中返回的clientConfig
 *  @param  callback: 返回token结果的callback,详细参数见2.3 SDKCallBack.ResultCallback介绍
 *  @return  void
 */
public void startFaceCert(Context context, CertConfig certConfig, String byteToken, String clientConfig, SDKCallBack.ResultCallback callback)

Example:

//有源比对
BytedFaceLiveManager.getInstance().startFaceCert(NativeFLN.this, new CertConfig(true, true, false), 
                                                    bytedToken, clientConfig, new SDKCallBack.ResultCallback(){
    @Override
    public void onResultFinish(int errorCode, String errorMsg, JSONObject jsonData) {
        if (loadingDialog != null) {
            loadingDialog.dismiss();
        }
        if (errorCode == 0) {
            Toast.makeText(mContext, "活体成功", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(mContext, "活体失败:" + errorMsg, Toast.LENGTH_SHORT).show();
        }
    }
});

1.7 启动完整认证流程,先做ocr再做有源比对

/**
 * 认证相关配置
 *  @param  needVerify: 是否需要进行后续服务的有源/无源比对。
 *  @param  refSource:  true为有源比对,false为无源比对。
 *  @param  textSpeech: 文本播报功能 默认值为false,表示不进行语音播报。
 */
class CertConfig(
     boolean needVerify,
     boolean refSource,
     boolean textSpeech)

/**
 *  @param  context:      Android上下文
 *  @param  certConfig:   认证相关配置
 *  @param  params:    活体配置参数,具体取值见3.params 活体配置参数介绍介绍
 *  @param  callback: 返回token结果的callback,详细参数见2.3 SDKCallBack.ResultCallback介绍
 *  @return  void
 */
public void beginAuthorizationWithParams(Context context, CertConfig certConfig, Map<String, String> params, SDKCallBack.ResultCallback callback)

Example:

HashMap<String, String> params = new HashMap<>();
params.put("risk_motion_list", ""risk_motion_list":{"free":["0","1","2","3"],"low":["0","1","2","3"], "medium":["0","1","2","3"],"high":["0","1","2","3"]}");
params.put("risk_motion_count", ""risk_motion_count":"free":2,"low":2,"medium":3,"high":4}");
params.put("liveness_timeout", 10);
params.put("risk_fixed_motion_list", ""risk_fixed_motion_list":{"free":["0","1","2","3"],"low":["0","1","2","3"], "medium":["0","1","2","3"],"high":["0","1","2","3"]}");
params.put("max_liveness_trial", mMaxLivenessTrial);
BytedFaceLiveManager.getInstance().beginAuthorizationWithParams(WelcomeActivity.this, true, params, new SDKCallBack.ResultCallback(){
    @Override
    public void onResultFinish(int errorCode, String errorMsg, JSONObject jsonData) {
        if (errorCode == 0) {
            Toast.makeText(mContext, "活体成功", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(mContext, "活体成功失败:" + errorMsg, Toast.LENGTH_SHORT).show();
        }
    }
});

2. callback

2.1 BytedCertUploadVideoFinishBlock

/**
 *  onUploadFinsh参数
 *  @param  bytedToken:  视频对应的bytedToken
 *  @param  errorCode:   错误码, 成功的话为0
 *  @param  errorMsg:    错误信息 成功的话为""
 *  @param  filePath:    录制的视频路径 失败的话为""
 */
interface UploadVideoCallback {
    void onUploadFinsh(String bytedToken, int errorCode, String errorMsg, String filePath);
}

2.2 SDKCallBack.OcrCallback

/**
 *  onOcrFinish参数
 *  @param  errorCode     错误码
 *  @param errorMsg      错误信息    
 *  @param identityCode  身份证id
 *  @paramd entityName   姓名
 */
interface OcrCallback {
    void onOcrFinish(int errorCode, String errorMsg, String identityCode, String identityName);
}

2.3 SDKCallBack.ResultCallback

返回数据jsonData的数据格式参考身份认证sdk返回内容说明

interface ResultCallback {
    //errorCode, 错误码
    //errorMsg,  错误信息
    //jsonData,  返回数据, 详细数据格式参考人脸核身服务端api的返回字段中的"resp_data"
    void onResultFinish(int errorCode, String errorMsg, JSONObject jsonData);
}

2.4 SDKCallBack.BytedTokenCallback

/**
 * onResultFinish参数
 *  @param  errorCode     错误码
 *  @param errorMsg      错误信息    
 *  @param bytedToken,   返回的bytenToken值
 *  @paramd client_config  客户端配置,原样传给startFaceCert即可
 */
interface BytedTokenCallback {
    void onResultFinish(int errorCode, String errorMsg, String bytedToken, String client_config);
}

3. params 活体配置参数介绍

key

说明

默认值

idcard_name

身份证名称, 有源比对需要传

idcard_no

身份证id,有源比对为需要传

risk_liveness_type

风险等级对应的活体类型,取值有
“motion”(动作活体),
“reflection”(炫彩活体)。
格式为json string ,各风险对应的活体类型的取值类型为String。

"risk_liveness_type":{ "free":"motion", //无风险,动作活体 "low":"motion", //低风险, 动作活体 "medium":"motion",//中风险 , 动作活体 "high":"reflection"//高风险, 动作活体 }

risk_motion_list

风险等级对应的下发动作列表,取值有
“0”(眨眼)
"1"(张嘴)
"2"(点头)
"3"(摇头)
格式为json string,各风险对应的动作的取值类型为String数组。

"risk_motion_list":{ "free":["0","1","2","3"],//无风险,全部下发 "low":["0","1","2","3"], //低风险, 全部下发 "medium":["0","1","2","3"],//中风险 , 全部下发 "high":["0","1","2","3"]//高风险, 全部下发 }

risk_motion_count

风险等级对应的下发动作数量,可选范围:[1, 4]
格式为json string,各风险对应的动作的取值类型为Int。
取值需要结合risk_motion_list配置的动作列表,风险的对应的下发动作数量不能大于对应的下发动作列表数量。

"risk_motion_count":{ ** "free":2, //无风险,下发两个动作* ** "low":2, //低风险, 下发两个动作* ** "medium":3, //中风险 , 下发三个动作* ** "high":4,//高风险, 下发两四动作* ** }*

risk_fixed_motion_list

风险等级对应的固定下发动作列表,取值有
“0”(眨眼)
"1"(张嘴)
"2"(点头)
"3"(摇头)
格式为json string,各风险对应的动作的取值类型为String数组。

默认不传

liveness_timeout

端上活体超时时长,可选范围: [5, 60]

10

max_liveness_trial

端上动作活体最大尝试次数, 可选范围:[1, 100]

10

4.活体认证信息回调说明

4.1 facelive_info数据结构

身份认证包含活体检测身份认证两个步骤, 如活体检测成功, 在启动活体/启动完整认证流程接口的回调里会把活体认证相关的结果(最佳帧数据和一小段视频数据)回调到ResultCallback的resp_data(JsonObject)信息中, 具体字段结构如下:

data = {
    "facelive_info": {
        "info": 认证信息
    }
}

"info": {
    "image": Base64编码数据,
    "video": Base64编码数据
}

4.2 活体信息处理

活体认证信息主要返回的信息为: 1. 认证过程中的最佳图片. 2. 认证过程中的最佳视频片段.

活体信息结果处理伪代码

fun handleResultData(context: Context, resp_data: JSONObject?) {
        GlobalScope.launch(Dispatchers.IO) {
            resp_data?.optJSONObject("facelive_info")?.let { faceLiveInfoJsonObject ->
                faceLiveInfoJsonObject.optJSONObject("info")?.let { infoJsonObject ->
                        //处理视频数据
                        infoJsonObject.optString("video").takeIf { it.isNotEmpty() }
                            ?.let { videoData ->
                                val base64dDecodeData = Base64.decode(videoData, Base64.NO_WRAP)
                                val targetFilePath = "${context.externalCacheDir?.absolutePath ?: context.filesDir.absolutePath}/test.mp4"
                                writeContentToFile(
                                    base64dDecodeData,
                                    targetFilePath
                                )
                                Log.d(TAG, "writeContentToFile video finish path $targetFilePath")
                            }

                         //处理图片数据
                        infoJsonObject.optString("image").takeIf { it.isNotEmpty() }
                            ?.let { imageData ->
                                val base64dDecodeData = Base64.decode(imageData, Base64.NO_WRAP)
                                val targetFilePath =
                                    "${context.externalCacheDir?.absolutePath ?: context.filesDir.absolutePath}/test.jpg"
                                writeContentToFile(base64dDecodeData, targetFilePath)
                                Log.d(TAG, "writeContentToFile image finish path $targetFilePath")
                            }
                }
            }
        }
    }

错误代码

说明

0

成功

-2

客户端上内部错误。一般出现在集成阶段,需检查logcat运行时的日志排查问题原因。

-4

您手动退出或因识别失败次数大于4次,导致客户端默认退出。

-1000

网络异常,请稍后再试

-1001

未知错误

-1002

活体中断

-1003

活体识别失败,请再试一次

-1004

算法初始化失败

-1005

活体参数设置失败

-1006

用户取消操作

-1007

用户取消证件识别

-1101

超过活体最大次数

-3001

网络数据包解析失败

-3002

请退出多屏模式,再重试一次

-3003

无法使用相机,请检查是否打开相机权限

-3006

相册图片获取失败

-3007

拍照失败

-5021

比对失败,请确认是本人

50000+

50000以上错误码,为透传服务端的错误码,请参考人脸核身服务端api的错误码说明