新增和完善业务数据

This commit is contained in:
huzhengkao 2025-06-06 15:22:24 +08:00
parent 19bfddd5fd
commit c5d6bc298b
29 changed files with 764 additions and 109 deletions

View File

@ -60,7 +60,7 @@ public class ProvTestClient {
public static void main(String[] args) throws Exception {
//数据文件内容主业务类型 10基础信息数据 20应用信息数据
//subType数据文件内容子业务类型 详见数据类型字典表 基本信息(1011-10199001-9002) 应用信息2011-20202051-2053
testProv("1011");
testProv("1013");
}

View File

@ -0,0 +1,18 @@
package com.alihealth.d2d.provtest.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author Jason 证书配置
* @date 2025年06月06日 14:09:26
*/
@Component
@ConfigurationProperties(prefix = "cert")
@Data
public class CertConfig {
private String path;
private String password;
private String algorithm;
}

View File

@ -2,6 +2,7 @@ package com.alihealth.d2d.provtest.controller;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alihealth.d2d.provtest.config.CertConfig;
import com.alihealth.d2d.provtest.domain.DomesticDrugProductionApplyInfo;
import com.alihealth.d2d.provtest.domain.DomesticPharmaBaseInfo;
import com.alihealth.d2d.provtest.domain.ReceiveDataLog;
@ -46,18 +47,9 @@ import java.util.Map;
public class ProvTestServerController {
Logger logger = LoggerFactory.getLogger(getClass());
/**
* 证书地址
*/
private static final String PFX_FILE_PATH = "D:\\ynyp\\药品追溯\\d2d\\yunnan.pfx";
/**
* 证书密码
*/
private static final String PFX_PASSWORD = "12345678";
/**
* 加密算法
*/
private static final String algorithm = "RSA";
@Autowired
private CertManager certManager;
@Autowired
@ -104,12 +96,12 @@ public class ProvTestServerController {
EventPojo eventPojo = JSON.parseObject(event, EventPojo.class);
//获取私钥
String privateKey = getPrivateKey();
String privateKey = certManager.getPrivateKey();
logger.info("privateKey:{}",privateKey);
String de = testDecrypt(privateKey,eventPojo.getData());
String de = certManager.testDecrypt(privateKey,eventPojo.getData());
String xml = StreamUtil.getUnStreamContent(de);
logger.info("解密之后的文件内容:{}", xml);
@ -125,18 +117,6 @@ public class ProvTestServerController {
log.setVer(ver);
receiveDataLogService.save(log);
//解析xml
// List<DomesticPharmaBaseInfo> list= XmlStringParser.parseVaccineManufacturers(xml,eventPojo.getSubType());
//解析并保存数据
// XmlStringParser.parseXml(xml, "1011", data -> {
// domesticPharmaBaseInfoService.save((DomesticPharmaBaseInfo) data);
// });
// List<DomesticPharmaBaseInfo> producers = xmlParserService.parseXml1(
// xml,
// DomesticPharmaBaseInfo.class
// );
//解析并处理数据
processingService.processEvent(eventPojo, xml,eventId);
@ -149,67 +129,5 @@ public class ProvTestServerController {
}
/**
* 私钥解密
* @param key
* @param data
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws NoSuchPaddingException
* @throws InvalidKeySpecException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws IOException
*/
public static String testDecrypt(String key,String data) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException, IOException{
byte[] decode = java.util.Base64.getDecoder().decode(key);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(algorithm).generatePrivate(new PKCS8EncodedKeySpec(decode));
//RSA解密
Cipher ci = Cipher.getInstance(algorithm);
ci.init(Cipher.DECRYPT_MODE, priKey);
byte[] bytes = java.util.Base64.getDecoder().decode(data);
int inputLen = bytes.length;
int offLen = 0;
int i = 0;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
while(inputLen - offLen > 0){
byte[] cache;
if(inputLen - offLen > 128){
cache = ci.doFinal(bytes,offLen,128);
}else{
cache = ci.doFinal(bytes,offLen,inputLen - offLen);
}
byteArrayOutputStream.write(cache);
i++;
offLen = 128 * i;
}
byteArrayOutputStream.close();
byte[] byteArray = byteArrayOutputStream.toByteArray();
return new String(byteArray);
}
/**
* 获取私钥
* @return
* @throws Exception
*/
private static String getPrivateKey() throws Exception {
KeyStore keyStore = KeyStoreUtil.loadKetStore(PFX_FILE_PATH,PFX_PASSWORD);
return Base64.encode(KeyStoreUtil.getPrivateKey(keyStore, PFX_PASSWORD).getEncoded());
}
/**
* 获取公钥
* @return
* @throws Exception
*/
private static String getPublicKey() throws Exception {
KeyStore keyStore = KeyStoreUtil.loadKetStore(PFX_FILE_PATH,PFX_PASSWORD);
PublicKey publicKey = KeyStoreUtil.getPublicKey(keyStore);
return Base64.encode(publicKey.getEncoded());
}
}

View File

@ -0,0 +1,139 @@
package com.alihealth.d2d.provtest.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
* 境外药品生产企业基本信息数据子集
* </p>
*
* @author Jason
* @since 2025-06-06
*/
@Data
@TableName("abroad_pharma_base_info")
public class AbroadPharmaBaseInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 事件流水号
*/
private String eventId;
/**
* 境外药品生产企业代码
*/
@JacksonXmlProperty(localName = "JWYPSCQYDM")
private String jwypscqydm;
/**
* 境外药品生产企业名称中文
*/
@JacksonXmlProperty(localName = "JWYPSCQYMCZW")
private String jwypscqymczw;
/**
* 境外药品生产企业名称英文
*/
@JacksonXmlProperty(localName = "JWYPSCQYMCYW")
private String jwypscqymcyw;
/**
* 境外药品生产企业地址中文
*/
@JacksonXmlProperty(localName = "JWYPSCQYDZZW")
private String jwypscqydzzw;
/**
* 境外药品生产企业地址英文
*/
@JacksonXmlProperty(localName = "JWYPSCQYDZYW")
private String jwypscqydzyw;
/**
* 境外药品生产企业国家或地区
*/
@JacksonXmlProperty(localName = "JWYPSCQYGJHDQ")
private String jwypscqygjhdq;
/**
* 境外药品生产企业国家或地区中文
*/
@JacksonXmlProperty(localName = "JWYPSCQYGJHDQZW")
private String jwypscqygjhdqzw;
/**
* 境外药品生产企业国家或地区英文
*/
@JacksonXmlProperty(localName = "JWYPSCQYGJHDQYW")
private String jwypscqygjhdqyw;
/**
* 固定电话号码
*/
@JacksonXmlProperty(localName = "GDDHHM")
private String gddhhm;
/**
* 传真号码
*/
@JacksonXmlProperty(localName = "CZHM")
private String czhm;
/**
* 电子信箱
*/
@JacksonXmlProperty(localName = "DZXX")
private String dzxx;
/**
* 企业网址
*/
@JacksonXmlProperty(localName = "QYWZ")
private String qywz;
/**
* 联系人
*/
@JacksonXmlProperty(localName = "LXR")
private String lxr;
/**
* 联系电话
*/
@JacksonXmlProperty(localName = "LXDH")
private String lxdh;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 是否删除(0- 1-)
*/
private Integer isDeleted;
}

View File

@ -0,0 +1,156 @@
package com.alihealth.d2d.provtest.domain;
import com.alihealth.d2d.provtest.utils.LocalDateDeserializer;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* <p>
* 药品生产许可证基本信息数据子集
* </p>
*
* @author Jason
* @since 2025-06-06
*/
@Getter
@Setter
@TableName("pharmaceutical_production_license_base_info")
public class PharmaceuticalProductionLicenseBaseInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 事件流水号
*/
private String eventId;
/**
* 生产许可证编号
*/
@JacksonXmlProperty(localName = "SCXKZBH")
private String scxkzbh;
/**
* 境内药品生产企业名称
*/
@JacksonXmlProperty(localName = "JNYPSCQYMC")
private String jnypscqymc;
/**
* 统一社会信用代码
*/
@JacksonXmlProperty(localName = "TYSHXYDM")
private String tyshxydm;
/**
* 注册地址
*/
@JacksonXmlProperty(localName = "ZCDZ")
private String zcdz;
/**
* 法定代表人
*/
@JacksonXmlProperty(localName = "FDDBR")
private String fddbr;
/**
* 企业负责人
*/
@JacksonXmlProperty(localName = "QYFZR")
private String qyfzr;
/**
* 质量负责人
*/
@JacksonXmlProperty(localName = "ZLFZR")
private String zlfzr;
/**
* 分类码
*/
@JacksonXmlProperty(localName = "FLM")
private String flm;
/**
* 有效期
*/
@JacksonXmlProperty(localName = "YXQ")
@JsonDeserialize(using = LocalDateDeserializer.class)
private LocalDate yxq;
/**
* 生产地址
*/
@JacksonXmlProperty(localName = "SCDZ")
private String scdz;
/**
* 生产范围
*/
@JacksonXmlProperty(localName = "SCFW")
private String scfw;
/**
* 发证机关
*/
@JacksonXmlProperty(localName = "FZJG")
private String fzjg;
/**
* 签发人
*/
@JacksonXmlProperty(localName = "QFR")
private String qfr;
/**
* 签发日期
*/
@JacksonXmlProperty(localName = "QFRQ")
@JsonDeserialize(using = LocalDateDeserializer.class)
private LocalDate qfrq;
/**
* 日常监督管理机构
*/
@JacksonXmlProperty(localName = "RCJDGLJG")
private String rcjdgljg;
/**
* 投诉举报电话
*/
@JacksonXmlProperty(localName = "SCJBDH")
private String scjbdh;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 是否删除(0- 1-)
*/
private Integer isDeleted;
}

View File

@ -17,7 +17,7 @@ import java.time.LocalDateTime;
//@MappedSuperclass
@Data
public abstract class BaseEntity<T extends BaseEntity<T>> implements XmlEntity<T>{
@TableId(type = IdType.AUTO) // 明确指定使用数据库自增
@TableId(value = "id", type = IdType.AUTO) // 明确指定使用数据库自增
private Long id;
@Column(name = "event_id")

View File

@ -16,6 +16,7 @@ import java.nio.file.Paths;
public class CodeGenerator {
public static void main(String[] args) {
String tables="pharmaceutical_production_license_base_info";// 生成多个指定表,逗号分隔
FastAutoGenerator.create("jdbc:mysql://47.109.202.121:3306/supervisionx_trace_data", "root", "TCCT3.1415926")
.globalConfig(builder -> builder
.author("Jason")
@ -23,7 +24,7 @@ public class CodeGenerator {
.commentDate("yyyy-MM-dd")
)
.packageConfig(builder -> builder
.parent("com.alihealth.d2d.provtest.generator")
.parent("com.alihealth.d2d.provtest.generator.temp")
.entity("domain")
.mapper("mapper")
.service("service")
@ -31,11 +32,12 @@ public class CodeGenerator {
.xml("mapper.xml")
)
.strategyConfig(builder -> builder
.addInclude(tables)
.entityBuilder()
.enableLombok()
)
.templateEngine(new FreemarkerTemplateEngine())
.execute();
System.out.println("数据表"+tables+"--------生成实体成功!!");
}
}

View File

@ -0,0 +1,16 @@
package com.alihealth.d2d.provtest.mapper;
import com.alihealth.d2d.provtest.domain.AbroadPharmaBaseInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 境外药品生产企业基本信息数据子集 Mapper 接口
* </p>
*
* @author Jason
* @since 2025-06-06
*/
public interface AbroadPharmaBaseInfoMapper extends BaseMapper<AbroadPharmaBaseInfo> {
}

View File

@ -0,0 +1,16 @@
package com.alihealth.d2d.provtest.mapper;
import com.alihealth.d2d.provtest.domain.PharmaceuticalProductionLicenseBaseInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 药品生产许可证基本信息数据子集 Mapper 接口
* </p>
*
* @author Jason
* @since 2025-06-06
*/
public interface PharmaceuticalProductionLicenseBaseInfoMapper extends BaseMapper<PharmaceuticalProductionLicenseBaseInfo> {
}

View File

@ -0,0 +1,16 @@
package com.alihealth.d2d.provtest.service;
import com.alihealth.d2d.provtest.domain.AbroadPharmaBaseInfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 境外药品生产企业基本信息数据子集 服务类
* </p>
*
* @author Jason
* @since 2025-06-06
*/
public interface IAbroadPharmaBaseInfoService extends IService<AbroadPharmaBaseInfo> {
}

View File

@ -0,0 +1,16 @@
package com.alihealth.d2d.provtest.service;
import com.alihealth.d2d.provtest.domain.PharmaceuticalProductionLicenseBaseInfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 药品生产许可证基本信息数据子集 服务类
* </p>
*
* @author Jason
* @since 2025-06-06
*/
public interface IPharmaceuticalProductionLicenseBaseInfoService extends IService<PharmaceuticalProductionLicenseBaseInfo> {
}

View File

@ -3,8 +3,11 @@ package com.alihealth.d2d.provtest.service;
import com.alihealth.d2d.provtest.domain.DomesticPharmaBaseInfo;
import com.alihealth.d2d.provtest.entity.VTTSBasic;
import com.alihealth.d2d.provtest.entity.VTTSEventS;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.xml.bind.*;
@ -24,6 +27,7 @@ import java.util.stream.Collectors;
*/
@Service
public class XmlParserService {
protected final Logger log = LoggerFactory.getLogger(getClass());
private static final Map<Class<?>, JAXBContext> CONTEXT_CACHE = new ConcurrentHashMap<>();
@ -38,12 +42,17 @@ public class XmlParserService {
* @param <T>
* @throws IOException
*/
public <T> VTTSBasic<T> parseDataXml(String xml, Class<T> dataType) throws IOException {
public <T> VTTSBasic<T> parseDataXml(String xml, Class<T> dataType) {
JavaType type = xmlMapper.getTypeFactory().constructParametricType(
VTTSBasic.class,
dataType
);
return xmlMapper.readValue(xml, type);
try {
return xmlMapper.readValue(xml, type);
} catch (JsonProcessingException e) {
log.error("数据解析错误:"+e.getMessage());
throw new RuntimeException(e);
}
}
/**

View File

@ -52,15 +52,10 @@ public class SubType1011Handler extends AbstractEventDataHandler<DomesticPharmaB
@Override
public void handleBase(String xml,String eventId) {
VTTSBasic<DomesticPharmaBaseInfo> result = null;
try {
result = xmlParserService.parseDataXml(
VTTSBasic<DomesticPharmaBaseInfo> result = xmlParserService.parseDataXml(
xml,
DomesticPharmaBaseInfo.class
);
} catch (IOException e) {
throw new RuntimeException(e);
}
List<DomesticPharmaBaseInfo> list = result.getDataset();
if(list!=null && !list.isEmpty()){
list.stream()

View File

@ -0,0 +1,74 @@
package com.alihealth.d2d.provtest.service.handle.business;
import com.alihealth.d2d.provtest.domain.AbroadPharmaBaseInfo;
import com.alihealth.d2d.provtest.domain.DomesticPharmaBaseInfo;
import com.alihealth.d2d.provtest.entity.EventBody;
import com.alihealth.d2d.provtest.entity.InstanceDetail;
import com.alihealth.d2d.provtest.entity.ItemDetail;
import com.alihealth.d2d.provtest.entity.VTTSBasic;
import com.alihealth.d2d.provtest.service.IAbroadPharmaBaseInfoService;
import com.alihealth.d2d.provtest.service.IDomesticPharmaBaseInfoService;
import com.alihealth.d2d.provtest.service.XmlParserService;
import com.alihealth.d2d.provtest.service.handle.AbstractEventDataHandler;
import com.alihealth.d2d.provtest.service.handle.EventSubType;
import com.baomidou.mybatisplus.extension.service.IService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.List;
/**
* @author Jason 境外药品生产企业基本信息数据子集
* @date 2025年06月05日 11:14:43
*/
@Service
@EventSubType("1012")
public class SubType1012Handler extends AbstractEventDataHandler<AbroadPharmaBaseInfo> {
protected final Logger log = LoggerFactory.getLogger(getClass());
@Autowired
private IAbroadPharmaBaseInfoService service;
@Autowired
private XmlParserService xmlParserService;
@Override
protected Class<AbroadPharmaBaseInfo> getEntityClass() {
return AbroadPharmaBaseInfo.class;
}
@Override
protected IService<AbroadPharmaBaseInfo> getService() {
return service;
}
@Override
protected AbroadPharmaBaseInfo convertToEntity(EventBody eventBody, ItemDetail item, InstanceDetail instance) {
return null;
}
@Override
public String getSubType() {
return "1012";
}
@Override
public void handleBase(String xml,String eventId) {
VTTSBasic<AbroadPharmaBaseInfo> result = xmlParserService.parseDataXml(
xml,
AbroadPharmaBaseInfo.class
);
List<AbroadPharmaBaseInfo> list = result.getDataset();
if(list!=null && !list.isEmpty()){
list.stream()
.forEach(item -> {
item.setEventId(eventId);
});
getService().saveBatch(list);
log.info("数据类型:"+getSubType()+",入库的数据条数:{}", list.size());
}
}
}

View File

@ -0,0 +1,73 @@
package com.alihealth.d2d.provtest.service.handle.business;
import com.alihealth.d2d.provtest.domain.AbroadPharmaBaseInfo;
import com.alihealth.d2d.provtest.domain.PharmaceuticalProductionLicenseBaseInfo;
import com.alihealth.d2d.provtest.entity.EventBody;
import com.alihealth.d2d.provtest.entity.InstanceDetail;
import com.alihealth.d2d.provtest.entity.ItemDetail;
import com.alihealth.d2d.provtest.entity.VTTSBasic;
import com.alihealth.d2d.provtest.service.IAbroadPharmaBaseInfoService;
import com.alihealth.d2d.provtest.service.IPharmaceuticalProductionLicenseBaseInfoService;
import com.alihealth.d2d.provtest.service.XmlParserService;
import com.alihealth.d2d.provtest.service.handle.AbstractEventDataHandler;
import com.alihealth.d2d.provtest.service.handle.EventSubType;
import com.baomidou.mybatisplus.extension.service.IService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author Jason 药品生产许可证基本信息数据子集
* @date 2025年06月05日 11:14:43
*/
@Service
@EventSubType("1013")
public class SubType1013Handler extends AbstractEventDataHandler<PharmaceuticalProductionLicenseBaseInfo> {
protected final Logger log = LoggerFactory.getLogger(getClass());
@Autowired
private IPharmaceuticalProductionLicenseBaseInfoService service;
@Autowired
private XmlParserService xmlParserService;
@Override
protected Class<PharmaceuticalProductionLicenseBaseInfo> getEntityClass() {
return PharmaceuticalProductionLicenseBaseInfo.class;
}
@Override
protected IService<PharmaceuticalProductionLicenseBaseInfo> getService() {
return service;
}
@Override
protected PharmaceuticalProductionLicenseBaseInfo convertToEntity(EventBody eventBody, ItemDetail item, InstanceDetail instance) {
return null;
}
@Override
public String getSubType() {
return "1013";
}
@Override
public void handleBase(String xml,String eventId) {
VTTSBasic<PharmaceuticalProductionLicenseBaseInfo> result = xmlParserService.parseDataXml(
xml,
PharmaceuticalProductionLicenseBaseInfo.class
);
List<PharmaceuticalProductionLicenseBaseInfo> list = result.getDataset();
if(list!=null && !list.isEmpty()){
list.stream()
.forEach(item -> {
item.setEventId(eventId);
});
getService().saveBatch(list);
log.info("数据类型:"+getSubType()+",入库的数据条数:{}", list.size());
}
}
}

View File

@ -0,0 +1,20 @@
package com.alihealth.d2d.provtest.service.impl;
import com.alihealth.d2d.provtest.domain.AbroadPharmaBaseInfo;
import com.alihealth.d2d.provtest.mapper.AbroadPharmaBaseInfoMapper;
import com.alihealth.d2d.provtest.service.IAbroadPharmaBaseInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 境外药品生产企业基本信息数据子集 服务实现类
* </p>
*
* @author Jason
* @since 2025-06-06
*/
@Service
public class AbroadPharmaBaseInfoServiceImpl extends ServiceImpl<AbroadPharmaBaseInfoMapper, AbroadPharmaBaseInfo> implements IAbroadPharmaBaseInfoService {
}

View File

@ -0,0 +1,20 @@
package com.alihealth.d2d.provtest.service.impl;
import com.alihealth.d2d.provtest.domain.PharmaceuticalProductionLicenseBaseInfo;
import com.alihealth.d2d.provtest.mapper.PharmaceuticalProductionLicenseBaseInfoMapper;
import com.alihealth.d2d.provtest.service.IPharmaceuticalProductionLicenseBaseInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 药品生产许可证基本信息数据子集 服务实现类
* </p>
*
* @author Jason
* @since 2025-06-06
*/
@Service
public class PharmaceuticalProductionLicenseBaseInfoServiceImpl extends ServiceImpl<PharmaceuticalProductionLicenseBaseInfoMapper, PharmaceuticalProductionLicenseBaseInfo> implements IPharmaceuticalProductionLicenseBaseInfoService {
}

View File

@ -0,0 +1,125 @@
package com.alihealth.d2d.provtest.utils;
import com.alihealth.d2d.provtest.config.CertConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
/**
* @author Jason 证书管理
* @date 2025年06月06日 14:24:09
*/
@Component
public class CertManager {
private static volatile String privateKey;
private static volatile String publicKey;
@Autowired
private CertConfig certConfig;
/**
* 私钥解密
* @param key
* @param data
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
* @throws NoSuchPaddingException
* @throws InvalidKeySpecException
* @throws BadPaddingException
* @throws IllegalBlockSizeException
* @throws IOException
*/
public String testDecrypt(String key,String data) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException, IOException{
byte[] decode = java.util.Base64.getDecoder().decode(key);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(certConfig.getAlgorithm()).generatePrivate(new PKCS8EncodedKeySpec(decode));
//RSA解密
Cipher ci = Cipher.getInstance(certConfig.getAlgorithm());
ci.init(Cipher.DECRYPT_MODE, priKey);
byte[] bytes = java.util.Base64.getDecoder().decode(data);
int inputLen = bytes.length;
int offLen = 0;
int i = 0;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
while(inputLen - offLen > 0){
byte[] cache;
if(inputLen - offLen > 128){
cache = ci.doFinal(bytes,offLen,128);
}else{
cache = ci.doFinal(bytes,offLen,inputLen - offLen);
}
byteArrayOutputStream.write(cache);
i++;
offLen = 128 * i;
}
byteArrayOutputStream.close();
byte[] byteArray = byteArrayOutputStream.toByteArray();
return new String(byteArray);
}
@PostConstruct
public synchronized void init() throws Exception {
if (privateKey == null) {
privateKey = initPrivateKey();
}
if(publicKey == null) {
publicKey = initPublicKey();
}
}
/**
* 获取私钥
* @return
* @throws Exception
*/
public String initPrivateKey() throws Exception {
KeyStore keyStore = KeyStoreUtil.loadKetStore(certConfig.getPath(),certConfig.getPassword());
return Base64.encode(KeyStoreUtil.getPrivateKey(keyStore, certConfig.getPassword()).getEncoded());
}
public String getPrivateKey() {
if (privateKey == null) {
throw new IllegalStateException("获取私钥失败,证书未初始化");
}
return privateKey;
}
/**
* 获取公钥
* @return
* @throws Exception
*/
public String initPublicKey() throws Exception {
KeyStore keyStore = KeyStoreUtil.loadKetStore(certConfig.getPath(),certConfig.getPassword());
PublicKey publicKey = KeyStoreUtil.getPublicKey(keyStore);
return Base64.encode(publicKey.getEncoded());
}
public String getPublicKey() {
if (publicKey == null) {
throw new IllegalStateException("获取公钥失败,证书未初始化");
}
return publicKey;
}
}

View File

@ -77,7 +77,6 @@ public class KeyStoreUtil {
* 获取私钥
*
* @param keyStore
* @param keyAlias
* @param pfxPassword
* @return
*/
@ -103,7 +102,6 @@ public class KeyStoreUtil {
* 获取公钥
*
* @param keyStore
* @param keyAlias
* @return
*/
public static PublicKey getPublicKey(KeyStore keyStore) {
@ -183,7 +181,7 @@ public class KeyStoreUtil {
/**
* 私钥解密
*
* @param data
* @param encodestr
* @param privateKey
* @return
* @throws Exception
@ -201,7 +199,6 @@ public class KeyStoreUtil {
* 验证Certificate是否过期或无效
*
* @param keyStore
* @param keyAlias
* @param date
* 当前时间
* @return
@ -265,8 +262,8 @@ public class KeyStoreUtil {
* 验证签名
*
* @param keyStore
* @param pfxPassword
* @param dataStr
* @param signStr
* @return
*/
public static boolean verfySignature(KeyStore keyStore, String dataStr,
@ -294,9 +291,8 @@ public class KeyStoreUtil {
/**
* 验证签名使用公钥
*
* @param keyStore
* @param pfxPassword
* @param dataStr
* @param signStr
* @return
*/
public static boolean verfySignatureWithPublic(byte[] publicKeyArr,

View File

@ -0,0 +1,23 @@
package com.alihealth.d2d.provtest.utils;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
* @author Jason
* @date 2025年06月06日 15:06:07
*/
public class LocalDateDeserializer extends JsonDeserializer<LocalDate> {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
@Override
public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String dateStr = p.getText();
return LocalDate.parse(dateStr, FORMATTER);
}
}

View File

@ -31,4 +31,12 @@ logging:
org.springframework: WARN
com.alihealth.d2d.provtest: DEBUG
mybatis: DEBUG
com.baomidou.mybatisplus: DEBUG
com.baomidou.mybatisplus: DEBUG
cert:
#本地
#path: D:\ynyp\药品追溯\d2d\yunnan.pfx
#服务器
path: /data/cert/d2d/yunnan.pfx
password: 12345678
algorithm: RSA

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.alihealth.d2d.provtest.generator.mapper.AbroadPharmaBaseInfoMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.alihealth.d2d.provtest.generator.temp.mapper.PharmaceuticalProductionLicenseBaseInfoMapper">
</mapper>

View File

@ -31,4 +31,9 @@ logging:
org.springframework: WARN
com.alihealth.d2d.provtest: DEBUG
mybatis: DEBUG
com.baomidou.mybatisplus: DEBUG
com.baomidou.mybatisplus: DEBUG
cert:
path: D:\ynyp\药品追溯\d2d\yunnan.pfx
password: 12345678
algorithm: RSA