Browse Source

扫码营业执照

master
蟑螂恶霸 4 weeks ago
parent
commit
03b3255174
  1. 59
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/CrawlerUtil.java
  2. 97
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfEnterpriseInformationController.java
  3. 2
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/ISsztJbxx110497NewService.java
  4. 50
      zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/SsztJbxx110497NewServiceImpl.java
  5. 1
      zdxt-web-client/zdxt-admin-plus-ui/package.json
  6. 1
      zdxt-web-client/zdxt-efcode-enterprise-app/package.json
  7. 8
      zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml

59
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/common/util/CrawlerUtil.java

@ -0,0 +1,59 @@
package com.zdxt.enforcementcode.common.util;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebClientOptions;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import net.sourceforge.htmlunit.corejs.javascript.EcmaError;
import java.util.Objects;
import java.util.logging.LogManager;
/**
* 爬虫 读取页面工具
* @author 陈瑞
* @date 2024-11-11 18:33
*/
public class CrawlerUtil {
public static WebClient webClient;
static {
webClient = new WebClient(BrowserVersion.CHROME);
WebClientOptions options = webClient.getOptions();
options.setUseInsecureSSL(true);
options.setCssEnabled(false);
options.setThrowExceptionOnScriptError(false);
options.setThrowExceptionOnFailingStatusCode(false);
options.setJavaScriptEnabled(true);
options.setTimeout(10000);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
LogManager.getLogManager().reset();
}
/**
* 爬取页面固定数据
* @param url
* @return
* @throws Exception
*/
public static String getCreditCode(String url) throws Exception {
HtmlPage htmlPage = null;
try {
htmlPage = webClient.getPage(url);
} catch (EcmaError e) {
}
if (Objects.nonNull(htmlPage)) {
DomElement codeElement = htmlPage.getElementById("lblEntSCCode");
if (codeElement != null) {
// HtmlUnit 2.55+ 已移除 asText(),改用 asNormalizedText()
String code = codeElement.asNormalizedText();
return code;
}
}
return null;
}
}

97
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/controller/app/enforcement/AppEnfEnterpriseInformationController.java

