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

news2024/11/17 11:30:23

一、概述

人脸识别,使用官方API:腾讯云人脸核身之独立H5接入。接口官方返回code = 0 表示成功,其他code码值均为对应码值信息,详见错误码。
注意:
1.合作方上送身份信息的计算签名参数与启动人脸核身计算签名参数不一致,有部分区别。
2.wbappid = webankAppId = app_id

二、合作方后台上送身份信息~实现流程

2.1. 前端入参

前端入参:客户身份证号、客户姓名、用户 ID (userId)、from(App || browser)
controller

    @Autowired
    private PCH5SendIdentityService pch5SendIdentityService;

    /**
     * 合作方后台上送身份信息 PC H5
     * 文档:https://cloud.tencent.com/document/product/1007/35893
     * <p>
     * 请求 URL:https://miniprogram-kyc.tencentcloudapi.com/api/server/h5/geth5faceid?orderNo=xxx
     * 请求方法:POST
     * 报文格式:Content-Type: application/json
     * </p>
     *
     * @param faceDetectUserVO 身份信息
     */
    @PostMapping("/sendH5IdentityInfoUserInfo")
    public TXH5IdentityInfoDTO sendH5IdentityInfoUserInfo(@RequestBody FaceDetectUserVO faceDetectUserVO) {
        return pch5SendIdentityService.sendH5IdentityInfoUserInfo(faceDetectUserVO);
    }

entity

@Data
@AllArgsConstructor
@NoArgsConstructor
public class FaceDetectUserVO {

    // https://cloud.tencent.com/document/product/1007/35893
    private String name;//姓名
    private String idNo;//证件号码
    private String userId;//用户 ID ,用户的唯一标识(不能带有特殊字符),需要跟生成签名的 userId 保持一致
    private String from;//来源 App || browser)
}

2.2. 后端固定参数

后端固定参数:wbappid = webankAppId = app_id(API中介绍命名不同,注意)、orderNo(可自定义随机生成不唯一)、userId(可自定义随机生成不唯一)、version

2.3. 获取 Access Token

https://cloud.tencent.com/document/product/1007/57603

 /**
     * 获取 access_token
     * 文档: https://cloud.tencent.com/document/product/1007/37304
     *
     * @return
     */
    @Override
    public String getAccessTokenTencent() {

        // 从redis中获取accessTokenTencent
        String accessTokenTencent = redisUtils.get("accessTokenTencent");
        log.info("获取redis中的accessToken,为:[{}]", accessTokenTencent);

        if (StringUtils.isEmpty(accessTokenTencent)) {
            String accessTokenUrl = String.format(TencentCloudConfig.ACCESS_TOKEN_URL, appId, secret);
            String jsonStr = HttpUtil.doGet(accessTokenUrl, null);

            log.info("返回报文;->{}", jsonStr);
            Map<String, String> jsonMap = ConvertUtils.stringToMap(jsonStr);

            if (!"0".equals(jsonMap.get("code"))) {
                String msg = jsonMap.get("msg");
                log.error("获取腾讯token信息错误,code:{},msg:{}", jsonMap.get("code"), msg);
                GraceJSONResult.errorMsg(msg);
                /**
                 * 错误响应示例:
                 * {
                 *     "code": "66660000",
                 *     "msg": "请求参数异常",
                 *     "bizSeqNo": "22090720001184453210262184859700",
                 *     "transactionTime": "20220907102621",
                 *     "success": false,
                 *     "expire_in": 0
                 * }
                 */
            }
            /**
             * 正确响应示例:
             * {
             *  "code":"0","msg":"请求成功",
             *  "transactionTime":"20151022043831",
             *  "access_token":"accessToken_string",
             *  "expire_time":"20151022043831",
             *  "expire_in":"7200"
             * }
             */
            // 获取 access_token
            accessTokenTencent = jsonMap.get("access_token");

            // 过期时间 默认7200L  设置6800L提前重新获取
            redisUtils.set("accessTokenTencent", accessTokenTencent, 6800L);
        }

        log.info("返回有效accessToken,为:[{}]", accessTokenTencent);
        return accessTokenTencent;
    }

