版本更新

This commit is contained in:
Zhang.WH
2025-10-16 17:17:24 +08:00
parent d23a594a4b
commit f515bb8fbb
600 changed files with 7881 additions and 35954 deletions

View File

@@ -0,0 +1,11 @@
package com.openhis.web.externalintegration.appservice;
/**
* BPC商户接口Service接口
*
* @author GuoRui
* @date 2025-10-16
*/
public interface IBankPosCloudAppService {
}

View File

@@ -0,0 +1,20 @@
package com.openhis.web.externalintegration.appservice;
import com.core.common.core.domain.R;
/**
* 食源性疾病病例数据智能采集Service接口
*
* @author GuoRui
* @date 2025-10-10
*/
public interface IFoodborneAcquisitionAppService {
/**
* 是否是食源性诊断
*
* @param encounterId 就诊ID
* @return 是否
*/
R<?> isFoodDiseasesNew(Long encounterId);
}

View File

@@ -0,0 +1,418 @@
package com.openhis.web.externalintegration.appservice.impl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.core.common.core.domain.R;
import com.core.common.enums.TenantOptionDict;
import com.core.web.util.TenantOptionUtil;
import com.openhis.web.externalintegration.appservice.IBankPosCloudAppService;
import com.openhis.web.externalintegration.dto.BpcTransactionRequestDto;
import com.openhis.web.externalintegration.dto.BpcTransactionResponseDto;
import com.openhis.web.externalintegration.enums.BpcPayType;
import com.openhis.web.externalintegration.enums.BpcTranType;
import com.openhis.web.externalintegration.utils.BpcHttpUtil;
import com.openhis.web.externalintegration.utils.BpcTraceNoGenerator;
import lombok.extern.slf4j.Slf4j;
/**
* BPC商户接口Service业务层处理
*
* @author GuoRui
* @date 2025-10-16
*/
@Slf4j
@Service
public class BankPosCloudAppServiceImpl implements IBankPosCloudAppService {
/**
* 被扫消费
*
* @param txnAmt 交易金额
* @param merTradeNo 商户系统订单号
* @param scanCode 二维码信息
* @param posNo 设备终端编号
* @return 结果
*/
public R<?> processConsumerScan(String txnAmt, String merTradeNo, String scanCode, String posNo) {
// 参数验证
if (StringUtils.isEmpty(txnAmt)) {
return R.fail("交易金额不能为空");
}
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
}
if (StringUtils.isEmpty(scanCode)) {
return R.fail("二维码信息不能为空");
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
// 交易类型,被扫消费
.setTranType(BpcTranType.C.getValue())
// 交易金额
.setTxnAmt(txnAmt)
// 商户系统订单号
.setMerTradeNo(merTradeNo)
// 二维码信息
.setScanCode(scanCode)
// 设备终端编号
.setPosNo(posNo);
log.info("【BPC被扫消费】交易金额{},商户系统订单号:{},二维码信息:{},设备终端编号:{}", txnAmt, merTradeNo, scanCode, posNo);
// 发起交易请求
return submitTransactionRequest(requestDto);
}
/**
* 主扫下单
*
* @param txnAmt 交易金额
* @param merTradeNo 商户系统订单号
* @param posNo 设备终端编号
* @return 结果
*/
public R<?> createMerchantScanOrder(String txnAmt, String merTradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(txnAmt)) {
return R.fail("交易金额不能为空");
}
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
// 交易类型,主扫下单
.setTranType(BpcTranType.F.getValue())
// 交易金额
.setTxnAmt(txnAmt)
// 商户系统订单号
.setMerTradeNo(merTradeNo)
// 设备终端编号
.setPosNo(posNo);
log.info("【BPC主扫下单】交易金额{},商户系统订单号:{},设备终端编号:{}", txnAmt, merTradeNo, posNo);
// 发起交易请求
return submitTransactionRequest(requestDto);
}
/**
* 消费订单查询
*
* @param merTradeNo 商户系统订单号
* @param tradeNo 原交易订单号
* @param posNo 设备终端编号
* @return 结果
*/
public R<?> queryPaymentOrder(String merTradeNo, String tradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
}
// if (StringUtils.isEmpty(tradeNo)) {
// return R.fail("原交易订单号不能为空");
// }
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
// 交易类型,支付结果查询
.setTranType(BpcTranType.G.getValue())
// 商户系统订单号
.setMerTradeNo(merTradeNo)
// 原交易订单号
.setTradeNo(tradeNo)
// 设备终端编号
.setPosNo(posNo);
log.info("【BPC消费订单查询】商户系统订单号{},原交易订单号:{},设备终端编号:{}", merTradeNo, tradeNo, posNo);
// 发起交易请求
return submitTransactionRequest(requestDto);
}
/**
* 关闭订单
*
* @param merTradeNo 商户系统订单号
* @param tradeNo 原交易订单号
* @param posNo 设备终端编号
* @return 结果
*/
public R<?> closeOrder(String merTradeNo, String tradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
}
if (StringUtils.isEmpty(tradeNo)) {
return R.fail("原交易订单号不能为空");
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
// 交易类型,关闭订单
.setTranType(BpcTranType.S.getValue())
// 商户系统订单号
.setMerTradeNo(merTradeNo)
// 原交易订单号
.setTradeNo(tradeNo)
// 设备终端编号
.setPosNo(posNo);
log.info("【BPC关闭订单】商户系统订单号{},原交易订单号:{},设备终端编号:{}", merTradeNo, tradeNo, posNo);
// 发起交易请求
return submitTransactionRequest(requestDto);
}
/**
* 申请退货
*
* @param txnAmt 交易金额
* @param vfTradeNo 退款退订定金单号
* @param merTradeNo 商户系统订单号
* @param tradeNo 原交易订单号
* @param posNo 设备终端编号
* @return 结果
*/
public R<?> applyForRefund(String txnAmt, String vfTradeNo, String merTradeNo, String tradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(txnAmt)) {
return R.fail("交易金额不能为空");
}
if (StringUtils.isEmpty(vfTradeNo)) {
return R.fail("退款退订定金单号不能为空");
}
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
}
if (StringUtils.isEmpty(tradeNo)) {
return R.fail("原交易订单号不能为空");
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
// 交易类型,退货
.setTranType(BpcTranType.R.getValue())
// 交易金额
.setTxnAmt(txnAmt)
// 退款退订定金单号
.setVfTradeNo(vfTradeNo)
// 商户系统订单号
.setMerTradeNo(merTradeNo)
// 原交易订单号
.setTradeNo(tradeNo)
// 设备终端编号
.setPosNo(posNo);
log.info("【BPC申请退货】交易金额{},退款退订定金单号:{},商户系统订单号:{},原交易订单号:{},设备终端编号:{}", txnAmt, vfTradeNo, merTradeNo, tradeNo,
posNo);
// 发起交易请求
return submitTransactionRequest(requestDto);
}
/**
* 查询退货订单
*
* @param vfTradeNo 退款退订定金单号
* @param posNo 设备终端编号
* @return 结果
*/
public R<?> queryRefundOrder(String vfTradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(vfTradeNo)) {
return R.fail("退款退订定金单号不能为空");
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
// 交易类型,退款结果查询
.setTranType(BpcTranType.J.getValue())
// 退款退订定金单号
.setVfTradeNo(vfTradeNo)
// 设备终端编号
.setPosNo(posNo);
log.info("【BPC查询退货订单】退款退订定金单号{}", vfTradeNo);
// 发起交易请求
return submitTransactionRequest(requestDto);
}
/**
* 消费撤销
*
* @param txnAmt 交易金额
* @param vfTradeNo 退款退订定金单号
* @param merTradeNo 商户系统订单号
* @param tradeNo 原交易订单号
* @param posNo 设备终端编号
* @return 结果
*/
public R<?> reversePayment(String txnAmt, String vfTradeNo, String merTradeNo, String tradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(txnAmt)) {
return R.fail("交易金额不能为空");
}
if (StringUtils.isEmpty(vfTradeNo)) {
return R.fail("退款退订定金单号不能为空");
}
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
}
if (StringUtils.isEmpty(tradeNo)) {
return R.fail("原交易订单号不能为空");
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
// 交易类型,消费撤销
.setTranType(BpcTranType.D.getValue())
// 交易金额
.setTxnAmt(txnAmt)
// 退款退订定金单号
.setVfTradeNo(vfTradeNo)
// 商户系统订单号
.setMerTradeNo(merTradeNo)
// 原交易订单号
.setTradeNo(tradeNo)
// 设备终端编号
.setPosNo(posNo);
log.info("【BPC消费撤销】交易金额{},退款退订定金单号:{},商户系统订单号:{},原交易订单号:{},设备终端编号:{}", txnAmt, vfTradeNo, merTradeNo, tradeNo,
posNo);
// 发起交易请求
return submitTransactionRequest(requestDto);
}
/**
* 查询撤销订单
*
* @param merTradeNo 商户系统订单号
* @param posNo 设备终端编号
* @return 结果
*/
public R<?> queryReversalOrder(String merTradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(merTradeNo)) {
return R.fail("商户系统订单号不能为空");
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
// 交易类型,撤销结果查询
.setTranType(BpcTranType.Z.getValue())
// 商户系统订单号
.setMerTradeNo(merTradeNo)
// 设备终端编号
.setPosNo(posNo);
log.info("【BPC查询撤销订单】商户系统订单号{},设备终端编号:{}", merTradeNo, posNo);
// 发起交易请求
return submitTransactionRequest(requestDto);
}
/**
* 银行卡退货功能
*
* @param txnAmt 交易金额
* @param pan 银行卡号
* @param vfTradeNo 退款退订定金单号
* @param posNo 设备终端编号
* @return 结果
*/
public R<?> processCardRefund(String txnAmt, String pan, String vfTradeNo, String posNo) {
// 参数验证
if (StringUtils.isEmpty(txnAmt)) {
return R.fail("交易金额不能为空");
}
if (StringUtils.isEmpty(pan)) {
return R.fail("银行卡号不能为空");
}
if (StringUtils.isEmpty(vfTradeNo)) {
return R.fail("退款退订定金单号不能为空");
}
if (StringUtils.isEmpty(posNo)) {
return R.fail("设备终端编号不能为空");
}
// 作成请求参数
BpcTransactionRequestDto requestDto = new BpcTransactionRequestDto()
// 交易类型,退货
.setTranType(BpcTranType.R.getValue())
// 交易金额
.setTxnAmt(txnAmt)
// 终端流水号
.setPayType(BpcPayType.BANK_CARD.getValue())
// 银行卡号
.setPan(pan)
// 退款退订定金单号
.setVfTradeNo(vfTradeNo)
// 设备终端编号
.setPosNo(posNo);
log.info("【BPC银行卡退货功能】交易金额{},银行卡号:{},退款退订定金单号:{},设备终端编号:{}", txnAmt, pan, vfTradeNo, posNo);
// 发起交易请求
return submitTransactionRequest(requestDto);
}
/**
* 发送交易请求
*
* @param requestDto 请求参数
* @return 结果
*/
private R<?> submitTransactionRequest(BpcTransactionRequestDto requestDto) {
// 验证租户配置
String mid = TenantOptionUtil.getOptionContent(TenantOptionDict.BPC_MID);
if (StringUtils.isEmpty(mid)) {
return R.fail("BPC商户号未配置");
}
String tid = TenantOptionUtil.getOptionContent(TenantOptionDict.BPC_TID);
if (StringUtils.isEmpty(tid)) {
return R.fail("BPC终端号未配置");
}
String md5SharedSecret = TenantOptionUtil.getOptionContent(TenantOptionDict.BPC_MD5_SHARED_SECRET);
if (StringUtils.isEmpty(md5SharedSecret)) {
return R.fail("BPCMD5签名密钥未配置");
}
String requestUrl = TenantOptionUtil.getOptionContent(TenantOptionDict.BPC_REQUEST_URL);
if (StringUtils.isEmpty(requestUrl)) {
return R.fail("BPC请求URL未配置");
}
// 生成终端流水号
String traceNo = BpcTraceNoGenerator.nextTraceNo();
// 设置请求终端流水号
requestDto.setTraceNo(traceNo);
// 设置其他固定参数
requestDto.setMid(mid).setTid(tid);
// 将参数转化为json字符串
String jsonStr = JSON.toJSONString(requestDto);
log.info("【BPC请求报文】{}", jsonStr);
// 发起post请求
String postResponse;
try {
postResponse = BpcHttpUtil.httpPost(jsonStr, md5SharedSecret, requestUrl);
} catch (Exception e) {
return R.fail(e.getMessage());
}
log.info("【BPC响应报文】{}", postResponse);
// 解析响应报文
BpcTransactionResponseDto responseDto;
try {
responseDto = JSON.parseObject(postResponse, BpcTransactionResponseDto.class);
if (StringUtils.isNotEmpty(responseDto.getTraceNo()) && !traceNo.equals(responseDto.getTraceNo())) {
return R.fail("终端流水号不一致,交易失败");
}
} catch (Exception e) {
return R.fail("报文解析失败");
}
// 返回响应结果
return R.ok(responseDto);
}
}

