diff --git a/src/main/java/com/dpkj/modules/chs/hischs/service/impl/HispayServiceImpl.java b/src/main/java/com/dpkj/modules/chs/hischs/service/impl/HispayServiceImpl.java new file mode 100644 index 0000000..2c77493 --- /dev/null +++ b/src/main/java/com/dpkj/modules/chs/hischs/service/impl/HispayServiceImpl.java @@ -0,0 +1,267 @@ +package com.dpkj.modules.chs.hischs.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.XmlUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.dpkj.common.vo.ResultData; +import com.dpkj.modules.chs.hischs.constant.ChsPayStateConst; +import com.dpkj.modules.chs.hischs.service.IHispayService; +import com.dpkj.modules.chs.hischs.vo.OutpatientBeginModel; +import com.dpkj.modules.chs.hischs.vo.OutpatientFinalModel; +import com.jacob.activeX.ActiveXComponent; +import com.jacob.com.Dispatch; +import com.jacob.com.Variant; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.w3c.dom.Document; + +import javax.annotation.PostConstruct; +import java.util.Map; + + +/** + * @Auther: 萧道子 + * @Date: 2025/3/22 16:29 + * @Description: + */ +@Slf4j +@Service +// @AllArgsConstructor +public class HispayServiceImpl implements IHispayService { + + // COM对象 + private static ActiveXComponent dispatch; + + @PostConstruct + public void postConstruct() { + dispatch = instanceActive(); + } + + /** + * 获取HIS医保实例 + * + * @return com.jacob.activeX.ActiveXComponent + * @author 萧道子 2025/5/21 + */ + private static ActiveXComponent instanceActive() { + try { + // 初始化 + // ComThread.InitSTA(); //容易导致线程发生阻塞 + ActiveXComponent activeXComponent = new ActiveXComponent("PayClient.clsPayClient"); + log.info("[HispayServiceImpl][instanceActive][HIS医保COM库] 加载成功"); + return activeXComponent; + } catch (UnsatisfiedLinkError e) { + log.error("[HispayServiceImpl][instanceActive][HIS医保COM库] 加载失败:{}", e.getMessage()); + throw new RuntimeException("HIS医保COM库加载失败:" + e.getMessage(), e); + } + } + + + /** + * 释放资源 + * + * @return void + * @author 萧道子 2025/5/21 + */ + private void releaseActive() { + // ComThread.Release(); //容易导致线程发生阻塞 + } + + /** + * 处理参数 + * + * @param params : 请求参数 + * @param password : 密码 + * @return java.lang.String + * @author 萧道子 2025/5/27 + */ + private String processParameters(JSONObject params, String password) { + JSONObject req = new JSONObject() {{ + put("timestamp", ""); // 请求发送时间 DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss") + put("requestid", ""); // 唯一请求id IDGenerator.getSnowflakeIdToStr() + put("operid", ""); // 调用者代码 hisConfig.getOperationId() + put("password", password); // 密码 + put("params", params); + }}; + Document document = XmlUtil.mapToXml(req, "request"); + return XmlUtil.toStr(document, "UTF-8", false, true); + } + + + /** + * 校验结果 + * + * @param resStr : + * @return com.alibaba.fastjson.JSONObject + * @author 萧道子 2025/5/28 + */ + private JSONObject verifyResult(String resStr) { + + if (StrUtil.isBlank(resStr)) { + throw new RuntimeException("信息获取失败"); + } + + Map resMap = XmlUtil.xmlToMap(resStr); + JSONObject resJson = new JSONObject(resMap); + + if (StrUtil.equals(resJson.getString("resultCode"), "1")) { + throw new RuntimeException(resJson.getString("resultMessage")); + } + + if (!resJson.containsKey("result")) { + throw new RuntimeException("result数据为空"); + } + + return resJson.getJSONObject("result"); + + } + + + @Override + public JSONObject readCode() { + /** 1、组装参数 */ + JSONObject val = new JSONObject() + .fluentPut("cardtype", "9") // 1.就诊卡,2.医保卡,5.门诊号,6.患者姓名和电话号码,8.电子健康码/卡,9.医保电子凭证 + .fluentPut("cardno", "") // 患者就诊卡号 + .fluentPut("sfzh", "") // 身份证号 + .fluentPut("hzxm", "") // 患者姓名 + .fluentPut("phone", ""); // 患者电话号码 + String params = processParameters(val, null); + log.debug("[HispayServiceImpl][readCode][医保读卡-电子凭证] 接口入参:{}", params); + + /** 2、调用COM函数 */ + Variant vres = new Variant("", true); + Variant call = Dispatch.call(dispatch, "fRun", "BMZXX010", params, vres); + + String resStr = vres.getStringRef(); + log.debug("[HispayServiceImpl][readCode][医保读卡-电子凭证] call返回值:{} 结果:{}", call, resStr); + + + /** 3、处理读卡结果 */ + JSONObject result = verifyResult(resStr); + if (!result.containsKey("item")) { + throw new RuntimeException("item数据为空"); + } + + return result.getJSONObject("item"); + } + + @Override + public JSONObject readCard(String password) { + + /** 1、组装参数 */ + JSONObject val = new JSONObject() + .fluentPut("cardtype", "2") // 1.就诊卡,2.医保卡,5.门诊号,6.患者姓名和电话号码,8.电子健康码/卡,9.医保电子凭证 + .fluentPut("cardno", "") // 患者就诊卡号 + .fluentPut("sfzh", "") // 身份证号 + .fluentPut("hzxm", "") // 患者姓名 + .fluentPut("phone", ""); // 患者电话号码 + String params = processParameters(val, password); + log.debug("[HispayServiceImpl][readCard][医保读卡-医保卡] 接口入参:{}", params); + + /** 2、调用COM函数 */ + Variant vres = new Variant("", true); + Variant call = Dispatch.call(dispatch, "fRun", "BMZXX010", params, vres); + + String resStr = vres.getStringRef(); + log.debug("[HispayServiceImpl][readCard][医保读卡-医保卡] call返回值:{} 结果:{}", call, resStr); + + /** 3、处理读卡结果 */ + JSONObject result = verifyResult(resStr); + if (!result.containsKey("item")) { + throw new RuntimeException("item数据为空"); + } + + return result.getJSONObject("item"); + } + + + private ResultData outpatientBudget(OutpatientBeginModel data) { + + /** 1、组装参数 */ + JSONObject val = new JSONObject() + .fluentPut("patid", data.getPatientId()) // 病人ID + .fluentPut("cfxhhj", data.getPrescriptionNo()) // 划价单据,格式:单据1,单据2,单据3 + .fluentPut("czksfbz", "0") // 是否扣院内账户,0不使用院内账户,1使用院内账户(默认不使用院内账户) + .fluentPut("zfjsbz", "0") // 是否自费结算,0根据医保代码缴费,1自费结算(默认自费结算) + .fluentPut("ybrc", ""); // 医保入参,xml节点 + String params = processParameters(val, data.getPassword()); + log.debug("[HispayServiceImpl][outpatientBudget][门诊缴费-预算] 接口入参:{}", params); + + String requestTime = DateUtil.now(); + + /** 2、调用COM函数 */ + Variant resVariant = new Variant("", true); + Variant call = Dispatch.call(dispatch, "fRun", "BMZJF001", params, resVariant); + + String responseTime = DateUtil.now(); + String resStr = resVariant.getStringRef(); + log.debug("[HispayServiceImpl][outpatientBudget][门诊缴费-预算] call返回值:{} 结果:{}", call, resStr); + + + /** 3、处理结果 */ + JSONObject result = verifyResult(resStr); + + return new ResultData() + .setRequestTime(requestTime) + .setRequestContent(params) + .setResponseTime(responseTime) + .setPatientId(data.getPatientId()) + .setResponseContent(resStr) + .setResult(result); + } + + + @Override + public ResultData chsCodeAsOutpatientBegin(OutpatientBeginModel data) { + // 用户读卡-生成token + JSONObject userInfo = readCode(); + String patientId = userInfo.getString("patid"); + data.setPatientId(patientId); + + // 更新常量状态 已读卡 + ChsPayStateConst.put(data.getPrescriptionNo(), 1); + + return outpatientBudget(data); + } + + + @Override + public ResultData chsCodeAsOutpatientFinal(OutpatientFinalModel data) { + + /** 1、组装参数 */ + String requestTime = DateUtil.now(); + data.setPaytime(requestTime); + JSONObject val = ((JSONObject) JSON.toJSON(data)) + .fluentPut("czksfbz", "0") // 是否扣院内账户,与预算保持一致 + .fluentPut("zfjsbz", "0") // 是否自费结算,与预算保持一致,0根据病人医保代码结算,1自费结算 + .fluentPut("ybrc", "") + .fluentPut("ptlsh", "") + .fluentPut("jysm", ""); + String params = processParameters(val, null); + log.debug("[HispayServiceImpl][chsCodeAsOutpatientFinal][门诊缴费-结算] 接口入参:{}", params); + + /** 2、调用COM函数 */ + Variant resVariant = new Variant("", true); + Variant call = Dispatch.call(dispatch, "fRun", "BMZJF002", params, resVariant); + + String responseTime = DateUtil.now(); + String resStr = resVariant.getStringRef(); + log.debug("[HispayServiceImpl][chsCodeAsOutpatientFinal][门诊缴费-结算] call返回值:{} 结果:{}", call, resStr); + + /** 3、处理结果 */ + JSONObject result = verifyResult(resStr); + + return new ResultData() + .setRequestTime(requestTime) + .setRequestContent(params) + .setResponseTime(responseTime) + .setPatientId(data.getPatid()) + .setResponseContent(resStr) + .setResult(result); + } + + +}