2.4. 获取 SIGN ticket

https://cloud.tencent.com/document/product/1007/57613
通过token获取signTicket

 /**
     * 获取 SIGN ticket
     * 请求地址: http://localhost:9900/getSignTicketTencent
     * 文档: https://cloud.tencent.com/document/product/1007/37305
     *
     * @param accessTokenTencent access_token
     * @return
     */
    @Override
    public String getSignTicketTencent(String accessTokenTencent) {
        // 从redis中获取nonceTicketTencent
        String signTicketTencent = redisUtils.get("signTicketTencent");
        log.info("获取redis中的signTicketTencent,为:[{}]", signTicketTencent);

        String signTicketValue = null;
        if (StringUtils.isEmpty(signTicketTencent)) {
            String getSignTicketUrl = String.format(TencentCloudConfig.SIGN_TICKET_URL, appId, accessTokenTencent);
            String jsonStr = HttpUtil.doGet(getSignTicketUrl, null);
            log.info("返回报文;->{}", jsonStr);

            TicketDTO ticketDTO = JSON.parseObject(jsonStr, TicketDTO.class);
            if (!"0".equals(ticketDTO.getCode())) {
                String msg = ticketDTO.getMsg();
                log.error("获取腾讯signTicket信息错误,code:{},msg:{}", ticketDTO.getCode(), msg);
                GraceJSONResult.errorMsg(msg);
            }

            /**
             * 正确响应示例:
             * {
             *       "code": "0",
             *       "msg": "请求成功",
             *       "transactionTime": "20151022044027",
             *       "tickets": [
             *         {
             *              "value": "ticket_string",
             *              "expire_in": "3600",
             *              "expire_time": "20151022044027"
             *         }
             *     ]
             * }
             */
            signTicketValue = ticketDTO.getTickets().get(0).getValue();
            // 过期时间 默认3600L  设置3200L提前重新获取
            redisUtils.set("signTicketTencent", signTicketValue, 3000L);
        }

        return signTicketValue;
    }

2.5. 生成签名

计算合作方上送身份信息签名,参数有:wbappid、orderNo、name、idNo、userId、version、signTicket
在这里插入图片描述
计算签名

  /**
     * PC 端 H5 接入 > 合作方上送身份信息计算签名
     * 文档地址:https://cloud.tencent.com/document/product/1007/35893
     *
     * @param faceDetectUserVO
     * @param signTicket
     * @return
     */
    public String signH5(FaceDetectUserVO faceDetectUserVO, String signTicket) {

        //为计算签名做准备
        //为计算签名做准备
        List<String> list = new ArrayList<>();
        list.add(appId);
        list.add(faceDetectUserVO.getOrderNo());
        list.add(faceDetectUserVO.getName());
        list.add(faceDetectUserVO.getIdNo());
        list.add(faceDetectUserVO.getUserId());
        list.add(TencentCloudConfig.VERSION);
        return SignUtils.getSign(list, signTicket);
    }

2.6. 合作方后台上送身份信息

