diff --git a/src/main/java/com/saye/hgddmz/controller/GetDateController.java b/src/main/java/com/saye/hgddmz/controller/GetDateController.java index 44dd5a0..3074a03 100644 --- a/src/main/java/com/saye/hgddmz/controller/GetDateController.java +++ b/src/main/java/com/saye/hgddmz/controller/GetDateController.java @@ -1,8 +1,16 @@ package com.saye.hgddmz.controller; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.text.csv.CsvData; +import cn.hutool.core.text.csv.CsvReader; +import cn.hutool.core.text.csv.CsvRow; +import cn.hutool.core.text.csv.CsvUtil; import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.XmlUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONUtil; import com.saye.hgddmz.commons.date.DateDUtil; import com.saye.hgddmz.commons.string.StringDUtil; import com.saye.hgddmz.entity.BankbillHistory; @@ -19,6 +27,7 @@ import org.springframework.web.bind.annotation.*; import java.io.File; import java.io.FileInputStream; +import java.io.IOException; import java.io.InputStream; import java.text.DecimalFormat; import java.util.*; @@ -28,6 +37,8 @@ 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.w3c.dom.Document; +import org.w3c.dom.Element; /** @@ -46,6 +57,8 @@ public class GetDateController { private static String appid = "wx45acd2b4907cb8f4"; private static String secret = "895b90585c4698485c07e113711eac85"; private static String key = "Nxwj20250903Jojubanking12091209x"; + + private static String key_yb = "086831b6021364d2e96e523771087a02"; // 微信消息推送相关常量 private static String WX_APP_ID = "wx45acd2b4907cb8f4"; @@ -1550,4 +1563,306 @@ public class GetDateController { // Spring会在响应完成后自动处理资源清理 } } + + @PostMapping("/getBankDataByMedicalInsuranceAPI") + @ResponseBody + public HashMap getBankDataByMedicalInsuranceAPI(@RequestBody HashMap map) { + List list = new ArrayList<>(); + log.info("开始获取微信医保账单"); + HashMap responseMap = new HashMap<>(); + String errCode = "0"; + String errMsg = ""; + + try { + String localPath = StringDUtil.changeNullToEmpty(map.get("LOCAL_PATH")); + String mch_id = StringDUtil.changeNullToEmpty(map.get("MCH_ID")); + String trade_date = StringDUtil.changeNullToEmpty(map.get("trade_date")); + + log.info("开始获取微信账单,参数: mch_id={}, trade_date={}", mch_id, trade_date); + + HashMap reqMap = new HashMap<>(); + reqMap.put("grant_type", grant_type); + reqMap.put("appid", appid); + reqMap.put("secret", secret); + + String randomStr = RandomUtil.randomString(32); + +// String signString = "appid=" + appid + "&bill_date=" + trade_date + "&bill_type=ALL&mch_id=" + mch_id + "&nonce_str=" + randomStr + "&key="+ key; +// String sign = SecureUtil.md5(signString).toUpperCase(); +// String reqXml = "\n" + +// " " + appid + "\n" + +// " " + trade_date + "\n" + +// " ALL\n" + +// " " + mch_id + "\n" + +// " " + randomStr + "\n" + +// " " + sign + "\n" + +// ""; +// // 获取access_token +// log.info("开始调用微信账单接口,参数: mch_id={}, trade_date={}", mch_id, trade_date); +// String body1 = HttpUtil.createPost("https://api.mch.weixin.qq.com/pay/downloadbill") +// .header("Content-Type", "text/xml") +// .timeout(30000) // 设置30秒超时 +// .body(reqXml) +// .execute() +// .body(); +// log.info("微信账单接口返回数据长度: {}", body1 != null ? body1.length() : 0); +// log.info("微信账单接口返回数据: {}", body1); +// +// // 检查微信接口返回状态 +// +// if (body1.contains("")) { +// log.info("账单正在生成中,请稍后重试"); +// errCode = "999"; +// errMsg = "微信账单正在生成中,请稍后重试"; +// responseMap.put("errCode", errCode); +// responseMap.put("errMsg", errMsg); +// return responseMap; +// } +// +// // 检查是否无账单数据 +// if (body1.contains("")) { +// log.info("该日期无账单数据"); +// errCode = "999"; +// errMsg = "该日期无账单数据"; +// responseMap.put("errCode", errCode); +// responseMap.put("errMsg", errMsg); +// return responseMap; +// } +// +// String[] split = body1.split("\n"); +// for (int i = 1; i < split.length - 2; i++) { +// String[] split1 = split[i].split(","); +// if (Arrays.toString(split1).equals("[]")) { +// break; +// } +// // 检查是否是账单正在生成状态 +// if (Arrays.toString(split1).contains("Bill Creating")) { +// log.info("账单正在生成中,跳过处理"); +// break; +// } +// +// BankbillHistory bankbillHistory = new BankbillHistory(); +// int flag = 0; +// +// // 解析CSV数据到BankbillHistory实体 +// for (int j = 0; j < split1.length; j++) { +// String value = split1[j].replaceAll("`", "").trim(); +// +// switch (j) { +// case 0: // 交易时间 +// if (value.contains(" ")) { +// String[] timeSplit = value.split(" "); +// bankbillHistory.setCQsrq(timeSplit[0]); // 清算日期 +// bankbillHistory.setCJyrq(timeSplit[0]); // 交易日期 +// bankbillHistory.setCJysj(timeSplit[1]); // 交易时间 +// } +// break; +// case 4: // 设备号 +// bankbillHistory.setCZdh(value); +// break; +// case 5: // 微信订单号 +// bankbillHistory.setCYsddh(value); +// break; +// case 6: // 商户订单号 +// bankbillHistory.setCShddh(value); +// break; +// case 7: // 用户标识 +// bankbillHistory.setCCard(value); +// break; +// case 8: // 交易类型 +// bankbillHistory.setCJylx(value); +// break; +// case 9: // 交易状态 +// if ("REFUND".equals(value)) { +// flag = -1; +// } +// break; +// case 10: // 付款银行 +// bankbillHistory.setCFkh(value); +// break; +// case 12: // 应结订单金额 +// bankbillHistory.setCQsje(value); +// break; +// case 24: // 订单金额 +// // 只有在非退款状态时才设置订单金额 +// if (flag >= 0) { +// bankbillHistory.setCJyje(value); +// } +// break; +// case 20: // 商品名称 +// bankbillHistory.setCBzzd(value); +// break; +// case 22: // 手续费 +// bankbillHistory.setCSxf(value); +// break; +// case 14: // 微信退款单号 +// bankbillHistory.setCThddh(value); +// break; +// case 15: // 商户退款单号 +// bankbillHistory.setCYjylsh(value); +// break; +// case 25: // 申请退款金额 +// if (!"0.00".equals(value) && !value.isEmpty()) { +// bankbillHistory.setCJyje("-" + value); +// } +// break; +// } +// } +// +// // 设置支付方式 +// bankbillHistory.setCZffs("微信支付"); +// +// // 设置表名 +// bankbillHistory.setBillTableName("微信支付账单"); +// +// list.add(bankbillHistory); +// } + // 获取access_token + String body = HttpUtil.createPost("https://api.weixin.qq.com/cgi-bin/stable_token").body(JSONUtil.toJsonStr(reqMap)).execute().body(); + + String access_token = JSONUtil.parseObj(body).getStr("access_token"); + // 获取医保账单下载地址 + // https://api.weixin.qq.com/payinsurance/billdownload?access_token=ACCESS_TOKEN + String signYBString = "appid=" + appid + "&bill_date=" + trade_date + "&bill_type=ALL&mch_id=" + mch_id + "&nonce_str=" + randomStr + "&key="+key_yb; + log.info("微信账单签名:" + signYBString); + String signYB = SecureUtil.md5(signYBString).toUpperCase(); + log.info("微信账单签名结果:" + signYB); + String reqYbXml = "\n" + + " " + appid + "\n" + + " " + trade_date + "\n" + + " ALL\n" + + " " + mch_id + "\n" + + " " + randomStr + "\n" + + " " + signYB + "\n" + + ""; + log.info("微信账单请求参数:" + reqYbXml); + String resBody = HttpUtil.createPost("https://api.weixin.qq.com/payinsurance/billdownload?access_token=" + access_token).header("Content-Type", "text/xml").body(reqYbXml).execute().body(); + log.info("微信账单下载返回结果:" + resBody); + Document document = XmlUtil.parseXml(resBody); + Element elementG = XmlUtil.getRootElement(document); + Element returnCode = XmlUtil.getElement(elementG, "return_code"); + + if (returnCode.getTextContent().equals("SUCCESS")) {// 响应成功 + // 下载文件 + Element downloadUrl = XmlUtil.getElement(elementG, "download_url"); + String dwUrl = downloadUrl.getTextContent(); + log.info("开始下载文件"); + HttpUtil.downloadFileFromUrl(dwUrl, localPath + File.separator + trade_date + ".csv"); + HttpUtil.downloadFileFromUrl(dwUrl, localPath + File.separator + trade_date + ".txt"); + // HttpUtil.downloadFileFromUrl(dwUrl, localPath); + log.info("下载文件成功"); + CsvReader reader = CsvUtil.getReader(); + try { + CsvData read = reader.read(FileUtil.file(localPath + File.separator + trade_date + ".csv")); + List rows = read.getRows(); + if (rows.size() > 1) { + for (int i = 1; i < rows.size(); i++) { + CsvRow row = rows.get(i); + BankbillHistory bankbillHistory = new BankbillHistory(); + String s = row.get(0).replaceAll("`", ""); + String[] s1 = s.split(" "); + log.info("s1 is :" + Arrays.toString(s1)); + bankbillHistory.setCJyrq(s1[0]); + bankbillHistory.setCQsrq(s1[0]); + bankbillHistory.setCJysj(s1[1]); + bankbillHistory.setCZdh(row.get(1).replaceAll("`", "")); + bankbillHistory.setCCkh(row.get(2).replaceAll("`", "")); + bankbillHistory.setCLsh(row.get(5).replaceAll("`", "")); + bankbillHistory.setCShddh(row.get(6).replaceAll("`", "")); + bankbillHistory.setCCard(row.get(7).replaceAll("`", "")); + bankbillHistory.setCYsddh(row.get(25).replaceAll("`", "")); + + // 处理交易金额,不跳过0.00的记录 + String amount = row.get(46).replaceAll("`", ""); + if (row.get(45).replaceAll("`", "").equals("REFUND")) { + // 退款记录,金额为负数 + if (!"0.00".equals(amount) && !amount.isEmpty()) { + bankbillHistory.setCJyje("-" + amount); + } else { + bankbillHistory.setCJyje("0.00"); + } + } else { + // 普通交易记录 + bankbillHistory.setCJyje(amount); + } + + // 医保账户金额(医保个账金额,第53列,索引52) + if (row.size() > 52) { + String acctPay = row.get(52).replaceAll("`", ""); + bankbillHistory.setAcctPay(acctPay); + } + + // 医保统筹金额(第54列,索引53) + if (row.size() > 53) { + String fundPaySumamt = row.get(53).replaceAll("`", ""); + bankbillHistory.setFundPaySumamt(fundPaySumamt); + } + + // 医疗总费用(订单总金额,第49列,索引48) + if (row.size() > 48) { + String medfeeSumamt = row.get(48).replaceAll("`", ""); + bankbillHistory.setMedfeeSumamt(medfeeSumamt); + } + + bankbillHistory.setBillTableName("微信医保账单"); + list.add(bankbillHistory); + + // 打印第一条记录的完整实体类信息 + if (i == 1) { + log.info("========== 微信账单解析实体类示例 =========="); + log.info("实体类完整信息(JSON格式):"); + log.info(JSONUtil.toJsonStr(bankbillHistory)); + log.info(""); + log.info("实体类字段详情:"); + log.info(" 交易日期(cJyrq): {}", bankbillHistory.getCJyrq()); + log.info(" 清算日期(cQsrq): {}", bankbillHistory.getCQsrq()); + log.info(" 交易时间(cJysj): {}", bankbillHistory.getCJysj()); + log.info(" 终端号(cZdh): {}", bankbillHistory.getCZdh()); + log.info(" 参考号(cCkh): {}", bankbillHistory.getCCkh()); + log.info(" 流水号(cLsh): {}", bankbillHistory.getCLsh()); + log.info(" 商户订单号(cShddh): {}", bankbillHistory.getCShddh()); + log.info(" 用户标识(cCard): {}", bankbillHistory.getCCard()); + log.info(" 微信订单号(cYsddh): {}", bankbillHistory.getCYsddh()); + log.info(" 交易金额(cJyje): {}", bankbillHistory.getCJyje()); + log.info(" 医疗总费用(medfeeSumamt): {}", bankbillHistory.getMedfeeSumamt()); + log.info(" 医保账户金额(acctPay): {}", bankbillHistory.getAcctPay()); + log.info(" 医保统筹金额(fundPaySumamt): {}", bankbillHistory.getFundPaySumamt()); + log.info(" 表名(billTableName): {}", bankbillHistory.getBillTableName()); + log.info("=========================================="); + } + } + } + responseMap.put("list", list); + } catch (IORuntimeException e) { + throw new RuntimeException(e); + } finally { + try { + reader.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + if (list.size() > 0) { + log.info("集合大小为"+ list.size()); + responseMap.put("list", list); + } else { + errCode = "999"; + errMsg = "账单数据为空,或未获取到账单!"; + } + responseMap.put("errCode", errCode); + responseMap.put("errMsg", errMsg); + return responseMap; + + } catch (Exception e) { + log.error("微信账单获取异常", e); + errCode = "999"; + errMsg = "微信账单获取异常: " + e.getMessage(); + responseMap.put("errCode", errCode); + responseMap.put("errMsg", errMsg); + return responseMap; + } + } } + + diff --git a/src/main/java/com/saye/hgddmz/entity/BankbillHistory.java b/src/main/java/com/saye/hgddmz/entity/BankbillHistory.java index 42803da..5556e6d 100644 --- a/src/main/java/com/saye/hgddmz/entity/BankbillHistory.java +++ b/src/main/java/com/saye/hgddmz/entity/BankbillHistory.java @@ -1,5 +1,6 @@ package com.saye.hgddmz.entity; +import com.alibaba.fastjson.annotation.JSONField; import lombok.Getter; import lombok.Setter; @@ -139,5 +140,20 @@ public class BankbillHistory implements Serializable { * 对账表名 */ private String billTableName; + /** + * 医保账户金额(医保个账金额) + */ + @JSONField(name = "acct_pay") + private String acctPay; + /** + * 医保统筹金额 + */ + @JSONField(name = "fund_pay_sumamt") + private String fundPaySumamt; + /** + * 医疗总费用(订单总金额) + */ + @JSONField(name = "medfee_sumamt") + private String medfeeSumamt; }