java实现腾讯云人脸核身pc端和移动端(浏览器)H5接入

PC端H5接入

  1. 获取AccessToken
    作 用: 后续获取签名和接口调用都会用到。
    注意事项: Access Token 必须缓存在磁盘,并定时刷新,且不能并发刷新,建议每20分钟请求新的 Access Token,获取之后立即使用最新的 Access Token。旧的只有一分钟的并存期。
  2. 获取SignTicket
    作 用: 制作签名用到,签名用在后面接口中
    注意事项: 和AccessToken一样
  3. 根据SignTicket生成签名(用于geth5faceid接口)
  4. 调用geth5faceid接口
  5. 获取NonceTicket
  6. 获取H5人脸认证签名
  7. 获取“启动H5人脸合身”链接
    注意事项: 随机数和上面生成签名的随机数保持一致
  • 代码是按照上面7个步骤排列来处理的
  • 代码中用到的HttpClient请求请参考另外一篇文章:http://t.csdn.cn/gQNP9
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.facedetection.faceVerify.entity.AccessTokenEntity;
import com.example.facedetection.faceVerify.entity.FaceidRsultEntity;
import com.example.facedetection.faceVerify.entity.SiginTicketEntity;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import java.io.UnsupportedEncodingException;
import java.util.*;
/**
 * @author kxz
 * @title FaceVerifyPcUtil
 * @Description: 人脸核身Pc端调用工具类(包含部分移动端共用方法)
 * @date 2022/7/9
 */
public class FaceVerifyPcUtil {
    private static String access_token_url = "https://miniprogram-kyc.tencentcloudapi.com/api/oauth2/access_token";
    private static String api_ticket_url = "https://miniprogram-kyc.tencentcloudapi.com/api/oauth2/api_ticket";
    private static String geth5faceid_url = "https://miniprogram-kyc.tencentcloudapi.com/api/server/h5/geth5faceid";
    public static String accessToken = "WAA0f-dGGlQHTVClazkxtmW6FX_nRhpUB01QpWs5MbZluhUFn7WNPkTDcYYesaX-iJtc09MkkN152qd9It4AsQ8Mwg";
    public static String signTicket = "bqpmxJrLtmJYk8BRN9RXhQPeaeWygLEf8QwpPHugBhBURaaLvBYAbXwJXU5NICK7";
    public static void main(String[] args) throws UnsupportedEncodingException {
        // 1.获取AccessToken
        AccessTokenEntity accessTokenEntity = getAccessToken();
        accessToken = accessTokenEntity.getAccessToken();
        System.out.println("====accessToken:"+accessToken);
        // 2.获取签名
        SiginTicketEntity siginTicketEntity = FaceVerifyPcUtil.getSignTicket(FaceVerifyPcUtil.accessToken);
        signTicket = siginTicketEntity.getTickets().get(0).getValue();
        System.out.println("====signTicket:"+signTicket);
    }

    /**
     * 1.获取AccessToken
     * Access Token 必须缓存在磁盘,并定时刷新,且不能并发刷新,
     * 建议每20分钟请求新的 Access Token,获取之后立即使用最新的 Access Token。
     * 旧的只有一分钟的并存期。
     */
    public static AccessTokenEntity getAccessToken(){
        // 请求链接
        String accessTokenUrl = access_token_url
                +"?app_id=" + FaceConfig.APP_ID
                +"&secret=" + FaceConfig.SECRET
                +"&grant_type=" + FaceConfig.GRANT_TYPE
                +"&version=" + FaceConfig.VERSION;
        String accessTokenObj = HttpClientUtil.doGet(accessTokenUrl, "utf-8");

        AccessTokenEntity accessToken = JSON.parseObject(accessTokenObj, AccessTokenEntity.class);
        return accessToken;
    }
    /**
     * 2.获取SignTicket
     * SignTicket 必须缓存在磁盘,并定时刷新,且不能并发刷新,
     * 建议每20分钟请求新的 SignTicket,获取之后立即使用最新的 SignTicket。
     * 旧的只有一分钟的并存期。
      */
    public static SiginTicketEntity getSignTicket(String accessToken){
        // 请求链接
        String accessTokenUrl = api_ticket_url
                        +"?app_id=" + FaceConfig.APP_ID
                        +"&access_token=" + accessToken
                        +"&type=" + FaceConfig.TYPE_SIGN
                        +"&version=" + FaceConfig.VERSION;
        String signTicketObj = HttpClientUtil.doGet(accessTokenUrl, "utf-8");
        SiginTicketEntity siginTicketEntity = JSON.parseObject(signTicketObj, SiginTicketEntity.class);
        return siginTicketEntity;
    }

    // 3. 生成签名(用于geth5faceid接口)
    public static String getSignTicketSign(String orderNo, String userId, String userName, String idCard, String signTicket){
        // 获取SIGN ticket
        List<String> list = new ArrayList<>();
        // wbappid
        list.add(FaceConfig.APP_ID);
        // orderNo
        list.add(orderNo);
        // name
        list.add(userName);
        // idNo
        list.add(idCard);
        // userId
        list.add(userId);
        // version
        list.add("1.0.0");
        // 生成签名
        String sign = sign(list, signTicket);
        System.out.println("=======sign:"+sign);
        return sign;
    }

