AI-腾讯云人脸核身之独立H5接入

概述

AI人脸识别,使用官方API:腾讯云人脸核身之独立H5接入。接口官方返回code = 0 表示成功,其他code码值均为对应码值信息,详见错误码
注意:
1.合作方上送身份信息的计算签名参数与启动人脸核身计算签名参数不一致,有部分区别。
2.wbappid = webankAppId = app_id(如果我没理解错的话,API中介绍命名不同)
3.建议token和signticket一起做下20分钟定时刷新机制,保证缓存里的signticket是最新并且有效的

实现流程

合作方后台上送身份信息
  1. 前端入参:客户身份证号、客户姓名、from(App || browser)
  2. 后端固定参数:wbappid = webankAppId = app_id(API中介绍命名不同,注意)、orderNo(可自定义随机生成不唯一)、userId(可自定义随机生成不唯一)、version
  3. 获取signTicket(通过token)---- 获取方式代码见下
  4. 计算合作方上送身份信息签名,参数有:wbappid、orderNo、name、idNo、userId、version、signTicket ---- 计算方式代码见下
启动H5人脸核身
  1. 在合作方成功上送身份信息后,可以获取到h5faceId
  2. 获取nonce(32位随机数)
  3. 获取nonceTicket(通过token & userId)
  4. 计算启动H5人脸核身签名,参数有:wbappid、orderNo、userId、version、h5faceId、nonce、nonceTicket
  5. 将成功拉起人脸核身验证通过后的回调页面链接配置至配置文件,同时对该链接进行encode编码
  6. 获取到所有拉起人脸核身所需参数后,向链接https://ida.webank.com/api/web/login拼接上参数:webankAppId、version、nonce、orderNo、h5faceId、url、sign、from、userId。例如:
https://ida.webank.com/api/web/login?webankAppId="+wbappid+"&version=1.0.0&nonce="+nonce+"&orderNo="+orderNo+"&h5faceId="+h5faceId+"&url="+url+"&userId="+userId+"&sign="+sign+"&from="+userVo.getFrom()+"

拼接好后,直接将该链接返回前端去打开即可拉起人脸核身。请注意,该链接仅一次有效!!!

核心代码实现

获取accessToken
    @Override
    public String getToken(){

        String accessTokenTencent = (String) redisService.get("accessTokenTencent");
        log.info("获取redis中的accessToken,为:[{}]", accessTokenTencent);
        if ("".equals(accessTokenTencent) || accessTokenTencent == null) {

            Map<String, String> param = new HashMap<>(16);
            String tokenUrl = "https://idasc.webank.com/api/oauth2/access_token?app_id={app_id}&secret={secret" +
                    "}&grant_type={grant_type}&version=1.0.0";
            param.put("app_id", wbappid);
            param.put("secret", secret);
            param.put("grant_type", "client_credential");
            TencentTokenDto tokenDto = template.getForObject(tokenUrl, TencentTokenDto.class, param);
            if (!"0".equals(tokenDto.getCode())) {
                log.error("获取腾讯token信息错误,errorCde:{},errMessage:{}", tokenDto.getCode(), tokenDto.getMsg());
                return "";
            }
            accessTokenTencent = tokenDto.getAccessToken();
            redisService.set("accessTokenTencent", accessTokenTencent, 6800L);
        }
        log.info("返回有效accessToken,为:[{}]", accessTokenTencent);
        return accessTokenTencent;
    }
