腾讯云人脸核身基础版SDK接入-Java

前言

本文主要针对手机app端调用人脸核身接口,主要讲解java开发部分,关于人脸核身的申请,接口地址之类的信息详见腾讯云文档:
腾讯云人脸核身接口文档

一.准备工作

实体类
返回参数

package com.sinosoft.springbootplus.agency.domain.entity;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

/**
 * <pre>
 * 人脸认证对象
 * </pre>
 *
 * @author mc
 * @date 2021-02-05
 */
@Data
@Accessors(chain = true)
@ApiModel(value = "FaceAuth对象", description = "人脸认证对象")
public class FaceAuth {
    
    

    @ApiModelProperty(value = "业务流水号")
    private String bizSeqNo;

    @ApiModelProperty(value = "请求时间")
    private String transactionTime;

    @ApiModelProperty(value = "合作方订单号")
    private String orderNo;

    @ApiModelProperty(value = "人脸id")
    private String faceId;

    @ApiModelProperty(value = "是否成功 此字段false无意义")
    private boolean success;

    @ApiModelProperty(value = "订单号")
    private String nonceStr;

    @ApiModelProperty(value = "keyLicence")
    private String keyLicence;

    @ApiModelProperty(value = "签名")
    private String sign;

    @ApiModelProperty(value = "userId")
    private String userId;

}

请求参数

package com.sinosoft.springbootplus.agency.param;

import com.sinosoft.springbootplus.mybatis.param.OrderQueryParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import javax.validation.constraints.NotBlank;

/**
 * <pre>
 * 人脸认证 参数对象
 * </pre>
 *
 * @author mc
 * @date 2021-02-05
 */
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "FaceAuthQueryParam对象", description = "人脸认证参数")
public class FaceAuthParam extends OrderQueryParam {
    
    
    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "姓名", required = true)
    @NotBlank(message = "姓名不能为空")
    private String name;

    @ApiModelProperty(value = "身份证号", required = true)
    @NotBlank(message = "身份证号不能为空")
    private String idNo;

    @ApiModelProperty(value = "用户标识")
    private Long userId;

    @ApiModelProperty(value = "NONCE ticket,有效期120秒")
    private String ticket;

    @ApiModelProperty(value = "32位随机数")
    private String nonceStr;

}

配置信息

package com.sinosoft.springbootplus.agency.domain.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * <pre>
 * 人脸认证配置文件 
 * </pre>
 *
 * @author mc
 * @since 2021/4/16
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "third-part.face")
public class FaceAuthProperties {
    
    

    private String appId = "";
    private String secretValue = "";
    private String keyLicence = "";
    private String accessTokenUrl = "https://idasc.webank.com/api/oauth2/access_token";
    private String apiTicketUrl = "https://idasc.webank.com/api/oauth2/api_ticket";
    private String signTicketUrl = "https://miniprogram-kyc.tencentcloudapi.com/api/oauth2/api_ticket";
    private String faceUrl = "https://miniprogram-kyc.tencentcloudapi.com/api/server/getfaceid?orderNo=";

}

认证常量

package com.sinosoft.springbootplus.agency.domain.config;

/**
 * <pre>
 * 腾讯银行卡认证常量类
 * </pre>
 *
 * @author mc
 * @since 2021/4/16
 */
public interface TencentFaceAuthConstants {
    
    

    /**
     * 业务流程唯一标识,即 wbappid
     */
    String APP_ID = "app_id";
    /**
     * wbappid 对应的密钥
     */
    String SECRET = "secret";
    /**
     * 授权类型
     */
    String GRANT_TYPE = "grant_type";
    /**
     * 授权类型 默认值
     */
    String GRANT_TYPE_VALUE = "client_credential";
    /**
     * version
     */
    String VERSION = "version";
    /**
     * version版本号
     */
    String VERSION_VALUE = "1.0.0";

    String TYPE = "type";

    String NONCE = "NONCE";

}

用户信息常量

package com.sinosoft.springbootplus.agency.domain.constant;

/**
 * <pre>
 * 用户中心常量
 * </pre>
 *
 * @author mc
 * @date 2021-03-03
 */
