feat(hjc): 企业注册一站式——证件材料同事务入库 + 阿里云OCR识别 + 匿名注册上传
- HjcEnterprise 新增 idCardNo(经办人身份证号),配套迁移: src/main/resources/sql/hjc_enterprise_add_id_card_no.sql(需在目标库执行) - HjcAuthRequest 新增 idCardNo / materials;/hjc/auth/register 同事务保存 4 类证件材料, 并按「企业联系电话、企业地址选填,其余必填」补充后端校验 - 新增 POST /hjc/auth/upload:注册页登录前的匿名证件上传(复用 FileServerUtil, 按 setting:upload 决定自建文件服 / OSS 域名;不写 file_record 表) - 新增 POST /hjc/ocr/recognize:阿里云文字识别 OCR(aliyun-java-sdk-ocr 1.0.6) · idcard_front → agentName / idCardNo · license → creditCode / address(企业名称与法定代表人仅返回,供前端只读核对) · AK 走 aliyun.ocr.*,当前为占位空值;未配置时返回失败,由前端提示手动填写、不阻断注册 - SecurityConfig:/hjc/auth/upload 与 /hjc/ocr/recognize 匿名放行(与后台 /file/upload 隔离)
This commit is contained in:
@@ -213,6 +213,12 @@
|
|||||||
<artifactId>aliyun-java-sdk-core</artifactId>
|
<artifactId>aliyun-java-sdk-core</artifactId>
|
||||||
<version>4.4.3</version>
|
<version>4.4.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!--阿里云文字识别 OCR(身份证/营业执照识别)-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>aliyun-java-sdk-ocr</artifactId>
|
||||||
|
<version>1.0.6</version>
|
||||||
|
</dependency>
|
||||||
<!--阿里支付 老版本 SDK-->
|
<!--阿里支付 老版本 SDK-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alipay.sdk</groupId>
|
<groupId>com.alipay.sdk</groupId>
|
||||||
|
|||||||
@@ -82,7 +82,10 @@ public class SecurityConfig {
|
|||||||
"/api/shop/order-delivery/notify",
|
"/api/shop/order-delivery/notify",
|
||||||
"/api/hjc/push/project",
|
"/api/hjc/push/project",
|
||||||
"/api/hjc/auth/register",
|
"/api/hjc/auth/register",
|
||||||
"/api/hjc/auth/login"
|
"/api/hjc/auth/login",
|
||||||
|
// 注册页专用:证件上传与 OCR 识别在登录前发生
|
||||||
|
"/api/hjc/auth/upload",
|
||||||
|
"/api/hjc/ocr/recognize"
|
||||||
)
|
)
|
||||||
.permitAll()
|
.permitAll()
|
||||||
.anyRequest()
|
.anyRequest()
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package com.gxwebsoft.hjc.controller;
|
package com.gxwebsoft.hjc.controller;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.gxwebsoft.common.core.config.ConfigProperties;
|
import com.gxwebsoft.common.core.config.ConfigProperties;
|
||||||
import com.gxwebsoft.common.core.security.JwtSubject;
|
import com.gxwebsoft.common.core.security.JwtSubject;
|
||||||
import com.gxwebsoft.common.core.security.JwtUtil;
|
import com.gxwebsoft.common.core.security.JwtUtil;
|
||||||
|
import com.gxwebsoft.common.core.utils.FileServerUtil;
|
||||||
|
import com.gxwebsoft.common.core.utils.RedisUtil;
|
||||||
import com.gxwebsoft.common.core.web.ApiResult;
|
import com.gxwebsoft.common.core.web.ApiResult;
|
||||||
import com.gxwebsoft.common.core.web.BaseController;
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
import com.gxwebsoft.common.system.entity.Role;
|
import com.gxwebsoft.common.system.entity.Role;
|
||||||
@@ -16,6 +19,8 @@ import com.gxwebsoft.common.system.service.UserRoleService;
|
|||||||
import com.gxwebsoft.common.system.service.UserService;
|
import com.gxwebsoft.common.system.service.UserService;
|
||||||
import com.gxwebsoft.hjc.dto.HjcAuthRequest;
|
import com.gxwebsoft.hjc.dto.HjcAuthRequest;
|
||||||
import com.gxwebsoft.hjc.entity.HjcEnterprise;
|
import com.gxwebsoft.hjc.entity.HjcEnterprise;
|
||||||
|
import com.gxwebsoft.hjc.entity.HjcEnterpriseMaterial;
|
||||||
|
import com.gxwebsoft.hjc.service.HjcEnterpriseMaterialService;
|
||||||
import com.gxwebsoft.hjc.service.HjcEnterpriseService;
|
import com.gxwebsoft.hjc.service.HjcEnterpriseService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
@@ -23,9 +28,16 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 汇吉采 网站企业 注册/登录(企业名称+密码)
|
* 汇吉采 网站企业 注册/登录(企业名称+密码)
|
||||||
@@ -45,14 +57,61 @@ public class HjcAuthController extends BaseController {
|
|||||||
private ConfigProperties configProperties;
|
private ConfigProperties configProperties;
|
||||||
@Resource
|
@Resource
|
||||||
private HjcEnterpriseService hjcEnterpriseService;
|
private HjcEnterpriseService hjcEnterpriseService;
|
||||||
|
@Resource
|
||||||
|
private HjcEnterpriseMaterialService hjcEnterpriseMaterialService;
|
||||||
|
@Resource
|
||||||
|
private RedisUtil redisUtil;
|
||||||
|
|
||||||
@Operation(summary = "企业注册(企业名称+密码,注册后待审核)")
|
/** 注册必传的资质证件材料类型 */
|
||||||
|
private static final List<String> REQUIRED_MATERIAL_TYPES =
|
||||||
|
Arrays.asList("idcard_front", "idcard_back", "handbook", "license");
|
||||||
|
|
||||||
|
@Operation(summary = "注册证件上传(匿名,注册页专用,不写文件表)")
|
||||||
|
@PostMapping("/upload")
|
||||||
|
public ApiResult<Map<String, Object>> upload(@RequestParam("file") MultipartFile file) {
|
||||||
|
if (file == null || file.isEmpty()) {
|
||||||
|
return fail("上传文件不能为空", null);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String dir = configProperties.getUploadPath();
|
||||||
|
File upload = FileServerUtil.upload(file, dir, Boolean.TRUE.equals(configProperties.getUploadUuidName()));
|
||||||
|
String path = upload.getAbsolutePath().replace("\\", "/").substring(dir.length() - 1);
|
||||||
|
// 默认走自建文件服务器
|
||||||
|
String url = configProperties.getFileServer() + "/api/file" + path;
|
||||||
|
// 云存储(OSS)时改用 bucketDomain
|
||||||
|
Integer tenantId = getTenantId();
|
||||||
|
if (tenantId != null) {
|
||||||
|
JSONObject setting = JSONObject.parseObject(redisUtil.get("setting:upload:" + tenantId));
|
||||||
|
if (setting != null) {
|
||||||
|
String uploadMethod = setting.getString("uploadMethod");
|
||||||
|
String bucketDomain = setting.getString("bucketDomain");
|
||||||
|
if (StrUtil.isNotBlank(uploadMethod) && !"file".equals(uploadMethod)
|
||||||
|
&& StrUtil.isNotBlank(bucketDomain)) {
|
||||||
|
url = bucketDomain + path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map<String, Object> data = new HashMap<>(4);
|
||||||
|
data.put("url", url);
|
||||||
|
data.put("name", file.getOriginalFilename());
|
||||||
|
return success(data);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return fail("上传失败", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "企业注册(一站式:企业+经办人+授权+证件,提交后待审核)")
|
||||||
@PostMapping("/register")
|
@PostMapping("/register")
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public ApiResult<LoginResult> register(@RequestBody HjcAuthRequest request) {
|
public ApiResult<LoginResult> register(@RequestBody HjcAuthRequest request) {
|
||||||
if (StrUtil.isBlank(request.getEnterpriseName()) || StrUtil.isBlank(request.getPassword())) {
|
if (StrUtil.isBlank(request.getEnterpriseName()) || StrUtil.isBlank(request.getPassword())) {
|
||||||
return fail("企业名称和密码不能为空", null);
|
return fail("企业名称和密码不能为空", null);
|
||||||
}
|
}
|
||||||
|
String invalid = validateRegister(request);
|
||||||
|
if (invalid != null) {
|
||||||
|
return fail(invalid, null);
|
||||||
|
}
|
||||||
Integer tenantId = getTenantId();
|
Integer tenantId = getTenantId();
|
||||||
if (tenantId == null) {
|
if (tenantId == null) {
|
||||||
return fail("租户ID不能为空", null);
|
return fail("租户ID不能为空", null);
|
||||||
@@ -97,16 +156,69 @@ public class HjcAuthController extends BaseController {
|
|||||||
enterprise.setAgentName(request.getAgentName());
|
enterprise.setAgentName(request.getAgentName());
|
||||||
enterprise.setAgentEmail(request.getAgentEmail());
|
enterprise.setAgentEmail(request.getAgentEmail());
|
||||||
enterprise.setAgentPhone(request.getAgentPhone());
|
enterprise.setAgentPhone(request.getAgentPhone());
|
||||||
|
enterprise.setIdCardNo(request.getIdCardNo());
|
||||||
enterprise.setAuthorizeExpire(request.getAuthorizeExpire());
|
enterprise.setAuthorizeExpire(request.getAuthorizeExpire());
|
||||||
enterprise.setAuthStatus(0);
|
enterprise.setAuthStatus(0);
|
||||||
enterprise.setTenantId(tenantId);
|
enterprise.setTenantId(tenantId);
|
||||||
hjcEnterpriseService.save(enterprise);
|
hjcEnterpriseService.save(enterprise);
|
||||||
|
|
||||||
|
// 一站式注册:同事务保存资质证件材料
|
||||||
|
List<HjcEnterpriseMaterial> materials = request.getMaterials();
|
||||||
|
if (materials != null) {
|
||||||
|
for (HjcEnterpriseMaterial m : materials) {
|
||||||
|
if (StrUtil.isBlank(m.getFileUrl())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
m.setId(null);
|
||||||
|
m.setEnterpriseId(enterprise.getId());
|
||||||
|
m.setTenantId(tenantId);
|
||||||
|
hjcEnterpriseMaterialService.save(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String token = JwtUtil.buildToken(new JwtSubject(user.getUsername(), user.getTenantId()),
|
String token = JwtUtil.buildToken(new JwtSubject(user.getUsername(), user.getTenantId()),
|
||||||
configProperties.getTokenExpireTime(), configProperties.getTokenKey());
|
configProperties.getTokenExpireTime(), configProperties.getTokenKey());
|
||||||
return success("注册成功", new LoginResult(token, user));
|
return success("注册成功", new LoginResult(token, user));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册必填校验:企业联系电话、企业地址选填,其余必填;4 类证件必传
|
||||||
|
*
|
||||||
|
* @return 错误信息;校验通过返回 null
|
||||||
|
*/
|
||||||
|
private String validateRegister(HjcAuthRequest request) {
|
||||||
|
if (StrUtil.isBlank(request.getCreditCode())) {
|
||||||
|
return "纳税人识别号不能为空";
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(request.getContactEmail())) {
|
||||||
|
return "企业邮箱不能为空";
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(request.getAgentName())) {
|
||||||
|
return "经办人姓名不能为空";
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(request.getAgentEmail())) {
|
||||||
|
return "经办人邮箱不能为空";
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(request.getAgentPhone())) {
|
||||||
|
return "经办人手机号不能为空";
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(request.getIdCardNo())) {
|
||||||
|
return "经办人身份证号不能为空";
|
||||||
|
}
|
||||||
|
if (request.getAuthorizeExpire() == null) {
|
||||||
|
return "授权到期时间不能为空";
|
||||||
|
}
|
||||||
|
List<HjcEnterpriseMaterial> materials = request.getMaterials();
|
||||||
|
for (String type : REQUIRED_MATERIAL_TYPES) {
|
||||||
|
boolean present = materials != null && materials.stream()
|
||||||
|
.anyMatch(m -> type.equals(m.getMaterialType()) && StrUtil.isNotBlank(m.getFileUrl()));
|
||||||
|
if (!present) {
|
||||||
|
return "请上传全部证件(身份证正反面、授权委托书、营业执照)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Operation(summary = "企业登录(企业名称+密码)")
|
@Operation(summary = "企业登录(企业名称+密码)")
|
||||||
@PostMapping("/login")
|
@PostMapping("/login")
|
||||||
public ApiResult<LoginResult> login(@RequestBody HjcAuthRequest request) {
|
public ApiResult<LoginResult> login(@RequestBody HjcAuthRequest request) {
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.gxwebsoft.hjc.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.gxwebsoft.common.core.web.ApiResult;
|
||||||
|
import com.gxwebsoft.common.core.web.BaseController;
|
||||||
|
import com.gxwebsoft.hjc.dto.HjcOcrRecognizeRequest;
|
||||||
|
import com.gxwebsoft.hjc.dto.HjcOcrResult;
|
||||||
|
import com.gxwebsoft.hjc.service.HjcOcrService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 汇吉采 证件 OCR 识别(注册页在登录前调用,SecurityConfig 已匿名放行)
|
||||||
|
*/
|
||||||
|
@Tag(name = "汇吉采-证件OCR")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/hjc/ocr")
|
||||||
|
public class HjcOcrController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private HjcOcrService hjcOcrService;
|
||||||
|
|
||||||
|
@Operation(summary = "识别证件(身份证人像面/营业执照),回填表单字段")
|
||||||
|
@PostMapping("/recognize")
|
||||||
|
public ApiResult<HjcOcrResult> recognize(@RequestBody HjcOcrRecognizeRequest request) {
|
||||||
|
if (StrUtil.isBlank(request.getMaterialType()) || StrUtil.isBlank(request.getFileUrl())) {
|
||||||
|
return fail("materialType 与 fileUrl 不能为空", null);
|
||||||
|
}
|
||||||
|
HjcOcrResult result = hjcOcrService.recognize(request.getMaterialType(), request.getFileUrl());
|
||||||
|
if (result == null) {
|
||||||
|
return fail("识别失败或该类型无需识别,请手动填写", null);
|
||||||
|
}
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
package com.gxwebsoft.hjc.dto;
|
package com.gxwebsoft.hjc.dto;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.gxwebsoft.hjc.entity.HjcEnterpriseMaterial;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 汇吉采 网站企业 注册/登录 请求(企业名称+密码)
|
* 汇吉采 网站企业 注册/登录 请求(企业名称+密码)
|
||||||
@@ -40,7 +42,13 @@ public class HjcAuthRequest {
|
|||||||
@Schema(description = "经办人手机号")
|
@Schema(description = "经办人手机号")
|
||||||
private String agentPhone;
|
private String agentPhone;
|
||||||
|
|
||||||
|
@Schema(description = "经办人身份证号")
|
||||||
|
private String idCardNo;
|
||||||
|
|
||||||
@Schema(description = "授权委托书到期时间")
|
@Schema(description = "授权委托书到期时间")
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private LocalDateTime authorizeExpire;
|
private LocalDateTime authorizeExpire;
|
||||||
|
|
||||||
|
@Schema(description = "资质证件材料")
|
||||||
|
private List<HjcEnterpriseMaterial> materials;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.gxwebsoft.hjc.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 汇吉采 证件 OCR 识别请求
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(name = "HjcOcrRecognizeRequest", description = "汇吉采证件OCR识别请求")
|
||||||
|
public class HjcOcrRecognizeRequest {
|
||||||
|
|
||||||
|
@Schema(description = "材料类型:idcard_front(身份证人像面)/ license(营业执照)", required = true)
|
||||||
|
private String materialType;
|
||||||
|
|
||||||
|
@Schema(description = "已上传证件的可访问地址(fileUrl)", required = true)
|
||||||
|
private String fileUrl;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.gxwebsoft.hjc.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 汇吉采 证件 OCR 识别结果
|
||||||
|
*
|
||||||
|
* <p>字段按材料类型填写:营业执照填 enterpriseName/creditCode/address/legalPerson;
|
||||||
|
* 身份证人像面填 agentName/idCardNo;未识别到的字段为 null。</p>
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(name = "HjcOcrResult", description = "汇吉采证件OCR识别结果")
|
||||||
|
public class HjcOcrResult {
|
||||||
|
|
||||||
|
@Schema(description = "材料类型:idcard_front / license")
|
||||||
|
private String materialType;
|
||||||
|
|
||||||
|
@Schema(description = "营业执照-企业名称(仅作只读核对,不覆盖登录账号)")
|
||||||
|
private String enterpriseName;
|
||||||
|
|
||||||
|
@Schema(description = "营业执照-统一社会信用代码")
|
||||||
|
private String creditCode;
|
||||||
|
|
||||||
|
@Schema(description = "营业执照-住所/企业地址")
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
@Schema(description = "营业执照-法定代表人(仅展示供人工参考)")
|
||||||
|
private String legalPerson;
|
||||||
|
|
||||||
|
@Schema(description = "身份证-经办人姓名")
|
||||||
|
private String agentName;
|
||||||
|
|
||||||
|
@Schema(description = "身份证-经办人身份证号")
|
||||||
|
private String idCardNo;
|
||||||
|
}
|
||||||
@@ -55,6 +55,9 @@ public class HjcEnterprise implements Serializable {
|
|||||||
@Schema(description = "经办人手机号")
|
@Schema(description = "经办人手机号")
|
||||||
private String agentPhone;
|
private String agentPhone;
|
||||||
|
|
||||||
|
@Schema(description = "经办人身份证号")
|
||||||
|
private String idCardNo;
|
||||||
|
|
||||||
@Schema(description = "授权委托书到期时间")
|
@Schema(description = "授权委托书到期时间")
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private LocalDateTime authorizeExpire;
|
private LocalDateTime authorizeExpire;
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.gxwebsoft.hjc.service;
|
||||||
|
|
||||||
|
import com.gxwebsoft.hjc.dto.HjcOcrResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 汇吉采 证件 OCR 识别(阿里云文字识别 OCR,服务端调用)
|
||||||
|
*/
|
||||||
|
public interface HjcOcrService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 识别证件
|
||||||
|
*
|
||||||
|
* @param materialType 材料类型:idcard_front(身份证人像面)/ license(营业执照)
|
||||||
|
* @param fileUrl 已上传证件的可访问地址
|
||||||
|
* @return 识别结果;不支持的材料类型或识别失败返回 null
|
||||||
|
*/
|
||||||
|
HjcOcrResult recognize(String materialType, String fileUrl);
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package com.gxwebsoft.hjc.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.aliyuncs.DefaultAcsClient;
|
||||||
|
import com.aliyuncs.IAcsClient;
|
||||||
|
import com.aliyuncs.ocr.model.v20191230.RecognizeBusinessLicenseRequest;
|
||||||
|
import com.aliyuncs.ocr.model.v20191230.RecognizeBusinessLicenseResponse;
|
||||||
|
import com.aliyuncs.ocr.model.v20191230.RecognizeIdentityCardRequest;
|
||||||
|
import com.aliyuncs.ocr.model.v20191230.RecognizeIdentityCardResponse;
|
||||||
|
import com.aliyuncs.profile.DefaultProfile;
|
||||||
|
import com.gxwebsoft.hjc.dto.HjcOcrResult;
|
||||||
|
import com.gxwebsoft.hjc.service.HjcOcrService;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 汇吉采 证件 OCR 识别实现(阿里云文字识别 OCR)
|
||||||
|
*
|
||||||
|
* <p>AK 需具备 OCR 服务权限;未配置(占位值为空)时直接返回 null,由前端提示「识别失败,请手动填写」,
|
||||||
|
* 不阻断注册流程。</p>
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class HjcOcrServiceImpl implements HjcOcrService {
|
||||||
|
|
||||||
|
/** 材料类型:身份证人像面 */
|
||||||
|
public static final String MATERIAL_IDCARD_FRONT = "idcard_front";
|
||||||
|
/** 材料类型:营业执照 */
|
||||||
|
public static final String MATERIAL_LICENSE = "license";
|
||||||
|
|
||||||
|
@Value("${aliyun.ocr.access-key-id:}")
|
||||||
|
private String accessKeyId;
|
||||||
|
|
||||||
|
@Value("${aliyun.ocr.access-key-secret:}")
|
||||||
|
private String accessKeySecret;
|
||||||
|
|
||||||
|
@Value("${aliyun.ocr.region:cn-hangzhou}")
|
||||||
|
private String region;
|
||||||
|
|
||||||
|
@Value("${aliyun.ocr.endpoint:ocr-api.cn-hangzhou.aliyuncs.com}")
|
||||||
|
private String endpoint;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HjcOcrResult recognize(String materialType, String fileUrl) {
|
||||||
|
if (StrUtil.isBlank(materialType) || StrUtil.isBlank(fileUrl)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (StrUtil.isBlank(accessKeyId) || StrUtil.isBlank(accessKeySecret)) {
|
||||||
|
// OCR 未配置 AK(占位),不阻断注册
|
||||||
|
System.out.println("HjcOcr: aliyun.ocr 未配置 AccessKey,跳过识别");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
IAcsClient client = createClient();
|
||||||
|
if (MATERIAL_IDCARD_FRONT.equals(materialType)) {
|
||||||
|
return recognizeIdCard(client, fileUrl);
|
||||||
|
}
|
||||||
|
if (MATERIAL_LICENSE.equals(materialType)) {
|
||||||
|
return recognizeBusinessLicense(client, fileUrl);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IAcsClient createClient() throws Exception {
|
||||||
|
DefaultProfile profile = DefaultProfile.getProfile(region, accessKeyId, accessKeySecret);
|
||||||
|
DefaultProfile.addEndpoint(region, region, "ocr", endpoint);
|
||||||
|
return new DefaultAcsClient(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 身份证人像面:回填经办人姓名 + 身份证号 */
|
||||||
|
private HjcOcrResult recognizeIdCard(IAcsClient client, String fileUrl) throws Exception {
|
||||||
|
RecognizeIdentityCardRequest request = new RecognizeIdentityCardRequest();
|
||||||
|
request.setImageURL(fileUrl);
|
||||||
|
request.setSide("face");
|
||||||
|
RecognizeIdentityCardResponse response = client.getAcsResponse(request);
|
||||||
|
if (response == null || response.getData() == null
|
||||||
|
|| response.getData().getFrontResult() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
RecognizeIdentityCardResponse.Data.FrontResult front = response.getData().getFrontResult();
|
||||||
|
HjcOcrResult result = new HjcOcrResult();
|
||||||
|
result.setMaterialType(MATERIAL_IDCARD_FRONT);
|
||||||
|
result.setAgentName(front.getName());
|
||||||
|
result.setIdCardNo(front.getIDNumber());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 营业执照:回填统一社会信用代码 + 企业地址;企业名称/法定代表人仅作展示提示 */
|
||||||
|
private HjcOcrResult recognizeBusinessLicense(IAcsClient client, String fileUrl) throws Exception {
|
||||||
|
RecognizeBusinessLicenseRequest request = new RecognizeBusinessLicenseRequest();
|
||||||
|
request.setImageURL(fileUrl);
|
||||||
|
RecognizeBusinessLicenseResponse response = client.getAcsResponse(request);
|
||||||
|
if (response == null || response.getData() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
RecognizeBusinessLicenseResponse.Data data = response.getData();
|
||||||
|
HjcOcrResult result = new HjcOcrResult();
|
||||||
|
result.setMaterialType(MATERIAL_LICENSE);
|
||||||
|
result.setEnterpriseName(data.getName());
|
||||||
|
result.setCreditCode(data.getRegisterNumber());
|
||||||
|
result.setAddress(data.getAddress());
|
||||||
|
result.setLegalPerson(data.getLegalPerson());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -77,3 +77,9 @@ aliyun:
|
|||||||
access-key-id: LTAI5tEsyhW4GCKbds1qsopg
|
access-key-id: LTAI5tEsyhW4GCKbds1qsopg
|
||||||
access-key-secret: zltFlQrYVAoq2KMFDWgLa3GhkMNeyO
|
access-key-secret: zltFlQrYVAoq2KMFDWgLa3GhkMNeyO
|
||||||
endpoint: mt.cn-hangzhou.aliyuncs.com
|
endpoint: mt.cn-hangzhou.aliyuncs.com
|
||||||
|
# 阿里云文字识别 OCR(身份证/营业执照识别),AK 需具备 OCR 服务权限;未开通前为占位值
|
||||||
|
ocr:
|
||||||
|
access-key-id: ""
|
||||||
|
access-key-secret: ""
|
||||||
|
region: cn-hangzhou
|
||||||
|
endpoint: ocr-api.cn-hangzhou.aliyuncs.com
|
||||||
|
|||||||
@@ -105,6 +105,14 @@ config:
|
|||||||
bucketDomain: https://oss.wsdns.cn
|
bucketDomain: https://oss.wsdns.cn
|
||||||
aliyunDomain: https://oss-gxwebsoft.oss-cn-shenzhen.aliyuncs.com
|
aliyunDomain: https://oss-gxwebsoft.oss-cn-shenzhen.aliyuncs.com
|
||||||
|
|
||||||
|
# 阿里云文字识别 OCR(身份证/营业执照识别),AK 需具备 OCR 服务权限;未开通前为占位值
|
||||||
|
aliyun:
|
||||||
|
ocr:
|
||||||
|
access-key-id: ""
|
||||||
|
access-key-secret: ""
|
||||||
|
region: cn-hangzhou
|
||||||
|
endpoint: ocr-api.cn-hangzhou.aliyuncs.com
|
||||||
|
|
||||||
# 商城订单配置
|
# 商城订单配置
|
||||||
shop:
|
shop:
|
||||||
order:
|
order:
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- 汇吉采:企业资质新增「经办人身份证号」字段(注册/资质认证页,身份证人像面 OCR 回填)
|
||||||
|
ALTER TABLE `hjc_enterprise`
|
||||||
|
ADD COLUMN `id_card_no` varchar(64) DEFAULT NULL COMMENT '经办人身份证号' AFTER `agent_phone`;
|
||||||
@@ -51,6 +51,7 @@ CREATE TABLE `hjc_enterprise` (
|
|||||||
`agent_name` varchar(64) DEFAULT NULL COMMENT '经办人姓名',
|
`agent_name` varchar(64) DEFAULT NULL COMMENT '经办人姓名',
|
||||||
`agent_email` varchar(128) DEFAULT NULL COMMENT '经办人邮箱',
|
`agent_email` varchar(128) DEFAULT NULL COMMENT '经办人邮箱',
|
||||||
`agent_phone` varchar(32) DEFAULT NULL COMMENT '经办人手机号',
|
`agent_phone` varchar(32) DEFAULT NULL COMMENT '经办人手机号',
|
||||||
|
`id_card_no` varchar(64) DEFAULT NULL COMMENT '经办人身份证号',
|
||||||
`authorize_expire` datetime DEFAULT NULL COMMENT '授权委托书到期时间',
|
`authorize_expire` datetime DEFAULT NULL COMMENT '授权委托书到期时间',
|
||||||
`auth_status` tinyint(4) DEFAULT 0 COMMENT '资质状态:0待审核 1已通过 2已驳回',
|
`auth_status` tinyint(4) DEFAULT 0 COMMENT '资质状态:0待审核 1已通过 2已驳回',
|
||||||
`reject_reason` varchar(500) DEFAULT NULL COMMENT '驳回原因',
|
`reject_reason` varchar(500) DEFAULT NULL COMMENT '驳回原因',
|
||||||
|
|||||||
Reference in New Issue
Block a user