通过accessToken获取signTicket
@Override
    public String getSignTicket(String txAccessToken){

        String signTicket = (String) redisService.get("signTicket");
        log.info("获取redis中的signTicket,为:[{}]", signTicket);
        if ("".equals(signTicket) || signTicket == null) {
            Map<String, String> param = new HashMap<>(16);
            String tokenUrl = "https://idasc.webank.com/api/oauth2/api_ticket?app_id={app_id}&access_token" +
                    "={access_token}&type={type}&version=1.0.0";
            param.put("app_id", wbappid);
            param.put("access_token", txAccessToken);
            param.put("type", "SIGN");
            TencentTicketDto ticketDto = template.getForObject(tokenUrl, TencentTicketDto.class, param);
            if (!"0".equals(ticketDto.getCode())) {
                log.error("获取腾讯signTicket信息错误,errorCde:{},errMessage:{}", ticketDto.getCode(), ticketDto.getMsg());
                return "";
            }
            signTicket = ticketDto.getTickets().get(0).getValue();
            redisService.set("signTicket", signTicket, 3000L);
        }
        log.info("返回有效signTicket,为:[{}]", signTicket);
        return signTicket;
    }
合作方上送身份信息计算签名
@Override
    public String sign(String orderNo, String idNo, String name, String signTicket, String userId) {
        //为计算签名做准备
        List<String> list = new ArrayList<>();
        String version = "1.0.0";
        list.add(wbappid);
        list.add(orderNo);
        list.add(name);
        list.add(idNo);
        list.add(userId);
        list.add(version);
        String sign = getSign(list, signTicket);
        return sign;
    }
private String getSign(List<String> values, String signTicket) {
        if (values == null) {
            throw new NullPointerException("values is null");
        }
        // remove null
        values.removeAll(Collections.singleton(null));
        values.add(signTicket);
        log.info("启动人脸核身签名排序前参数为:[{}]",values);
        java.util.Collections.sort(values);
        log.info("启动人脸核身签名排序后参数为:[{}]",values);
        StringBuilder sb = new StringBuilder();
        for (String s : values) {
            sb.append(s);
        }
        return Hashing.sha1().hashString(sb, Charsets.UTF_8).toString().toUpperCase();
    }
合作方上送身份信息
@Override
    public TxCodeDto sendUserInfo(UserVo userVo){
        //获取accessToken
        String accessToken = getToken();
        //获取signTicket
        String signTicket = getSignTicket(accessToken);
        //合作方上送计算签名
        String sign = sign(userVo.getOrderNo(), userVo.getIdNo(), userVo.getName(), signTicket, userVo.getUserId());

        Map<String, String> param = new HashMap<>(16);
        param.put("webankAppId", wbappid);
        param.put("orderNo", userVo.getOrderNo());
        param.put("name", userVo.getName());
        param.put("idNo", userVo.getIdNo());
        param.put("userId", userVo.getUserId());
        param.put("version", "1.0.0");
        param.put("sign", sign);
        log.debug("合作方上送身份信息参数有:[{}]", param);
        String url = "https://idasc.webank.com/api/server/h5/geth5faceid";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map> entity = new HttpEntity<>(param, headers);
        TxCodeDto txCodeDto = this.template.postForObject(url, entity, TxCodeDto.class);
        log.info("合作方上送身份信息接口返回:[{}]", txCodeDto);
        return txCodeDto;
    }
通过accessToken & userId获取nonceTicket
@Override
    public String getNonceTicket(String txAccessToken, String userId){
        String nonceTicket = (String) redisService.get("nonceTicket");
        log.info("获取redis中的nonceTicket,为:[{}]", nonceTicket);
        if ("".equals(nonceTicket) || nonceTicket == null) {

            Map<String, String> param = new HashMap<>(16);
            String tokenUrl = "https://idasc.webank.com/api/oauth2/api_ticket?app_id={app_id}&access_token" +
                    "={access_token}&type={type}&version=1.0.0&user_id={user_id}";
            param.put("app_id", wbappid);
            param.put("access_token", txAccessToken);
            param.put("type", "NONCE");
            param.put("user_id", userId);
            log.info("获取腾讯NONCE ticket,为:[{}]", param);
            TencentTicketDto ticketDto = template.getForObject(tokenUrl, TencentTicketDto.class, param);
            if (!"0".equals(ticketDto.getCode())) {
                log.error("获取腾讯NONCE ticket信息错误,errorCde:{},errMessage:{}", ticketDto.getCode(), ticketDto.getMsg());
                return "";
            }
            nonceTicket = ticketDto.getTickets().get(0).getValue();
            redisService.set("nonceTicket", ticketDto.getTickets().get(0).getValue(), 100L);
        }
        log.info("返回有效nonceTicket,为:[{}]", nonceTicket);
        return nonceTicket;
    }