public interface UserCenterConstant {
    
    

    /**
     * 返回编码 0
     */
    String RESULT_CODE_ZERO = "0";

    /**
     * 返回编码 1
     */
    String RESULT_CODE_ONE = "1";

    /**
     * 返回编码 200
     */
    int RESULT_SUCCESS_CODE = 200;

    /**
     * 用户类型:个人用户
     */
    Integer USER_TYPE_PERSON = 0;

    /**
     * 用户类型:法人用户
     */
    Integer USER_TYPE_COMPANY = 1;

    /**
     * 数字2
     */
    int NUM_TWO = 2;

    // ================  用户认证等级  ================

    /**
     * 用户中心 用户认证等级 未认证
     */
    Integer UC_ZERO_AUTH = 0;

    /**
     * 用户中心 用户认证等级 手机号认证
     */
    Integer UC_FIRST_AUTH = 1;

    /**
     * 用户中心 用户认证等级 身份证号认证
     */
    Integer UC_SECOND_AUTH = 2;

    /**
     * 统一认证中心 用户认证等级 未认证
     */
    Integer ID_ZERO_AUTH = 0;

    /**
     * 统一认证中心 用户认证等级 初级认证
     */
    Integer ID_FIRST_AUTH = 1;

    /**
     * 统一认证中心 用户认证等级 中级认证
     */
    Integer ID_SECOND_AUTH = 2;

    // ================  用户认证等级  ================

}

人脸认证枚举类

package com.sinosoft.springbootplus.agency.domain.config;

import com.sinosoft.springbootplus.common.enums.ThirdRepositoryEnum;

/**
 * <pre>
 * 人脸认证枚举类 
 * </pre>
 *
 * @author mc
 * @since 2021/4/16
 */
public enum FaceAuthEnum implements ThirdRepositoryEnum {
    
    

    /**
     * 腾讯银行卡认证
     */
    TENCENT_FACE_ACCESS_TOKEN("tencent_face_access_token_get", "人脸认证accessToken获取", "腾讯"),
    TENCENT_FACE_API_TICKET("tencent_face_api_ticket_get", "人脸认证apiTicket获取", "腾讯"),
    TENCENT_FACE_AUTH("tencent_face_auth", "人脸认证", "腾讯");

    private String code;
    private String name;
    private String provider;

    FaceAuthEnum(String code, String name, String provider) {
    
    
        this.code = code;
        this.name = name;
        this.provider = provider;
    }

    @Override
    public String getCode() {
    
    
        return code;
    }

    @Override
    public String getName() {
    
    
        return name;
    }

    @Override
    public String getProvider() {
    
    
        return provider;
    }
}

Controller

package com.sinosoft.springbootplus.agency.controller;

import com.alibaba.spring.util.ObjectUtils;
import com.sinosoft.springbootplus.agency.application.service.impl.FaceAuthServiceImpl;
import com.sinosoft.springbootplus.agency.domain.entity.FaceAuth;
import com.sinosoft.springbootplus.agency.param.FaceAuthParam;
import com.sinosoft.springbootplus.agency.utils.QRCodeUtil;
import com.sinosoft.springbootplus.common.api.ApiResult;
import com.sinosoft.springbootplus.common.exception.BusinessException;
import com.sinosoft.springbootplus.core.context.RequestContext;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;

/**
 * <pre>
 * 人脸认证 API接口
 * </pre>
 *
 * @author mc
 * @date 2021-02-05
 */
@Slf4j
@RestController
@RequestMapping("/face")
@Api(tags="人脸核身 API")
public class FaceAuthController {
    
    

    private FaceAuthServiceImpl faceAuthService;

    public FaceAuthController(FaceAuthServiceImpl faceAuthService) {
    
    
        this.faceAuthService = faceAuthService;
    }

    @PostMapping("/tencentFace")
    @RequiresUser
    public ApiResult<FaceAuth> authByFace(@Valid @RequestBody FaceAuthParam faceAuthParam) throws Exception {
    
    
        return faceAuthService.authByFace(faceAuthParam);
    }
}

ServiceImpl

