update:医保对账
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
package com.saye.hospitalgd.scheduler.jobMethod;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.saye.hospitalgd.commons.date.DateDUtil;
|
||||
import com.saye.hospitalgd.commons.getBean.GetBeanUtil;
|
||||
import com.saye.hospitalgd.commons.log.LogUtil;
|
||||
import com.saye.hospitalgd.commons.string.StringDUtil;
|
||||
import com.saye.hospitalgd.commons.uuid.UUIDGenerator;
|
||||
import com.saye.hospitalgd.service.HisDetailService;
|
||||
import com.saye.hospitalgd.service.MedicalInsuranceReconciliationService;
|
||||
import com.saye.hospitalgd.service.impl.HisDetailServiceImpl;
|
||||
import com.saye.hospitalgd.service.impl.MedicalInsuranceReconciliationServiceImpl;
|
||||
import com.saye.hospitalgd.service.system.DicinfoService;
|
||||
import com.saye.hospitalgd.service.system.impl.DicinfoServiceImpl;
|
||||
import com.saye.hospitalgd.util.SSLUtil;
|
||||
import com.saye.hospitalgd.util.pojo.HttpResult;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author thuang
|
||||
* @version 1.0
|
||||
* @description: 医保对账方法
|
||||
* @date 2025/10/24
|
||||
*/
|
||||
public class MedicalInsuranceReconciliationMethod {
|
||||
|
||||
// 普通医保局对账接口地址
|
||||
private static final String MEDICAL_INSURANCE_URL = "https://10.134.97.159/fsi/api/ybSettlementStmtService/stmtTotal";
|
||||
|
||||
// 工商医保对账接口地址(险种99410专用)
|
||||
private static final String GONGSHANG_INSURANCE_URL = "http://10.150.4.74:8111/gssetl/api/hisbiz";
|
||||
|
||||
// 工商医保险种代码
|
||||
private static final String GONGSHANG_INSUTYPE = "99410";
|
||||
|
||||
// 固定参数
|
||||
private static final String SETL_OPTINS = "640104";
|
||||
private static final String INFNO = "3201";
|
||||
private static final String INFVER = "1.0";
|
||||
private static final String FIXMEDINS_CODE = "H64010400022";
|
||||
private static final String FIXMEDINS_NAME = "中国人民武装警察部队宁夏回族自治区总队医院";
|
||||
private static final String INSUPLC_ADMDVS = "410000";
|
||||
private static final String MDTRTAREA_ADMVS = "411302";
|
||||
private static final String OPTER = "ADMIN";
|
||||
private static final String OPTER_NAME = "系统管理员";
|
||||
private static final String OPTER_TYPE = "1";
|
||||
private static final String RECER_SYS_CODE = "HIS";
|
||||
private static final String SIGNTYPE = "SM3";
|
||||
|
||||
/**
|
||||
* 执行医保对账
|
||||
* @param trade_date 对账日期
|
||||
* @return 对账结果
|
||||
*/
|
||||
public HashMap<Object, Object> executeMedicalInsuranceReconciliation(String trade_date) {
|
||||
HashMap<Object, Object> responseMap = new HashMap<>();
|
||||
String errCode = "0";
|
||||
String errMsg = "";
|
||||
|
||||
try {
|
||||
LogUtil.info(this.getClass(), "开始执行医保对账,日期:" + trade_date);
|
||||
|
||||
LogUtil.info(this.getClass(), "开始查询医保数据(不限制PayType)");
|
||||
|
||||
// 1. 从数据库查询医保数据,按险种和清算类别分组统计(不限制PayType)
|
||||
HisDetailService hisDetailService = GetBeanUtil.getBean(HisDetailServiceImpl.class);
|
||||
|
||||
HashMap<Object, Object> queryMap = new HashMap<>();
|
||||
queryMap.put("trade_date", trade_date);
|
||||
|
||||
// 查询所有有险种和清算类别的记录(不限制PayType)
|
||||
List<HashMap<Object, Object>> medicalRecords = hisDetailService.findMedicalInsuranceGroupData(queryMap);
|
||||
|
||||
if (medicalRecords == null || medicalRecords.size() == 0) {
|
||||
LogUtil.info(this.getClass(), "医保对账:当日没有医保数据,日期:" + trade_date);
|
||||
errMsg = "当日没有医保数据";
|
||||
responseMap.put("errCode", errCode);
|
||||
responseMap.put("errMsg", errMsg);
|
||||
responseMap.put("reconciliationResults", new ArrayList<>());
|
||||
return responseMap;
|
||||
}
|
||||
|
||||
LogUtil.info(this.getClass(), "查询到医保分组数据:" + medicalRecords.size() + " 组");
|
||||
|
||||
// 删除当天旧的对账结果
|
||||
MedicalInsuranceReconciliationService reconciliationService =
|
||||
GetBeanUtil.getBean(MedicalInsuranceReconciliationServiceImpl.class);
|
||||
HashMap<Object, Object> deleteMap = new HashMap<>();
|
||||
deleteMap.put("trade_date", trade_date);
|
||||
reconciliationService.deleteMedicalInsuranceReconciliationResult(deleteMap);
|
||||
|
||||
// 2. 遍历每个险种和清算类别的组合,调用医保局接口
|
||||
List<HashMap<Object, Object>> reconciliationResults = new ArrayList<>();
|
||||
|
||||
for (HashMap<Object, Object> record : medicalRecords) {
|
||||
String insutype = StringDUtil.changeNullToEmpty(record.get("INSUTYPE"));
|
||||
String clrType = StringDUtil.changeNullToEmpty(record.get("CLR_TYPE"));
|
||||
String medfee_sumamt = StringDUtil.changeNullToEmpty(record.get("MEDFEE_SUMAMT"));
|
||||
String fund_pay_sumamt = StringDUtil.changeNullToEmpty(record.get("FUND_PAY_SUMAMT"));
|
||||
String acct_pay = StringDUtil.changeNullToEmpty(record.get("ACCT_PAY"));
|
||||
String fixmedins_setl_cnt = StringDUtil.changeNullToEmpty(record.get("FIXMEDINS_SETL_CNT"));
|
||||
|
||||
// 跳过空的险种或清算类别
|
||||
if ("".equals(insutype) || "".equals(clrType)) {
|
||||
LogUtil.info(this.getClass(), "跳过险种或清算类别为空的记录");
|
||||
continue;
|
||||
}
|
||||
|
||||
LogUtil.info(this.getClass(), String.format("处理险种:%s,清算类别:%s,交易笔数:%s,总金额:%s",
|
||||
insutype, clrType, fixmedins_setl_cnt, medfee_sumamt));
|
||||
|
||||
try {
|
||||
// 3. 调用医保局对账接口
|
||||
HashMap<Object, Object> callResult = callMedicalInsuranceAPI(
|
||||
trade_date, insutype, clrType, medfee_sumamt,
|
||||
fund_pay_sumamt, acct_pay, fixmedins_setl_cnt
|
||||
);
|
||||
|
||||
// 4. 记录对账结果
|
||||
HashMap<Object, Object> resultMap = new HashMap<>();
|
||||
resultMap.put("id", UUIDGenerator.getUUID());
|
||||
resultMap.put("trade_date", trade_date);
|
||||
resultMap.put("insutype", insutype);
|
||||
resultMap.put("clr_type", clrType);
|
||||
resultMap.put("medfee_sumamt", medfee_sumamt);
|
||||
resultMap.put("fund_pay_sumamt", fund_pay_sumamt);
|
||||
resultMap.put("acct_pay", acct_pay);
|
||||
resultMap.put("fixmedins_setl_cnt", fixmedins_setl_cnt);
|
||||
resultMap.put("setl_optins", callResult.get("setl_optins"));
|
||||
resultMap.put("stmt_rslt", callResult.get("stmt_rslt"));
|
||||
resultMap.put("stmt_rslt_dscr", callResult.get("stmt_rslt_dscr"));
|
||||
resultMap.put("infcode", callResult.get("infcode"));
|
||||
resultMap.put("err_msg", callResult.get("err_msg"));
|
||||
resultMap.put("warn_msg", callResult.get("warn_msg"));
|
||||
resultMap.put("refmsg_time", callResult.get("refmsg_time"));
|
||||
resultMap.put("respond_time", callResult.get("respond_time"));
|
||||
resultMap.put("inf_refmsgid", callResult.get("inf_refmsgid"));
|
||||
resultMap.put("api_result", callResult.get("api_result"));
|
||||
resultMap.put("create_time", DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd_HH_mm_ss));
|
||||
resultMap.put("modify_time", DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd_HH_mm_ss));
|
||||
|
||||
reconciliationResults.add(resultMap);
|
||||
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(this.getClass(), String.format("医保对账失败,险种:%s,清算类别:%s,错误:%s",
|
||||
insutype, clrType, e.getMessage()));
|
||||
|
||||
// 记录失败结果
|
||||
HashMap<Object, Object> resultMap = new HashMap<>();
|
||||
resultMap.put("id", UUIDGenerator.getUUID());
|
||||
resultMap.put("trade_date", trade_date);
|
||||
resultMap.put("insutype", insutype);
|
||||
resultMap.put("clr_type", clrType);
|
||||
resultMap.put("medfee_sumamt", medfee_sumamt);
|
||||
resultMap.put("fund_pay_sumamt", fund_pay_sumamt);
|
||||
resultMap.put("acct_pay", acct_pay);
|
||||
resultMap.put("fixmedins_setl_cnt", fixmedins_setl_cnt);
|
||||
resultMap.put("stmt_rslt", "9");
|
||||
resultMap.put("stmt_rslt_dscr", "调用医保局接口失败:" + e.getMessage());
|
||||
resultMap.put("api_result", "ERROR");
|
||||
resultMap.put("create_time", DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd_HH_mm_ss));
|
||||
resultMap.put("modify_time", DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd_HH_mm_ss));
|
||||
|
||||
reconciliationResults.add(resultMap);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 批量保存对账结果到数据库
|
||||
if (reconciliationResults.size() > 0) {
|
||||
reconciliationService.insertMedicalInsuranceReconciliationResultBatch(reconciliationResults);
|
||||
}
|
||||
|
||||
responseMap.put("reconciliationResults", reconciliationResults);
|
||||
LogUtil.info(this.getClass(), "医保对账完成,共处理 " + reconciliationResults.size() + " 组数据");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
errCode = "999";
|
||||
errMsg = "医保对账失败:" + e.getMessage();
|
||||
LogUtil.error(this.getClass(), errMsg);
|
||||
}
|
||||
|
||||
responseMap.put("errCode", errCode);
|
||||
responseMap.put("errMsg", errMsg);
|
||||
return responseMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用医保局对账接口
|
||||
*/
|
||||
private HashMap<Object, Object> callMedicalInsuranceAPI(
|
||||
String trade_date, String insutype, String clr_type,
|
||||
String medfee_sumamt, String fund_pay_sumamt, String acct_pay,
|
||||
String fixmedins_setl_cnt) throws Exception {
|
||||
|
||||
HashMap<Object, Object> result = new HashMap<>();
|
||||
|
||||
// 计算日期范围(当日到当日)
|
||||
String stmt_begndate = trade_date;
|
||||
String stmt_enddate = trade_date;
|
||||
|
||||
// 生成当前时间
|
||||
String inf_time = DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd_HH_mm_ss);
|
||||
|
||||
// 生成消息ID(机构编码+时间戳+序号)
|
||||
String msgid = FIXMEDINS_CODE + DateDUtil.DateToStr("yyyyMMddHHmmss", new Date()) + "0001";
|
||||
|
||||
// 构建请求JSON
|
||||
JSONObject requestJson = new JSONObject();
|
||||
requestJson.put("cainfo", "");
|
||||
requestJson.put("dev_no", "");
|
||||
requestJson.put("dev_safe_info", "");
|
||||
requestJson.put("fixmedins_code", FIXMEDINS_CODE);
|
||||
requestJson.put("fixmedins_name", FIXMEDINS_NAME);
|
||||
requestJson.put("inf_time", inf_time);
|
||||
requestJson.put("infno", INFNO);
|
||||
requestJson.put("infver", INFVER);
|
||||
requestJson.put("insuplc_admdvs", INSUPLC_ADMDVS);
|
||||
requestJson.put("mdtrtarea_admvs", MDTRTAREA_ADMVS);
|
||||
requestJson.put("msgid", msgid);
|
||||
requestJson.put("opter", OPTER);
|
||||
requestJson.put("opter_name", OPTER_NAME);
|
||||
requestJson.put("opter_type", OPTER_TYPE);
|
||||
requestJson.put("recer_sys_code", RECER_SYS_CODE);
|
||||
requestJson.put("sign_no", "");
|
||||
requestJson.put("signtype", SIGNTYPE);
|
||||
|
||||
// 构建input.data
|
||||
JSONObject inputData = new JSONObject();
|
||||
inputData.put("acct_pay", acct_pay);
|
||||
inputData.put("clr_type", clr_type);
|
||||
inputData.put("fixmedins_setl_cnt", fixmedins_setl_cnt);
|
||||
inputData.put("fund_pay_sumamt", fund_pay_sumamt);
|
||||
inputData.put("insutype", insutype);
|
||||
inputData.put("medfee_sumamt", medfee_sumamt);
|
||||
inputData.put("setl_optins", SETL_OPTINS);
|
||||
inputData.put("stmt_begndate", stmt_begndate);
|
||||
inputData.put("stmt_enddate", stmt_enddate);
|
||||
|
||||
JSONObject input = new JSONObject();
|
||||
input.put("data", inputData);
|
||||
requestJson.put("input", input);
|
||||
|
||||
LogUtil.info(this.getClass(), "医保对账请求(日期范围:" + stmt_begndate + " 到 " + stmt_enddate + "):" + requestJson.toJSONString());
|
||||
|
||||
// 根据险种选择接口地址
|
||||
String apiUrl;
|
||||
boolean isGongshang = GONGSHANG_INSUTYPE.equals(insutype);
|
||||
if (isGongshang) {
|
||||
apiUrl = GONGSHANG_INSURANCE_URL;
|
||||
LogUtil.info(this.getClass(), "险种99410使用工商医保接口(当日到当日):" + apiUrl);
|
||||
} else {
|
||||
apiUrl = MEDICAL_INSURANCE_URL;
|
||||
LogUtil.info(this.getClass(), "使用普通医保接口(当日到当日):" + apiUrl);
|
||||
}
|
||||
|
||||
// 发送HTTP请求(使用信任所有SSL证书的HttpClient)
|
||||
CloseableHttpClient httpClient = null;
|
||||
try {
|
||||
httpClient = SSLUtil.createSSLClientDefault();
|
||||
} catch (Exception e) {
|
||||
LogUtil.error(this.getClass(), "创建SSL HttpClient失败:" + e.getMessage());
|
||||
// 如果创建SSL HttpClient失败,使用默认的HttpClient
|
||||
httpClient = HttpClients.createDefault();
|
||||
}
|
||||
|
||||
HttpPost httpPost = new HttpPost(apiUrl);
|
||||
httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
|
||||
httpPost.setEntity(new StringEntity(requestJson.toJSONString(), StandardCharsets.UTF_8));
|
||||
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
response = httpClient.execute(httpPost);
|
||||
String responseStr = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
|
||||
|
||||
LogUtil.info(this.getClass(), "医保对账响应:" + responseStr);
|
||||
|
||||
// 解析响应
|
||||
JSONObject responseJson = JSON.parseObject(responseStr);
|
||||
|
||||
// 存储基础响应信息
|
||||
result.put("infcode", responseJson.getInteger("infcode"));
|
||||
result.put("err_msg", responseJson.getString("err_msg"));
|
||||
result.put("warn_msg", responseJson.getString("warn_msg"));
|
||||
result.put("refmsg_time", responseJson.getString("refmsg_time"));
|
||||
result.put("respond_time", responseJson.getString("respond_time"));
|
||||
result.put("inf_refmsgid", responseJson.getString("inf_refmsgid"));
|
||||
|
||||
Integer infcode = responseJson.getInteger("infcode");
|
||||
if (infcode != null && infcode == 0) {
|
||||
// 请求成功
|
||||
JSONObject output = responseJson.getJSONObject("output");
|
||||
if (output != null && output.containsKey("stmtinfo")) {
|
||||
JSONObject stmtinfo = output.getJSONObject("stmtinfo");
|
||||
result.put("setl_optins", stmtinfo.getString("setl_optins"));
|
||||
|
||||
String stmt_rslt = stmtinfo.getString("stmt_rslt");
|
||||
String stmt_rslt_dscr = stmtinfo.getString("stmt_rslt_dscr");
|
||||
|
||||
// 工商医保的对账结果处理(99410险种)
|
||||
if (isGongshang) {
|
||||
// 工商医保返回格式:
|
||||
// stmt_rslt: "101" 表示有差异(对应普通医保的"1"失败)
|
||||
// stmt_rslt: "0" 表示一致(对应普通医保的"0"成功)
|
||||
if ("101".equals(stmt_rslt)) {
|
||||
result.put("stmt_rslt", "1"); // 转换为标准的失败标识
|
||||
LogUtil.info(this.getClass(), "工商医保对账结果:有差异 - " + stmt_rslt_dscr);
|
||||
} else if ("0".equals(stmt_rslt)) {
|
||||
result.put("stmt_rslt", "0"); // 成功
|
||||
LogUtil.info(this.getClass(), "工商医保对账结果:一致");
|
||||
} else {
|
||||
result.put("stmt_rslt", stmt_rslt); // 保持原值
|
||||
LogUtil.info(this.getClass(), "工商医保对账结果:" + stmt_rslt);
|
||||
}
|
||||
} else {
|
||||
// 普通医保直接使用返回值
|
||||
result.put("stmt_rslt", stmt_rslt);
|
||||
}
|
||||
|
||||
result.put("stmt_rslt_dscr", stmt_rslt_dscr);
|
||||
result.put("api_result", "SUCCESS");
|
||||
} else {
|
||||
result.put("stmt_rslt", "9");
|
||||
result.put("stmt_rslt_dscr", "返回数据格式错误");
|
||||
result.put("api_result", "ERROR");
|
||||
}
|
||||
} else {
|
||||
// 请求失败
|
||||
String err_msg = responseJson.getString("err_msg");
|
||||
result.put("stmt_rslt", "9");
|
||||
result.put("stmt_rslt_dscr", "医保局返回错误:" + err_msg);
|
||||
result.put("api_result", "ERROR");
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
httpClient.close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user