From 6cc5dc58de97a273a4cc0274cfa9ae6ed159016c Mon Sep 17 00:00:00 2001
From: wucongxing8150 <815046773@qq.com>
Date: Mon, 30 Jun 2025 16:48:39 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BA=86=E8=BA=AB=E4=BB=BD?=
=?UTF-8?q?=E8=AF=81=E8=AF=86=E5=88=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sa-admin/pom.xml | 5 +
.../admin/constant/AdminSwaggerTagConst.java | 2 +-
.../sa/admin/extend/baidubce/Base.java | 33 +++++
.../lab1024/sa/admin/extend/baidubce/Ocr.java | 30 +++++
.../sa/admin/extend/fangxinqian/Base.java | 2 +-
.../expert/controller/ExpertController.java | 2 -
.../app/expert/service/ExpertService.java | 2 -
.../app/file/controller/ImageController.java | 51 ++++++++
.../app/file/domain/vo/GetIdCardOcrVo.java | 16 +++
.../module/app/file/service/OcrService.java | 116 ++++++++++++++++++
.../src/main/resources/dev/application.yaml | 27 ++--
11 files changed, 269 insertions(+), 17 deletions(-)
create mode 100644 sa-admin/src/main/java/net/lab1024/sa/admin/extend/baidubce/Base.java
create mode 100644 sa-admin/src/main/java/net/lab1024/sa/admin/extend/baidubce/Ocr.java
create mode 100644 sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/controller/ImageController.java
create mode 100644 sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/domain/vo/GetIdCardOcrVo.java
create mode 100644 sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/service/OcrService.java
diff --git a/sa-admin/pom.xml b/sa-admin/pom.xml
index 3bc1422..27b7998 100644
--- a/sa-admin/pom.xml
+++ b/sa-admin/pom.xml
@@ -33,6 +33,11 @@
weixin-java-miniapp
+
+ com.baidu.aip
+ java-sdk
+ 4.16.22
+
diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminSwaggerTagConst.java b/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminSwaggerTagConst.java
index d9eb902..74bfe7e 100644
--- a/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminSwaggerTagConst.java
+++ b/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminSwaggerTagConst.java
@@ -60,7 +60,7 @@ public class AdminSwaggerTagConst extends SwaggerTagConst {
public static final String Expert = "前端-登录、注册、首页";
public static final String ExpertSign = "前端-医生签名";
- public static final String OSS = "前端-oss";
+ public static final String OSS = "前端-文件";
public static final String WX_MINI = "前端-微信小程序";
}
}
diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/extend/baidubce/Base.java b/sa-admin/src/main/java/net/lab1024/sa/admin/extend/baidubce/Base.java
new file mode 100644
index 0000000..afdb394
--- /dev/null
+++ b/sa-admin/src/main/java/net/lab1024/sa/admin/extend/baidubce/Base.java
@@ -0,0 +1,33 @@
+package net.lab1024.sa.admin.extend.baidubce;
+
+import com.baidu.aip.ocr.AipOcr;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+@Slf4j
+@Getter
+@Component("baiducebase")
+public class Base {
+ @Value("${baiduce.app-id}")
+ private String appId;
+
+ @Value("${baiduce.app-key}")
+ private String appkey;
+
+ @Value("${baiduce.app-secret}")
+ private String appSecret;
+
+ // AipOcr 实例
+ protected AipOcr ocrClient;
+
+ @PostConstruct
+ public void init() {
+ ocrClient = new AipOcr(appId, appkey, appSecret);
+ ocrClient.setConnectionTimeoutInMillis(2000);
+ ocrClient.setSocketTimeoutInMillis(60000);
+ }
+}
diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/extend/baidubce/Ocr.java b/sa-admin/src/main/java/net/lab1024/sa/admin/extend/baidubce/Ocr.java
new file mode 100644
index 0000000..519edd0
--- /dev/null
+++ b/sa-admin/src/main/java/net/lab1024/sa/admin/extend/baidubce/Ocr.java
@@ -0,0 +1,30 @@
+package net.lab1024.sa.admin.extend.baidubce;
+
+import java.util.HashMap;
+
+import com.baidu.aip.ocr.AipOcr;
+import net.lab1024.sa.common.common.domain.ResponseDTO;
+import net.lab1024.sa.common.common.exception.BusinessException;
+import org.json.JSONObject;
+import org.springframework.stereotype.Component;
+
+// 通用文字识别
+@Component
+public class Ocr extends Base {
+
+ /**
+ * 身份证识别
+ */
+ public JSONObject idCard(byte[] imageBytes,String idCardSide) {
+ try {
+ HashMap options = new HashMap<>();
+ options.put("detect_direction", "true");
+ options.put("detect_risk", "true");
+
+ return ocrClient.idcard(imageBytes, idCardSide, options);
+
+ } catch (Exception e) {
+ throw new BusinessException("OCR识别失败: " + e.getMessage());
+ }
+ }
+}
diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/extend/fangxinqian/Base.java b/sa-admin/src/main/java/net/lab1024/sa/admin/extend/fangxinqian/Base.java
index 13c468e..c5182db 100644
--- a/sa-admin/src/main/java/net/lab1024/sa/admin/extend/fangxinqian/Base.java
+++ b/sa-admin/src/main/java/net/lab1024/sa/admin/extend/fangxinqian/Base.java
@@ -18,7 +18,7 @@ import java.util.Map;
import java.util.concurrent.TimeUnit;
@Slf4j
-@Component
+@Component("fangxinqianbase")
@Getter
public class Base {
private static final ObjectMapper objectMapper = new ObjectMapper();
diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/expert/controller/ExpertController.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/expert/controller/ExpertController.java
index 40437b2..f1981c1 100644
--- a/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/expert/controller/ExpertController.java
+++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/expert/controller/ExpertController.java
@@ -634,6 +634,4 @@ public class ExpertController {
return ResponseDTO.error(ExpertBankVerifyFail);
}
}
-
-
}
diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/expert/service/ExpertService.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/expert/service/ExpertService.java
index 2bc34f6..1f74b7c 100644
--- a/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/expert/service/ExpertService.java
+++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/expert/service/ExpertService.java
@@ -77,6 +77,4 @@ public class ExpertService {
addForm.setToken(token);
return addForm;
}
-
-
}
diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/controller/ImageController.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/controller/ImageController.java
new file mode 100644
index 0000000..4e6facc
--- /dev/null
+++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/controller/ImageController.java
@@ -0,0 +1,51 @@
+package net.lab1024.sa.admin.module.app.file.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import net.lab1024.sa.admin.constant.AdminSwaggerTagConst;
+import net.lab1024.sa.admin.extend.baidubce.Ocr;
+import net.lab1024.sa.admin.module.app.file.domain.vo.GetIdCardOcrVo;
+import net.lab1024.sa.admin.module.app.file.service.OcrService;
+import net.lab1024.sa.admin.module.business.bankcard.domain.form.CaseplatformBankAddForm;
+import net.lab1024.sa.common.common.domain.ResponseDTO;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+
+@RestController
+@Api(tags = {AdminSwaggerTagConst.App.OSS})
+public class ImageController {
+
+ @Resource
+ private OcrService ocrService;
+
+ @ApiOperation(value = "身份证识别-ocr")
+ @PostMapping("/ocr/idCard")
+ public ResponseDTO getIdCardOcr(
+ @RequestParam("frontFile") MultipartFile frontFile,
+ @RequestParam("backFile") MultipartFile backFile
+ ){
+ if (frontFile == null || frontFile.isEmpty()) {
+ return ResponseDTO.userErrorParam("参数错误");
+ }
+
+ if (backFile == null || backFile.isEmpty()) {
+ return ResponseDTO.userErrorParam("参数错误");
+ }
+
+ try {
+ byte[] frontBytes = frontFile.getBytes();
+ byte[] backBytes = backFile.getBytes();
+
+ // 调用 Service
+ GetIdCardOcrVo result = ocrService.getIdCardOcr(frontBytes, backBytes);
+ return ResponseDTO.app_ok(result);
+
+ } catch (Exception e) {
+ return ResponseDTO.userErrorParam("识别失败:" + e.getMessage());
+ }
+
+ }
+}
diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/domain/vo/GetIdCardOcrVo.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/domain/vo/GetIdCardOcrVo.java
new file mode 100644
index 0000000..44ed69c
--- /dev/null
+++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/domain/vo/GetIdCardOcrVo.java
@@ -0,0 +1,16 @@
+package net.lab1024.sa.admin.module.app.file.domain.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class GetIdCardOcrVo {
+ @ApiModelProperty(value = "身份证姓名")
+ private String idCardName;
+
+ @ApiModelProperty(value = "身份证号")
+ private String idCardNo;
+}
+
diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/service/OcrService.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/service/OcrService.java
new file mode 100644
index 0000000..706951a
--- /dev/null
+++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/app/file/service/OcrService.java
@@ -0,0 +1,116 @@
+package net.lab1024.sa.admin.module.app.file.service;
+
+import net.lab1024.sa.admin.extend.baidubce.Ocr;
+import net.lab1024.sa.admin.extend.fangxinqian.company.Company;
+import net.lab1024.sa.admin.module.app.expert.admin.ExpertSignVO;
+import net.lab1024.sa.admin.module.app.expert.dao.ExpertSignDao;
+import net.lab1024.sa.admin.module.app.file.domain.vo.GetIdCardOcrVo;
+import net.lab1024.sa.common.common.exception.BusinessException;
+import net.lab1024.sa.common.common.util.SmartRequestUtil;
+import org.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+@Service
+public class OcrService {
+
+ @Resource
+ private Ocr ocr;
+
+ /**
+ * 身份证识别
+ */
+ public GetIdCardOcrVo getIdCardOcr(byte[] frontBytes,byte[] backBytes) {
+ try {
+ // 反面
+ JSONObject result = ocr.idCard(backBytes,"back");
+
+ String imageStatus = result.getString("image_status");
+ switch (imageStatus) {
+ case "normal":
+ // 识别正常,继续处理
+ break;
+ case "reversed_side":
+ throw new BusinessException("身份证未摆正,请重新上传");
+ case "non_idcard":
+ throw new BusinessException("上传的图片中不包含身份证,请上传正确图片");
+ case "blurred":
+ throw new BusinessException("身份证模糊,请重新上传清晰图片");
+ case "over_exposure":
+ throw new BusinessException("身份证关键字段反光或过曝,请重新拍摄");
+ case "unknown":
+ default:
+ throw new BusinessException("无法识别身份证,请重新上传");
+ }
+
+ if (result.has("risk_type")) {
+ String riskType = result.getString("risk_type");
+ if (!"normal".equals(riskType)) {
+ switch (riskType) {
+ case "copy":
+ throw new BusinessException("检测到复印件身份证,请上传原件");
+ case "temporary":
+ throw new BusinessException("检测到临时身份证,请上传正式身份证");
+ case "screen":
+ throw new BusinessException("检测到翻拍身份证,请上传原件照片");
+ case "unknow":
+ default:
+ throw new BusinessException("身份证真实性存疑,请重新上传");
+ }
+ }
+ }
+
+ // 正面
+ result = ocr.idCard(frontBytes,"front");
+
+ imageStatus = result.getString("image_status");
+ switch (imageStatus) {
+ case "normal":
+ // 识别正常,继续处理
+ break;
+ case "reversed_side":
+ throw new BusinessException("身份证未摆正,请重新上传");
+ case "non_idcard":
+ throw new BusinessException("上传的图片中不包含身份证,请上传正确图片");
+ case "blurred":
+ throw new BusinessException("身份证模糊,请重新上传清晰图片");
+ case "over_exposure":
+ throw new BusinessException("身份证关键字段反光或过曝,请重新拍摄");
+ case "unknown":
+ default:
+ throw new BusinessException("无法识别身份证,请重新上传");
+ }
+
+ if (result.has("risk_type")) {
+ String riskType = result.getString("risk_type");
+ if (!"normal".equals(riskType)) {
+ switch (riskType) {
+ case "copy":
+ throw new BusinessException("检测到复印件身份证,请上传原件");
+ case "temporary":
+ throw new BusinessException("检测到临时身份证,请上传正式身份证");
+ case "screen":
+ throw new BusinessException("检测到翻拍身份证,请上传原件照片");
+ case "unknow":
+ default:
+ throw new BusinessException("身份证真实性存疑,请重新上传");
+ }
+ }
+ }
+
+ // 解析识别结果
+ String name = result.getJSONObject("words_result").getJSONObject("姓名").getString("words");
+ String idNo = result.getJSONObject("words_result").getJSONObject("公民身份号码").getString("words");
+
+ // 构建返回对象
+ GetIdCardOcrVo vo = new GetIdCardOcrVo();
+ vo.setIdCardName(name);
+ vo.setIdCardNo(idNo);
+ return vo;
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+}
diff --git a/sa-admin/src/main/resources/dev/application.yaml b/sa-admin/src/main/resources/dev/application.yaml
index c9dba14..2ced62f 100644
--- a/sa-admin/src/main/resources/dev/application.yaml
+++ b/sa-admin/src/main/resources/dev/application.yaml
@@ -54,14 +54,19 @@ fxq:
client-secret: 97acf8ebb09641cbb90accf06e74ccf5
client-url: https://saasapi.fangxinqian.cn/openapi/v2/
- # json序列化相关配置
- jackson:
- serialization:
- write-enums-using-to-string: true
- write-dates-as-timestamps: false
- deserialization:
- read-enums-using-to-string: true
- fail-on-unknown-properties: false
- default-property-inclusion: always
- date-format: yyyy-MM-dd HH:mm:ss
- time-zone: GMT+8
\ No newline at end of file
+baiduce:
+ app-id: 119377580
+ app-key: 2YFRnP3ryU8IP0IqbqybTu6u
+ app-secret: Zw8pTeM1ovys7kOsNUlElOc6jBi6zsFU
+
+# json序列化相关配置
+jackson:
+ serialization:
+ write-enums-using-to-string: true
+ write-dates-as-timestamps: false
+ deserialization:
+ read-enums-using-to-string: true
+ fail-on-unknown-properties: false
+ default-property-inclusion: always
+ date-format: yyyy-MM-dd HH:mm:ss
+ time-zone: GMT+8
\ No newline at end of file