启动人脸核身计算签名
private String faceSign(String orderNo, String userId, String nonceTicket, String h5faceId, String nonce) {
        //为计算签名做准备
        List<String> list = new ArrayList<>();
        list.add(wbappid);
        list.add(orderNo);
        list.add(userId);
        list.add("1.0.0");
        list.add(h5faceId);
        list.add(nonce);
        String sign = getSign(list, nonceTicket);
        log.info("启动人脸核身返回签名为:[{}]",sign);
        return sign;
    }
启动人脸核身获取启动链接
 @Override
    public String startCheckFace(UserVo userVo){
        //随机生成32位唯一用户ID和订单ID
        String userId = getOrderNoOrUserIdRandom(32,"userId");
        String orderNo = getOrderNoOrUserIdRandom(32,"orderNo");
        userVo.setOrderNo(orderNo);
        userVo.setUserId(userId);
        String requestUrl = "";
        try {
            //获取accessToken
            String accessToken = getToken();
            //上送合作方用户信息
            TxCodeDto txCodeDto = sendUserInfo(userVo);
            if(!"0".equals(txCodeDto.getCode())){
                log.info("启动人脸核身--上送合作方用户信息异常,异常原因为:[{}]]",txCodeDto.getMsg());
                return requestUrl;
            }
            //获取h5/geth5faceid 接口返回的唯一标识
            String h5faceId = txCodeDto.getResult().getH5faceId();
            //获取32位随机数
            String nonce = getRandom();
            //获取nonceTicket
            String nonceTicket = getNonceTicket(accessToken, userId);
            //启动人脸核身计算签名
            String sign = faceSign(orderNo, userId, nonceTicket,h5faceId,nonce);
            //成功拉起人脸识别并识别成功或失败后的回调路径
            String path = "http://127.0.0.1:8080/#/start?state=";
            log.debug("人脸核身通过后的回调地址-拼接路径加密前:url = [{}]",path);
          String url = getURLEncoderString(path);
            log.debug("人脸核身通过后的回调地址-拼接路径加密后:url = [{}]",url);
         requestUrl = "https://ida.webank.com/api/web/login?webankAppId="+wbappid+"&version=1.0.0&nonce="+nonce+"&orderNo="+orderNo+"&h5faceId="+h5faceId+"&url="+url+"&userId="+userId+"&sign="+sign+"&from="+userVo.getFrom()+"";
        } catch (Exception e) {
            log.error("启动人脸核身异常,异常原因为:[{}]",e.getMessage());
        }
        log.info("启动人脸核身--请求路径为:[{}]]",requestUrl);
        return requestUrl;
    }
postMan调用示例:

参数:姓名、身份证号、from(App || browser)

H5人脸核身结果跳转
验证结果之前端获取结果验证签名
/**
     * 前端获取结果验证签名
     * @param checkVo
     */
    @Override
    public String checkSign(CheckVo checkVo) {
        //获取accessToken
        String accessToken = getToken();
        //获取signTicket
        String signTicket = getSignTicket(accessToken);
        List<String> list = new ArrayList<>();
        list.add(wbappid);
        list.add(checkVo.getOrderNo());
        list.add(checkVo.getCode());
        String sign = getSign(list, signTicket);
        log.info("前端获取结果验证签名值为:[{}]",sign);
        return sign;
    }