/**
     * 合作方后台上送身份信息 PC H5
     * 文档:https://cloud.tencent.com/document/product/1007/35893
     * <p>
     * 请求 URL:https://miniprogram-kyc.tencentcloudapi.com/api/server/h5/geth5faceid?orderNo=xxx
     * 请求方法:POST
     * 报文格式:Content-Type: application/json
     * </p>
     *
     * @param faceDetectUserVO 身份信息
     * @return
     */
    @Override
    public TXH5IdentityInfoDTO sendH5IdentityInfoUserInfo(FaceDetectUserVO faceDetectUserVO) {
        //获取accessToken
        String accessToken = commonIdentityService.getAccessTokenTencent();
        //获取signTicket
        String signTicket = commonIdentityService.getSignTicketTencent(accessToken);
        //订单号
        String orderNo = SignUtils.GenerateRandom32Number(32);
        faceDetectUserVO.setOrderNo(orderNo);
        //合作方上送计算签名
        String sign = signH5(faceDetectUserVO, signTicket);

        Map<String, String> param = new HashMap<>(16);
        param.put("webankAppId", appId);
        param.put("orderNo", orderNo);
        param.put("name", faceDetectUserVO.getName());
        param.put("idNo", faceDetectUserVO.getIdNo());
        param.put("userId", faceDetectUserVO.getUserId());
        param.put("version", TencentCloudConfig.VERSION);
        param.put("sign", sign);

        log.debug("合作方上送身份信息参数有:[{}]", param);
        String getFaceidUrl = String.format(TencentCloudConfig.GET_H5_FACEID_URL, orderNo);
        String jsonStr = HttpUtil.doPost(getFaceidUrl, JSON.toJSONString(param));
        log.info("返回报文;->{}", jsonStr);

        TXH5IdentityInfoDTO txh5IdentityInfoDTO = JSON.parseObject(jsonStr, TXH5IdentityInfoDTO.class);
        log.info("合作方上送身份信息接口返回:[{}]", txh5IdentityInfoDTO);
        return txh5IdentityInfoDTO;
    }


三、启动H5人脸核身

3.1. 获取h5faceId

在合作方成功上送身份信息后,可以获取到h5faceId

3.2. 获取nonce

(32位随机数)

3.3. 获取nonceTicket

获取nonceTicket(通过token & userId)

3.4. 计算启动签名

https://cloud.tencent.com/document/product/1007/61074
计算启动H5人脸核身签名,参数有:wbappid、orderNo、userId、version、h5faceId、nonce、nonceTicket
在这里插入图片描述

   /**
     * 启用 H5 人脸认证 人脸核身计算签名
     * 文档:https://cloud.tencent.com/document/product/1007/35894
     *
     * @param orderNo     订单号,字母/数字组成的字符串,本次人脸验证合作伙伴上送的订单号,唯一标识
     * @param userId      用户 ID ,用户的唯一标识(不要带有特殊字符)
     * @param nonceTicket 合作伙伴服务端实时获取的 tikcet,注意是 NONCE 类型
     * @param h5faceId    h5/geth5faceid 接口返回的唯一标识
     * @param nonce       随机数:32位随机串(字母+数字组成的随机数)
     * @return
     */
    private String faceSignH5(String orderNo, String userId, String nonceTicket, String h5faceId, String nonce) {

        //为计算签名做准备
        List<String> list = new ArrayList<>();
        list.add(appId);
        list.add(orderNo);
        list.add(userId);
        list.add(TencentCloudConfig.VERSION);
        list.add(h5faceId);
        list.add(nonce);
        String sign = SignUtils.getSign(list, nonceTicket);
        log.info("启动人脸核身返回签名为:[{}]", sign);
        return sign;
    }

3.5. 构建回调页面链接

将成功拉起人脸核身验证通过后的回调页面链接配置至配置文件,同时对该链接进行encode编码
获取到所有拉起人脸核身所需参数后,向链接https://ida.webank.com/api/web/login拼接上参数:webankAppId、version、nonce、orderNo、h5faceId、url、sign、from、userId。例如:

https://ida.webank.com/api/web/login?webankAppId=%s&version=1.0.0&nonce=%s&orderNo=%s&h5faceId=%s&url&userId=%s&sign=%s&from=%s

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


    /**
     * 构造人脸核身获取启动链接
     * 文档:https://cloud.tencent.com/document/product/1007/35894
     *
     * @param faceDetectUserVO
     * @return
     */
    @Override
    public GraceJSONResult startCheckFace(FaceDetectUserVO faceDetectUserVO) {
        //随机生成32位唯一用户ID和订单ID
        String userId = SignUtils.GenerateRandom32Number(32);
        String orderNo = SignUtils.GenerateRandom32Number(32);
        faceDetectUserVO.setOrderNo(orderNo);
        faceDetectUserVO.setUserId(userId);
        String requestUrl = "";
        try {

            //获取accessToken
            String accessToken = commonIdentityService.getAccessTokenTencent();
            //上送合作方用户信息
            TXH5IdentityInfoDTO txh5IdentityInfoDTO = sendH5IdentityInfoUserInfo(faceDetectUserVO);

            if (!"0".equals(txh5IdentityInfoDTO.getCode())) {
                String msg = txh5IdentityInfoDTO.getMsg();
                log.info("启动人脸核身--上送合作方用户信息异常,异常原因为:[{}]]", msg);
                GraceJSONResult.errorMsg(msg);
            }

            //获取h5/geth5faceid 接口返回的唯一标识
            String h5faceId = txh5IdentityInfoDTO.getResult().getH5faceId();

            //获取32位随机数
            String nonce = SignUtils.GenerateRandom32Number(32);

            //获取nonceTicket
            String nonceTicket = commonIdentityService.getNonceTicketTencent(accessToken, userId);

            //启动人脸核身计算签名
            String sign = faceSignH5(orderNo, userId, nonceTicket, h5faceId, nonce);

            //成功拉起人脸识别并识别成功或失败后的回调路径
            String oauthCallback = TencentCloudConfig.OAUTH_CALLBACK_URL;
            log.debug("人脸核身通过后的回调地址-拼接路径加密前:url = [{}]", oauthCallback);

            String oauthRedirectUrl = URLEncoder.encode(oauthCallback, "utf-8");
            log.debug("人脸核身通过后的回调地址-拼接路径加密后:url = [{}]", oauthRedirectUrl);

            /**
             * https://miniprogram-kyc.tencentcloudapi.com/api/pc/login?webankAppId=appId001
             * &version=1.0.0
             * &nonce=4bu6a5nv9t678m2t9je5819q46y9hf93
             * &orderNo=161709188560917432576916585
             * &h5faceId=wb04f10695c3651ce155fea7070b74c9
             * &url=https%3a%2f%2fcloud.tencent.com
             * &userId=23333333333333
             * &sign=5DD4184F4FB26B7B9F6DC3D7D2AB3319E5F7415F
             */
            requestUrl = String.format(TencentCloudConfig.REQUEST_URL, appId, nonce, orderNo, h5faceId, oauthRedirectUrl, userId, sign, faceDetectUserVO.getFrom());
        } catch (Exception e) {
            log.error("启动人脸核身异常,异常原因为:[{}]", e.getMessage());
        }
        log.info("启动人脸核身--请求路径为:[{}]]", requestUrl);
        return GraceJSONResult.ok(requestUrl);
    }

四、查询核身结果

4.1. 启动H5人脸核身

