
腾讯云 人脸核身接口 移动浮层H5接入
最近接触到了这个功能,下面看代码。
·
最近接触到了这个功能,下面看代码
主要工具类
public class FacialTools {
private static double expireTimeToken;
private static double expireTimeTicket;
private static final String access_token_url = "https://miniprogram-kyc.tencentcloudapi.com/api/oauth2/access_token";
private static final String api_ticket_url = "https://miniprogram-kyc.tencentcloudapi.com/api/oauth2/api_ticket";
private static final String geth5faceid_url = "https://miniprogram-kyc.tencentcloudapi.com/api/server/h5/geth5faceid";
private static final String ADVFACE_URL = "https://miniprogram-kyc.tencentcloudapi.com/api/server/getAdvFaceId";
private static final String queryfacerecord_url = "https://miniprogram-kyc.tencentcloudapi.com/api/v2/base/queryfacerecord";
private static String accessToken = "hie-bro!!";
private static String signTicket = "hie-bro!!!";
//设置wbappid等参数
private static final String app_id = "*******";
private static final String secret = "********";
private static final String grant_type = "client_credential";
private static final String version = "1.0.0";
public static final String type = "SIGN";
public static final String userId = "*********";//子账户id
public static void main(String[] args) throws Exception {
// System.out.println(FacialTools.getSignTicket(FacialTools.getAccessToken()));
}
/**
* 1.获取AccessToken
* Access Token 必须缓存在磁盘,并定时刷新,且不能并发刷新,
* 建议每20分钟请求新的 Access Token,获取之后立即使用最新的 Access Token。
* 旧的只有一分钟的并存期。
*
* 此方法会判断内存中现有的accessToken是否失效,如果没有失效就不会发送新的请求----
*/
public static String getAccessToken() throws Exception {
if (FacialTools.tokenIsExpired()){//判断是否超时
FacialTools.getAccessTokenByUrl();
}
return FacialTools.accessToken;
}
private static void getAccessTokenByUrl() throws Exception{
// 请求链接
String accessTokenUrl = access_token_url
+ "?app_id=" + app_id
+ "&secret=" + secret
+ "&grant_type=" + grant_type
+ "&version=" + version;
JSONObject accessTokenObj = HttpHelper.doGet(accessTokenUrl);
AccessTokenEntity accessToken = JSON.parseObject(accessTokenObj.toJSONString(), AccessTokenEntity.class);
FacialTools.expireTimeToken = Double.parseDouble(accessToken.getExpire_time());
FacialTools.accessToken = accessToken.getAccessToken();
}
/**
* 2.获取SignTicket
* SignTicket 必须缓存在磁盘,并定时刷新,且不能并发刷新,
* 建议每20分钟请求新的 SignTicket,获取之后立即使用最新的 SignTicket。
* 旧的只有一分钟的并存期。
*/
public static String getSignTicket(String accessToken) throws Exception{
if (FacialTools.ticketIsExpired()){
FacialTools.getSignTicketByUrl(accessToken);
}
return FacialTools.signTicket;
}
private static void getSignTicketByUrl(String accessToken) throws Exception {
// 请求链接
String accessTokenUrl = api_ticket_url
+"?app_id=" + app_id
+"&access_token=" + accessToken
+"&type=" + type
+"&version=" + version;
JSONObject signTicketObj = HttpHelper.doGet(accessTokenUrl);
SiginTicketEntity siginTicketEntity = JSON.parseObject(signTicketObj.toJSONString(), SiginTicketEntity.class);
SiginTicket siginTicket = siginTicketEntity.getTickets().get(0);
FacialTools.expireTimeTicket = Double.parseDouble(siginTicket.getExpire_time());
FacialTools.signTicket = siginTicket.getValue();
}
/**
* 3. 生成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(FacialTools.app_id);
// userId
list.add(userId);
// version
list.add("1.0.0");
// 32位随机数
list.add(nonce);
// 生成签名
String sign = FacialTools.sign(list, signTicket);
System.out.println("=======sign:"+sign);
return sign;
}
/**
* 4. 调用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) throws Exception {
JSONObject jsonObject = new JSONObject();
jsonObject.put("appId", FacialTools.app_id);
jsonObject.put("orderNo", orderNo);
jsonObject.put("name", name);
jsonObject.put("idNo", idCard);
jsonObject.put("userId", userId);
jsonObject.put("version", FacialTools.version);
jsonObject.put("sign", ticketSign);
jsonObject.put("nonce", nonce);
// post请求
JSONObject h5faceidResult = HttpHelper.doPost(ADVFACE_URL+"?orderNo="+orderNo, jsonObject);
FaceidRsultEntity faceidRsultEntity = JSON.parseObject(h5faceidResult.toJSONString(), FaceidRsultEntity.class);
return faceidRsultEntity;
}
/**
* 5. 获取NONCE ticket
* @param accessToken
* @param userId
* @return
*/
public static SiginTicketEntity getNonceTicket(String accessToken, String userId) throws Exception{
// 请求链接
String accessTokenUrl = api_ticket_url
+"?app_id=" + FacialTools.app_id
+"&access_token=" + accessToken
+"&type=" + FacialTools.type
+"&version=" + FacialTools.version
+"&user_id=" + userId;
JSONObject signTicketObj = HttpHelper.doGet(accessTokenUrl);
SiginTicketEntity siginTicketEntity = JSON.parseObject(signTicketObj.toJSONString(), SiginTicketEntity.class);
return siginTicketEntity;
}
/**
* 6. 生成Nonce签名
* @param orderNo
* @param userId
* @param faceId
* @param noceTicketSign
* @param nonce
* @return
*/
public static String getNonceTicketSign(String orderNo, String userId, String faceId, String noceTicketSign, String nonce){
// 获取SIGN ticket
List<String> list = new ArrayList<>();
// wbappid
list.add(FacialTools.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 = FacialTools.sign(list, noceTicketSign);
System.out.println("=======sign:"+sign);
return sign;
}
/**
* 7. 生成“启动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(FacialTools.app_id);
sb.append("&version=").append(FacialTools.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();
}
/**
* 8、人脸核身结果查询接口(升级)
* @param orderNo 订单号,字母/数字组成的字符串,是您需要查询结果的人脸核身订单号
* @param ticketSign 签名值,使用本页第一步生成的签名
* @param nonce 随机数
* 附加参数 getFile 是否需要获取人脸识别的视频和文件,值为1则返回视频和照片、值为2则返回照片、值为3则返回视频;其他则不返回
* 附加参数 queryVersion 查询接口版本号(传1.0则返回 sdk 版本号和 trtc 标识)
* @return
* @throws Exception
*/
public static FaceidRsultEntity getFacialResult(String orderNo, String ticketSign, String nonce) throws Exception {
JSONObject jsonObject = new JSONObject();
jsonObject.put("appId", FacialTools.app_id);
jsonObject.put("orderNo", orderNo);
jsonObject.put("version", FacialTools.version);
jsonObject.put("sign", ticketSign);
jsonObject.put("nonce", nonce);
// post请求
JSONObject h5faceidResult = HttpHelper.doPost(queryfacerecord_url+"?orderNo="+orderNo, jsonObject);
FaceidRsultEntity faceidRsultEntity = JSON.parseObject(h5faceidResult.toJSONString(), FaceidRsultEntity.class);
return faceidRsultEntity;
}
/**
* 9. 生成SIGN ticket签名--- [8、人脸核身结果查询接口(升级)]专用
* @param orderNo 唯一订单流水号
* @param signTicket Sign ticket获取的值
* @param nonce 32位随机数
* @return
*/
public static String getSignTicketSignForQuery(String orderNo, String signTicket, String nonce){
// 获取SIGN ticket
//WBappid、orderNo、version、ticket、nonce
List<String> list = new ArrayList<>();
// wbappid
list.add(FacialTools.app_id);
// orderNo
list.add(orderNo);
// version
list.add("1.0.0");
// 32位随机数
list.add(nonce);
// 生成签名
String sign = FacialTools.sign(list, signTicket);
System.out.println("=======sign:"+sign);
return sign;
}
/**
* 签名公共方法
* @param values
* @param ticket
* @return
*/
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();
}
/**
* 判断是否超时
* @return
*/
private static boolean tokenIsExpired(){
Date date = new Date(); // 返回当前时间戳格式
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyyMMddHHmmss"); // 改变格式
double now = Double.parseDouble(dateFormat.format(date));
return now>FacialTools.expireTimeToken;
}
private static boolean ticketIsExpired(){
Date date = new Date(); // 返回当前时间戳格式
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyyMMddHHmmss"); // 改变格式
double now = Double.parseDouble(dateFormat.format(date));
return now>FacialTools.expireTimeTicket;
}
}
http请求工具类
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
/**
* HTTP请求封装,建议直接使用sdk的API
*/
public class HttpHelper {
/**
* @desc :1.发起GET请求
*
* @param url
* @return JSONObject
* @throws Exception
*/
public static JSONObject doGet(String url) throws Exception {
//1.生成一个请求
HttpGet httpGet = new HttpGet(url);
//2.配置请求的属性
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build();//2000
httpGet.setConfig(requestConfig);
//3.发起请求,获取响应信息
//3.1 创建httpClient
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
try {
//3.2 发起请求,获取响应信息
response = httpClient.execute(httpGet, new BasicHttpContext());
//如果返回结果的code不等于200,说明出错了
if (response.getStatusLine().getStatusCode() != 200) {
System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+ ", url=" + url);
return null;
}
//4.解析请求结果
HttpEntity entity = response.getEntity(); //reponse返回的数据在entity中
if (entity != null) {
String resultStr = EntityUtils.toString(entity, "utf-8"); //将数据转化为string格式
System.out.println("GET请求结果:"+resultStr);
JSONObject result = JSON.parseObject(resultStr); //将String转换为 JSONObject
if(result.getInteger("errcode")==null) {
return result;
}else if (0 == result.getInteger("errcode")) {
return result;
}else {
System.out.println("request url=" + url + ",return value=");
System.out.println(resultStr);
int errCode = result.getInteger("errcode");
String errMsg = result.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/** 2.发起POST请求
* @desc :
*
* @param url 请求url
* @param data 请求参数(json)
* @return
* @throws Exception JSONObject
*/
public static JSONObject doPost(String url, Object data) throws Exception {
//1.生成一个请求
HttpPost httpPost = new HttpPost(url);
//2.配置请求属性
//2.1 设置请求超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(100000).setConnectTimeout(100000).build();
httpPost.setConfig(requestConfig);
//2.2 设置数据传输格式-json
httpPost.addHeader("Content-Type", "application/json");
//2.3 设置请求实体,封装了请求参数
StringEntity requestEntity = new StringEntity(JSON.toJSONString(data), "utf-8");
httpPost.setEntity(requestEntity);
//3.发起请求,获取响应信息
//3.1 创建httpClient
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
try {
//3.3 发起请求,获取响应
response = httpClient.execute(httpPost, new BasicHttpContext());
if (response.getStatusLine().getStatusCode() != 200) {
System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+ ", url=" + url);
return null;
}
//获取响应内容
HttpEntity entity = response.getEntity();
if (entity != null) {
String resultStr = EntityUtils.toString(entity, "utf-8");
System.out.println("POST请求结果:"+resultStr);
//解析响应内容
JSONObject result = JSON.parseObject(resultStr);
if(result.getInteger("errcode")==null) {
return result;
}else if (0 == result.getInteger("errcode")) {
return result;
}else {
System.out.println("request url=" + url + ",return value=");
System.out.println(resultStr);
int errCode = result.getInteger("errcode");
String errMsg = result.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* @desc : 3.上传文件
*
* @param url 请求url
* @param file 上传的文件
* @return
* @throws Exception JSONObject
*/
public static JSONObject uploadMedia(String url, File file) throws Exception {
HttpPost httpPost = new HttpPost(url);
CloseableHttpResponse response = null;
CloseableHttpClient httpClient = HttpClients.createDefault();
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).build();
httpPost.setConfig(requestConfig);
//2.3 设置请求实体,封装了请求参数
HttpEntity requestEntity = MultipartEntityBuilder.create().addPart("media",
new FileBody(file, ContentType.create("multipart/form-data", Consts.UTF_8), file.getName())).build();
//FileEntity requestEntity = new FileEntity(file,ContentType.MULTIPART_FORM_DATA);
httpPost.setEntity(requestEntity);
try {
response = httpClient.execute(httpPost, new BasicHttpContext());
if (response.getStatusLine().getStatusCode() != 200) {
System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+ ", url=" + url);
return null;
}
HttpEntity entity = response.getEntity();
if (entity != null) {
String resultStr = EntityUtils.toString(entity, "utf-8");
JSONObject result = JSON.parseObject(resultStr);
//上传临时素材失败
if (result.getInteger("errcode") != null && 0 != result.getInteger("errcode") ) {
System.out.println("request url=" + url + ",return value=");
System.out.println(resultStr);
int errCode = result.getInteger("errcode");
String errMsg = result.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
//上传临时素材成功
}else {
//result.remove("errcode");
//result.remove("errmsg");
return result;
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* @desc : 上传PDF
* 见微信电子发票章节
* 9. 向用户提供发票或其它消费凭证PDF
*
* @param url
* @param file
* @return
* @throws Exception
* JSONObject
*/
public static JSONObject uploadPDF(String url, File file) throws Exception {
HttpPost httpPost = new HttpPost(url);
CloseableHttpResponse response = null;
CloseableHttpClient httpClient = HttpClients.createDefault();
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).build();
httpPost.setConfig(requestConfig);
//2.3 设置请求实体,封装了请求参数
HttpEntity requestEntity = MultipartEntityBuilder.create().addPart("media",
new FileBody(file, ContentType.create("multipart/form-data", Consts.UTF_8), file.getName())).build();
httpPost.setEntity(requestEntity);
try {
response = httpClient.execute(httpPost, new BasicHttpContext());
if (response.getStatusLine().getStatusCode() != 200) {
System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+ ", url=" + url);
return null;
}
HttpEntity entity = response.getEntity();
if (entity != null) {
String resultStr = EntityUtils.toString(entity, "utf-8");
JSONObject result = JSON.parseObject(resultStr);
//上传临时素材成功
if (result.getString("errcode")== null) {
// 成功
//result.remove("errcode");
//result.remove("errmsg");
return result;
} else {
System.out.println("request url=" + url + ",return value=");
System.out.println(resultStr);
int errCode = result.getInteger("errcode");
String errMsg = result.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* @desc : 4.下载文件 -get
*
* @param url 请求url
* @param fileDir 下载路径
* @return
* @throws Exception File
*/
public static File downloadMedia(String url, String fileDir) throws Exception {
//1.生成一个请求
HttpGet httpGet = new HttpGet(url);
//2.配置请求属性
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(100000).setConnectTimeout(100000).build();
httpGet.setConfig(requestConfig);
//3.发起请求,获取响应信息
//3.1 创建httpClient
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
//4.设置本地保存的文件
//File file = new File(fileDir);
File file = null;
try {
//5. 发起请求,获取响应信息
response = httpClient.execute(httpGet, new BasicHttpContext());
System.out.println("HttpStatus.SC_OK:"+HttpStatus.SC_OK);
System.out.println("response.getStatusLine().getStatusCode():"+response.getStatusLine().getStatusCode());
System.out.println("http-header:"+JSON.toJSONString( response.getAllHeaders() ));
System.out.println("http-filename:"+getFileName(response) );
//请求成功
if(HttpStatus.SC_OK==response.getStatusLine().getStatusCode()){
//6.取得请求内容
HttpEntity entity = response.getEntity();
if (entity != null) {
//这里可以得到文件的类型 如image/jpg /zip /tiff 等等 但是发现并不是十分有效,有时明明后缀是.rar但是取到的是null,这点特别说明
System.out.println(entity.getContentType());
//可以判断是否是文件数据流
System.out.println(entity.isStreaming());
//6.1 输出流
//6.1.1获取文件名,拼接文件路径
String fileName=getFileName(response);
fileDir=fileDir+fileName;
file = new File(fileDir);
//6.1.2根据文件路径获取输出流
FileOutputStream output = new FileOutputStream(file);
//6.2 输入流:从钉钉服务器返回的文件流,得到网络资源并写入文件
InputStream input = entity.getContent();
//6.3 将数据写入文件:将输入流中的数据写入到输出流
byte b[] = new byte[1024];
int j = 0;
while( (j = input.read(b))!=-1){
output.write(b,0,j);
}
output.flush();
output.close();
}
if (entity != null) {
entity.consumeContent();
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
/**
* @desc : 5.下载文件 - post
*
* @param url 请求url
* @param data post请求参数
* @param fileDir 文件下载路径
* @return
* @throws Exception File
*/
public static File downloadMedia(String url, Object data, String fileDir) throws Exception {
//1.生成一个请求
HttpPost httpPost = new HttpPost(url);
//2.配置请求属性
//2.1 设置请求超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(100000).setConnectTimeout(100000).build();
httpPost.setConfig(requestConfig);
//2.2 设置数据传输格式-json
httpPost.addHeader("Content-Type", "application/json");
//2.3 设置请求参数
StringEntity requestEntity = new StringEntity(JSON.toJSONString(data), "utf-8");
httpPost.setEntity(requestEntity);
//3.发起请求,获取响应信息
//3.1 创建httpClient
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
//4.设置本地保存的文件
//File file = new File(fileDir);
File file = null;
try {
//5. 发起请求,获取响应信息
response = httpClient.execute(httpPost, new BasicHttpContext());
System.out.println("HttpStatus.SC_OK:"+HttpStatus.SC_OK);
System.out.println("response.getStatusLine().getStatusCode():"+response.getStatusLine().getStatusCode());
System.out.println("http-header:"+JSON.toJSONString( response.getAllHeaders() ));
System.out.println("http-filename:"+getFileName(response) );
//请求成功
if(HttpStatus.SC_OK==response.getStatusLine().getStatusCode()){
//6.取得请求内容
HttpEntity entity = response.getEntity();
if (entity != null) {
//这里可以得到文件的类型 如image/jpg /zip /tiff 等等 但是发现并不是十分有效,有时明明后缀是.rar但是取到的是null,这点特别说明
System.out.println(entity.getContentType());
//可以判断是否是文件数据流
System.out.println(entity.isStreaming());
//6.1 输出流
//6.1.1获取文件名,拼接文件路径
String fileName=getFileName(response);
fileDir=fileDir+fileName;
file = new File(fileDir);
//6.1.2根据文件路径获取输出流
FileOutputStream output = new FileOutputStream(file);
//6.2 输入流:从钉钉服务器返回的文件流,得到网络资源并写入文件
InputStream input = entity.getContent();
//6.3 将数据写入文件:将输入流中的数据写入到输出流
byte b[] = new byte[1024];
int j = 0;
while( (j = input.read(b))!=-1){
output.write(b,0,j);
}
output.flush();
output.close();
}
if (entity != null) {
entity.consumeContent();
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
/** 5. 获取response header中Content-Disposition中的filename值
* @desc :
*
* @param response 响应
* @return String
*/
public static String getFileName(HttpResponse response) {
Header contentHeader = response.getFirstHeader("Content-Disposition");
String filename = null;
if (contentHeader != null) {
HeaderElement[] values = contentHeader.getElements();
if (values.length == 1) {
NameValuePair param = values[0].getParameterByName("filename");
if (param != null) {
try {
//filename = new String(param.getValue().toString().getBytes(), "utf-8");
//filename=URLDecoder.decode(param.getValue(),"utf-8");
filename = param.getValue();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return filename;
}
}
AccessTokenEntity
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AccessTokenEntity extends FaceBaseEntity {
/**
* 是否成功
*/
private Boolean success;
/**
* access_token 的值
*/
private String accessToken;
/**
* access_token 失效的绝对时间
*/
private int expire_in;
/**
* access_token 的最大生存时间
*/
private String expire_time;
// public Boolean getSuccess() {
// return success;
// }
// public void setSuccess(Boolean success) {
// this.success = success;
// }
// public String getAccessToken() {
// return accessToken;
// }
//
// public void setAccessToken(String accessToken) {
// this.accessToken = accessToken;
// }
//
// public int getExpire_in() {
// return expire_in;
// }
//
// public void setExpire_in(int expire_in) {
// this.expire_in = expire_in;
// }
//
// public String getExpire_time() {
// return expire_time;
// }
//
// public void setExpire_time(String expire_time) {
// this.expire_time = expire_time;
// }
}
FaceBaseEntity
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class FaceBaseEntity {
/**
* 0:成功
* 非0:失败
*/
private String code;
/**
* 请求结果描述
*/
private String msg;
/**
* 调用接口的时间
*/
private String transactionTime;
// public String getCode() {
// return code;
// }
//
// public void setCode(String code) {
// this.code = code;
// }
//
// public String getMsg() {
// return msg;
// }
//
// public void setMsg(String msg) {
// this.msg = msg;
// }
//
// public String getTransactionTime() {
// return transactionTime;
// }
//
// public void setTransactionTime(String transactionTime) {
// this.transactionTime = transactionTime;
// }
}
FaceDetectUserVO
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class FaceDetectUserVO {
private String name;//姓名
private String idNo;//证件号码
private String userId;//用户 ID ,用户的唯一标识(不能带有特殊字符),需要跟生成签名的 userId 保持一致
private String from = "browser";//来源 App || browser)
private String orderNo;
private String returnUrl;//人脸核身结束后的回调url
}
FaceidRsultEntity
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class FaceidRsultEntity extends FaceBaseEntity{
/**
* 请求业务流水号
*/
private String bizSeqNo;
/**
* 结果
*/
private ResultEntity result;
}
ResultEntity
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ResultEntity {
/**
* 请求业务流水号
*/
private String bizSeqNo;
/**
* 接口请求的时间
*/
private String transactionTime;
private String oriCode;
/**
* 订单编号
*/
private String orderNo;
/**
* 此次刷脸用户标识-pc端
*/
private String h5faceId;
/**
* 此次刷脸用户标识-移动端
*/
private String faceId;
/**
* 启动 H5 人脸核身步骤中调用 login 接口使用的域名
*/
private String optimalDomain;
/**
* 请求是否成功
*/
private Boolean success;
}
SiginTicket
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class SiginTicket {
//ticket_string
private String value;
// 有效时间/秒
private String expire_in;
//截至过期时间
private String expire_time;
}
SiginTicketEntity
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
@Setter
@Getter
public class SiginTicketEntity {
/**
* 0:成功
* 非0:失败
*/
private String code;
/**
* 请求结果描述
*/
private String msg;
/**
* 调用接口的时间
*/
private String transactionTime;
private String bizSeqNo;
private List<SiginTicket> tickets = new ArrayList<>();
}
service层
@Override
public String facialNuclearBody(FaceDetectUserVO faceDetectUserVO) throws Exception {
try {
String orderNo = FacialTools.randomAlphanumeric();//获取32位随机数
String userId = FacialTools.userId;
String nonce = FacialTools.randomAlphanumeric();//获取32位随机数
String name = faceDetectUserVO.getName();
String idCard = faceDetectUserVO.getIdNo();
String from = "browser";
//1、获取 access_token
String accessToken = FacialTools.getAccessToken();
//2、获取 sign_ticket
String signTicket = FacialTools.getSignTicket(accessToken);
//3、生成 sign_ticket 签名
String ticketSign = FacialTools.getSignTicketSign(userId,signTicket,nonce);
//4、调用AdvFaceId接口---获取 faceId
FaceidRsultEntity faceidRsultEntity = FacialTools.getAdvFaceId(orderNo, name, idCard, userId, ticketSign, nonce);
String faceId = faceidRsultEntity.getResult().getFaceId();//移动端faceId
String optimalDomain = faceidRsultEntity.getResult().getOptimalDomain()==null?"kyc.qcloud.com":faceidRsultEntity.getResult().getOptimalDomain();//获取域名
//5、获取nonce_ticket签名
SiginTicketEntity siginTicketEntity = FacialTools.getNonceTicket(accessToken,userId);
String noceTicketSign = siginTicketEntity.getTickets().get(0).getValue();
//6、 生成Nonce签名---sign
String nonceSign = FacialTools.getNonceTicketSign(orderNo,userId,faceId,noceTicketSign,nonce);//nonce签名
//7. 生成“启动H5人脸核身”链接
String returnUrl = faceDetectUserVO.getReturnUrl();
String sendUrl = URLEncoder.encode(returnUrl);
String facialUrl = FacialTools.getLoginUrl(optimalDomain,nonce,orderNo,faceId,sendUrl,"",userId,nonceSign,from,"");
return facialUrl;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
更多推荐
所有评论(0)