package com.sinosoft.springbootplus.agency.application.service.impl;

import cn.hutool.core.util.IdUtil;
import com.sinosoft.springbootplus.agency.domain.constant.UserCenterConstant;
import com.sinosoft.springbootplus.agency.domain.entity.FaceAuth;
import com.sinosoft.springbootplus.agency.domain.repository.FaceAuthRepository;
import com.sinosoft.springbootplus.agency.param.FaceAuthParam;
import com.sinosoft.springbootplus.api.system.dto.UserOrgInfo;
import com.sinosoft.springbootplus.api.system.service.SystemOrgServiceApi;
import com.sinosoft.springbootplus.common.api.ApiResult;

import com.sinosoft.springbootplus.common.exception.BusinessException;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * <pre>
 * 人脸认证 服务类
 * </pre>
 *
 * @author mc
 * @date 2021-02-05
 */
@Slf4j
@Service
public class FaceAuthServiceImpl {
    
    

    private FaceAuthRepository faceAuthRepository;
    private SystemOrgServiceApi systemOrgServiceApi;

    public FaceAuthServiceImpl(FaceAuthRepository faceAuthRepository,SystemOrgServiceApi systemOrgServiceApi) {
    
    
        this.faceAuthRepository = faceAuthRepository;
        this.systemOrgServiceApi = systemOrgServiceApi;
    }

    /**
     * 人脸识别上传身份信息
     *
     * @param faceAuthParam 人脸认证 查询参数对象
     * @return ApiResult
     * @throws Exception 异常
     */
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<FaceAuth> authByFace(FaceAuthParam faceAuthParam) throws Exception {
    
    
        // 根据用户id查询用户实名信息
        //获取当前登录人的机构信息及机构等级
        UserOrgInfo userOrg = systemOrgServiceApi.getUserOrg(faceAuthParam.getUserId());
        String realName = userOrg.getPersonName();
        String idCard = userOrg.getUserName();

        if (StringUtils.isBlank(realName) || StringUtils.isBlank(idCard)) {
    
    
            throw new BusinessException("请先进行实名认证再进行人脸认证");
        }
        faceAuthParam.setName(realName);
        faceAuthParam.setIdNo(idCard);

        ApiResult<String> accessTokenResult = faceAuthRepository.getAccessToken();
        if (UserCenterConstant.RESULT_SUCCESS_CODE != accessTokenResult.getCode()) {
    
    
            return ApiResult.fail(accessTokenResult.getMsg());
        }
        String accessToken = accessTokenResult.getData();
        log.info("【人脸核身】获取accessToken为:{}", accessToken);

        ApiResult<String> apiTicketResult = faceAuthRepository.getApiTicket(accessToken, faceAuthParam.getUserId().toString());
        if (UserCenterConstant.RESULT_SUCCESS_CODE != apiTicketResult.getCode()) {
    
    
            return ApiResult.fail(accessTokenResult.getMsg());
        }
        String apiTicket = apiTicketResult.getData();
        log.info("【人脸核身】获取apiTicket为:{}", apiTicket);

        faceAuthParam.setTicket(apiTicket);
        String nonceStr = IdUtil.simpleUUID();
        log.info("【人脸核身】获取nonceStr为:{}", nonceStr);
        faceAuthParam.setNonceStr(nonceStr);

        ApiResult<String> signTicketResult = faceAuthRepository.getSignTicket(accessToken);
        if (UserCenterConstant.RESULT_SUCCESS_CODE != signTicketResult.getCode()) {
    
    
            return ApiResult.fail(signTicketResult.getMsg());
        }
        String signTicket = signTicketResult.getData();
        log.info("【人脸核身】获取signTicket为:{}", signTicket);

        ApiResult<FaceAuth> apiResult = faceAuthRepository.authByFace(faceAuthParam,signTicket);
        // 认证成功
//        if (UserCenterConstant.RESULT_SUCCESS_CODE == apiResult.getCode()) {
    
    
//            // 人脸识别临时表中添加用户已进行人脸核身身份记录
//            faceAuthTmpDomain.addFaceAuthTmp(faceAuthParam);
//        }
        return apiResult;
    }

}