View File

@@ -0,0 +1,176 @@
package com.openhis.web.externalintegration.appservice.impl;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.core.common.core.domain.R;
import com.core.common.enums.TenantOptionDict;
import com.core.common.utils.StringUtils;
import com.core.web.util.TenantOptionUtil;
import com.openhis.common.enums.*;
import com.openhis.common.utils.CommonUtil;
import com.openhis.web.externalintegration.appservice.IFoodborneAcquisitionAppService;
import com.openhis.web.externalintegration.dto.FaSimplediseaseAddNopwParam;
import com.openhis.web.externalintegration.mapper.FoodborneAcquisitionAppMapper;
import lombok.extern.slf4j.Slf4j;
/**
* 食源性疾病病例数据智能采集Service业务层处理
*
* @author GuoRui
* @date 2025-10-10
*/
@Slf4j
@Service
public class FoodborneAcquisitionAppServiceImpl implements IFoodborneAcquisitionAppService {
@Autowired
private FoodborneAcquisitionAppMapper foodborneAcquisitionAppMapper;
/**
* 是否是食源性诊断
*
* @param encounterId 就诊ID
* @return 是否
*/
@Override
public R<?> isFoodDiseasesNew(Long encounterId) {
// 判断食源性开关状态
String foodborneSwitch = TenantOptionUtil.getOptionContent(TenantOptionDict.FOODBORNE_SWITCH);
if (!Whether.YES.getCode().equals(foodborneSwitch)) {
// 开关未开启时返回空OK结果跳过处理
return R.ok();
}
// 判断食源性接口地址是否为空
String foodborneApiUrl = TenantOptionUtil.getOptionContent(TenantOptionDict.FOODBORNE_API_URL);
if (StringUtils.isEmpty(foodborneApiUrl)) {
return R.fail("【食源性判断接口】租户配置项「食源性接口地址」未配置");
}
// 判断食源性医疗机构是否为空
String foodborneHospital = TenantOptionUtil.getOptionContent(TenantOptionDict.FOODBORNE_HOSPITAL);
if (StringUtils.isEmpty(foodborneHospital)) {
return R.fail("【食源性判断接口】租户配置项「食源性医疗机构」未配置");
}
// 判断食源性登录账号是否为空
String foodborneUserName = TenantOptionUtil.getOptionContent(TenantOptionDict.FOODBORNE_USER_NAME);
if (StringUtils.isEmpty(foodborneUserName)) {
return R.fail("【食源性判断接口】租户配置项「食源性登录账号」未配置");
}
// 定义诊断列表参数
List<String> diagnosisNameList = new ArrayList<>();
// TODO:郭睿 等待从doc_statistics表取主诉诊断
// 查询就诊诊断内容列表
List<String> encounterDiagnosisConditionNameList =
foodborneAcquisitionAppMapper.selectEncounterDiagnosisConditionNameList(encounterId);
diagnosisNameList.addAll(encounterDiagnosisConditionNameList);
// 判断诊断是否为空
if (diagnosisNameList.isEmpty()) {
return R.fail("【食源性判断接口】未找到有效诊断");
}
// 设置超时时间
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(3000)
.setSocketTimeout(30000).build();
// 创建无视SSL验证的HttpClient
CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig)
.setSSLSocketFactory(CommonUtil.createIgnoreSslSocketFactory()).build();
CloseableHttpResponse response = null;
// 发起HTTP请求
try {
// 对参数值进行URL编码
String encodedDiagnosisName =
URLEncoder.encode(String.join(",", diagnosisNameList), StandardCharsets.UTF_8.toString());
// 拼接完整的请求URL
String requestUrl = foodborneApiUrl + "/isFoodDiseasesNew?diagnosisName=" + encodedDiagnosisName;
// 创建HttpGet对象并设置URL
HttpGet httpGet = new HttpGet(requestUrl);
// 执行请求
response = httpClient.execute(httpGet);
// 获取响应
JSONObject object =
JSON.parseObject(EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8.toString()));
log.info("【食源性判断接口】入参encounterId{}返回值:{}", encounterId, object.toString());
// 判断返回的result字段
String result = String.valueOf(object.getInnerMap().get("result"));
if (!"true".equals(result)) {
// 返回不是true时返回空OK结果跳过处理
return R.ok();
}
// 查询食源性疾病病例数据智能采集上报跳转页面所需参数
FaSimplediseaseAddNopwParam simplediseaseAddNopwParam = foodborneAcquisitionAppMapper
.selectSimplediseaseAddNopwParam(encounterId, AdministrativeGender.MALE.getValue(),
AdministrativeGender.FEMALE.getValue(), EncounterType.FOLLOW_UP.getValue(),
EncounterClass.IMP.getValue(), ParticipantType.ADMITTER.getCode());
if (simplediseaseAddNopwParam == null) {
return R.fail("【食源性判断接口】跳转参数查询失败");
}
// 返回的标识字段 fillGuid
String fillGuid = String.valueOf(object.getInnerMap().get("fillGuid"));
// 拼装参数作成跳转URL
String jumpUrl = foodborneApiUrl + "/SimplediseaseAddNopw" + "?diseaseDate="
+ simplediseaseAddNopwParam.getDiseaseDate() + "&diseaseTreattime="
+ simplediseaseAddNopwParam.getDiseaseTreattime() + "&outPatientNumber="
+ URLEncoder.encode(simplediseaseAddNopwParam.getOutPatientNumber(), StandardCharsets.UTF_8.toString())
+ "&patientName="
+ URLEncoder.encode(simplediseaseAddNopwParam.getPatientName(), StandardCharsets.UTF_8.toString())
+ "&diseaseSex=" + simplediseaseAddNopwParam.getDiseaseSex() + "&guarderName="
+ URLEncoder.encode(simplediseaseAddNopwParam.getGuarderName(), StandardCharsets.UTF_8.toString())
+ "&diseaseIsreexam=" + simplediseaseAddNopwParam.getDiseaseIsreexam() + "&diseaseIspaint="
+ simplediseaseAddNopwParam.getDiseaseIspaint() + "&diseaseHospitalno="
+ simplediseaseAddNopwParam.getDiseaseHospitalno() + "&identityCard="
+ Optional.ofNullable(simplediseaseAddNopwParam.getIdentityCard()).orElse("") + "&diseaseBirthday="
+ Optional.ofNullable(simplediseaseAddNopwParam.getDiseaseBirthday()).orElse("") + "&phoneNumber="
+ Optional.ofNullable(simplediseaseAddNopwParam.getPhoneNumber()).orElse("") + "&workUnit="
+ URLEncoder.encode(Optional.ofNullable(simplediseaseAddNopwParam.getWorkUnit()).orElse(""),
StandardCharsets.UTF_8.toString())
+ "&deathDate=" + Optional.ofNullable(simplediseaseAddNopwParam.getDeathDate()).orElse("")
+ "&fillingDoctorName="
+ URLEncoder.encode(Optional.ofNullable(simplediseaseAddNopwParam.getFillingDoctorName()).orElse(""),
StandardCharsets.UTF_8.toString())
+ "&medicalInstiSeHospital=" + foodborneHospital + "&diseaseHometown=" + "&diseaseProvince="
+ URLEncoder.encode(Optional.ofNullable(simplediseaseAddNopwParam.getDiseaseProvince()).orElse(""),
StandardCharsets.UTF_8.toString())
+ "&diseaseCity="
+ URLEncoder.encode(Optional.ofNullable(simplediseaseAddNopwParam.getDiseaseCity()).orElse(""),
StandardCharsets.UTF_8.toString())
+ "&diseaseDistrict="
+ URLEncoder.encode(Optional.ofNullable(simplediseaseAddNopwParam.getDiseaseDistrict()).orElse(""),
StandardCharsets.UTF_8.toString())
+ "&diseaseAddress="
+ URLEncoder.encode(Optional.ofNullable(simplediseaseAddNopwParam.getDiseaseAddress()).orElse(""),
StandardCharsets.UTF_8.toString())
+ "&diseaseOccupation=23009012" + "&uName=" + foodborneUserName + "&fillGuid=" + fillGuid;
// 返回非空OK结果并携带跳转URL
return R.ok(jumpUrl);
} catch (Exception e) {
log.error(e.getMessage(), e);
return R.fail("【食源性判断接口】发生异常:" + e.getMessage());
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

View File

@@ -0,0 +1,35 @@
package com.openhis.web.externalintegration.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.core.common.core.domain.R;
import com.openhis.web.externalintegration.appservice.IFoodborneAcquisitionAppService;
/**
* 食源性疾病病例数据智能采集Controller
*
* @author GuoRui
* @date 2025-10-10
*/
@RestController
@RequestMapping("/external-integration/foodborne-acquisition")
public class FoodborneAcquisitionAppController {
@Autowired
private IFoodborneAcquisitionAppService foodborneAcquisitionAppService;
/**
* 是否是食源性诊断
*
* @param encounterId 就诊ID
* @return 是否
*/
@GetMapping("/is-food-diseases-new")
R<?> isFoodDiseasesNew(@RequestParam("encounterId") Long encounterId) {
return foodborneAcquisitionAppService.isFoodDiseasesNew(encounterId);
}
}

View File

@@ -0,0 +1,179 @@
package com.openhis.web.externalintegration.dto;
import org.hibernate.validator.constraints.Length;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**
* 【BPC】数据元
*
* @author GuoRui
* @date 2025-10-16
*/
@Data
public class BpcDataElementDto {
/**
* 设备终端编号:设备的唯一编号
*/
@Length(max = 10)
@JSONField(name = "posNo")
private String posNo;
/**
* 终端实时经纬度信息:格式为为纬度/经度,+表示北纬、东经,-表示南纬、西 经。例:+37.12/-121.213。例:+37.12/-121.213
*/
@Length(max = 30)
@JSONField(name = "posGa")
private String posGa;
/**
* 交易类型枚举TranType
*/
@Length(max = 1)
@JSONField(name = "tranType")
private String tranType;
/**
* 交易金额:以分为单位的交易金额
*/
@Length(max = 12)
@JSONField(name = "txnAmt")
private String txnAmt;
/**
* 支付方式枚举PayType
*/
@Length(max = 4)
@JSONField(name = "payType")
private String payType;
/**
* 交易流水号
*/
@Length(max = 32)
@JSONField(name = "sysTrace")
private String sysTrace;
/**
* 原交易流水号:支付结果查询、退货、退货结果查询交易需要传入
*/
@Length(max = 32)
@JSONField(name = "orgSysTrace")
private String orgSysTrace;
/**
* 原交易时间yyyyMMddHHmmss该字段为消费成功后返回的日期时间在做退货、退货结果查询时,需要传入原消费交易的日期时间
*/
@Length(max = 14)
@JSONField(name = "orgTxnTime")
private String orgTxnTime;
/**
* 二维码信息:支付二维码,扫码消费订单查询时传入
*/
@Length(max = 64)
@JSONField(name = "scanCode")
private String scanCode;
/**
* 支付订单号:扫码支付交易订单号,扫码支付退货时传入
*/
@Length(max = 64)
@JSONField(name = "tradeNo")
private String tradeNo;
/**
* 通知URL交易延时响应时的交易结果通知URL
*/
@Length(max = 256)
@JSONField(name = "retUrl")
private String retUrl;
/**
* 清算商户号
*/
@Length(max = 15)
@JSONField(name = "mid")
private String mid;
/**
* 商户名称
*/
@Length(max = 64)
@JSONField(name = "merName")
private String merName;
/**
* 终端号
*/
@Length(max = 8)
@JSONField(name = "tid")
private String tid;
/**
* 商户系统订单号:由商户系统产生
*/
@Length(max = 64)
@JSONField(name = "merTradeNo")
private String merTradeNo;
/**
* 银行优惠金额
*/
@Length(max = 12)
@JSONField(name = "discountAmt")
private String discountAmt;
/**
* 收款方备注
*/
@Length(max = 64)
@JSONField(name = "txtRemarks")
private String txtRemarks;
/**
* 实名认证标志枚举RealNameAuthFlag
*/
@Length(max = 1)
@JSONField(name = "realNameAuth")
private String realNameAuth;
/**
* 付款人姓名当realNameAuth为1时必填
*/
@Length(max = 64)
@JSONField(name = "payerName")
private String payerName;
/**
* 付款人身份证件类型枚举PayerIdType当realNameAuth为1时必填
*/
@Length(max = 2)
@JSONField(name = "payerIDType")
private String payerIdType;
/**
* 付款人身份证件号码当realNameAuth为1时必填
*/
@Length(max = 20)
@JSONField(name = "payerID")
private String payerId;
/**
* 发起方IP地址支持IPv6格式
*/
@Length(max = 40)
@JSONField(name = "IP")
private String ip;
/**
* 终端设备类型枚举DeviceType
*/
@Length(max = 2)
@JSONField(name = "deviceType")
private String deviceType;
}

View File

@@ -0,0 +1,113 @@
package com.openhis.web.externalintegration.dto;
import org.hibernate.validator.constraints.Length;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**
* 【BPC】主扫支付结果通知
*
* @author GuoRui
* @date 2025-10-16
*/
@Data
public class BpcPaymentScanNotifyDto {
/**
* 商户系统订单号:申码交易商户系统订单号
*/
@Length(max = 64)
@JSONField(name = "merTradeNo")
private String merTradeNo;
/**
* 原交易订单号:银行订单号
*/
@Length(max = 64)
@JSONField(name = "orgSysTrace")
private String orgSysTrace;
/**
* 银行交易日期
*/
@JSONField(name = "bankDate")
private String bankDate;
/**
* 银行交易时间
*/
@JSONField(name = "bankTime")
private String bankTime;
/**
* 原申码订单号
*/
@Length(max = 64)
@JSONField(name = "oldQrOrderNo")
private String oldQrOrderNo;
/**
* 原商户号
*/
@JSONField(name = "oldTermId")
private String oldTermId;
/**
* 原支付方式
*/
@JSONField(name = "oldPayType")
private String oldPayType;
/**
* 原银行交易日期
*/
@JSONField(name = "oldBankDate")
private String oldBankDate;
/**
* 原银行交易时间
*/
@JSONField(name = "oldBankTime")
private String oldBankTime;
/**
* 原交易返回码
*/
@JSONField(name = "oldRespCode")
private String oldRespCode;
/**
* 原交易返回信息
*/
@JSONField(name = "oldRespMsg")
private String oldRespMsg;
/**
* 微信交易单号仅OldPayType=WEIX 时此域有值
*/
@Length(max = 64)
@JSONField(name = "oldTradeId")
private String oldTradeId;
/**
* 支付宝交易单号仅OldPayType=ZFBA 时此域有值
*/
@Length(max = 64)
@JSONField(name = "oldTradeNo")
private String oldTradeNo;
/**
* 响应码00 表示成功,其它表示失败
*/
@JSONField(name = "respCode")
private String respCode;
/**
* 响应码解释信息
*/
@JSONField(name = "respMsg")
private String respMsg;
}

View File

@@ -0,0 +1,224 @@
package com.openhis.web.externalintegration.dto;
import org.hibernate.validator.constraints.Length;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 【BPC】交易请求
*
* @author GuoRui
* @date 2025-10-16
*/
@Data
@Accessors(chain = true)
public class BpcTransactionRequestDto {
/**
* 设备终端编号:设备的唯一编号(必填)
*/
@Length(max = 10)
@JSONField(name = "posNo")
private String posNo;
/**
* 终端实时经纬度信息最新甲方确认可以不传tranType为C时必填格式为为纬度/经度,+表示北纬、东经,-表示南纬、西 经。例:+37.12/-121.213。例:+37.12/-121.213
*/
@Length(max = 30)
@JSONField(name = "posGa")
private String posGa;
/**
* 交易类型枚举TranType
*/
@Length(max = 1)
@JSONField(name = "tranType")
private String tranType;
/**
* 交易金额:以分为单位的交易金额
*/
@Length(max = 12)
@JSONField(name = "txnAmt")
private String txnAmt;
/**
* 银行优惠金额:撤销、退货交易时填写原消费交易的优惠金额,可以不填
*/
@Length(max = 12)
@JSONField(name = "discountAmt")
private String discountAmt;
/**
* 支付方式枚举PayType当tranType为F时payType不填写返回聚合码scanCode填写则返回订单数据payData部分收单行支持
*/
@Length(max = 4)
@JSONField(name = "payType")
private String payType;
/**
* 二维码信息:被扫交易,采集到的手机支付二维码信息,主扫交易该字段为空
*/
@Length(max = 64)
@JSONField(name = "scanCode")
private String scanCode;
/**
* 商户编号
*/
@Length(max = 15)
@JSONField(name = "mid")
private String mid;
/**
* 终端编号(可以不填)
*/
@Length(max = 8)
@JSONField(name = "tid")
private String tid;
/**
* 终端流水号:终端号系统跟踪号,从 000001 开始到 999999 循环应答报文原值返回客户端收到应答报文需要验证traceNo字段值如果不一致则丢包交易失败
*/
@Length(max = 6)
@JSONField(name = "traceNo")
private String traceNo;
/**
* 商品名称:自定义商品名称(可以不填,默认为“商品”)
*/
@Length(max = 200)
@JSONField(name = "goodsName")
private String goodsName;
/**
* 原交易订单号:银行订单号(可以不填)
*/
@Length(max = 64)
@JSONField(name = "tradeNo")
private String tradeNo;
/**
* 原交易日期时间yyyyMMddHHmmss撤销、退货时填写原消费交易返回的时间日期
*/
@Length(max = 14)
@JSONField(name = "orgTxnTime")
private String orgTxnTime;
/**
* 商户系统订单号:商户系统订单号,消费交易、定金交易,商户生成唯一订单号(如果不能生成,可以向扫码平台申请商户系统订单号);支付结果查询、定金支付结果查询、消费撤销、
* 消费撤销结果查询、退货交易需要传入原消费或定金交易商户系统订单号;退订、定金确认,填写原定金交易订单号;定金确认撤销、定金确认撤销结果查询,填写定金确认订单号
*/
@Length(max = 64)
@JSONField(name = "merTradeNo")
private String merTradeNo;
/**
* 退款退订定金单号:商户系统退货、退订、定金确认订单号(如果不能生成,可以向扫码平台申请商户系统订单号);退货结果查询、退订结果查询、定金确认查询,需要传入原商户系统退货单号
*/
@Length(max = 64)
@JSONField(name = "vfTradeNo")
private String vfTradeNo;
/**
* 有效时间:主扫二维码有效时间(可以不填,部分收单行不支持)
*/
@Length(max = 6)
@JSONField(name = "qrValidTime")
private String qrValidTime;
/**
* 通知URL主扫交易延时响应时的交易结果通知URL可以不填
*/
@Length(max = 256)
@JSONField(name = "retUrl")
private String retUrl;
/**
* 支付成功回调地址:主扫交易当使用微信和支付宝支付成功后,前端可通过此地址回调到商户提供的地址。注意:地址必须以 HTTP 或 HTTPS 开头,且 HTTPS 必须为颁发的有效证书。
* 回调地址不支持换行符等不可见字符以及特殊字符(可以不填,部分收单行不支持)微信需要对接微信点金计划,详情请参考微信相关文档
*/
@Length(max = 128)
@JSONField(name = "callBackUrl")
private String callBackUrl;
/**
* 商户应用ID当tranType为F时payType 值为ZFBA或WEIX时需填写
*/
@Length(max = 32)
@JSONField(name = "subAppId")
private String subAppId;
/**
* 商户用户openId当tranType为F时payType 值为ZFBA或WEIX时需填写。当上送wxApiType字段时可以不用填写。
*/
@Length(max = 64)
@JSONField(name = "subOpenId")
private String subOpenId;
/**
* 微信API类型当业务场景为微信APP支付时填写固定值APP其余交易不送该字段
*/
@Length(max = 10)
@JSONField(name = "wxApiType")
private String wxApiType;
/**
* 收款方备注
*/
@Length(max = 64)
@JSONField(name = "txtRemarks")
private String txtRemarks;
/**
* 实名标志枚举RealNameAuthFlag
*/
@Length(max = 1)
@JSONField(name = "realNameAuth")
private String realNameAuth;
/**
* 付款人姓名当realNameAuth为1时必填
*/
@Length(max = 64)
@JSONField(name = "payerName")
private String payerName;
/**
* 付款人身份证件类型当realNameAuth为1时必填
*/
@Length(max = 2)
@JSONField(name = "payerIDType")
private String payerIdType;
/**
* 付款人身份证件号码当realNameAuth为1时必填
*/
@Length(max = 20)
@JSONField(name = "payerID")
private String payerId;
/**
* 发起方IP地址支持IPv6格式
*/
@Length(max = 40)
@JSONField(name = "IP")
private String ip;
/**
* 终端类型枚举DeviceType
*/
@Length(max = 2)
@JSONField(name = "deviceType")
private String deviceType;
/**
* 银行卡号
*/
@JSONField(name = "pan")
private String pan;
}

View File

@@ -0,0 +1,158 @@
package com.openhis.web.externalintegration.dto;
import org.hibernate.validator.constraints.Length;
import com.alibaba.fastjson2.annotation.JSONField;
import lombok.Data;
/**
* 【BPC】交易回应
*
* @author GuoRui
* @date 2025-10-16
*/
@Data
public class BpcTransactionResponseDto {
/**
* 响应码枚举RespCode00 表示成功,其它表示失败
*/
@Length(max = 2)
@JSONField(name = "respCode")
private String respCode;
/**
* 响应码解释信息需要Base64解密
*/
@Length(max = 64)
@JSONField(name = "respMsg")
private String respMsg;
/**
* 交易类型枚举TranType
*/
@Length(max = 1)
@JSONField(name = "tranType")
private String tranType;
/**
* 交易金额:以分为单位的交易金额(订单总金额,同请求金额一致)
*/
@Length(max = 12)
@JSONField(name = "txnAmt")
private String txnAmt;
/**
* 支付方式枚举PayType
*/
@Length(max = 4)
@JSONField(name = "payType")
private String payType;
/**
* 终端流水号终端号系统跟踪号同请求报文原值返回客户端收到应答报文需要验证traceNo字段值需与请求报文值一致如果不一致则丢包交易失败
*/
@Length(max = 6)
@JSONField(name = "traceNo")
private String traceNo;
/**
* 交易时间yyyyMMddHHmmss
*/
@Length(max = 14)
@JSONField(name = "txnTime")
private String txnTime;
/**
* 支付订单号:银行返回系统订单号,需要保存该支付交易订单号
*/
@Length(max = 64)
@JSONField(name = "tradeNo")
private String tradeNo;
/**
* 第三方支付订单号
*/
@Length(max = 64)
@JSONField(name = "transNo")
private String transNo;
/**
* 商户号
*/
@Length(max = 15)
@JSONField(name = "mid")
private String mid;
/**
* 商户名称
*/
@Length(max = 64)
@JSONField(name = "merName")
private String merName;
/**
* 终端号
*/
@Length(max = 8)
@JSONField(name = "tid")
private String tid;
/**
* 商户系统订单号:同请求一致
*/
@Length(max = 64)
@JSONField(name = "merTradeNo")
private String merTradeNo;
/**
* 商户系统退款授权单号:同请求一致
*/
@Length(max = 64)
@JSONField(name = "vfTradeNo")
private String vfTradeNo;
/**
* 优惠金额
*/
@Length(max = 12)
@JSONField(name = "discountAmt")
private String discountAmt;
/**
* 有效时间:二维码本身的有效时间,是相对时间,单位为秒,以接收方收到报文时间为起始点计时。不同类型的订单以及不同的订单状况会对应不同的默认有效时间和最大有效时间(可以为空)
*/
@Length(max = 8)
@JSONField(name = "qrValidTime")
private String qrValidTime;
/**
* 二维码信息主扫支付二维码以二维码形式显示手机APP扫二维码码消费
*/
@Length(max = 128)
@JSONField(name = "scanCode")
private String scanCode;
/**
* 原交易类型1、订单查询类交易填写原交易类型被扫交易必填2、非订单查询填写交易类型与tranType一致可以为空
*/
@Length(max = 1)
@JSONField(name = "orgTranType")
private String orgTranType;
/**
* 原交易名称:订单查询类交易填写原交易名称,非订单查询填写交易名称(被扫交易必填)
*/
@Length(max = 30)
@JSONField(name = "orgTxnName")
private String orgTxnName;
/**
* 订单数据当tranType为F时payType 值为ZFBA或WEIX时支付宝返回的tradeNo 或者微信返回的prepayId
*/
@Length(max = 64)
@JSONField(name = "payData")
private String payData;
}

View File

@@ -0,0 +1,113 @@
package com.openhis.web.externalintegration.dto;
import lombok.Data;
/**
* 【食源性】跳转页面所需参数
*
* @author GuoRui
* @date 2025-10-10
*/
@Data
public class FaSimplediseaseAddNopwParam {
/**
* 【必填】发病时间YYYY-MM-DD HH:mm
*/
private String diseaseDate;
/**
* 【必填】就诊时间YYYY-MM-DD HH:mm
*/
private String diseaseTreattime;
/**
* 门诊ID号
*/
private String outPatientNumber;
/**
* 【必填】患者姓名
*/
private String patientName;
/**
* 【必填】患者性别0 女 1 男
*/
private String diseaseSex;
/**
* 监护人姓名
*/
private String guarderName;
/**
* 【必填】是否复诊0否 1是
*/
private String diseaseIsreexam;
/**
* 【必填】是否住院0否 1是
*/
private String diseaseIspaint;
/**
* 住院号:是否住院为是时必填
*/
private String diseaseHospitalno;
/**
* 身份证号
*/
private String identityCard;
/**
* 【必填】出生日期YYYY-MM-DD
*/
private String diseaseBirthday;
/**
* 【必填】联系电话
*/
private String phoneNumber;
/**
* 工作单位
*/
private String workUnit;
/**
* 死亡时间YYYY-MM-DD HH:mm
*/
private String deathDate;
/**
* 接诊医生
*/
private String fillingDoctorName;
/**
* 【必填】现住地址省
*/
private String diseaseProvince;
/**
* 【必填】现住地址市
*/
private String diseaseCity;
/**
* 【必填】现住地址区
*/
private String diseaseDistrict;
/**
* 【必填】现住地址具体
*/
private String diseaseAddress;
/**
* 【必填】职业:与国家平台编码保持一致
*/
private Integer diseaseOccupation;
}

View File

@@ -0,0 +1,59 @@
package com.openhis.web.externalintegration.enums;
/**
* 【BPC】支付方式
*
* @author GuoRui
* @date 2025-10-16
*/
public enum BpcPayType {
/**
* 支付宝
*/
ALIPAY("ZFBA", "支付宝"),
/**
* 微信
*/
WECHAT("WEIX", "微信"),
/**
* 银联二维码
*/
UNION_QR("UPAY", "银联二维码"),
/**
* 数字人民币
*/
DIGITAL_RMB("DCEP", "数字人民币"),
/**
* 银行卡
*/
BANK_CARD("0001", "银行卡");
private final String value;
private final String description;
BpcPayType(String value, String description) {
this.value = value;
this.description = description;
}
public String getValue() {
return value;
}
public String getDescription() {
return description;
}
public static BpcPayType getByValue(String value) {
if (value == null || "".equals(value.trim())) {
return null;
}
for (BpcPayType val : values()) {
if (val.getValue().equals(value)) {
return val;
}
}
return null;
}
}

View File

@@ -0,0 +1,83 @@
package com.openhis.web.externalintegration.enums;
/**
* 【BPC】付款人身份证件类型
*
* @author GuoRui
* @date 2025-10-16
*/
public enum BpcPayerIdType {
/**
* 身份证
*/
ID_CARD("0", "身份证"),
/**
* 护照
*/
PASSPORT("1", "护照"),
/**
* 军官证
*/
MILITARY_OFFICER_CERT("2", "军官证"),
/**
* 士兵证
*/
SOLDIER_CERT("3", "士兵证"),
/**
* 港澳居民来往内地通行证(原名回乡证)
*/
HOME_RETURN_PERMIT("4", "回乡证"),
/**
* 临时身份证
*/
TEMP_ID_CARD("5", "临时身份证"),
/**
* 户口本
*/
HOUSEHOLD_REGISTER("6", "户口本"),
/**
* 其他
*/
OTHER("7", "其他"),
/**
* 警官证
*/
POLICE_OFFICER_CERT("9", "警官证"),
/**
* 识别证
*/
IDENTIFICATION_CERT("10", "识别证"),
/**
* 驾驶执照
*/
DRIVING_LICENSE("11", "驾驶执照");
private final String value;
private final String description;
BpcPayerIdType(String value, String description) {
this.value = value;
this.description = description;
}
public String getValue() {
return value;
}
public String getDescription() {
return description;
}
public static BpcPayerIdType getByValue(String value) {
if (value == null || "".equals(value.trim())) {
return null;
}
for (BpcPayerIdType val : values()) {
if (val.getValue().equals(value)) {
return val;
}
}
return null;
}
}

View File

@@ -0,0 +1,47 @@
package com.openhis.web.externalintegration.enums;
/**
* 【BPC】实名认证标志
*
* @author GuoRui
* @date 2025-10-16
*/
public enum BpcRealNameAuthFlag {
/**
* 或不存在:无需实名认证
*/
NO_NEED("0", "无需实名认证"),
/**
* 实名支付支付通道需验证支付账户所有人和以下payerName/payerID/payerIDType信息一致
*/
NEED("1", "实名支付");
private final String value;
private final String description;
BpcRealNameAuthFlag(String value, String description) {
this.value = value;
this.description = description;
}
public String getValue() {
return value;
}
public String getDescription() {
return description;
}
public static BpcRealNameAuthFlag getByValue(String value) {
if (value == null || "".equals(value.trim())) {
return null;
}
for (BpcRealNameAuthFlag val : values()) {
if (val.getValue().equals(value)) {
return val;
}
}
return null;
}
}

View File

@@ -0,0 +1,55 @@
package com.openhis.web.externalintegration.enums;
/**
* 【BPC】交易返回应答码
*
* @author GuoRui
* @date 2025-10-16
*/
public enum BpcRespType {
/**
* 交易成功(终态)
*/
SUCCESS("00", "交易成功"),
/**
* 订单失败(终态)
*/
FAILED("77", "订单失败,无需继续订单查询"),
/**
* 等待付款(需重试查询)
*/
WAITING_PAYMENT("88", "等待付款(输密码),应再次发起订单查询"),
/**
* 交易状态未明(需重试查询)
*/
UNKNOWN("99", "交易状态未明,应再次发起订单查询");
private final String value;
private final String description;
BpcRespType(String value, String description) {
this.value = value;
this.description = description;
}
public String getValue() {
return value;
}
public String getDescription() {
return description;
}
public static BpcRespType getByValue(String value) {
if (value == null || "".equals(value.trim())) {
return null;
}
for (BpcRespType val : values()) {
if (val.getValue().equals(value)) {
return val;
}
}
return null;
}
}

View File

@@ -0,0 +1,91 @@
package com.openhis.web.externalintegration.enums;
/**
* 【BPC】交易类型
*
* @author GuoRui
* @date 2025-10-16
*/
public enum BpcTranType {
/**
* 被扫消费
*/
C("C", "被扫消费"),
/**
* 退货
*/
R("R", "退货"),
/**
* 数字人民币主扫下单
*/
E("E", "数字人民币主扫下单"),
/**
* 主扫下单(微信/支付宝/云闪付)
*/
F("F", "主扫下单"),
/**
* 关闭订单(部分收单行不支持)
*/
S("S", "关闭订单"),
/**
* 消费撤销(部分收单行不支持)
*/
D("D", "消费撤销"),
/**
* 定金支付(微信、支付宝,部分收单行不支持)
*/
A("A", "定金支付"),
/**
* 退定(微信、支付宝,部分收单行不支持)
*/
V("V", "退定"),
/**
* 定金确认(微信、支付宝,部分收单行不支持)
*/
B("B", "定金确认"),
/**
* 定金确认撤销(微信、支付宝,部分收单行不支持)
*/
W("W", "定金确认撤销"),
/**
* 表示订单支付结果查询、定金支付结果查询
*/
G("G", "支付结果查询"),
/**
* 表示消费撤销订单查询、定金确认撤销结果查询
*/
Z("Z", "撤销结果查询"),
/**
* 表示退货结果查询、退定结果查询、定金确认结果查询
*/
J("J", "退款结果查询");
private final String value;
private final String description;
BpcTranType(String value, String description) {
this.value = value;
this.description = description;
}
public String getValue() {
return value;
}
public String getDescription() {
return description;
}
public static BpcTranType getByValue(String value) {
if (value == null || "".equals(value.trim())) {
return null;
}
for (BpcTranType val : values()) {
if (val.getValue().equals(value)) {
return val;
}
}
return null;
}
}

View File

@@ -0,0 +1,43 @@
package com.openhis.web.externalintegration.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import com.openhis.web.externalintegration.dto.FaSimplediseaseAddNopwParam;
/**
* 食源性疾病病例数据智能采集Mapper
*
* @author GuoRui
* @date 2025-10-10
*/
@Repository
public interface FoodborneAcquisitionAppMapper {
/**
* 查询就诊诊断内容列表
*
* @param encounterId 就诊ID
* @return 就诊诊断内容列表
*/
List<String> selectEncounterDiagnosisConditionNameList(@Param("encounterId") Long encounterId);
/**
* 查询食源性疾病病例数据智能采集上报跳转页面所需参数
*
* @param encounterId 就诊ID
* @param genderEnumMale 性别枚举-男
* @param genderEnumFemale 性别枚举-女
* @param firstEnumFollowUp 初复诊标识-复诊
* @param encounterClassEnumImp 就诊类型-住院
* @param participantTypeAdmitter 参与者类型-接诊医生
* @return 所需参数
*/
FaSimplediseaseAddNopwParam selectSimplediseaseAddNopwParam(@Param("encounterId") Long encounterId,
@Param("genderEnumMale") Integer genderEnumMale, @Param("genderEnumFemale") Integer genderEnumFemale,
@Param("firstEnumFollowUp") Integer firstEnumFollowUp,
@Param("encounterClassEnumImp") Integer encounterClassEnumImp,
@Param("participantTypeAdmitter") String participantTypeAdmitter);
}

View File

@@ -0,0 +1,105 @@
package com.openhis.web.externalintegration.utils;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
/**
* 【BPC】HTTP请求共通方法
*
* @author GuoRui
* @date 2025-10-16
*/
@Slf4j
@Component
public class BpcHttpUtil {
/**
* 发起post请求
*
* @param jsonData JSON数据
* @param md5SharedSecret MD5签名密钥
* @param requestUrl 请求URL
* @return 请求结果
*/
public static String httpPost(String jsonData, String md5SharedSecret, String requestUrl) throws Exception {
HttpsURLConnection conn = null;
try {
// 生成MD5签名
String rawData = jsonData + "&" + md5SharedSecret;
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digestBytes = md.digest(rawData.getBytes());
StringBuilder hexString = new StringBuilder();
for (byte b : digestBytes) {
hexString.append(String.format("%02x", b & 0xff));
}
String md5Sign = hexString.toString();
// 发起请求
URL obj = new URL(requestUrl);
conn = (HttpsURLConnection)obj.openConnection();
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new SecureRandom());
conn.setSSLSocketFactory(sslContext.getSocketFactory());
conn.setHostnameVerifier((hostname, session) -> true);
conn.setRequestMethod("POST");
conn.setConnectTimeout(30_000);
conn.setReadTimeout(60_000);
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
conn.setRequestProperty("sign", md5Sign);
conn.setDoOutput(true);
try (OutputStream os = conn.getOutputStream()) {
byte[] input = jsonData.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
int responseCode = conn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
try (BufferedReader br =
new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
response.append(line);
}
return response.toString();
}
} else {
throw new RuntimeException("HTTP请求失败返回" + responseCode);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new Exception("HTTP请求发生未知异常");
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
}

View File

@@ -0,0 +1,20 @@
package com.openhis.web.externalintegration.utils;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 【BPC】终端流水号生成器
*
* @author GuoRui
* @date 2025-10-16
*/
public class BpcTraceNoGenerator {
private static final AtomicInteger COUNTER = new AtomicInteger(1);
private static final int MAX_VALUE = 999999;
public static String nextTraceNo() {
int nextValue = COUNTER.getAndUpdate(current -> current >= MAX_VALUE ? 1 : current + 1);
// 补零至6位
return String.format("%06d", nextValue);
}
}