    // 4. 调用geth5faceid接口
    //    API ticket 的 NONCE 类型,其有效期为120秒,且一次性有效,即每次启动 SDK 刷脸都要重新请求 NONCE ticket。
    public static FaceidRsultEntity getH5faceid(String name, String idCard, String userId, String orderNo, String sign){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("webankAppId", FaceConfig.APP_ID);
        jsonObject.put("name", name);
        jsonObject.put("orderNo", orderNo);
        jsonObject.put("idNo", idCard);
        jsonObject.put("userId", userId);
        jsonObject.put("version", FaceConfig.VERSION);
        jsonObject.put("sign", sign);
        System.out.println(jsonObject.toString());
        String h5faceidResult = HttpClientUtil.doPost(geth5faceid_url+"?orderNo="+orderNo, jsonObject);
        FaceidRsultEntity faceidRsultEntity = JSON.parseObject(h5faceidResult, FaceidRsultEntity.class);
        return faceidRsultEntity;
    }

    // 5. 获取NONCE ticket
    public static SiginTicketEntity getNonceTicket(String accessToken, String userId){
        // 请求链接
        String accessTokenUrl = api_ticket_url
                +"?app_id=" + FaceConfig.APP_ID
                +"&access_token=" + accessToken
                +"&type=" + FaceConfig.TYPE_NONCE
                +"&version=" + FaceConfig.VERSION
                +"&user_id=" + userId;
        String signTicketObj = HttpClientUtil.doGet(accessTokenUrl, "utf-8");
        SiginTicketEntity siginTicketEntity = JSON.parseObject(signTicketObj, SiginTicketEntity.class);
        return siginTicketEntity;
    }
    // 6. 获取H5人脸认证签名
    public static String getNonceTicketSgin(String orderNo, String userId, String h5faceId, String nonceTicket, String nonce){
        // 获取SIGN ticket
        List<String> list = new ArrayList<>();
        // wbappid
        list.add(FaceConfig.APP_ID);
        // version
        list.add(FaceConfig.VERSION);
        // orderNo
        list.add(orderNo);
        // userId
        list.add(userId);
        // h5faceId
        list.add(h5faceId);
        // nonce 随机数:32位随机串(字母+数字组成的随机数)

        list.add(nonce);
        // 生成签名
        String sign = sign(list, nonceTicket);
        System.out.println(sign);
        return sign;
    }
    // 7. 获取“启动H5人脸合身”链接
    public static String getH5Login(String optimalDomain, String userId, String orderNo, String h5faceId, String url, String signNonce, String nonce) {
        String h5Url = "https://"+optimalDomain+"/api/pc/login"
                + "?webankAppId=" + FaceConfig.APP_ID
                + "&version=" + FaceConfig.VERSION
                + "&nonce="+nonce
                + "&orderNo=" + orderNo
                + "&h5faceId=" + h5faceId
                + "&url=" + url
                + "&userId=" + userId
                + "&sign=" + signNonce;
        System.out.println("=========h5Url:"+h5Url);
        return h5Url;
    }
    // 签名公共方法
    protected static String sign(List<String> values, String ticket) { //values传ticket外的其他参数
        if (values == null) {
            throw new NullPointerException("values is null");
        }
        values.removeAll(Collections.singleton(null));// remove null
        values.add(ticket);
        java.util.Collections.sort(values);

        StringBuilder sb = new StringBuilder();
        for (String s : values) {
            sb.append(s);
        }
        return Hashing.sha1().hashString(sb, Charsets.UTF_8).toString().toUpperCase();
    }
    // 获取任意长度随机字符串
    public static String randomAlphanumeric(){
        String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        //指定字符串长度,拼接字符并toString
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 32; i++) {
            //获取指定长度的字符串中任意一个字符的索引值
            int number = random.nextInt(str.length());
            //根据索引值获取对应的字符
            char charAt = str.charAt(number);
            sb.append(charAt);
        }
        System.out.println("===========32位字符串:"+sb.toString());
        return sb.toString();
    }
}

移动端H5接入

  • 基本和Pc端步骤一样,只是个别调用接口名称和参数及返回值名称做了改变。
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.facedetection.faceVerify.entity.FaceidRsultEntity;
import java.util.ArrayList;
import java.util.List;

/**
 * @author kxz
 * @title FaceVerifyModUtils
 * @Description: 仅包含移动端独有方法,公用方法调用FaceVerifyPCUtil
 * @date 2022/7/11
 */