FaceAuthRepository

package com.sinosoft.springbootplus.agency.domain.repository;

import com.sinosoft.springbootplus.agency.domain.entity.FaceAuth;
import com.sinosoft.springbootplus.agency.param.FaceAuthParam;
import com.sinosoft.springbootplus.common.api.ApiResult;
import org.springframework.stereotype.Repository;

import java.util.Map;

/**
 * <pre>
 * 人脸识别 仓储层
 * </pre>
 *
 * @author mc
 * @since 2021-01-26
 */
@Repository
public interface FaceAuthRepository {
    
    

    /**
     * 人脸核身获取 AccessToken
     *
     * @return accessToken字符串
     * @throws Exception 获取异常
     */
    ApiResult<String> getAccessToken() throws Exception;

    /**
     * 人脸核身获取 ApiTicket
     *
     * @param accessToken accessToken
     * @param userId 用户id
     * @return ApiTicket字符串
     * @throws Exception 获取异常
     */
    ApiResult<String> getApiTicket(String accessToken, String userId) throws Exception;

    /**
     * 人脸核身上传身份信息
     *
     * @param faceAuthParam 人脸认证 查询参数对象
     * @return ApiResult
     * @throws Exception 信息上传异常
     */
    ApiResult<FaceAuth> authByFace(FaceAuthParam faceAuthParam,String signTicket) throws Exception;

    /**
     * 人脸核身获取
     *
     * @param accessToken accessToken
     * @return ApiTicket字符串
     * @throws Exception 获取异常
     */
    ApiResult<String> getSignTicket(String accessToken) throws Exception;
}

TencentFaceAuthRepository

package com.sinosoft.springbootplus.agency.domain.repository.impl;


import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.hash.Hashing;
import com.sinosoft.springbootplus.agency.domain.config.FaceAuthEnum;
import com.sinosoft.springbootplus.agency.domain.config.FaceAuthProperties;
import com.sinosoft.springbootplus.agency.domain.config.TencentFaceAuthConstants;
import com.sinosoft.springbootplus.agency.domain.constant.UserCenterConstant;
import com.sinosoft.springbootplus.agency.domain.entity.FaceAuth;
import com.sinosoft.springbootplus.agency.domain.repository.FaceAuthRepository;
import com.sinosoft.springbootplus.agency.param.FaceAuthParam;
import com.sinosoft.springbootplus.agency.vo.AccessTokenResultVo;
import com.sinosoft.springbootplus.agency.vo.ApiTicketResultVo;
import com.sinosoft.springbootplus.agency.vo.ApiTicketVo;
import com.sinosoft.springbootplus.common.api.ApiResult;

import com.sinosoft.springbootplus.common.event.RepositoryExceptionEvent;

import com.sinosoft.springbootplus.util.EventPublisher;
import com.sinosoft.springbootplus.util.OkHttpRequestUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.Charsets;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Repository;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.*;

/**
 * <pre>
 * 腾讯人脸识别 仓储层
 * </pre>
 *
 * @author mc
 * @since 2021-01-26
 */
@Slf4j
@Repository
@EnableConfigurationProperties(value = FaceAuthProperties.class)
public class TencentFaceAuthRepository implements FaceAuthRepository, TencentFaceAuthConstants {
    
    

    private FaceAuthProperties faceAuthProperties;
    TencentFaceAuthRepository(FaceAuthProperties faceAuthProperties) {
    
    
        this.faceAuthProperties = faceAuthProperties;
    }

    private static final Map<String, Object> GET_ACCESS_TOKEN_QUERY_MAP = new HashMap<>();
    private static final Map<String, Object> GET_API_TICKET_BASE_MAP = new HashMap<>();

    private static final String PUBLISH_FACE_AUTH_FORM = "header:{}, params:{}";
    private static final Map<String, Object> HEADER_MAP = MapUtil.of("Content-Type", "application/json");

