init:微信医保数据入库
This commit is contained in:
@@ -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<Object, Object> getBankDataByMedicalInsuranceAPI(@RequestBody HashMap<Object, Object> map) {
|
||||
List<BankbillHistory> list = new ArrayList<>();
|
||||
log.info("开始获取微信医保账单");
|
||||
HashMap<Object, Object> 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<String, Object> 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 = "<xml>\n" +
|
||||
// " <appid>" + appid + "</appid>\n" +
|
||||
// " <bill_date>" + trade_date + "</bill_date>\n" +
|
||||
// " <bill_type>ALL</bill_type>\n" +
|
||||
// " <mch_id>" + mch_id + "</mch_id>\n" +
|
||||
// " <nonce_str>" + randomStr + "</nonce_str>\n" +
|
||||
// " <sign>" + sign + "</sign>\n" +
|
||||
// "</xml>";
|
||||
// // 获取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("<return_msg><![CDATA[Bill Creating]]></return_msg>")) {
|
||||
// log.info("账单正在生成中,请稍后重试");
|
||||
// errCode = "999";
|
||||
// errMsg = "微信账单正在生成中,请稍后重试";
|
||||
// responseMap.put("errCode", errCode);
|
||||
// responseMap.put("errMsg", errMsg);
|
||||
// return responseMap;
|
||||
// }
|
||||
//
|
||||
// // 检查是否无账单数据
|
||||
// if (body1.contains("<return_msg><![CDATA[No Bill Exist]]></return_msg>")) {
|
||||
// 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("[<return_msg><![CDATA[No Bill Exist]]></return_msg>]")) {
|
||||
// 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 = "<xml>\n" +
|
||||
" <appid>" + appid + "</appid>\n" +
|
||||
" <bill_date>" + trade_date + "</bill_date>\n" +
|
||||
" <bill_type>ALL</bill_type>\n" +
|
||||
" <mch_id>" + mch_id + "</mch_id>\n" +
|
||||
" <nonce_str>" + randomStr + "</nonce_str>\n" +
|
||||
" <sign>" + signYB + "</sign>\n" +
|
||||
"</xml>";
|
||||
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<CsvRow> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user