百度AI的使用:解析身份证
百度API提供的几个工具类
解析身份证需要百度应用ID(clientId)和百度应用的秘钥(clientSecret)。附官网链接地址
package com.test.www;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.JSONObject;
import com.test.util.BaiDu_Base64Util;
import com.test.util.HttpUtil_BaiDu;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.jpay.util.StringUtils;
@Controller
@RequestMapping("/upload")
public class upload {
private static final Logger logger = LoggerFactory.getLogger(upload.class);
//百度解析身份证的接口地址
private static String idcardIdentificate = "https://aip.baidubce.com/rest/2.0/ocr/v1/idcard";
//百度解析身份获取token地址
private static String authHost = "https://aip.baidubce.com/oauth/2.0/token";
//官网获取的 API Key
private static String clientId = "***********NquAegus****";
//官网获取的 Secret Key
private static String clientSecret = "XfPMY5Rgi*************Avsng1yK";
/**
* 上传图片
* @param request
* @param response
* @param file
* @param idCardType 身份证正反面
* @param idCard 身份证
* @param name 姓名
* @param sex 性别
* @return 自己组装数据
*/
@RequestMapping(value = "/upload")
@ResponseBody
public result uploadImage(HttpServletRequest request, HttpServletResponse response,
@RequestParam(value = "file", required = false) MultipartFile file,
@RequestParam(value = "idCardType", required = true) String idCardType,
@RequestParam(value = "idCard", required = true) String idCard,
@RequestParam(value = "name", required = true) String name,
@RequestParam(value = "sex", required = true) String sex) {
if (!file.isEmpty() || StringUtils.isNotBlank(idCardType)) {
String fileName = file.getOriginalFilename();
String path = null;
String imgType = null;
imgType = Files.getFileExtension(fileName).toUpperCase();
if ("PNG".equals(imgType) || "JPG".equals(imgType) || "BMP".equals(imgType)) {
// 验证身份证信息
long begin = System.currentTimeMillis();
result resultJson = validateIdCard(file,
idCardType.equals("front") ? "front" : "back",
idCard, name, sex);
long end = System.currentTimeMillis();
logger.info("==========验证身份证花费时间:" + (end - begin) / 1000 + "s");
//判断验证身份证是否成功
if (!resultJson.boo) {
return resultJson;
}
// 根路径
String realPath = request.getSession().getServletContext().getRealPath("/");
// 文件名字
String trueFileName = idCard + "_" + idCardType + "." + imgType;
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
String dateString = sdf.format(new Date());
// 存放路径
String relativePath = "uploads" + File.separator + "idCard" + File.separator
+ dateString + File.separator;
path = realPath + relativePath;
try {
// 创建存放的文件
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
path += trueFileName;
File f = new File(path);
file.transferTo(f);
path = URLDecoder.decode(path, "UTF-8");
logger.info("图片存放的路径为:" + path);
return new result(Boolean.TRUE, relativePath + trueFileName, "上传成功!");
} catch (IllegalStateException | IOException e) {
logger.error("", e);
return new result(Boolean.FALSE, null, "图片上传失败!");
}
} else {
logger.info("图片类型不匹配!");
return new result(Boolean.FALSE, null, "图片类型不匹配!");
}
} else {
logger.info("图片为空!");
return new result(Boolean.FALSE, null, "图片为空!");
}
}
/**
* 验证上传身份证的正确性
*
* @return
*/
private result validateIdCard(MultipartFile file, String idCardSide, String idCard,
String name, String sex) {
String accessToken = getAuth();
String result = null;
try {
byte[] imgData = file.getBytes();
String imgStr = BaiDu_Base64Util.encode(imgData);
// 识别身份证正面id_card_side=front,识别身份证背面id_card_side=back;
String params = "id_card_side=" + idCardSide + "&" + URLEncoder.encode("image", "UTF-8")
+ "=" + URLEncoder.encode(imgStr, "UTF-8");
result = HttpUtil_BaiDu.post(idcardIdentificate, accessToken, params);
JSONObject jsonObject = JSONObject.parseObject(result);
// 身份证正面
if (idCardSide.equals("front")) {
JSONObject wordsResult = jsonObject.getJSONObject("words_result");
Map<String, String> resultMap = getMapByFront(wordsResult);
logger.info("解析正面的信息为:", resultMap);
if (resultMap.isEmpty()) {
return new result(Boolean.FALSE, null, "解析正面失败!");
}
if (StringUtils.isEmpty(resultMap.get("name"))) {
return new result(Boolean.FALSE, null, "解析姓名失败!");
}
if (StringUtils.isEmpty(resultMap.get("sex"))) {
return new result(Boolean.FALSE, null, "解析姓别失败!");
}
if (StringUtils.isEmpty(resultMap.get("card"))) {
return new result(Boolean.FALSE, null, "解析证件号码失败!");
}
if (!resultMap.get("name").equals(name)) {
return new result(Boolean.FALSE, null, "姓名不符!");
}
if (!resultMap.get("sex").equals(sex)) {
return new result(Boolean.FALSE, null, "姓别不符!");
}
if (!resultMap.get("card").equals(idCard)) {
return new result(Boolean.FALSE, null, "证件号码不符!");
}
return new result(Boolean.TRUE, resultMap, "解析正面成功!");
} else {
// 身份证反面
JSONObject wordsResult = jsonObject.getJSONObject("words_result");
Map<String, String> resultMap = getMapByBlack(wordsResult);
if (resultMap.isEmpty()) {
return new result(Boolean.FALSE, null, "解析反面失败!");
}
if (StringUtils.isBlank(resultMap.get("organization"))) {
return new result(Boolean.FALSE, null, "签发机关解析失败!");
}
if (StringUtils.isBlank(resultMap.get("endDate"))) {
return new result(Boolean.FALSE, null, "结束日期解析失败!");
}
if (StringUtils.isBlank(resultMap.get("beginDate"))) {
return new result(Boolean.FALSE, null, "开始时间解析失败!");
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Date endDate = sdf.parse(resultMap.get("endDate"));
// 身份证过期
if (new Date().after(endDate)) {
return new result(Boolean.FALSE, null, "证件已经过期!");
} else {
return new result(Boolean.TRUE, resultMap, "解析反面成功!");
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 解析身份证反面信息
*
* @param wordsResult
* @return
*/
public static HashMap<String, String> getMapByFront(JSONObject wordsResult) {
HashMap<String, String> map = Maps.newHashMap();
try {
Set<String> set = wordsResult.keySet();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String key = it.next();
JSONObject result = wordsResult.getJSONObject(key);
String value = result.getString("words");
switch (key) {
case "姓名":
map.put("name", value);
break;
case "民族":
map.put("nation", value);
break;
case "住址":
map.put("address", value);
break;
case "公民身份号码":
map.put("card", value);
break;
case "出生":
map.put("birth", value);
break;
case "性别":
map.put("sex", value);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
/**
* 解析身份证反面信息
*
* @param wordsResult
* @return
*/
public static HashMap<String, String> getMapByBlack(JSONObject wordsResult) {
HashMap<String, String> map = new HashMap<String, String>();
try {
Set<String> set = wordsResult.keySet();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String key = it.next();
JSONObject result = wordsResult.getJSONObject(key);
String value = result.getString("words");
switch (key) {
case "签发机关":
map.put("organization", value);
break;
case "失效日期":
map.put("endDate", value);
break;
case "签发日期":
map.put("beginDate", value);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
/**
* 获取权限token
*
* @return 返回示例: { "access_token":
* "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567",
* "expires_in": 2592000 }
*/
public String getAuth() {
String auth = getAuth(clientId, clientSecret);
if(StringUtils.isEmpty(auth)){
return getAuth(clientId, clientSecret);
}else{
return auth;
}
}
/**
* 获取API访问token 该token有一定的有效期,需要自行管理,当失效时需重新获取.
*
* @param ak - 百度云官网获取的 API Key
* @param sk - 百度云官网获取的 Securet Key
* @return assess_token 示例:
* "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"
*/
public String getAuth(String ak, String sk) {
String getAccessTokenUrl = authHost
// 1. grant_type为固定参数
+ "?grant_type=client_credentials"
// 2. 官网获取的 API Key
+ "&client_id=" + ak
// 3. 官网获取的 Secret Key
+ "&client_secret=" + sk;
try {
URL realUrl = new URL(getAccessTokenUrl);
// 打开和URL之间的连接
HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
connection.setRequestMethod("GET");
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
System.err.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
BufferedReader in =
new BufferedReader(new InputStreamReader(connection.getInputStream()));
String result = "";
String line;
while ((line = in.readLine()) != null) {
result += line;
}
/**
* 返回结果示例
*/
System.err.println("result:" + result);
JSONObject jsonObject = JSONObject.parseObject(result);
String access_token = jsonObject.getString("access_token");
return access_token;
} catch (Exception e) {
System.err.printf("获取token失败!");
e.printStackTrace(System.err);
}
return null;
}
/**
* 组装结果集
*/
@SuppressWarnings("unused")
class result {
private boolean boo = true;
private Object result;
private String messages;
public result(boolean boo, Object result, String messages) {
this.boo = boo;
this.result = result;
this.messages = messages;
}
}
}