    @Override
    public ApiResult<String> getAccessToken() {
    
    

        try {
    
    
            String resultJson = OkHttpRequestUtils.doGet(faceAuthProperties.getAccessTokenUrl(), GET_ACCESS_TOKEN_QUERY_MAP);
            log.debug("【人脸核身】获取accessToken返回数据:{}", resultJson);
            if (StringUtils.isNotBlank(resultJson)) {
    
    
                AccessTokenResultVo accessTokenResultVo = JSONUtil.toBean(resultJson, AccessTokenResultVo.class);
                // 返回码不为0是 请求失败
                if (UserCenterConstant.RESULT_CODE_ZERO.equals(accessTokenResultVo.getCode())) {
    
    
                    return ApiResult.ok(accessTokenResultVo.getAccessToken());
                }
                log.error("【人脸核身】获取accessToken接口失败,失败信息为;{}", accessTokenResultVo.getMsg());
            } else {
    
    
                log.error("【人脸核身】获取accessToken接口失败,返回信息为空");
                publishFaceGetAccessTokenError(GET_ACCESS_TOKEN_QUERY_MAP, null);
            }
            return ApiResult.fail("人脸验证失败,请重试");
        } catch (Exception e) {
    
    
            log.error("【人脸核身】获取accessToken接口失败", e);
            publishFaceGetAccessTokenError(GET_ACCESS_TOKEN_QUERY_MAP, e);
            return ApiResult.fail("人脸验证失败,请重试");
        }
    }

    @PostConstruct
    private void initBaseMap() {
    
    
        GET_ACCESS_TOKEN_QUERY_MAP.put(APP_ID, faceAuthProperties.getAppId());
        GET_ACCESS_TOKEN_QUERY_MAP.put(SECRET, faceAuthProperties.getSecretValue());
        GET_ACCESS_TOKEN_QUERY_MAP.put(GRANT_TYPE, GRANT_TYPE_VALUE);
        GET_ACCESS_TOKEN_QUERY_MAP.put(VERSION, VERSION_VALUE);

        GET_API_TICKET_BASE_MAP.put(APP_ID, faceAuthProperties.getAppId());
        GET_API_TICKET_BASE_MAP.put(TYPE, NONCE);
        GET_API_TICKET_BASE_MAP.put(VERSION, VERSION_VALUE);
    }

    @Override
    public ApiResult<String> getApiTicket(String accessToken, String userId) {
    
    
        Map<String, Object> apiTicketQueryMap = getApiTicketQueryMap(accessToken, userId);
        try {
    
    
            String resultJson = OkHttpRequestUtils.doGet(faceAuthProperties.getApiTicketUrl(), apiTicketQueryMap);
            log.debug("【人脸核身】获取apiTicket接口返回数据:{}", resultJson);
            if (StringUtils.isNotBlank(resultJson)) {
    
    
                ApiTicketResultVo apiTicketResultVo = JSONUtil.toBean(resultJson, ApiTicketResultVo.class);
                // 获取返回码
                String code = apiTicketResultVo.getCode();
                // 返回码不为0是 请求失败
                if (!UserCenterConstant.RESULT_CODE_ZERO.equals(code)) {
    
    
                    // 获取返回信息
                    String msg = apiTicketResultVo.getMsg();
                    log.error("【人脸核身】获取apiTicket失败,错误码为:{},错误信息为:{}", code, msg);
                    return ApiResult.fail("人脸验证失败,请重试");
                }
                List<ApiTicketVo> tickets = apiTicketResultVo.getTickets();
                return ApiResult.ok(tickets.get(0).getValue());
            } else {
    
    
                log.error("【人脸核身】获取apiTicket接口失败,返回信息为空");
                publishFaceGetApiTicketError(apiTicketQueryMap, null);
                return ApiResult.fail("人脸验证失败,请重试");
            }
        } catch (Exception e) {
    
    
            log.error("【人脸核身】获取apiTicket接口失败", e);
            publishFaceGetApiTicketError(apiTicketQueryMap, e);
            return ApiResult.fail("人脸验证失败,请重试");
        }
    }

    private Map<String, Object> getApiTicketQueryMap(String accessToken, String userId) {
    
    
        // 请求参数
        Map<String, Object> getApiTicketQueryMap = new HashMap<>(5);
        getApiTicketQueryMap.put("access_token", accessToken);
        getApiTicketQueryMap.put("user_id", userId);
        getApiTicketQueryMap.putAll(GET_API_TICKET_BASE_MAP);
        return getApiTicketQueryMap;
    }

