一.自助接入步骤。
1.登录腾讯云开通人脸核身服务。
2.选择微信h5。
3.填写用户授权信息,选择对比源。
4.在调用实名核身鉴权接口时,必须传入认证人姓名和身份证号。
5.配置结果。
二.时序图
三.后端接口
service
package com.ynfy.buss.exam.faceverify.service.impl;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.faceid.v20180301.FaceidClient;
import com.tencentcloudapi.faceid.v20180301.models.*;
import com.ynfy.buss.exam.faceverify.service.IFaceVerifyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Objects;
/**
* @Description: 人脸核验
* @Author: yangfeng
* @Date: 2024-04-01
* @Version: V1.0
*/
@Slf4j
@Service
public class FaceVerifyServiceImpl implements IFaceVerifyService {
@Value("${tencent.cloud.faceApi}")
private String faceApi;
@Value("${tencent.cloud.secretId}")
private String secretId;
@Value("${tencent.cloud.secretKey}")
private String secretKey;
@Value("${tencent.cloud.ruleId}")
private String ruleId;
@Value("${tencent.cloud.redirectUrl}")
private String redirectUrl;
/**
* 实名核身鉴权
*
* @return
*/
@Override
public DetectAuthResponse detectAuth(String examId, String realName, String idCard, String imageBase64) {
DetectAuthResponse resp = null;
try {
Credential cred = new Credential(secretId, secretKey);
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(faceApi);
httpProfile.setConnTimeout(10); // 请求连接超时时间,单位为秒(默认60秒)
httpProfile.setWriteTimeout(10); // 设置写入超时时间,单位为秒(默认0秒)
httpProfile.setReadTimeout(10);
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
FaceidClient client = new FaceidClient(cred, "", clientProfile);
DetectAuthRequest req = new DetectAuthRequest();
req.setRuleId(ruleId);
req.setIdCard(idCard);
req.setName(realName);
req.setImageBase64(imageBase64);
req.setRedirectUrl(redirectUrl + examId + "&isNeedFaceDetect=" + true);
resp = client.DetectAuth(req);
} catch (TencentCloudSDKException e) {
e.printStackTrace();
}
return resp;
}
/**
* 获取实名核身结果信息
*
* @param bizToken
* @return
*/
@Override
public GetDetectInfoEnhancedResponse getDetectInfo(String bizToken) {
GetDetectInfoEnhancedResponse resp = null;
try {
Credential cred = new Credential(secretId, secretKey);
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(faceApi);
httpProfile.setConnTimeout(10); // 请求连接超时时间,单位为秒(默认60秒)
httpProfile.setWriteTimeout(10); // 设置写入超时时间,单位为秒(默认0秒)
httpProfile.setReadTimeout(10);
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
FaceidClient client = new FaceidClient(cred, "", clientProfile);
GetDetectInfoEnhancedRequest req = new GetDetectInfoEnhancedRequest();
req.setBizToken(bizToken);
req.setInfoType("0");
req.setRuleId(ruleId);
resp = client.GetDetectInfoEnhanced(req);
} catch (TencentCloudSDKException e) {
e.printStackTrace();
}
return resp;
}
/**
* 实名核身是否通过
*
* @param bizToken
* @return
*/
@Override
public boolean faceDetectIsPass(String bizToken) {
GetDetectInfoEnhancedResponse resp = getDetectInfo(bizToken);
if (!Objects.isNull(resp)) {
DetectInfoText text = resp.getText();
return !Objects.isNull(text) && text.getErrCode().intValue() == 0;
}
return false;
}
}
controller
package com.ynfy.app.api.v1.controller;
import com.ynfy.app.api.v1.annoation.IgnoreAuth;
import com.ynfy.buss.exam.faceverify.service.IFaceVerifyService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.TokenUtil;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description: 人脸核验(目前仅适用微信h5)
* @Author: yangfeng
* @Date: 2024-04-01
* @Version: V1.0
*/
@Api(tags = "人脸核验")
@RestController
@RequestMapping("/api/v1/faceVerify")
@Slf4j
public class ApiFaceVerifyController extends ApiBaseController {
@Autowired
private IFaceVerifyService faceVerifyService;
@Autowired
private ISysUserService sysUserService;
/**
* 实名核身鉴权
*
* @return
*/
@ApiOperation(value = "实名核身鉴权", notes = "实名核身鉴权")
@GetMapping(value = "/detectAuth")
public Result<?> detectAuth(@RequestParam String examId) {
log.info("考试:{},实名核身鉴权开始...", examId);
SysUser user = sysUserService.getUserByName(TokenUtil.getUserName(TokenUtil.getToken(request)));
log.info("user:{}", user.toString());
return Result.OK(faceVerifyService.detectAuth(examId, user.getRealname(), user.getIdCard(), user.getImageBase64()));
}
/**
* 获取实名核身结果信息
*
* @param bizToken
* @return
*/
@IgnoreAuth
@ApiOperation(value = "获取实名核身结果信息", notes = "获取实名核身结果信息")
@GetMapping(value = "/getDetectInfo")
public Result<?> getDetectInfo(@RequestParam String bizToken) {
log.info("获取实名核身结果信息,bizToken:{}", bizToken);
return Result.OK("", faceVerifyService.getDetectInfo(bizToken));
}
/**
* 实名核身是否通过
*
* @param bizToken
* @return
*/
@IgnoreAuth
@ApiOperation(value = "实名核身是否通过", notes = "实名核身是否通过")
@GetMapping(value = "/faceDetectIsPass")
public Result<?> faceDetectIsPass(@RequestParam String bizToken) {
log.info("调用实名核身是否通过接口,bizToken:{}", bizToken);
return Result.OK(faceVerifyService.faceDetectIsPass(bizToken));
}
}
四.h5前端。
点击“开始考试”后,读取本次考试 是否需要进行人脸核验。如果需要,调用实名核身鉴权,接口会返回用于发起核身流程的URL。
async created() {
this.initFormData();
// #ifdef H5
if (this.isNeedFaceDetect && JSON.parse(this.isNeedFaceDetect)) {
//实名核身是否通过
const data = await apiFaceDetectIsPass(this.bizToken)
if (data) {
//通过的话则加载考试信息
this.loadExam()
}
}
// #endif
},
//开始考试
async startExam() {
//h5需要人脸核身验证后才可以开始
// #ifdef H5
//本考试是否支持人脸核身
if (!!this.form.globalFaceEnable && !!this.form.faceDetectEnable) {
const data = await apiDetectAuth(this.examId)
window.location.href = data.url
this.isNeedFaceDetect = true
} else {
this.loadExam()
}
// #endif
//非h5直接进入考试
// #ifndef H5
this.loadExam()
// #endif
},
跳转url核验,核验完成后,会根据实名核身鉴权接口传入的RedirectUrl,
跳转前端页面,监听BizToken参数和自助传入的参数,获取核验结果。如果通过,则可以进行考试。
五.效果。