服务端验证结果
/**
     * 服务端验证结果
     * @param checkVo
     * @return
     */
    @Override
    public ServerResultDto serverCheck(CheckVo checkVo) {
        //注意,随机数需要保持一致
        checkVo.setRandom(getRandom());
        String sign = serverSign(checkVo);
        Map<String, String> param = new HashMap<>(16);
        String url = "https://idasc.webank.com/api/server/sync?app_id={app_id}&nonce={nonce}&order_no={order_no}&version=1.0.0&sign={sign}&get_file={get_file}";

        param.put("app_id", wbappid);
        param.put("nonce", checkVo.getRandom());
        param.put("order_no", checkVo.getOrderNo());
        param.put("sign", sign);
        param.put("get_file", "1");
        log.debug("服务端验证结果参数有:[{}]", param);
        TxServerDto txServerDto = this.template.getForObject(url,TxServerDto.class,param);
        if (!"0".equals(txServerDto.getCode())) {
            log.error("服务端验证结果信息错误,errorCde:{},errMessage:{}", txServerDto.getCode(), txServerDto.getMsg());
            return null;
        }
        return txServerDto.getResult();
    }
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: 阿里云人脸活体检测是一种基于人工智能技术的人脸识别技术,通过对用户的面部进行实时检测和分析,以验证用户的真实性和活体性。在H5示例中,我们可以使用阿里云人脸活体检测的API接口,将其嵌入到网页中,实现人脸活体检测的功能。 具体步骤如下: 1. 在阿里云开发者平台上创建自己的应用,获取对应的Access Key和Secret Key。 2. 引入阿里云人脸活体检测SDK,在html文件中添加相应的引用。 3. 在需要进行人脸活体检测的地方,添加一个用于显示摄像头画面的画布元素。 4. 编写JavaScript代码,调用阿里云人脸活体检测的API接口。可以使用ajax等方式将用户的摄像头画面上传给阿里云,同时接收阿里云返回的检测结果。 5. 根据API返回的结果,进行相应的处理,如判断用户是否为真实人脸,是否存在动作等。 6. 根据具体需求,可自定义提示语、显示结果等,例如显示“活体检测通过”或“请眨眼”等文字提示。 7. 给予用户适当的反馈,如成功通过活体检测后跳转到另一页,或在检测失败时显示错误提示信息等。 8. 最后,在应用结束时,可调用相关API接口释放资源,避免资源占用。 通过以上步骤,可以实现将阿里云人脸活体检测接入H5示例,使网页能够进行人脸活体检测功能的展示。这样可以帮助开发者更好地应用人脸活体检测技术,提升用户的安全性和用户体验。 ### 回答2: 阿里云人脸活体检测是一种通过识别用户的面部特征以确定其真实性和活跃度的技术。阿里云提供了人脸活体检测接入H5示例,以方便开发者将此功能集成到自己的网页应用中。 首先,开发者需要在阿里云人脸识别控制台创建一个人脸活体检测API实例,并获取相应的API密钥和密钥对应的API密钥ID。 其次,开发者需要在网页应用的代码中引入阿里云人脸识别的JS SDK。开发者可以通过CDN引入阿里云人脸识别的JS SDK,也可以将SDK下载到本地并引入。 接着,开发者需要在网页应用的代码中创建一个用于展示人脸活体检测结果的HTML元素,例如一个div元素。 然后,开发者需要初始化阿里云人脸识别JS SDK,并设置密钥和密钥ID。 最后,开发者需要编写代码来调用阿里云人脸活体检测API,并将检测结果展示在之前创建的HTML元素中。开发者可以通过监听用户在网页中进行的操作(例如点击按钮)来触发人脸活体检测操作,然后将用户的面部特征传递给阿里云人脸识别API进行验证。 总体来说,通过引入阿里云人脸识别的JS SDK,并按照官方文档提供的示例代码进行配置和调用,开发者可以轻松地将阿里云人脸活体检测功能接入到自己的网页应用中。这样,开发者就可以在网页上实时验证用户的真实性和活跃度,提高网站的安全性和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值