    @Override
    public ApiResult<FaceAuth> authByFace(FaceAuthParam faceAuthParam,String signTicket) {
    
    
        String orderNo = faceAuthParam.getNonceStr();
        log.info("【人脸核身】上传身份信息的订单号为【{}】", orderNo);
        // 签名
        ArrayList<String> list = new ArrayList<>();
        list.add(faceAuthParam.getUserId().toString());
        list.add(faceAuthProperties.getAppId());
        list.add(faceAuthParam.getNonceStr());
        list.add(VERSION_VALUE);
        String sign = getSign(list,signTicket);
        // 请求参数组装
        String json = getAuthFaceParamMap(faceAuthParam, orderNo, sign);
        log.debug("【人脸核身】请求认证接口请求数据为:{}", json);
        try {
    
    
            String result = OkHttpRequestUtils.doPost(faceAuthProperties.getFaceUrl()+orderNo, HEADER_MAP, json);
            log.debug("【人脸核身】请求认证接口返回信息为:{}", result);
            if (StringUtils.isBlank(result)) {
    
    
                log.error("【人脸核身】请求认证接口失败,返回信息为空");
                publishFaceAuthError(json, null);
                return ApiResult.fail("人脸验证失败,请重试");
            }
            JSONObject jsonObject = JSONObject.parseObject(result);
            // 获取返回码
            String code = jsonObject.getString("code");
            // 返回码不为0是 请求失败
            if (!UserCenterConstant.RESULT_CODE_ZERO.equals(code)) {
    
    
                String msg = jsonObject.getString("msg");
                log.error("【人脸核身】获取apiTicket失败,错误码为:{},错误信息为:{}", code, msg);
                return ApiResult.fail(msg);
            }
            FaceAuth faceAuth = jsonObject.getObject("result", FaceAuth.class);
            log.info("【人脸核身】人脸验证后台上送信息成功,业务流水号为:{},时间为:{},合作方订单号为:{},人脸id为:{}", faceAuth.getBizSeqNo(),
                    faceAuth.getTransactionTime(), faceAuth.getOrderNo(), faceAuth.getFaceId());
            faceAuth.setNonceStr(faceAuthParam.getNonceStr());
            faceAuth.setKeyLicence(faceAuthProperties.getKeyLicence());
            //nonceTicket生成的sign
            ArrayList<String> nonceList = new ArrayList<>();
            nonceList.add(faceAuthParam.getUserId().toString());
            nonceList.add(faceAuthProperties.getAppId());
            nonceList.add(faceAuthParam.getNonceStr());
            nonceList.add(VERSION_VALUE);
            String nonceSign = getSign(nonceList,faceAuthParam.getTicket());
            faceAuth.setSign(sign);
            faceAuth.setUserId(faceAuthParam.getUserId().toString());
            return ApiResult.ok(faceAuth);
        } catch (IOException e) {
    
    
            log.error("【人脸核身】请求人脸验证后台信息上送接口失败", e);
            publishFaceAuthError(json, e);
            return ApiResult.fail("人脸验证失败,请重试");
        }
    }

