提交修改

This commit is contained in:
quyixiao 2026-05-20 19:59:35 +08:00
parent f50e9309b4
commit 25e68efd21
6 changed files with 210 additions and 10 deletions

View File

@ -20,14 +20,16 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/***
* 识别身份证
* 银行卡 2/3/4 要素聚合校验控制器
*
* 根据请求参数完整度自动路由到不同的校验通道
* - 4 要素银行卡号 + 姓名 + 身份证号 + 手机号
* - 3 要素银行卡号 + 姓名 + 身份证号
* - 2 要素银行卡号 + 姓名
*
* 阿里云市场对接文档
* https://market.aliyun.com/apimarket/detail/cmapi00066584#sku=yuncode60584000011
*
*
*
* https://marketnext.console.aliyun.com/bizlist
*
*/
@Slf4j
@RestController
@ -35,24 +37,35 @@ import org.springframework.web.bind.annotation.RestController;
@NotIntercept
public class BankCard234MetaController extends BaseController {
// 银行卡 2 要素校验处理器银行卡号 + 姓名
@Autowired
private ABank2MetaVerifyHandle bank2MetaVerifyHandle;
// 银行卡 3 要素校验处理器银行卡号 + 姓名 + 身份证号
@Autowired
private ABank3MetaVerifyHandle bank3MetaVerifyHandle;
// 银行卡 4 要素校验处理器银行卡号 + 姓名 + 身份证号 + 手机号
@Autowired
private ABank4MetaVerifyHandle bank4MetaVerifyHandle;
// 校验通过返回的提示语
public static final String SUCCESS_MSG = "信息匹配";
// 校验不通过返回的提示语
public static final String FAILED_MSG = "信息不匹配";
// 测试地址示例
// http://localhost:8888/bank/card/234/verify?bankCard=6214855713516769&realName=瞿贻晓&idCardNumber=430529199209255030&mobile=18458195149
// https://api.1024api.com/api-interface/bank/card/234/verify?bankCardNumber=6214855713516769&realName=瞿贻晓
/**
* 银行卡要素校验入口按入参完整度自动选用 2/3/4 要素接口
*
* @param bankCard4MetaRequest 银行卡校验请求参数卡号姓名身份证号手机号
* @return 统一响应 Rdata {@link BankCard2MetaResp}
*/
@RequestMapping("/verify")
@EbAuthentication(tencent = ApiConstants.TENCENT_AUTH)
public R verify(ABank4MetaVerifyRequest bankCard4MetaRequest) {
@ -60,11 +73,19 @@ public class BankCard234MetaController extends BaseController {
}
/**
* 实际执行银行卡要素校验的方法
* 根据非空字段数量决定调用 4 / 3 / 2 要素中的哪个处理器并将上游响应统一转成 {@link BankCard2MetaResp}
*
* @param bankCard4MetaRequest 银行卡校验请求参数
* @return 统一响应 R
*/
public R doVerifyBankCard4(ABank4MetaVerifyRequest bankCard4MetaRequest) {
BankCard2MetaResp bankCard2MetaResp = new BankCard2MetaResp();
// //1 一致 0 不一致2查无(卡状态异常或已注销)
// 上游校验结果1 一致0 不一致2 查无卡状态异常或已注销
ApiR<TBankMetaVerifyResponse> aR = null;
// 4 要素齐全调用 4 要素校验
if (StringUtils.isNotEmpty(bankCard4MetaRequest.getBankCard())
&& StringUtils.isNotEmpty(bankCard4MetaRequest.getRealName())
&& StringUtils.isNotEmpty(bankCard4MetaRequest.getIdCardNumber())
@ -75,35 +96,44 @@ public class BankCard234MetaController extends BaseController {
&& StringUtils.isNotEmpty(bankCard4MetaRequest.getRealName())
&& StringUtils.isNotEmpty(bankCard4MetaRequest.getIdCardNumber())
) {
// 缺手机号但其它三项齐全降级到 3 要素校验
aR = bank3MetaVerifyHandle.handle(bankCard4MetaRequest);
} else if (StringUtils.isNotEmpty(bankCard4MetaRequest.getBankCard())
&& StringUtils.isNotEmpty(bankCard4MetaRequest.getRealName())
) {
// 只有卡号 + 姓名 2 要素校验
aR = bank2MetaVerifyHandle.handle(bankCard4MetaRequest);
} else {
// 连卡号 + 姓名都凑不齐直接拒绝
return R.error("至少 银行卡号 + 姓名 不能为空");
}
// 上游调用成功解析业务结果
if (aR.isSuccess()) {
TBankMetaVerifyResponse bankMetaVerifyResponse = aR.getData();
if (bankMetaVerifyResponse != null) {
// 上游业务码 400业务失败原样回传错误信息
if (bankMetaVerifyResponse.getCode() == 400) {
bankCard2MetaResp.setCheckResult(ApiConstants.FAILED);
bankCard2MetaResp.setDesc(bankMetaVerifyResponse.getMsg());
return R.ok().setData(bankCard2MetaResp);
}
// 上游业务码 200 data 非空 result 翻译校验结果
if (bankMetaVerifyResponse.getCode() == 200 && bankMetaVerifyResponse.getData() != null) {
int result = bankMetaVerifyResponse.getData().getResult();
if (result == 0) {
// result=0 表示一致
bankCard2MetaResp.setCheckResult(ApiConstants.SUCCESS);
bankCard2MetaResp.setDesc(SUCCESS_MSG);
} else if (result == 1) {
// result=1 表示不一致
bankCard2MetaResp.setCheckResult(ApiConstants.FAILED);
bankCard2MetaResp.setDesc(FAILED_MSG);
} else {
// 其它 2查无原样透传上游 msg
bankCard2MetaResp.setCheckResult(result + "");
bankCard2MetaResp.setDesc(bankMetaVerifyResponse.getData().getMsg());
}
@ -112,6 +142,7 @@ public class BankCard234MetaController extends BaseController {
}
}
// 上游调用失败标记失败并回传错误信息
bankCard2MetaResp.setCheckResult(ApiConstants.FAILED);
bankCard2MetaResp.setDesc(aR.getErrorMsg());

View File

@ -32,25 +32,50 @@ import java.util.Map;
public class AccountOpeningController {
/**
* 百度云开户许可证识别处理器负责调用百度 OCR 接口并返回原始识别结果
*/
@Autowired
private BAccountOpeningHandle bAccountOpeningHandle;
/**
* 开户许可证识别接口
* <p>
* 接收上传的开户许可证图片调用百度云 OCR 服务进行识别
* 并将识别结果中的关键字段账号公司名称核准号法人编号开户银行
* 解析后封装到 {@link AccountOpeningResp} 中返回给前端
* <p>
* 使用 {@link CacheResult} 注解对相同入参的请求结果进行缓存避免重复调用百度云接口浪费配额
*
* @param request 开户许可证识别请求参数包含待识别的图片信息
* @return 识别成功时返回包含 {@link AccountOpeningResp} 的成功响应识别失败时返回错误响应
*/
@RequestMapping("/opening")
@CacheResult
public R recognize(BAccountOpeningRequest request) {
// 构建用于承载识别结果的响应对象
AccountOpeningResp accountOpeningResp = new AccountOpeningResp();
// 调用百度云 OCR 开户许可证识别接口获取原始识别结果
ApiR<Map> bR = bAccountOpeningHandle.handle(request);
if (bR.isSuccess()) {
// 百度云返回的 JSON 结构示例words_result.{字段名}.word.[0]
Map<String, Object> data = bR.getData();
// 账号
accountOpeningResp.setAccount(MapUtils.getByExpr(data, "words_result.账号.word.[0]"));
// 公司名称
accountOpeningResp.setCompanyName(MapUtils.getByExpr(data, "words_result.公司名称.word.[0]"));
// 核准号
accountOpeningResp.setCheckNumber(MapUtils.getByExpr(data, "words_result.核准号.word.[0]"));
// 法人
accountOpeningResp.setLegalPerson(MapUtils.getByExpr(data, "words_result.法人.word.[0]"));
// 编号
accountOpeningResp.setSerialNumber(MapUtils.getByExpr(data, "words_result.编号.word.[0]"));
// 开户银行
accountOpeningResp.setOpenAccountBank(MapUtils.getByExpr(data, "words_result.开户银行.word.[0]"));
return R.ok().setData(accountOpeningResp);
}
// 识别失败返回统一错误响应
return R.error();
}
}

View File

@ -33,49 +33,90 @@ import org.springframework.web.bind.annotation.RestController;
public class BirthCertificateController extends BaseController {
/**
* 百度云出生医学证明识别处理器封装了对百度 OCR 接口的调用细节
*/
@Autowired
private BBirthCertificateHandle birthCertificateHandle;
/**
* 出生医学证明识别接口
* <p>
* 接收前端传入的出生医学证明图片支持 Base64 与图片 URL 两种方式
* 通过百度云 OCR 服务对证件上的 23 个关键字段进行结构化识别
* 并将原始百度响应映射为业务统一的 {@link BirthCertificateResp} 返回给前端
* <p>
* 使用 {@link CacheResult} 注解对相同入参的请求结果进行缓存避免重复调用百度云接口浪费配额
*
* @param request 出生医学证明识别请求参数包含图片的 Base64 URL
* @return 识别成功时返回包含 {@link BirthCertificateResp} 的成功响应失败时返回带错误信息的错误响应
*/
@RequestMapping("/certificate")
@CacheResult
public R recognize(BirthCertificateReq request) {
// 构建用于承载识别结果的业务响应对象
BirthCertificateResp resp = new BirthCertificateResp();
// 将业务请求参数转换为百度云 OCR 接口所需的请求对象
BBirthCertificateRequest birthCertificateRequest = new BBirthCertificateRequest();
birthCertificateRequest.setImageBase64(request.getImageBase64());
birthCertificateRequest.setImageUrl(request.getImageUrl());
// 调用百度云 OCR 出生医学证明识别接口
ApiR<BBirthCertificateResp> bR = birthCertificateHandle.handle(birthCertificateRequest);
if(bR.isSuccess()){
// 取出百度云返回的识别结果并将其中的字段逐项映射到业务响应对象中
BBirthCertificateResp bBirthCertificateResp = bR.getData();
BBirthCertificateResp.WordsResultDTO wordsResultDTO = bBirthCertificateResp.getWordsResult();
// 出生省份
resp.setBirthProvince(wordsResultDTO.getBirthProvince().getWords());
// 出生体重
resp.setBirthWeight(wordsResultDTO.getBirthWeight().getWords());
// 母亲国籍
resp.setMotherNationality(wordsResultDTO.getMotherNationality().getWords());
// 父亲住址
resp.setFatherAddress(wordsResultDTO.getFatherAddress().getWords());
// 母亲民族
resp.setMotherEthnic(wordsResultDTO.getMotherEthnic().getWords());
// 母亲住址
resp.setMotherAddress(wordsResultDTO.getMotherAddress().getWords());
// 出生证编号
resp.setCode(wordsResultDTO.getCode().getWords());
// 新生儿性别
resp.setBabySex(wordsResultDTO.getBabySex().getWords());
// 出生城市
resp.setBirthCity(wordsResultDTO.getBirthCity().getWords());
// 新生儿出生日期
resp.setBabyBirthday(wordsResultDTO.getBabyBirthday().getWords());
// 新生儿姓名
resp.setBabyName(wordsResultDTO.getBabyName().getWords());
// 父亲年龄
resp.setFatherAge(wordsResultDTO.getFatherAge().getWords());
// 父亲民族
resp.setFatherEthnic(wordsResultDTO.getFatherEthnic().getWords());
// 母亲姓名
resp.setMotherName(wordsResultDTO.getMotherName().getWords());
// 母亲身份证号
resp.setMotherIdNumber(wordsResultDTO.getMotherID().getWords());
// 出生身长
resp.setBirthLength(wordsResultDTO.getBirthLength().getWords());
// 孕周
resp.setGestationalAge(wordsResultDTO.getGestationalAge().getWords());
// 出生城市与上方重复赋值保持原有逻辑不变
resp.setBirthCity(wordsResultDTO.getBirthCity().getWords());
// 母亲年龄
resp.setMotherAge(wordsResultDTO.getMotherAge().getWords());
// 接生医院
resp.setHospital(wordsResultDTO.getHospital().getWords());
// 父亲国籍
resp.setFatherNationality(wordsResultDTO.getFatherNationality().getWords());
// 父亲身份证号
resp.setFatherIdNumber(wordsResultDTO.getFatherID().getWords());
// 父亲姓名
resp.setFatherName(wordsResultDTO.getFatherName().getWords());
return R.ok().setData(resp);
}
// 识别失败返回携带百度云错误信息的错误响应
return R.error(bR.getErrorMsg());
}

View File

@ -33,55 +33,104 @@ import org.springframework.web.bind.annotation.RestController;
public class BouseholdRegisterController {
/**
* 百度云户口本识别处理器封装了对百度 OCR 户口本接口的调用细节
*/
@Autowired
private BBouseholdRegisterHandle bBouseholdRegisterHandle;
/**
* 户口本识别接口
* <p>
* 接收前端传入的户口本图片支持 Base64 与图片 URL 两种方式以及户口本面标识
* 调用百度云 OCR 服务对户口本进行结构化识别
* <ul>
* <li>常住人口登记卡22 个字段户号姓名与户主关系性别出生地民族出生日期身份证号等</li>
* <li>户主页5 个字段户别户主姓名户号住址户主页时间</li>
* </ul>
* 并将识别结果映射为业务统一的 {@link BouseholdRegisterResp} 返回给前端
* <p>
* 使用 {@link CacheResult} 注解对相同入参的请求结果进行缓存避免重复调用百度云接口浪费配额
*
* @param request 户口本识别请求参数包含图片的 Base64 URL以及户口本面标识
* @return 识别成功时返回包含 {@link BouseholdRegisterResp} 的成功响应失败时返回带错误信息的错误响应
*/
@RequestMapping("/recognize")
@CacheResult
public R recognize(BouseholdRegisterReq request) {
// 构建用于承载识别结果的业务响应对象
BouseholdRegisterResp resp = new BouseholdRegisterResp();
// 将业务请求参数转换为百度云 OCR 接口所需的请求对象
BBouseholdRegisterRequest bBouseholdRegisterRequest = new BBouseholdRegisterRequest();
// 户口本面常住人口登记卡 / 户主页
bBouseholdRegisterRequest.setHouseholdRegisterSide(request.getHouseholdRegisterSide());
bBouseholdRegisterRequest.setImageBase64(request.getImageBase64());
bBouseholdRegisterRequest.setImageUrl(request.getImageUrl());
// 调用百度云 OCR 户口本识别接口
ApiR<BBouseholdRegisterResp> bR = bBouseholdRegisterHandle.handle(bBouseholdRegisterRequest);
if (bR.isSuccess()) {
// 取出百度云返回的识别结果
BBouseholdRegisterResp bBouseholdRegisterResp = bR.getData();
// 字段识别结果集合将其中的字段逐项映射到业务响应对象中
BBouseholdRegisterResp.WordsResultDTO wordsResultDTO = bBouseholdRegisterResp.getWordsResult();
// 民族
resp.setNation(wordsResultDTO.getNation().getWords());
// 性别
resp.setSex(wordsResultDTO.getSex().getWords());
// 出生日期
resp.setBirthday(wordsResultDTO.getBirthday().getWords());
// 登记日期
resp.setDate(wordsResultDTO.getDate().getWords());
// 出生地
resp.setBirthAddress(wordsResultDTO.getBirthAddress().getWords());
// 姓名
resp.setName(wordsResultDTO.getName().getWords());
// 曾用名
resp.setFormerName(wordsResultDTO.getFormerName().getWords());
// 户号
resp.setHouseholdNum(wordsResultDTO.getHouseholdNum().getWords());
// 何时由何地迁往本市
resp.setWWToCity(wordsResultDTO.getWWToCity().getWords());
// 何时由何地迁往本址
resp.setWWHere(wordsResultDTO.getWWHere().getWords());
// 身份证号
resp.setCardNo(wordsResultDTO.getCardNo().getWords());
// 文化程度
resp.setEducation(wordsResultDTO.getEducation().getWords());
// 与户主关系
resp.setRelationship(wordsResultDTO.getRelationship().getWords());
// 身高
resp.setHeight(wordsResultDTO.getHeight().getWords());
// 职业
resp.setCareer(wordsResultDTO.getCareer().getWords());
// 服务处所
resp.setWorkAddress(wordsResultDTO.getWorkAddress().getWords());
// 籍贯
resp.setHometown(wordsResultDTO.getHometown().getWords());
// 本市县其他住址
resp.setOtherAddress(wordsResultDTO.getOtherAddress().getWords());
// 本市县其他住址与上方重复赋值保持原有逻辑不变
resp.setOtherAddress(wordsResultDTO.getOtherAddress().getWords());
// 宗教信仰
resp.setBelief(wordsResultDTO.getBelief().getWords());
// 血型
resp.setBloodType(wordsResultDTO.getBloodType().getWords());
// 婚姻状况
resp.setMaritalStatus(wordsResultDTO.getMaritalStatus().getWords());
// 兵役状况
resp.setVeteranStatus(wordsResultDTO.getVeteranStatus().getWords());
return R.ok().setData(resp);
}
// 识别失败返回携带百度云错误信息的错误响应
return R.error(bR.getErrorMsg());
}
}

View File

@ -39,20 +39,48 @@ import org.springframework.web.bind.annotation.RestController;
@NotIntercept
public class BusinesslicenseVerificationDetailedController extends BaseController {
/**
* 百度云企业工商信息查询高级版处理器封装了对百度云接口的调用细节
*/
@Autowired
private BBusinesslicenseVerificationDetailedHandle bBusinesslicenseVerificationDetailedHandle;
/**
* 企业工商信息查询高级版接口
* <p>
* 传入企业名称注册号统一社会信用代码中的任意一种通过 {@code verifyNum} 字段
* 调用百度云接口返回企业的全维度信息包括
* <ul>
* <li>工商基本信息分支机构信息企业变更信息</li>
* <li>纳税信息联系信息企业高管信息</li>
* <li>经营异常信息动产抵押信息曾用名信息</li>
* <li>股东信息行政处罚信息行政许可信息</li>
* <li>股权出资信息失信信息被执行信息等</li>
* </ul>
* 注意目前仅支持工商注册的企业认证事业单位律师事务所等暂不支持
* 发生工商变更或刚注册的企业预计在公示核准日期 T+3 个工作日后才可查询
* <p>
* 使用 {@link CacheResult} 注解对相同入参的请求结果进行缓存避免重复调用百度云接口浪费配额
*
* @param request 企业工商信息查询请求参数包含企业名称 / 注册号 / 统一社会信用代码中的任意一种
* @return 查询成功时返回包含企业全维度信息的成功响应失败时返回带错误信息的错误响应
*/
@RequestMapping("/berification")
@CacheResult
public R recognize(BusinesslicenseVerificationDetailedReq request) {
// 将业务请求参数转换为百度云接口所需的请求对象
BBusinesslicenseVerificationDetailedRequest bBusinesslicenseVerificationDetailedRequest = new BBusinesslicenseVerificationDetailedRequest();
// 企业名称 / 注册号 / 统一社会信用代码任意一种
bBusinesslicenseVerificationDetailedRequest.setVerifyNum(request.getVerifyNum());
// 调用百度云企业工商信息查询接口
ApiR<BBusinesslicenseVerificationDetailedResp> bR = bBusinesslicenseVerificationDetailedHandle.handle(bBusinesslicenseVerificationDetailedRequest);
if (bR.isSuccess()) {
// 查询成功直接将百度云返回的 wordsResult企业全维度信息作为业务数据返回
BBusinesslicenseVerificationDetailedResp bBusinesslicenseVerificationDetailedResp = bR.getData();
return R.ok().setData(bBusinesslicenseVerificationDetailedResp.getWordsResult());
}
// 查询失败返回携带百度云错误信息的错误响应
return R.error(bR.getErrorMsg());
}
}

View File

@ -39,63 +39,89 @@ import java.util.Map;
public class DivorceCertificateController extends BaseController {
// 注入百度云离婚证 OCR 识别处理器负责调用百度云接口完成 OCR 识别
@Autowired
private BDivorceCertificateHandle bDivorceCertificateHandle;
/**
* 离婚证识别接口
* 通过百度云 OCR 对离婚证图片进行结构化识别返回 14 个字段
* 男方与女方的姓名身份证件号出生日期国籍性别以及离婚证字号持证人备注登记日期
* @CacheResult 注解用于对识别结果进行缓存避免重复识别相同图片节省调用成本
*/
@RequestMapping("/recognize")
@CacheResult
public R recognize(BDivorceCertificateRequest request) {
// 构建响应对象用于承载识别后的结构化数据
DivorceCertificateResp resp = new DivorceCertificateResp();
// 调用百度云离婚证识别接口获取原始 OCR 返回数据
ApiR<Map> bR = bDivorceCertificateHandle.handle(request);
if (bR.isSuccess()) {
// 取出百度云返回的 words_result 数据按字段路径解析填充到响应对象中
Map<String, Object> data = bR.getData();
// 男方姓名及识别置信度
resp.setManRealName(MapUtils.getByExpr(data, "words_result.姓名_男.word"));
resp.setManRealNameConfidence(MapUtils.getByExpr(data, "words_result.姓名_男.probability"));
// 男方身份证件号及识别置信度
resp.setManIdCard(MapUtils.getByExpr(data, "words_result.身份证件号_男.word"));
resp.setManIdCardConfidence(MapUtils.getByExpr(data, "words_result.身份证件号_男.probability"));
// 男方出生日期及识别置信度
resp.setManBirthday(MapUtils.getByExpr(data, "words_result.出生日期_男.word"));
resp.setManBirthdayConfidence(MapUtils.getByExpr(data, "words_result.出生日期_男.probability"));
// 男方国籍及识别置信度
resp.setManNationality(MapUtils.getByExpr(data, "words_result.国籍_男.word"));
resp.setManNationalityConfidence(MapUtils.getByExpr(data, "words_result.国籍_男.probability"));
// 男方性别及识别置信度
resp.setManGender(MapUtils.getByExpr(data, "words_result.性别_男.word"));
resp.setManGenderConfidence(MapUtils.getByExpr(data, "words_result.性别_男.probability"));
// 女方姓名及识别置信度
resp.setWomanRealName(MapUtils.getByExpr(data, "words_result.姓名_女.word"));
resp.setWomanRealNameConfidence(MapUtils.getByExpr(data, "words_result.姓名_女.probability"));
// 女方身份证件号及识别置信度
resp.setWomanIdCard(MapUtils.getByExpr(data, "words_result.身份证件号_女.word"));
resp.setWomanIdCardConfidence(MapUtils.getByExpr(data, "words_result.身份证件号_女.probability"));
// 女方出生日期及识别置信度
resp.setWomanBirthday(MapUtils.getByExpr(data, "words_result.出生日期_女.word"));
resp.setWomanBirthdayConfidence(MapUtils.getByExpr(data, "words_result.出生日期_女.probability"));
// 女方国籍及识别置信度
resp.setWomanNationality(MapUtils.getByExpr(data, "words_result.国籍_女.word"));
resp.setWomanNationalityConfidence(MapUtils.getByExpr(data, "words_result.国籍_女.probability"));
// 女方性别及识别置信度
resp.setWomanGender(MapUtils.getByExpr(data, "words_result.性别_女.word"));
resp.setWomanGenderConfidence(MapUtils.getByExpr(data, "words_result.性别_女.probability"));
// 登记日期及识别置信度
resp.setRegisterDate(MapUtils.getByExpr(data, "words_result.登记日期.word"));
resp.setRegisterDateConfidence(MapUtils.getByExpr(data, "words_result.登记日期.probability"));
// 离婚证字号及识别置信度
resp.setDivorceNumber(MapUtils.getByExpr(data, "words_result.离婚证字号.word"));
resp.setDivorceNumberConfidence(MapUtils.getByExpr(data, "words_result.离婚证字号.probability"));
// 持证人及识别置信度
resp.setHolderCertified(MapUtils.getByExpr(data, "words_result.持证人.word"));
resp.setHolderCertifiedConfidence(MapUtils.getByExpr(data, "words_result.持证人.probability"));
// 备注及识别置信度
resp.setRemark(MapUtils.getByExpr(data, "words_result.备注.word"));
resp.setRemarkConfidence(MapUtils.getByExpr(data, "words_result.备注.probability"));
// 识别成功返回封装后的结构化数据
return R.ok().setData(resp);
}
// 识别失败返回百度云接口的错误信息
return R.error(bR.getErrorMsg());
}