在这里插入图片描述
在这里插入图片描述

    /**
     * 前端获取结果验证签名
     * API:https://cloud.tencent.com/document/product/1007/61302
     *
     * @param orderNo 订单号,字母/数字组成的字符串,本次人脸核身合作伙伴上送的订单号,唯一标识
     * @return
     */
    private String getCheckSign(String orderNo) {
        //获取accessToken
        String accessToken = commonIdentityService.getAccessTokenTencent();

        //获取signTicket
        String signTicket = commonIdentityService.getSignTicketTencent(accessToken);
        List list = new ArrayList<>();
        list.add(appId);
        list.add(orderNo);
        list.add(TencentCloudConfig.VERSION);
        list.add(SignUtils.GenerateRandom32Number(32));
        String sign = SignUtils.getSign(list, signTicket);
        log.info("前端获取结果验证签名值为\"[{}]", sign);
        return sign;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/419722.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python-DQN代码阅读(13)

目录 1.代码 1.1 代码阅读 1.2 代码分解 1.2.1 导入库 1.2.2 data np.loadtxt(performance.txt) 1.2.3 mva np.zeros((data.shape[0]), dtypenp.float) 1.2.4 mva[i] data[i,1]&#xff0c;mva[i] alpha * data[i,1] (1.0 - alpha) * mva[i-1] 1.2.5 plt.plot(data…

【C++项目】高并发内存池

前言&#xff1a; 本篇博客大致记录基于tcmalloc实现高并发内存池的思想与实现方案。 使用语言&#xff1a;C&#xff0c;编译器&#xff1a;vs2022&#xff0c;开始时间&#xff1a;2023/4/3&#xff0c;结束时间&#xff1a;2023/4/12。 项目源码地址&#xff1a;Cproject: 我…

第八天并发编程篇

一、简述线程、进程、程序的基本概念&#xff1f; 1.进程&#xff1a; 我们把运行中的程序叫做进程,每个进程都会占用内存与CPU资源,进程与进程之间互相独立. 2.线程&#xff1a; 线程就是进程中的一个执行单元&#xff0c;负责当前进程中程序的执行。一个进程可以包含多个线程…

【电子秤方案】LCD口袋秤芯片方案

LCD高精度口袋电子秤方案&#xff0c;即便携式称重仪&#xff0c;是一种应用于生活中的称重设备。便珠宝秤具有体积小、重量轻、功耗低、结构紧凑等特点。 LCD高精度口袋电子秤方案产品简介 口袋电子秤是一种体积小、重量轻、功耗低&#xff0c;可用于多种场合的电子秤。它通常…

如何检查 Linux 内存使用量是否耗尽?这5个命令堪称绝了!

在 Linux 操作系统中&#xff0c;内存是一个关键资源&#xff0c;用于存储正在运行的程序和操作系统本身的数据。如果系统的内存使用量过高&#xff0c;可能会导致性能下降、应用程序崩溃或者系统崩溃。因此&#xff0c;了解如何检查 Linux 内存使用量是否耗尽是非常重要的。下…

【网络安全】文件上传绕过思路

引言 分享一些文件上传绕过的思路&#xff0c;下文内容多包含实战图片&#xff0c;所以打码会非常严重&#xff0c;可多看文字表达&#xff1b;本文仅用于交流学习&#xff0c; 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人…

什么是划分子网?网络工程师划分子网有啥技巧?

随着互联网的快速发展&#xff0c;越来越多的组织和企业在其内部建立了复杂的网络系统来满足日常的信息传输和资源共享需求。而在这些网络系统中&#xff0c;划分子网&#xff08;也称为子网划分&#xff09;作为一种常见的网络管理方法&#xff0c;为组织和企业提供了更加灵活…

【面试】记一次安恒面试及总结

文章目录SQL 注入sql注入的原理&#xff1f;如何通过SQL注入判断对方数据库类型&#xff1f;补充一下其他方法判断数据库类型时间盲注的函数XPath注入抓不到http/https包&#xff0c;怎么办&#xff1f;app无自己的ssl证书app有自己的ssl证书-证书绑定(SSL pinning)逻辑漏洞有哪…

【学习笔记】滑动窗口

acwing.滑动窗口https://www.acwing.com/problem/content/156/ 给定一个大小为 n≤106≤106 的数组。 有一个大小为 k 的滑动窗口&#xff0c;它从数组的最左边移动到最右边。 你只能在窗口中看到 k 个数字。 每次滑动窗口向右移动一个位置。 以下是一个例子&#xff1a; …

Python使用Opencv进行图像人脸、眼睛识别实例演示

效果展示 下面使用 haarcasecade_eye.xml 进行人眼识别的效果图&#xff1a; 人脸识别是一种可以自动检测图像或视频中存在的人脸的技术。它可以用于各种应用&#xff0c;例如安全控制&#xff0c;自动标记照片和视频&#xff0c;以及人脸识别解锁设备等。在这篇博客中&#…

水声功率放大器模块基于通道接收和发射的水声通信机的应用

实验名称&#xff1a;基于多通道接收和发射的水声通信机 研究方向&#xff1a;水声通信 测试设备&#xff1a;数模转化器、ATA-ML180水声功率放大器模块、示波器、接收换能器、发射换能器等。 图&#xff1a;实验原理 一、发射机的双通道发送实验&#xff1a; 实验过程&#xf…

Redis与本地缓存组合使用(IT枫斗者)

Redis与本地缓存组合使用 前言 我们开发中经常用到Redis作为缓存&#xff0c;将高频数据放在Redis中能够提高业务性能&#xff0c;降低MySQL等关系型数据库压力&#xff0c;甚至一些系统使用Redis进行数据持久化&#xff0c;Redis松散的文档结构非常适合业务系统开发&#xf…

探索六西格玛在医疗行业的应用,提升医疗企业的市场竞争力

六西格玛是一种基于数据的管理方法&#xff0c;旨在通过对医疗流程和服务进行量化分析和改进&#xff0c;以优化医疗企业的运营和管理。它能够有效地解决医疗企业面临的各种问题和挑战&#xff0c;提高医疗服务的质量和效率&#xff0c;降低医疗成本和风险&#xff0c;增强医疗…

Linux: 性能分析之内存增长和泄漏

文章目录1. 前言2. 背景3. 内存增长和泄漏分析方法3.1 跟踪 malloc(), free() 等接口3.1.1 用 perf 采样3.1.2 用 ebpf 来跟踪3.2 跟踪 brk() 调用3.2.1 使用 perf 跟踪 brk()3.2.2 使用 ebpf 跟踪 brk()3.3 跟踪 mmap() 调用3.3.1 使用 perf 跟踪 mmap()3.3.2 使用 ebpf 跟踪 …

【FPGA】多功能ALU

目录 实验要求 源代码 顶层模块 数据输入模块 ALU运算模块 结果处理模块 扫描数码管模块 扫描数码管顶层 分频器 数码管显示 仿真代码 结构层图 管脚配置 实验板卡&#xff1a;xc7a100tlc sg324-2L&#xff0c;共20个开关 实验要求 通过高低位控制&#xff0c;实现32位数…

74-快速排序——一路快排

快速排序是影响二十世纪最伟大的排序算法之一。 JDK的双轴快速排序就是对快排的优化&#xff0c;本质还是快排。 从待排序区间选择一个数&#xff0c;作为基准值/分区点&#xff08;pivot&#xff09;&#xff0c;此时默认选择数组的第一个元素作为比较的基准值。partition&a…

【 SpringBoot 配置⽂件 】

文章目录一、配置⽂件作⽤二、配置文件格式2.1 特殊说明2.2 为配置⽂件安装提示插件三、properties 配置⽂件说明3.1 properties 基本语法3.2 读取配置⽂件3.3 解决 properties 中文乱码3.4 properties 缺点分析四、yml 配置⽂件说明4.1 yml 基本语法4.2 yml 配置读取4.3 yml 使…

前后端分离——SpringBoot+Vue——3天速成企业级项目

前后端分离——SpringBootVue使用到的技术&#xff1a;vue3&#xff08;区别vue2&#xff09;前言vue2 vs vue3双向绑定更新实例化生命周期获取props数据和方法的定义watchEffect那么什么是 watchEffect &#xff1f;组件通信注意attrs和listeners路由vue3路由写法&#xff1a;…

ROS学习——艰辛的环境安装之路一VMware

文章目录VMware 安装下载安装VMware 安装 一些没用的介绍&#xff1a; VMware Workstation中文版是一个“虚拟 PC”软件。它使你可以在一台机器上同时运行二个或更多 Windows、DOS、LINUX 系统。与“多启动”系统相比&#xff0c;VMWare 采用了完全不同的概念。多启动系统在一…

《Web前端应用开发》考试试卷(模拟题)

一、产品搜索页面 打开“考试文件夹”中的input.html&#xff0c;完成以下步骤&#xff1a; 注意&#xff1a;本题仅能在input.html的&#xff08;1&#xff09;为产品名称所在的div添加样式属性&#xff0c;使得产品名称保持在文本框的左边&#xff1b; &#xff08;2&#xf…