public class FaceVerifyModUtils {
    private static String ADVFACE_URL = "https://miniprogram-kyc.tencentcloudapi.com/api/server/getAdvFaceId";
    // 1. 获取Sign ticket--与pc端共用,此处略
    /**
     * 2. 生成SIGN ticket签名
     * @param userId 用户 ID ,用户的唯一标识(不要带有特殊字符)
     * @param signTicket Sign ticket获取的值
     * @param nonce 32位随机数
     * @return
     */
    public static String getSignTicketSign(String userId, String signTicket, String nonce){
        // 获取SIGN ticket
        List<String> list = new ArrayList<>();
        // wbappid
        list.add(FaceConfig.APP_ID);
        // userId
        list.add(userId);
        // version
        list.add("1.0.0");
        // 32位随机数
        list.add(nonce);
        // 生成签名
        String sign = FaceVerifyPcUtil.sign(list, signTicket);
        System.out.println("=======sign:"+sign);
        return sign;
    }

    /**
     * 3. 调用AdvFaceId接口
     * @param orderNo 订单号,字母/数字组成的字符串,每次(同一次人脸核身)唯一,不能超过32位
     * @param name 姓名
     * @param idCard 证件号码
     * @param userId 用户 ID ,用户的唯一标识(不能带有特殊字符),需要跟生成签名的 userId 保持一致
     * @param ticketSign 签名:使用上面生成的签名
     * @param nonce 随机数(和上面签名随机数保持一致)
     * @return
     */
    public static FaceidRsultEntity getAdvFaceId(String orderNo, String name, String idCard, String userId, String ticketSign, String nonce){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("appId", FaceConfig.APP_ID);
        jsonObject.put("orderNo", orderNo);
        jsonObject.put("name", name);
        jsonObject.put("idNo", idCard);
        jsonObject.put("userId", userId);
        jsonObject.put("version", FaceConfig.VERSION);
        jsonObject.put("sign", ticketSign);
        jsonObject.put("nonce", nonce);
        // post请求
        String h5faceidResult = HttpClientUtil.doPost(ADVFACE_URL+"?orderNo="+orderNo, jsonObject);
        FaceidRsultEntity faceidRsultEntity = JSON.parseObject(h5faceidResult, FaceidRsultEntity.class);
        return faceidRsultEntity;
    }
    // 4. 获取NonceTicket-使用pc端的,此处略
    // 5. 生成Nonce签名
    public static String getNonceTicketSign(String orderNo, String userId, String faceId, String noceTicketSign, String nonce){
        // 获取SIGN ticket
        List<String> list = new ArrayList<>();
        // wbappid
        list.add(FaceConfig.APP_ID);
        // orderNo
        list.add(orderNo);
        // userId
        list.add(userId);
        // faceId
        list.add(faceId);
        // version
        list.add("1.0.0");
        // 32位随机数
        list.add(nonce);
        // 生成签名
        String sign = FaceVerifyPcUtil.sign(list, noceTicketSign);
        System.out.println("=======sign:"+sign);
        return sign;
    }

    /**
     * 6. 生成“启动H5人脸核身”链接
     * @param optimalDomain 必填;使用getAdvFaceId接口返回的 optimalDomain 域名
     * @param nonce 必填;随机数:32位随机串(字母 + 数字组成的随机数),需与Nonce签名保持一致
     * @param orderNo 必填;订单号,字母/数字组成的字符串,每次唯一,此信息为本次人脸核身上送的信息,不能超过32位
     * @param faceId 必填;getAdvFaceId接口返回的唯一标识
     * @param url 必填;H5 人脸核身完成后回调的第三方 URL,需要第三方提供完整 URL 且做 URL Encode
     * @param resultType 非必填;是否显示结果页面,参数值为“1”时直接跳转到 url 回调地址,null 或其他值跳转提供的结果页面
     * @param userId 必填;用户 ID ,用户的唯一标识(不要带有特殊字符)
     * @param noceSign 必填;签名:使用上面Nonce生成的签名
     * @param from 必填;browser:表示在浏览器启动刷脸;App:表示在 App 里启动刷脸,默认值为 App;公众号属于浏览器
     * @param redirectType 非必填;跳转模式,参数值为“1”时,刷脸页面使用 replace 方式跳转,不在浏览器 history 中留下记录;不传或其他值则正常跳转
     * @return
     */
    public static String getLoginUrl(String optimalDomain, String nonce, String orderNo, String faceId,
                                     String url, String resultType, String userId, String noceSign, String from,
                                     String redirectType){
        StringBuilder sb = new StringBuilder("https://");
        sb.append(optimalDomain).append("/api/web/login");
        sb.append("?webankAppId=").append(FaceConfig.APP_ID);
        sb.append("&version=").append(FaceConfig.VERSION);
        sb.append("&nonce=").append(nonce);
        sb.append("&orderNo=").append(orderNo);
        sb.append("&faceId=").append(faceId);
        sb.append("&url=").append(url);
        sb.append("&resultType=").append(resultType);
        sb.append("&userId=").append(userId);
        sb.append("&sign=").append(noceSign);
        sb.append("&from=").append(from);
        sb.append("&redirectType=").append(redirectType);
        System.out.println("=========h5Url:"+ sb);
        return sb.toString();
    }
}

付完整demo,开箱即用:https://download.csdn.net/download/just_you_java/86092683

参考文档:

  1. 腾讯云-PC 端 H5 接入
  2. 腾讯云-移动 H5 人脸核身介绍

你可能感兴趣的:(软件,java,腾讯云,人脸核身)