refactor(equipment): 优化身份证校验逻辑,抽取为独立方法

- 将身份证真实性校验代码抽取到 verifyIdCard 私有方法中
- 在校验方法中添加异常捕获,避免接口异常导致程序崩溃
- 优化图片数据解析和参数校验逻辑,提升健壮性
- 校验失败时返回详细错误信息,便于定位问题
- 身份证识别通过后自动回填订单和用户的实名信息
- 保持接口调用流程简洁,提高代码可读性和维护性
This commit is contained in:
2026-07-26 14:12:21 +08:00
parent 1a5ff59324
commit 1555fe1898

View File

@@ -411,32 +411,10 @@ public class OpenEquipmentController extends BaseController {
// if(receiptStatus == 20){
// return fail("订单已确认收货,不能重复确认!");
// }
// 验证身份证真实性
if(StringUtils.hasText(receiptParam.getOrderSourceData())) {
String orderSourceDataString = receiptParam.getOrderSourceData();
List<String> images = JSONObject.parseArray(orderSourceDataString, String.class);
String front = ImageUtil.ImageBase64(images.get(0) + "?x-oss-process=image/resize,w_750/quality,Q_80");
String back = ImageUtil.ImageBase64(images.get(1) + "?x-oss-process=image/resize,w_750/quality,Q_80");
IdcardRespVO verify = idcardService.verify(front, back);
System.out.println("verify res : " + verify);
if(!"FP00000".equals(verify.getCode())) {
return fail("请上传身份证正面照片." + verify.getMessage() + verify.getCode());
}
if(verify.getIssueDate() == null || verify.getIssueOrg() == null || verify.getExpireDate() == null) {
return fail("请上传身份证反面照片");
}
order.setRealName(verify.getName());
order.setIdCode(verify.getIdCardNo());
order.setAddress(verify.getAddress());
//更新用户信息
User user = userService.getById(order.getUserId());
user.setRealName(verify.getName());
user.setIdCard(verify.getIdCardNo());
user.setAddress(verify.getAddress());
userService.updateUser(user);
// 验证身份证真实性(校验不通过时返回 fail 结果,通过则返回 null
ApiResult<?> idcardResult = verifyIdCard(receiptParam.getOrderSourceData(), order);
if (idcardResult != null) {
return idcardResult;
}
// 短信验证码校验
@@ -460,6 +438,74 @@ public class OpenEquipmentController extends BaseController {
return success("确认收货成功");
}
/**
* 身份证 OCR 真实性校验,并把识别到的实名信息回填到 order / user。
* orderSourceData 约定顺序:[0]=身份证正面、[1]=身份证反面、[2]=人车合照、[3]=车子照片、[4]=安装照片
*
* @param orderSourceData 前端传入的图片地址 JSON 数组字符串
* @param order 当前订单(校验通过时回填实名信息)
* @return 校验失败返回 ApiResult(fail),校验通过返回 null
*/
private ApiResult<?> verifyIdCard(String orderSourceData, Order order) {
// 1. 解析图片数组
List<String> images;
try {
images = JSONObject.parseArray(orderSourceData, String.class);
} catch (Exception e) {
log.error("身份证图片数据解析失败, orderSourceData={}", orderSourceData, e);
return fail("身份证图片数据格式有误,请重新上传");
}
// 2. 必须包含身份证正反面(约定下标 0=正面、1=反面)
if (images == null || images.size() < 2
|| !StringUtils.hasText(images.get(0)) || !StringUtils.hasText(images.get(1))) {
return fail("请上传身份证正面和反面照片");
}
// 3. 调第三方 OCR 识别(加保护,避免接口异常导致 NPE
String front = ImageUtil.ImageBase64(images.get(0) + "?x-oss-process=image/resize,w_750/quality,Q_80");
String back = ImageUtil.ImageBase64(images.get(1) + "?x-oss-process=image/resize,w_750/quality,Q_80");
IdcardRespVO verify;
try {
verify = idcardService.verify(front, back);
} catch (Exception e) {
log.error("身份证识别服务调用异常", e);
return fail("身份证识别服务暂时不可用,请稍后重试");
}
if (verify == null) {
return fail("身份证识别失败,请稍后重试");
}
// 4. 正面校验:非 FP00000 说明传的不是有效身份证人像面
if (!"FP00000".equals(verify.getCode())) {
// 内部错误码仅记录日志,不回吐给用户
log.warn("身份证正面识别失败 code={}, message={}", verify.getCode(), verify.getMessage());
return fail("身份证正面照片识别失败,请重新上传清晰的身份证人像面照片");
}
// 5. 反面校验:签发机关/日期缺失说明传的不是有效身份证国徽面
if (StringUtils.isEmpty(verify.getIssueDate())
|| StringUtils.isEmpty(verify.getIssueOrg())
|| StringUtils.isEmpty(verify.getExpireDate())) {
return fail("身份证反面照片识别失败,请重新上传清晰的身份证国徽面照片");
}
// 6. 校验通过,回填实名信息
order.setRealName(verify.getName());
order.setIdCode(verify.getIdCardNo());
order.setAddress(verify.getAddress());
User user = userService.getById(order.getUserId());
if (user != null) {
user.setRealName(verify.getName());
user.setIdCard(verify.getIdCardNo());
user.setAddress(verify.getAddress());
userService.updateUser(user);
}
return null;
}
/*@ApiOperation("确认收货")
@PostMapping("/receipt")
public ApiResult<?> receipt(@RequestBody Order order) {