    @Override
    public ApiResult<String> getSignTicket(String accessToken) throws Exception {
    
    
        // 请求参数
        Map<String, Object> getSignTicketQueryMap = new HashMap<>(5);
        getSignTicketQueryMap.put("access_token", accessToken);
        getSignTicketQueryMap.put("app_id", faceAuthProperties.getAppId());
        getSignTicketQueryMap.put("type", "SIGN");
        getSignTicketQueryMap.put("version", VERSION_VALUE);
        try {
    
    
            String resultJson = OkHttpRequestUtils.doGet(faceAuthProperties.getSignTicketUrl(), getSignTicketQueryMap);
            log.debug("【人脸核身】获取signTicket接口返回数据:{}", resultJson);
            if (StringUtils.isNotBlank(resultJson)) {
    
    
                ApiTicketResultVo apiTicketResultVo = JSONUtil.toBean(resultJson, ApiTicketResultVo.class);
                // 获取返回码
                String code = apiTicketResultVo.getCode();
                // 返回码不为0是 请求失败
                if (!UserCenterConstant.RESULT_CODE_ZERO.equals(code)) {
    
    
                    // 获取返回信息
                    String msg = apiTicketResultVo.getMsg();
                    log.error("【人脸核身】获取signTicket失败,错误码为:{},错误信息为:{}", code, msg);
                    return ApiResult.fail("人脸验证失败,请重试");
                }
                List<ApiTicketVo> tickets = apiTicketResultVo.getTickets();
                return ApiResult.ok(tickets.get(0).getValue());
            } else {
    
    
                log.error("【人脸核身】获取signTicket接口失败,返回信息为空");
                publishFaceGetApiTicketError(getSignTicketQueryMap, null);
                return ApiResult.fail("人脸验证失败,请重试");
            }
        } catch (Exception e) {
    
    
            log.error("【人脸核身】获取signTicket接口失败", e);
            publishFaceGetApiTicketError(getSignTicketQueryMap, e);
            return ApiResult.fail("人脸验证失败,请重试");
        }
    }

    private String getAuthFaceParamMap(FaceAuthParam faceAuthParam, String orderNo, String sign) {
    
    
        Map<String, Object> paramMap = new HashMap<>(8);
        paramMap.put("webankAppId", faceAuthProperties.getAppId());
        paramMap.put("orderNo", orderNo);
        paramMap.put("name", faceAuthParam.getName());
        paramMap.put("idNo", faceAuthParam.getIdNo());
        paramMap.put("userId", faceAuthParam.getUserId());
        paramMap.put("sourcePhotoType", "1");
        paramMap.put(VERSION, VERSION_VALUE);
        paramMap.put("sign", sign);
        paramMap.put("nonce", orderNo);
        return JSON.toJSONString(paramMap);
    }

    /**
     * 生成签名
     */
    private String getSign(List<String> list,String signTicket) {
    
    
        if (list == null) {
    
    
            throw new NullPointerException("values is null");
        }
        list.removeAll(Collections.singleton(null));// remove null
        list.add(signTicket);
        java.util.Collections.sort(list);

        StringBuilder sb = new StringBuilder();
        for (String s : list) {
    
    
            sb.append(s);
        }
        return Hashing.sha1().hashString(sb, Charsets.UTF_8).toString().toUpperCase();
    }

    private void publishFaceGetAccessTokenError(Map<String, Object> map, Exception exception) {
    
    
        RepositoryExceptionEvent repositoryExceptionEvent = new RepositoryExceptionEvent(
                FaceAuthEnum.TENCENT_FACE_ACCESS_TOKEN, JSONObject.toJSONString(map), exception);
        EventPublisher.publishEvent(repositoryExceptionEvent);
    }

    private void publishFaceGetApiTicketError(Map<String, Object> map, Exception exception) {
    
    
        RepositoryExceptionEvent repositoryExceptionEvent = new RepositoryExceptionEvent(
                FaceAuthEnum.TENCENT_FACE_API_TICKET, JSONObject.toJSONString(map), exception);
        EventPublisher.publishEvent(repositoryExceptionEvent);
    }

    private void publishFaceAuthError(String params, Exception exception) {
    
    
        String json = StrUtil.format(PUBLISH_FACE_AUTH_FORM, HEADER_MAP, params);
        RepositoryExceptionEvent repositoryExceptionEvent = new RepositoryExceptionEvent(
                FaceAuthEnum.TENCENT_FACE_AUTH, json, exception);
        EventPublisher.publishEvent(repositoryExceptionEvent);
    }

}

注意事项

在进行人脸识别的过程中会有两次请求用到生成签名,一次是调用人脸识别合作方后台上传身份信息接口,另外就是调用sdk的时候,这两次签名生成所需要的的Ticket是不同的
第一次用的是下面
在这里插入图片描述
第二次用的是这个
在这里插入图片描述
不然会一直报签名错误

猜你喜欢

转载自blog.csdn.net/mcband/article/details/130366504
今日推荐