# 视频活体实名核验数字证书服务API
视频实名认证产品:主要用于在H5场景下,通过用户新录制并上传一个视频,进行活体检测的判断,是活体,再对比身份证姓名是否一致,最后比对人脸是否是本人。验证通过后签发具有法律效力的第三方可信数字证书
# 一、请求说明
请求地址:http://api.spiderid.cn/api/router/rest,https://api.spiderid.cn/api/router/rest
服务接口名称(即公共参数method的值): realid.liveness.videoAuth
请求方式:POST
# 二、请求参数
- 请求参数以表单形式提交,Content-Type值为: application/x-www-form-urlencoded;charset=utf-8
名称 | 类型 | 是否必须 | 描述 |
---|---|---|---|
realname | String | 是 | 姓名(身份证);参数支持数据加密,详情参照加解密方法说明 |
idcard | String | 是 | 身份证号码;参数支持数据加密,详情参照加解密方法说明 |
livenessRate | Double | 是 | 活体分数阀值,高于阀值才会进行人脸比对 |
videoData | String | 是 | 视频数据,以base64:开头 (视频base64数据), 以fs: 开头(文件云文件);参数支持数据加密,详情参照加解密方法说明 |
- 分数阀值介绍
阀值 | 拒绝率 | 误拒率 | 通过率 |
---|---|---|---|
0.022403 | 0.90325733 | 0.1% | 99.9% |
0.393241(推荐) | 0.96254072 | 0.5% | 99.5% |
0.649192 | 0.97557003 | 1% | 99% |
0.933801 | 0.98990228 | 2% | 98% |
0.973637 | 0.99446254 | 3% | 97% |
0.988479 | 0.99641694 | 4% | 96% |
0.994058 | 0.99739414 | 5% | 95% |
关于以上数值的概念介绍:
- 拒绝率(TRR):如99%,代表100次作弊假体攻击,会有99次被拒绝。
- 误拒率(FRR):如0.5%,指1000次真人请求,会有5次因为活体分数低于阈值被错误拒绝。
- 通过率(TAR):如99%,指100次真人请求,会有99次因为活体分数高于阈值而通过。
- 阈值(Threshold):高于此数值,则可判断为活体。
请求示例:
http或https://api.spiderid.cn/api/router/rest?
<[公共请求参数]>
realname=XXX&idcard=XXX&livenessRate=XXX&videoData=XXX
# 三、响应参数
data 结果信息 | 类型 | 描述 |
---|---|---|
incorrect | Integer | 返回码 |
message | String | 描述(100:成功 其他为失败信息) |
livingScore | Double | 活体分数 |
faceScore | Double | 人脸比对成功才有,人脸比对分数;faceScore分数在0到1之间,值越大相似度越高,0<faceScore<0.40(系统判断为不同人), 0.40≤faceScore≤0.44(不能确定是否为同一人),0.45≤faceScore(系统判断同一人) |
faceAdvise | String | 人脸比对成功才有,人脸比对建议 |
pictures | List | 活体比对成功才有,解析出的图片地址,有效期24小时,过期后下载不了 |
certificate | String | 证书 |
# 四、成功示例
JSON示例
{
"code": 0,
"requestId":"dsd24...",
"message": "success",
"data": {
"message": "检测成功",
"incorrect":100,
"livingScore":0.9457,
"faceScore":0.8,
"faceAdvise":"系统判断为同一人",
"pictures":[".....",
"....."
]
}
}
# 五、失败示例
JSON示例
{
"code": 0,
"requestId":"dsd24...",
"message": "success",
"data": {
"message": "视频活体检测失败",
"incorrect":124
}
}
# 六、返回码说明(incorrect)
返回码 | 描述 | 是否收费 |
---|---|---|
100 | 检测成功 | 是 |
110 | 不支持该视频文件 | 否 |
121 | 视频未检测到人脸 | 否 |
122 | 视频检测到多张人脸 | 是 |
123 | 视频检测人脸质量较差:[光线有问题,人脸模糊等] | 是 |
124 | 视频活体检测失败 | 否 |
125 | 视频活体检测完成,分数过低,未进行人脸比对 | 是 |
126 | 视频活体检测完成,身份核验失败,身份证姓名不合法 | 是 |
127 | 视频活体检测完成,身份核验失败,身份证号码和姓名不匹配 | 是 |
128 | 视频活体检测完成,身份核验失败,身份证号码不存在 | 是 |
129 | 视频活体检测完成,身份核验成功,人脸比对失败 | 是 |
130 | 视频活体检测完成,照片质量不合格,未进行人脸比对 | 是 |
131 | 视频活体检测完成,身份核验成功,库中无照片 | 是 |
132 | 视频活体检测完成,身份核验成功,特征提取失败 | 是 |
133 | 视频活体检测完成,身份核验成功,检测到多于一张人脸 | 是 |
134 | 视频活体检测完成,身份核验成功,图片不合法 | 是 |
# SDK 请求示例
public static void main(String[] args) {
//提供的url
String url = "http://api.spiderid.cn/api/router/rest";
//您的appKey
String appkey = "XXX";
//您的appSecret
String secretKey = "XXX";
try {
//1.默认客户端
ApiClient apiClient = new DefaultApiClient(url, appkey, secretKey);
//2.调用出错自动重试客户端
//AutoRetryApiClient apiClient = new AutoRetryApiClient(url, appkey, secretKey);
VideoLivenessAuthRequest req = new VideoLivenessAuthRequest();
req.setRealname("XXX");
req.setIdcard("XXX");
req.setLivenessRate(0.393241);
// //1.以base64:开头,图片转换成base64位字符串
// String video = Base64.encodeBase64String(FileUtils.readFileToByteArray(new ClassPathResource("/data/qq.mp4").getFile()));
// req.setVideoDataBase64(video);
//2.fs:开头,需要调用我们提供的上传接口,获取bucket,和objectKey,格式为:fs:+bucket:+objectKey
String bucket = "XXX";
String objectKey = "XXX";
String videoData = bucket + ":" + objectKey;
req.setVideoDataFs(videoData);
// 配置此参数时,会对请求参数中的realname、realname、videoData属性做加密
// req.setEncMethod(EncryptMethod.SM4);
// 当设置encMethod后,fs上传文件也需要加密
// byte[] encPassword = SecretGenerateUtils.getSecretKey(appkey, secretKey);
// String fsKey = uploadFile(apiClient, "liveness_video", "/data/qq.mp4", encPassword);
// req.setVideoDataFs(fsKey);
VideoLivenessAuthResponse rsp = apiClient.execute(req);
//后续业务处理
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 上传文件
*
* @param apiClient 客户端
* @param bizType 文件上传业务类型
* @param path 需要上传的文件路径
* @param encPassword 文件加密密码,不为null对文件进行加密
* @return bucket:objectKey
*/
private static String uploadFile(ApiClient apiClient, String bizType, String path, byte[] encPassword) throws ApiException, IOException {
FsUploadPolicyRequest fsUploadPolicyRequest = new FsUploadPolicyRequest();
fsUploadPolicyRequest.setBizType(bizType);
//获取文件上传权限
FsUploadPolicyResponse fsResponse = apiClient.execute(fsUploadPolicyRequest);
//获取权限识别
if (null == fsResponse.getData()) {
throw new ApiException();
}
//上传文件示例
Map<String, String> params = new HashMap<String, String>(5);
params.put("token", fsResponse.getData().getToken());
if (fsResponse.getData().getObjectKey().endsWith("/")) {
params.put("key", fsResponse.getData().getObjectKey() + "${filename}");
} else {
params.put("key", fsResponse.getData().getObjectKey());
}
//需要上传的文件
Map<String, FileItem> fileParams = new HashMap<String, FileItem>(5);
File file = new File(path);
// encPassword不为空对上传的文件进行加密
if (encPassword != null) {
byte[] bytes = FileUtils.readFileToByteArray(file);
byte[] encryptContent = Sm4Utils.encrypt(bytes, encPassword);
String fileName = file.getName();
FileItem fileItem = new FileItem(fileName, encryptContent, FileContentTypeUtils.mimeTypeByFilename(fileName));
fileParams.put("file", fileItem);
} else {
fileParams.put("file", new FileItem(file));
}
//上传
String uploadUrl = fsResponse.getData().getUploadUrl();
String json = WebUtils.doPost(uploadUrl, params, fileParams, 30000, 30000);
JSONObject jsonObject = JSON.parseObject(json);
return jsonObject.getString("bucket") + ":" + jsonObject.getString("objectKey");
}