提交修改

This commit is contained in:
quyixiao 2026-06-04 01:40:28 +08:00
parent 206f836bc3
commit 88bfc16289

View File

@ -1,42 +1,530 @@
package com.heyu.api.controller.car; package com.heyu.api.controller.car;
import com.heyu.api.baidu.handle.traffic.BDriverLicenseHandle;
import com.heyu.api.baidu.request.traffic.BDriverLicenseRequest;
import com.heyu.api.controller.BaseController; import com.heyu.api.controller.BaseController;
import com.heyu.api.controller.ocr.BaiduOcrResult;
import com.heyu.api.data.annotation.EbAuthentication; import com.heyu.api.data.annotation.EbAuthentication;
import com.heyu.api.data.constants.ApiConstants; import com.heyu.api.data.constants.ApiConstants;
import com.heyu.api.data.utils.MapUtils;
import com.heyu.api.data.utils.R; import com.heyu.api.data.utils.R;
import com.heyu.api.data.utils.StringUtils; import com.heyu.api.data.utils.StringUtils;
import com.heyu.api.request.car.DriverLicenseRecognizeRequest; import com.heyu.api.request.car.DriverLicenseRecognizeRequest;
import org.springframework.beans.factory.annotation.Autowired; import com.heyu.api.resp.car.RecognizeDriverLicenseBackResp;
import com.heyu.api.resp.car.RecognizeDriverLicenseFaceResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* 驾驶证识别控制器
* <p>
* 对机动车驾驶证正页副页及电子驾驶证正页进行结构化识别
* 校验请求组装结果封装及异常处理均在 Controller 层完成
* </p>
* <p>
* 接口路径POST /driver/license/recognize
* </p>
* <p>
* 返回约定进入平台识别链路组装请求体之后一律 {@code R.ok()}若有异常则将详细提示写入 {@code msg}
* 仅入参校验失败时返回 {@code R.error()}未调用平台识别不计费
* </p>
*
* @author heyu
* @since 1.0.0
*/
@Slf4j
@RestController @RestController
@RequestMapping("/driver/license") @RequestMapping("/driver/license")
public class RecognizeDriverLicenseController extends BaseController { public class RecognizeDriverLicenseController extends BaseController {
@Autowired private static final String DRIVING_LICENSE_URI = "/rest/2.0/ocr/v1/driving_license";
private BDriverLicenseHandle bDriverLicenseHandle;
/** 平台错误码 → 对外原因说明(每条语义独立,便于客服判读) */
private static final Map<String, String> PLATFORM_ERROR_HINTS = new HashMap<>();
static {
PLATFORM_ERROR_HINTS.put("17", "本接口当日累计调用次数已触达平台日配额上限,本次识别请求被拒绝");
PLATFORM_ERROR_HINTS.put("18", "单位时间请求过于密集,已触发平台 QPS 限流,请拉长调用间隔后重试");
PLATFORM_ERROR_HINTS.put("19", "平台侧总调用配额已耗尽,需运营侧扩容或次日再试");
PLATFORM_ERROR_HINTS.put("100", "提交的表单字段组合不符合驾驶证识别接口契约,请对照文档核对字段名与取值");
PLATFORM_ERROR_HINTS.put("110", "平台鉴权凭证校验未通过,属服务端配置异常,需运维刷新令牌");
PLATFORM_ERROR_HINTS.put("111", "平台鉴权凭证已超过有效期,属服务端配置异常,需运维重新签发");
PLATFORM_ERROR_HINTS.put("216100", "存在非法或与接口不匹配的参数项");
PLATFORM_ERROR_HINTS.put("216101", "影像入参缺失:未提供可用的 image 或 url 字段");
PLATFORM_ERROR_HINTS.put("216103", "单个参数字段长度超限(常见于 url 过长或 base64 体积过大)");
PLATFORM_ERROR_HINTS.put("216110", "当前应用未开通驾驶证识别能力或授权范围不包含本接口");
PLATFORM_ERROR_HINTS.put("216200", "解码后的图片数据为空,上传环节可能未完成或内容损坏");
PLATFORM_ERROR_HINTS.put("216201", "图片编码格式不在允许列表,仅支持 jpg、jpeg、png、bmp");
PLATFORM_ERROR_HINTS.put("216202", "像素尺寸或编码后体积不满足规范(边长 15~4096px编码后≤4M");
PLATFORM_ERROR_HINTS.put("216203", "引擎无法从当前画面中稳定提取驾驶证文本,多见于模糊、过曝或非证件照");
PLATFORM_ERROR_HINTS.put("216630", "证件版面识别失败,建议重拍并保证四角完整、无遮挡");
PLATFORM_ERROR_HINTS.put("282000", "平台识别引擎内部异常,属短暂性故障,可间隔数秒后重试");
}
@EbAuthentication(tencent = ApiConstants.TENCENT_AUTH) @EbAuthentication(tencent = ApiConstants.TENCENT_AUTH)
@PostMapping("/recognize") @PostMapping("/recognize")
public R recognize(DriverLicenseRecognizeRequest request) { public R recognize(DriverLicenseRecognizeRequest request) {
return BaiduOcrResult.raw(bDriverLicenseHandle.handle(toBaiduRequest(request))); long start = System.currentTimeMillis();
try {
String validateError = validateRequest(request);
if (validateError != null) {
log.info("[驾驶证识别] 阶段=入参校验 结论=拦截 说明=请求未进入识别链路(不计费) "
+ "入参摘要={} 对外提示摘要={}",
buildInputLogContext(request), abbreviate(validateError, 120));
return R.error(validateError);
}
String drivingLicenseSide = resolveDrivingLicenseSide(request);
String imageMode = resolveImageMode(request);
String inputContext = buildInputLogContext(request);
String content = buildRequestContent(request, drivingLicenseSide);
if (isBlank(content)) {
log.error("[驾驶证识别] 阶段=报文组装 结论=失败 目标页面={} 页面标签={} 影像模式={} "
+ "请求体字节长度=0 入参摘要={} 原因=未写入有效image或url节点",
drivingLicenseSide, sideLabel(drivingLicenseSide), imageMode, inputContext);
return okResult(drivingLicenseSide, formatHint(
"报文组装异常",
"识别请求体在序列化后未包含任何影像载荷,平台侧无法受理本次识别",
"请核对 imageBase64 是否已 urlencode、imageUrl 是否非空字符串;"
+ "请求头须为 application/x-www-form-urlencoded",
"目标页面=" + sideLabel(drivingLicenseSide) + ",影像模式=" + imageMode
), null);
}
int requestBodyLength = content.length();
log.info("[驾驶证识别] 阶段=平台调用 开始 目标页面={} 页面标签={} 影像模式={} "
+ "请求体字节长度={} 入参摘要={}",
drivingLicenseSide, sideLabel(drivingLicenseSide), imageMode, requestBodyLength, inputContext);
Map<String, Object> platformResult = requestBaidu(DRIVING_LICENSE_URI, content);
if (platformResult == null) {
log.error("[驾驶证识别] 阶段=平台调用 结论=无回执 目标页面={} 页面标签={} 影像模式={} "
+ "请求体字节长度={} 入参摘要={} 可能原因=链路超时/鉴权失败/响应不可解析",
drivingLicenseSide, sideLabel(drivingLicenseSide), imageMode, requestBodyLength, inputContext);
return okResult(drivingLicenseSide, formatHint(
"服务无回执",
"识别指令已下发,但在约定时间内未收到平台可解析的 JSON 回执",
"建议间隔 3~5 秒重试;若连续失败,请记录 traceId、调用时刻与 side 并联系技术支持排查链路",
"目标页面=" + sideLabel(drivingLicenseSide) + ",影像模式=" + imageMode
), null);
}
String hint = resolvePlatformHint(platformResult, drivingLicenseSide, inputContext, imageMode);
Object data = ApiConstants.back.equals(drivingLicenseSide)
? buildBackResp(platformResult)
: buildFaceResp(platformResult);
if (hint == null && isRecognizeDataEmpty(data)) {
log.info("[驾驶证识别] 阶段=字段映射 结论=全空 目标页面={} 页面标签={} 影像模式={} "
+ "入参摘要={} 平台回执摘要={} 已映射字段数=0 说明=回执结构正常但未抽取到任何业务字段",
drivingLicenseSide, sideLabel(drivingLicenseSide), imageMode,
inputContext, buildPlatformReceiptSummary(platformResult));
hint = formatHint(
"字段映射为空",
"平台回执已通过结构校验,但证号、姓名、准驾车型等结构化字段均未命中",
ApiConstants.back.equals(drivingLicenseSide)
? "副页识别请确认 side=back且画面包含「记录」「档案编号」等区域避免裁剪或反光"
: "正页识别请确认 side=face/front画面须包含完整证面电子驾驶证需保证截图清晰",
"目标页面=" + sideLabel(drivingLicenseSide) + ",已映射字段数=0"
);
}
long cost = System.currentTimeMillis() - start;
int mappedFieldCount = countMappedFields(data);
if (StringUtils.isNotBlank(hint)) {
log.info("[驾驶证识别] 阶段=请求结束 结论=成功(含业务提示) 目标页面={} 页面标签={} 影像模式={} "
+ "耗时={}ms 已映射字段数={} 入参摘要={} 平台回执摘要={} 对外提示摘要={}",
drivingLicenseSide, sideLabel(drivingLicenseSide), imageMode, cost, mappedFieldCount,
inputContext, buildPlatformReceiptSummary(platformResult), abbreviate(hint, 120));
} else {
log.info("[驾驶证识别] 阶段=请求结束 结论=成功 目标页面={} 页面标签={} 影像模式={} "
+ "耗时={}ms 已映射字段数={} 入参摘要={} 平台回执摘要={}",
drivingLicenseSide, sideLabel(drivingLicenseSide), imageMode, cost, mappedFieldCount,
inputContext, buildPlatformReceiptSummary(platformResult));
}
return okResult(drivingLicenseSide, hint, data);
} catch (Exception e) {
long cost = System.currentTimeMillis() - start;
String side = request != null ? resolveDrivingLicenseSide(request) : ApiConstants.front;
log.error("[驾驶证识别] 阶段=运行时 结论=未捕获异常 耗时={}ms 目标页面={} 页面标签={} 影像模式={} "
+ "入参摘要={} 异常类型={} 异常信息={}",
cost, side, sideLabel(side),
request != null ? resolveImageMode(request) : "未知",
buildInputLogContext(request),
e.getClass().getName(),
e.getMessage() != null ? e.getMessage() : "", e);
return okResult(side, formatHint(
"运行时故障",
"服务端在处理识别流程时抛出未预期异常,识别结果不可用",
"请勿重复高频重试;请保存 traceId、异常发生时间及 side由技术支持结合堆栈进一步定位",
"异常类型=" + e.getClass().getSimpleName()
+ (e.getMessage() != null ? ",摘要=" + e.getMessage() : "")
), null);
}
} }
private BDriverLicenseRequest toBaiduRequest(DriverLicenseRecognizeRequest request) { private String validateRequest(DriverLicenseRecognizeRequest request) {
BDriverLicenseRequest bRequest = new BDriverLicenseRequest();
if (request == null) { if (request == null) {
return bRequest; log.info("[驾驶证识别] 阶段=入参校验 结论=拒绝 原因=Spring未绑定到请求Bean "
+ "入参摘要=request=null 计费标记=未调用平台");
return formatHint(
"入参绑定失败",
"控制器未接收到可绑定的表单对象,所有业务字段均为空",
"请确认使用 POST 提交Content-Type 为 application/x-www-form-urlencoded"
+ "字段名与接口文档一致imageBase64 / imageUrl / side",
"绑定结果=DriverLicenseRecognizeRequest 为 null"
);
} }
bRequest.setImageBase64(request.getImageBase64()); if (isBlank(request.getImageBase64()) && isBlank(request.getImageUrl())) {
bRequest.setImageUrl(request.getImageUrl()); log.info("[驾驶证识别] 阶段=入参校验 结论=拒绝 原因=影像双字段皆空 入参摘要={} 计费标记=未调用平台",
if (StringUtils.isNotBlank(request.getSide())) { buildInputLogContext(request));
bRequest.setDrivingLicenseSide(ApiConstants.face.equals(request.getSide()) ? ApiConstants.front : request.getSide()); return formatHint(
"影像源缺失",
"imageBase64 与 imageUrl 均未提供,识别引擎没有可处理的图像输入",
"任选其一:① imageBase64 传 jpg/jpeg/png/bmp 的 base64urlencode 后≤4M"
+ "② imageUrl 传可公网直连的 HTTPS/HTTP 地址≤1024 字符,关闭防盗链)",
"side=" + (isBlank(request.getSide()) ? "未传(将按正页处理)" : request.getSide().trim())
);
} }
return bRequest; if (StringUtils.isNotBlank(request.getImageBase64()) && StringUtils.isNotBlank(request.getImageUrl())) {
log.info("[驾驶证识别] 阶段=入参兼容 说明=Base64与URL同时存在按规范丢弃URL仅保留Base64流 入参摘要={}",
buildInputLogContext(request));
}
if (resolveDrivingLicenseSide(request) == null) {
log.info("[驾驶证识别] 阶段=入参校验 结论=拒绝 原因=side非法 入参摘要={} 计费标记=未调用平台",
buildInputLogContext(request));
return formatHint(
"页面标识无效",
"参数 side 的取值无法映射到驾驶证正页或副页识别模式",
"正页(含纸质正页、电子驾驶证正页)请传 face 或 front"
+ "副页(含实习记录等)请传 back",
"当前 side=" + request.getSide() + ",合法取值=face|front|back"
);
}
return null;
}
private String resolveImageMode(DriverLicenseRecognizeRequest request) {
if (request == null) {
return "未知";
}
if (StringUtils.isNotBlank(request.getImageBase64())) {
return StringUtils.isNotBlank(request.getImageUrl()) ? "Base64优先(已忽略URL)" : "Base64";
}
if (StringUtils.isNotBlank(request.getImageUrl())) {
return "URL";
}
return "";
}
private String resolveDrivingLicenseSide(DriverLicenseRecognizeRequest request) {
if (request == null || isBlank(request.getSide())) {
return ApiConstants.front;
}
String side = request.getSide().trim();
if (ApiConstants.face.equals(side) || ApiConstants.front.equals(side)) {
return ApiConstants.front;
}
if (ApiConstants.back.equals(side)) {
return ApiConstants.back;
}
return null;
}
private String sideLabel(String drivingLicenseSide) {
return ApiConstants.back.equals(drivingLicenseSide) ? "副页(back)" : "正页(front/face)";
}
private String buildRequestContent(DriverLicenseRecognizeRequest request, String drivingLicenseSide) {
StringBuilder sb = new StringBuilder();
if (StringUtils.isNotBlank(request.getImageBase64())) {
sb.append("&image=").append(request.getImageBase64());
} else if (StringUtils.isNotBlank(request.getImageUrl())) {
sb.append("&url=").append(request.getImageUrl());
}
sb.append("&detect_direction=false");
sb.append("&driving_license_side=").append(drivingLicenseSide);
sb.append("&unified_valid_period=false");
sb.append("&quality_warn=false");
sb.append("&risk_warn=false");
return sb.toString();
}
private R okResult(String drivingLicenseSide, String hint, Object data) {
if (data == null) {
data = ApiConstants.back.equals(drivingLicenseSide)
? new RecognizeDriverLicenseBackResp()
: new RecognizeDriverLicenseFaceResp();
}
R result = StringUtils.isNotBlank(hint) ? R.ok(hint) : R.ok();
return result.setData(data);
}
private String resolvePlatformHint(Map<String, Object> platformResult, String drivingLicenseSide,
String inputContext, String imageMode) {
Object errorCodeObj = platformResult.get("error_code");
if (errorCodeObj != null) {
String errorCode = String.valueOf(errorCodeObj);
Object errorMsgObj = platformResult.get("error_msg");
String errorMsg = errorMsgObj != null ? errorMsgObj.toString() : "平台未返回文字描述";
String knownHint = PLATFORM_ERROR_HINTS.get(errorCode);
String category = resolveErrorCategory(errorCode);
log.error("[驾驶证识别] 阶段=平台回执 结论=业务拒绝 目标页面={} 页面标签={} 影像模式={} "
+ "错误分类={} 错误码={} 错误描述={} 是否命中本地错误码说明={} "
+ "入参摘要={} 平台回执摘要={}",
drivingLicenseSide, sideLabel(drivingLicenseSide), imageMode,
category, errorCode, errorMsg, knownHint != null,
inputContext, buildPlatformReceiptSummary(platformResult));
return formatHint(
category,
knownHint != null ? knownHint : "平台返回了未在本地维护的错误码,需结合错误描述人工判读",
buildPlatformErrorSuggestion(errorCode, drivingLicenseSide),
"错误码=" + errorCode + ",错误描述=" + errorMsg + ",目标页面=" + sideLabel(drivingLicenseSide)
);
}
if (isWordsResultEmpty(platformResult)) {
log.info("[驾驶证识别] 阶段=结果解析 结论=空集 目标页面={} 页面标签={} 影像模式={} "
+ "入参摘要={} 平台回执摘要={} 说明=回执中不存在可遍历的结构化结果节点",
drivingLicenseSide, sideLabel(drivingLicenseSide), imageMode,
inputContext, buildPlatformReceiptSummary(platformResult));
return formatHint(
"结构化结果缺失",
"平台回执未包含可解析的识别结果集合,无法进入字段映射环节",
"优先排查:① 上传内容是否为驾驶证对应页面;② side 是否与实物一致;"
+ "③ 使用 URL 时确保平台抓取节点可访问且无 403/302 拦截",
"目标页面=" + sideLabel(drivingLicenseSide) + ",解析状态=结果集为空"
);
}
return null;
}
private String resolveErrorCategory(String errorCode) {
if ("17".equals(errorCode)) {
return "日配额耗尽";
}
if ("18".equals(errorCode)) {
return "并发限流";
}
if ("19".equals(errorCode)) {
return "总配额耗尽";
}
if ("110".equals(errorCode) || "111".equals(errorCode)) {
return "鉴权失效";
}
if (errorCode.startsWith("2162")) {
return "影像不合规";
}
if ("282000".equals(errorCode)) {
return "引擎内部错误";
}
return "平台业务拒绝";
}
private String buildPlatformErrorSuggestion(String errorCode, String drivingLicenseSide) {
if ("17".equals(errorCode)) {
return "请安排次日再试,或联系运营提升日调用配额";
}
if ("18".equals(errorCode)) {
return "请在客户端增加限流/退避策略,避免瞬时并发过高";
}
if ("19".equals(errorCode)) {
return "请联系运营确认平台总配额与续费状态";
}
if ("110".equals(errorCode)) {
return "属服务端鉴权配置问题,需技术支持检查平台密钥与令牌缓存";
}
if ("111".equals(errorCode)) {
return "属服务端令牌过期,需技术支持重新获取并刷新缓存";
}
if ("216200".equals(errorCode)) {
return "请重新上传图片,确认 base64 未截断、未混入换行或非法字符";
}
if ("216201".equals(errorCode)) {
return "请将图片转为 jpg/jpeg/png/bmp 之一后重新编码上传";
}
if ("216202".equals(errorCode)) {
return "请压缩或裁剪图片保证最长边≤4096px、最短边≥15px且 urlencode 后≤4M";
}
if ("216203".equals(errorCode)) {
return "请在自然光下重拍确保证面占画面主体且文字可辨side=" + sideLabel(drivingLicenseSide);
}
if ("216630".equals(errorCode)) {
return "请平铺证件拍摄,避免手指遮挡关键字段;副页识别务必传 side=back";
}
if ("282000".equals(errorCode)) {
return "短暂性故障,建议 5~10 秒后单次重试,不宜连续轰炸接口";
}
return "请依据错误描述调整入参或影像后重试;持续失败请附带 traceId 联系技术支持";
}
@SuppressWarnings("unchecked")
private boolean isWordsResultEmpty(Map<String, Object> platformResult) {
Object wordsResult = platformResult.get("words_result");
if (wordsResult == null) {
return true;
}
if (wordsResult instanceof Map) {
return ((Map<String, Object>) wordsResult).isEmpty();
}
return false;
}
private boolean isRecognizeDataEmpty(Object data) {
if (data instanceof RecognizeDriverLicenseFaceResp) {
RecognizeDriverLicenseFaceResp r = (RecognizeDriverLicenseFaceResp) data;
return isBlank(r.getLicenseNumber()) && isBlank(r.getName()) && isBlank(r.getGender())
&& isBlank(r.getNationality()) && isBlank(r.getBirthDate()) && isBlank(r.getIssueDate())
&& isBlank(r.getVehicleType()) && isBlank(r.getAddress()) && isBlank(r.getIssueUnit())
&& isBlank(r.getStartDate()) && isBlank(r.getEndDate()) && isBlank(r.getAccumulatedPoints())
&& isBlank(r.getStatus()) && isBlank(r.getArchiveNumber()) && isBlank(r.getGenerateTime())
&& isBlank(r.getCurrentTime()) && isBlank(r.getBarcodeNumber());
}
if (data instanceof RecognizeDriverLicenseBackResp) {
RecognizeDriverLicenseBackResp r = (RecognizeDriverLicenseBackResp) data;
return isBlank(r.getName()) && isBlank(r.getRecord()) && isBlank(r.getCardNumber())
&& isBlank(r.getArchiveNumber());
}
return true;
}
private String formatHint(String category, String reason, String suggestion, String detail) {
StringBuilder sb = new StringBuilder();
sb.append("【驾驶证识别·").append(category).append("").append(reason);
if (StringUtils.isNotBlank(detail)) {
sb.append("|定位信息:").append(detail);
}
sb.append("|处置指引:").append(suggestion);
return sb.toString();
}
private String abbreviate(String text, int maxLen) {
if (text == null || text.length() <= maxLen) {
return text;
}
return text.substring(0, maxLen) + "...";
}
/**
* 入参日志摘要不打印 base64 正文仅长度与 url 长度
*/
private String buildInputLogContext(DriverLicenseRecognizeRequest request) {
if (request == null) {
return "request=null";
}
String sideParam = isBlank(request.getSide()) ? "未传" : request.getSide().trim();
String resolvedSide = resolveDrivingLicenseSide(request);
String targetPage = resolvedSide == null ? "无法解析" : sideLabel(resolvedSide);
return "side入参=" + sideParam
+ ",目标页面=" + targetPage
+ ",影像模式=" + resolveImageMode(request)
+ ",base64长度=" + textLength(request.getImageBase64())
+ ",url长度=" + textLength(request.getImageUrl())
+ ",url是否为空=" + isBlank(request.getImageUrl());
}
/**
* 平台回执日志摘要便于失败排查
*/
private String buildPlatformReceiptSummary(Map<String, Object> platformResult) {
if (platformResult == null) {
return "platformResult=null";
}
StringBuilder sb = new StringBuilder();
sb.append("error_code=").append(platformResult.get("error_code"));
sb.append(",error_msg=").append(platformResult.get("error_msg"));
sb.append(",log_id=").append(platformResult.get("log_id"));
sb.append(",words_result_num=").append(platformResult.get("words_result_num"));
sb.append(",direction=").append(platformResult.get("direction"));
Object wordsResult = platformResult.get("words_result");
if (wordsResult instanceof Map) {
sb.append(",结果字段数=").append(((Map<?, ?>) wordsResult).size());
} else {
sb.append(",结果字段数=不可解析");
}
return sb.toString();
}
private int textLength(String value) {
return value == null ? 0 : value.length();
}
private int countMappedFields(Object data) {
if (data instanceof RecognizeDriverLicenseFaceResp) {
RecognizeDriverLicenseFaceResp r = (RecognizeDriverLicenseFaceResp) data;
int count = 0;
if (StringUtils.isNotBlank(r.getLicenseNumber())) count++;
if (StringUtils.isNotBlank(r.getName())) count++;
if (StringUtils.isNotBlank(r.getGender())) count++;
if (StringUtils.isNotBlank(r.getNationality())) count++;
if (StringUtils.isNotBlank(r.getBirthDate())) count++;
if (StringUtils.isNotBlank(r.getIssueDate())) count++;
if (StringUtils.isNotBlank(r.getVehicleType())) count++;
if (StringUtils.isNotBlank(r.getAddress())) count++;
if (StringUtils.isNotBlank(r.getIssueUnit())) count++;
if (StringUtils.isNotBlank(r.getStartDate())) count++;
if (StringUtils.isNotBlank(r.getEndDate())) count++;
if (StringUtils.isNotBlank(r.getAccumulatedPoints())) count++;
if (StringUtils.isNotBlank(r.getStatus())) count++;
if (StringUtils.isNotBlank(r.getArchiveNumber())) count++;
if (StringUtils.isNotBlank(r.getGenerateTime())) count++;
if (StringUtils.isNotBlank(r.getCurrentTime())) count++;
if (StringUtils.isNotBlank(r.getBarcodeNumber())) count++;
return count;
}
if (data instanceof RecognizeDriverLicenseBackResp) {
RecognizeDriverLicenseBackResp r = (RecognizeDriverLicenseBackResp) data;
int count = 0;
if (StringUtils.isNotBlank(r.getName())) count++;
if (StringUtils.isNotBlank(r.getRecord())) count++;
if (StringUtils.isNotBlank(r.getCardNumber())) count++;
if (StringUtils.isNotBlank(r.getArchiveNumber())) count++;
return count;
}
return 0;
}
private RecognizeDriverLicenseFaceResp buildFaceResp(Map<String, Object> data) {
RecognizeDriverLicenseFaceResp resp = new RecognizeDriverLicenseFaceResp();
resp.setLicenseNumber(getWords(data, "证号"));
resp.setName(getWords(data, "姓名"));
resp.setGender(getWords(data, "性别"));
resp.setNationality(getWords(data, "国籍"));
resp.setBirthDate(getWords(data, "出生日期"));
resp.setIssueDate(getWords(data, "初次领证日期"));
resp.setVehicleType(getWords(data, "准驾车型"));
resp.setAddress(getWords(data, "住址"));
resp.setIssueUnit(getWords(data, "发证单位"));
resp.setStartDate(firstNonBlank(getWords(data, "有效起始日期"), getWords(data, "有效期限")));
resp.setEndDate(firstNonBlank(getWords(data, "失效日期"), getWords(data, "")));
resp.setAccumulatedPoints(getWords(data, "累积记分"));
resp.setStatus(getWords(data, "状态"));
resp.setArchiveNumber(getWords(data, "档案编号"));
resp.setGenerateTime(getWords(data, "生成时间"));
resp.setCurrentTime(getWords(data, "当前时间"));
resp.setBarcodeNumber(getWords(data, "条形码下编号"));
return resp;
}
private RecognizeDriverLicenseBackResp buildBackResp(Map<String, Object> data) {
RecognizeDriverLicenseBackResp resp = new RecognizeDriverLicenseBackResp();
resp.setName(getWords(data, "姓名"));
resp.setRecord(getWords(data, "记录"));
resp.setCardNumber(getWords(data, "证号"));
resp.setArchiveNumber(getWords(data, "档案编号"));
return resp;
}
private String getWords(Map<String, Object> data, String field) {
return MapUtils.getByExpr(data, "words_result." + field + ".words");
}
private String firstNonBlank(String first, String second) {
if (StringUtils.isNotBlank(first)) {
return first;
}
return second;
} }
} }