@ -1,23 +1,34 @@
package com.zdxt.enforcementcode.controller.app.enforcement;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zdxt.enforcementcode.common.util.CrawlerUtil;
import com.zdxt.enforcementcode.domain.EnterpriseInformation;
import com.zdxt.enforcementcode.domain.bo.EnterpriseInformationBo;
import com.zdxt.enforcementcode.domain.vo.EnterpriseInformationVo;
import com.zdxt.enforcementcode.domain.vo.QrCodeGenerateHistoryVo;
import com.zdxt.enforcementcode.service.IEnterpriseInformationService;
import com.zdxt.enforcementcode.service.IQrCodeGenerateHistoryService;
import com.zdxt.enforcementcode.service.ISsztJbxx110497NewService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -32,6 +43,7 @@ public class AppEnfEnterpriseInformationController {
private final IEnterpriseInformationService enterpriseInformationService;
private final IQrCodeGenerateHistoryService qrCodeGenerateHistoryService;
private final ISsztJbxx110497NewService iSsztJbxx110497NewService;
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
/**
@ -51,6 +63,56 @@ public class AppEnfEnterpriseInformationController {
public R<EnterpriseInformationVo> getEntInfoByQRCode(@RequestParam("qrContent") String qrContent) {
log.info("执法端扫码获取企业信息,二维码内容: {}", qrContent);
// 按二维码原文分流:http/https 开头为市监公示 URL,否则为本系统 JSON
if (StrUtil.startWith(qrContent, "http://") || StrUtil.startWith(qrContent, "https://")) {
//解析路由获取企业统一信用代码
String cid = null;
try {
cid = getUrlParams(qrContent, "cid");
if(StringUtils.isNotEmpty(cid)) {
//初始化对象
EnterpriseInformationVo enterpriseVo = null;
//查询企业表中是否存在企业信息
enterpriseVo = enterpriseInformationService.queryByEnterpriseNumber(cid);
log.warn("企业信息表中查询企业信息,企业:{}", JSONObject.toJSONString(enterpriseVo));
//判断企业信息为空
if(BeanUtil.isEmpty(enterpriseVo)){
enterpriseVo = iSsztJbxx110497NewService.queryByTyshxydmOne(cid);
if(BeanUtil.isNotEmpty(enterpriseVo) &&
StringUtils.isNotEmpty(enterpriseVo.getEnterpriseNumber())){
//默认ID
enterpriseVo.setId(IdUtil.simpleUUID());
//企业表中新增
EnterpriseInformation enterprise = new EnterpriseInformation();
BeanUtils.copyProperties(enterpriseVo, enterprise);
int i = enterpriseInformationService.insertEnterpriseInformation(enterprise);
if(i > 0){
log.info("企业信息表中新增成功,新增企业:{}", JSONObject.toJSONString(enterpriseVo));
}else{
log.info("企业信息表中新增失败,失败企业:{}", JSONObject.toJSONString(enterpriseVo));
}
}
}
return R.ok(enterpriseVo);
} else {
log.error("企业营业执照二维码中不存在企业统一信用代码,访问地址:{}",qrContent);
//爬取页面统一信用代码
String s = CrawlerUtil.getCreditCode(qrContent);
if (StringUtils.isNotEmpty(s)) {
EnterpriseInformationVo enterpriseVo = iSsztJbxx110497NewService.queryByTyshxydmOne(s);
return R.ok(enterpriseVo);
}
}
} catch (Exception e) {
log.warn("营业执照解析错误: {}", cid);
}
log.info("企业信息表中查询企业信息,统一信用代码:{}", cid);
log.info("识别为市监公示系统二维码,后续解析待补充,原始内容: {}", qrContent);
return R.fail("无法通过该二维码识别企业信息");
}
// 1. 判断 qrContent 是否为 JSON,是则转为 Map,否则打印日志
Map<String, String> qrMap = null;
try {
@ -211,4 +273,39 @@ public class AppEnfEnterpriseInformationController {
log.info("执法端查询企业信息详情成功,企业: {}", enterprise.getEnterpriseName());
return R.ok(enterprise);
}
public String getUrlParams(String urlStr,String paramKey) throws IOException {
URL url = new URL(urlStr);
URLConnection connection = url.openConnection();
// 获取查询字符串,即URL中"?"后面的部分
String query = url.getQuery();
// 将查询字符串拆分为键值对
Map<String, String> queryParams = new HashMap<>();
if (query != null) {
String split_flag = "&";
if (query.indexOf("&") < 0) {
if (query.indexOf("&") < 0) {
split_flag = "%26";
} else {
split_flag = "&";
}
} else {
split_flag = "&";
}
// String split_flag = query.indexOf("&") < 0 ?"%26":"&"; // 有些链接的 & 会被转义成 %26
String[] pairs = query.split(split_flag);
for (String pair : pairs) {
int idx = pair.indexOf("=");
String key = pair.substring(0, idx);
String value = pair.substring(idx + 1);
queryParams.put(key, value);
}
}
// 输出参数
queryParams.forEach((k, v) -> System.out.println(k + " = " + v));
return queryParams.get(paramKey);
}
}

2
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/ISsztJbxx110497NewService.java

@ -1,5 +1,6 @@
package com.zdxt.enforcementcode.service;
import com.zdxt.enforcementcode.domain.vo.EnterpriseInformationVo;
import com.zdxt.enforcementcode.domain.vo.SsztJbxx110497NewVo;
import com.zdxt.enforcementcode.domain.bo.SsztJbxx110497NewBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@ -48,6 +49,7 @@ public interface ISsztJbxx110497NewService {
* @return 企业信息
*/
List<SsztJbxx110497NewVo> queryByTyshxydm(String tyshxydm);
EnterpriseInformationVo queryByTyshxydmOne(String tyshxydm);
/**
* 新增请填写功能名称

50
zdxt-modules/zdxt-enforcement-code/src/main/java/com/zdxt/enforcementcode/service/impl/SsztJbxx110497NewServiceImpl.java

@ -1,6 +1,7 @@
package com.zdxt.enforcementcode.service.impl;
import com.zdxt.enforcementcode.domain.bean.SsztJbxx110497New;
import com.zdxt.enforcementcode.domain.vo.EnterpriseInformationVo;
import com.zdxt.enforcementcode.mapper.SsztJbxx110497NewMapper;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
@ -96,6 +97,55 @@ public class SsztJbxx110497NewServiceImpl implements ISsztJbxx110497NewService {
return result;
}
@Override
public EnterpriseInformationVo queryByTyshxydmOne(String tyshxydm) {
if (StringUtils.isBlank(tyshxydm)) {
log.warn("统一社会信用代码不能为空");
return null;
}
LambdaQueryWrapper<SsztJbxx110497New> lqw = Wrappers.lambdaQuery();
lqw.eq(SsztJbxx110497New::getTyshxydm, tyshxydm.trim());
// 市监可能有重复数据,取最新一条
lqw.last("ORDER BY updatetime DESC LIMIT 1");
SsztJbxx110497NewVo ssztJbxx110497 = baseMapper.selectVoOne(lqw);
if (ssztJbxx110497 == null) {
log.info("根据统一社会信用代码[{}]未查询到企业信息", tyshxydm);
return null;
}
log.info("根据统一社会信用代码[{}]查询到企业信息", tyshxydm);
EnterpriseInformationVo enterpriseInformation = new EnterpriseInformationVo();
//企业名称
enterpriseInformation.setEnterpriseName(ssztJbxx110497.getQymc());
//统一信用代码
enterpriseInformation.setEnterpriseNumber(ssztJbxx110497.getTyshxydm());
//法定代表人
enterpriseInformation.setLegalPerson(ssztJbxx110497.getFddbr());
//成立日期
if (StringUtils.isNotBlank(ssztJbxx110497.getClrq())) {
try {
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
enterpriseInformation.setEstablishmentTime(sdf.parse(ssztJbxx110497.getClrq()));
} catch (Exception e) {
log.warn("成立日期格式转换失败: {}", ssztJbxx110497.getClrq(), e);
}
}
//经营期限-开始
enterpriseInformation.setOperatingTerm(ssztJbxx110497.getJyqxq());
//经营期限-结束
enterpriseInformation.setOperatingTermEnd(ssztJbxx110497.getJyqxz());
//注册资本
enterpriseInformation.setRegisteredCapital(ssztJbxx110497.getZczb() != null ? String.valueOf(ssztJbxx110497.getZczb()) : null);
//经营范围
enterpriseInformation.setBusinessScope(ssztJbxx110497.getJyfw());
//注册地址
enterpriseInformation.setEnterpriseAddress(ssztJbxx110497.getJycs());
//TODO 企业类型
return enterpriseInformation;
}
private LambdaQueryWrapper<SsztJbxx110497New> buildQueryWrapper(SsztJbxx110497NewBo bo) {
Map<String, Object> params = bo.getParams();

1
zdxt-web-client/zdxt-admin-plus-ui/package.json

@ -12,6 +12,7 @@
"vite-server-web-supervision-dev-wmy": "vite serve --mode development-wmy-cust",
"build:prod": "vite build --mode production --outDir dist/prod",
"build:dev": "vite build --mode development --outDir dist/dev",
"build-zdxt-admin-plus-ui:dev": "vite build --mode development --outDir dist/dev",
"build-zdxt-admin-plus-ui:prod": "vite build --mode production --outDir dist/prod",
"zdxt-admin-plus-ui-preview": "vite preview --outDir dist/prod",
"zdxt-admin-plus-ui-lint:eslint": "eslint",

1
zdxt-web-client/zdxt-efcode-enterprise-app/package.json

@ -10,6 +10,7 @@
"vite-server-app:enterprise-dev-wmy": "vite --mode enterprise-dev-wmy",
"build:dev": "vite build --mode enterprise-dev --outDir dist/enterprise-dev",
"build:prod": "vite build --mode enterprise-prod --outDir dist/enterprise-prod",
"build-app:enterprise-dev": "vite build --mode enterprise-dev --outDir dist/enterprise-dev",
"build-app:enterprise-prod": "vite build --mode enterprise-prod --outDir dist/enterprise-prod"
},
"dependencies": {

8
zdxt-web-server/zdxt-admin-web-server/src/main/resources/application-dev.yml

@ -1,8 +1,8 @@
zdxt:
file:
# Windows/Linux 本地开发均可用;生产环境在 application-prod.yml 覆盖
# upload-path: D:\zfjdm\uploadPath
upload-path: /usr/local/uploadPath
upload-path: D:\zfjdm\uploadPath
# upload-path: /usr/local/uploadPath
# upload-path: /Users/vincent/uploadPath
url-prefix: /profile
qr_code_url: /usr/local/uploads/zfjd_logo.png
@ -110,14 +110,14 @@ spring.data:
redis:
# 地址
# host: 139.186.148.21
host: 172.16.20.72
host: 127.0.0.1
# 端口,默认为6379
port: 6379
# 数据库索引
database: 0
# redis 密码必须配置
# password: zdxt@123
password:
# password:
# 连接超时时间
timeout: 10s
# 是否开启ssl

Loading…
Cancel
Save