Files
dzpt-server/src/main/java/com/saye/hgddmz/controller/GetDateController.java

1886 lines
84 KiB
Java
Raw Normal View History

2025-09-15 18:52:59 +08:00
package com.saye.hgddmz.controller;
2025-11-17 17:27:12 +08:00
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;
2025-09-15 18:52:59 +08:00
import cn.hutool.core.util.RandomUtil;
2025-11-17 17:27:12 +08:00
import cn.hutool.core.util.XmlUtil;
2025-09-15 18:52:59 +08:00
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
2025-11-17 17:27:12 +08:00
import cn.hutool.json.JSONUtil;
2025-09-15 18:52:59 +08:00
import com.saye.hgddmz.commons.date.DateDUtil;
import com.saye.hgddmz.commons.string.StringDUtil;
import com.saye.hgddmz.entity.BankbillHistory;
2025-10-31 09:08:46 +08:00
import com.saye.hgddmz.entity.UserOrder;
2025-09-15 18:52:59 +08:00
import com.saye.hgddmz.util.DownloadFtpUtil;
2025-10-31 09:08:46 +08:00
import com.saye.hgddmz.util.HttpClientUtil;
2025-09-15 18:52:59 +08:00
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
2025-10-31 09:08:46 +08:00
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.*;
2025-09-15 18:52:59 +08:00
import org.springframework.stereotype.Controller;
2025-10-31 09:08:46 +08:00
import org.springframework.web.bind.annotation.*;
2025-09-15 18:52:59 +08:00
import java.io.File;
import java.io.FileInputStream;
2025-11-17 17:27:12 +08:00
import java.io.IOException;
2025-10-31 09:08:46 +08:00
import java.io.InputStream;
import java.text.DecimalFormat;
2025-09-15 18:52:59 +08:00
import java.util.*;
2025-10-31 09:08:46 +08:00
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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;
2025-11-17 17:27:12 +08:00
import org.w3c.dom.Document;
import org.w3c.dom.Element;
2025-09-15 18:52:59 +08:00
/**
* @author thuang
* @version 1.0
* @description: TODO
* @date 2021/9/22 13:55
*/
@Controller
@Slf4j
public class GetDateController {
private static String grant_type = "client_credential";
private static String appid = "wx45acd2b4907cb8f4";
private static String secret = "895b90585c4698485c07e113711eac85";
private static String key = "Nxwj20250903Jojubanking12091209x";
2025-11-17 17:27:12 +08:00
private static String key_yb = "086831b6021364d2e96e523771087a02";
2025-10-31 09:08:46 +08:00
// 微信消息推送相关常量
private static String WX_APP_ID = "wx45acd2b4907cb8f4";
private static String WX_SECRET = "895b90585c4698485c07e113711eac85";
2025-09-15 18:52:59 +08:00
/**
* 安全获取单元格字符串值
* @param row 行对象
* @param cellIndex 单元格索引
* @return 单元格字符串值如果单元格为空则返回空字符串
*/
private static String getCellStringValue(HSSFRow row, int cellIndex) {
if (row == null) {
return "";
}
HSSFCell cell = row.getCell(cellIndex);
if (cell == null) {
return "";
}
try {
cell.setCellType(Cell.CELL_TYPE_STRING);
String value = cell.getStringCellValue();
return value != null ? value.trim() : "";
} catch (Exception e) {
log.warn("获取单元格值失败,行: {}, 列: {}, 错误: {}", row.getRowNum(), cellIndex, e.getMessage());
return "";
}
}
/**
* 安全获取单元格日期值
* @param row 行对象
* @param cellIndex 单元格索引
* @return 日期字符串如果单元格为空或不是日期格式则返回空字符串
*/
private static String getCellDateValue(HSSFRow row, int cellIndex) {
if (row == null) {
return "";
}
HSSFCell cell = row.getCell(cellIndex);
if (cell == null) {
return "";
}
try {
cell.setCellType(Cell.CELL_TYPE_NUMERIC);
if (HSSFDateUtil.isCellDateFormatted(cell)) {
Date dateCellValue = cell.getDateCellValue();
return DateDUtil.DateToStr(DateDUtil.yyyy_MM_dd, dateCellValue);
}
return "";
} catch (Exception e) {
log.warn("获取单元格日期值失败,行: {}, 列: {}, 错误: {}", row.getRowNum(), cellIndex, e.getMessage());
return "";
}
}
/**
* @description: 获取银行端商户对账数据
* @author thuang
* @date 2021/9/22 13:57
* @version 1.0
*/
@PostMapping("/getBankDataBySH")
@ResponseBody
public HashMap<Object, Object> getBankDataBySH(@RequestBody HashMap<Object, Object> map) {
HashMap<Object, Object> responseMap = new HashMap<>();
String errCode = "0";
String errMsg = "";
// 先下载文件
String host = StringDUtil.changeNullToEmpty(map.get("FTP_HOST"));
String portStr = StringDUtil.changeNullToEmpty(map.get("FTP_PORT"));
int port = Integer.parseInt("".equals(portStr) ? "21" : portStr);
String username = StringDUtil.changeNullToEmpty(map.get("FTP_USER"));
String password = StringDUtil.changeNullToEmpty(map.get("FTP_PASSWORD"));
String localPath = StringDUtil.changeNullToEmpty(map.get("LOCAL_PATH"));
String mch_id = StringDUtil.changeNullToEmpty(map.get("MCH_ID"));
String ftp_path = StringDUtil.changeNullToEmpty(map.get("FTP_PATH"));
String ftp_file_name = StringDUtil.changeNullToEmpty(map.get("FTP_FILE_NAME"));
String bill_table_name = StringDUtil.changeNullToEmpty(map.get("BILL_TABLE_NAME"));
String thirdConfigId = StringDUtil.changeNullToEmpty(map.get("ID"));
String trade_date = StringDUtil.changeNullToEmpty(map.get("trade_date"));
HSSFWorkbook sheets = null;
try {
// 下载文件
log.info("开始下载FTP文件: " + ftp_file_name);
boolean b = DownloadFtpUtil.downloadFtpFile(host, username, password, port, ftp_path, localPath, ftp_file_name);
// 判断是否下载到文件
if (!b) {
log.error("FTP文件下载失败: " + ftp_file_name);
errCode = "1";
errMsg = "FTP文件下载失败请检查FTP连接参数和文件是否存在";
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
// 判断本地是否有文件
File file = new File(localPath + "/" + ftp_file_name);
if (file.exists()) {
// 存在 开始解析 存入数据库
FileInputStream fileInputStream = new FileInputStream(localPath + "/" + ftp_file_name);
sheets = new HSSFWorkbook(fileInputStream);
HSSFSheet sheet = sheets.getSheetAt(0);
// 获取sheet中第一行行号
int firstRowNum = sheet.getFirstRowNum();
// 获取sheet中最后一行行号
int lastRowNum = sheet.getLastRowNum();
List<BankbillHistory> list = new ArrayList<>();
for (int i = firstRowNum + 3; i <= lastRowNum - 2; i++) {// 因为表格中第一行为说明,第二行为列标题
HSSFRow row = sheet.getRow(i);
if (row == null) {
continue;
}
BankbillHistory bankbillHistory = new BankbillHistory();
// 清算日期
String qsrqStr = getCellStringValue(row, 0);
// 拿第一个字段判断这条记录是否为空 如果为空直接跳出 一般这字段为空就是数据结束了或根本没有
// 为合计也跳出
if ("".equals(qsrqStr) || "合计".equals(qsrqStr)) {
break;
}
bankbillHistory.setCQsrq(qsrqStr);
// 交易日期
String jyrqStr = getCellDateValue(row, 1);
bankbillHistory.setCJyrq(jyrqStr);
if (i == firstRowNum + 3) {
trade_date = jyrqStr;
}
// 交易时间
String jysjStr = getCellStringValue(row, 2);
bankbillHistory.setCJysj(jysjStr);
// 卡号
String khStr = getCellStringValue(row, 3);
bankbillHistory.setCCard(khStr);
// 交易类型
String jylxStr = getCellStringValue(row, 4);
bankbillHistory.setCJylx(jylxStr);
// 交易金额
String jyjeStr = getCellStringValue(row, 5);
bankbillHistory.setCJyje(jyjeStr);
// 终端号
String zdhStr = getCellStringValue(row, 6);
bankbillHistory.setCZdh(zdhStr);
// 清算金额
String qsjeStr = getCellStringValue(row, 7);
bankbillHistory.setCQsje(qsjeStr);
// 手续费
String sxfStr = getCellStringValue(row, 8);
bankbillHistory.setCSxf(sxfStr);
// 参考号
String ckhStr = getCellStringValue(row, 9);
bankbillHistory.setCCkh(ckhStr);
// 流水号
String lshStr = getCellStringValue(row, 10);
bankbillHistory.setCLsh(lshStr);
// 卡类型
String klxStr = getCellStringValue(row, 11);
bankbillHistory.setCKlx(klxStr);
// 商户订单号
String shddhStr = getCellStringValue(row, 12);
bankbillHistory.setCShddh(shddhStr);
// 支付方式
String zffsStr = getCellStringValue(row, 13);
bankbillHistory.setCZffs(zffsStr);
// 银商订单号
String ysddhStr = getCellStringValue(row, 14);
bankbillHistory.setCYsddh(ysddhStr);
// 退货订单号
String thddhStr = getCellStringValue(row, 15);
bankbillHistory.setCThddh(thddhStr);
// 实际支付金额
String sjzfjeStr = getCellStringValue(row, 16);
bankbillHistory.setCSjzfje(sjzfjeStr);
// 备注字段
String bzzdStr = getCellStringValue(row, 17);
bankbillHistory.setCBzzd(bzzdStr);
// 付款附言
String fkfyStr = getCellStringValue(row, 18);
bankbillHistory.setCFkfy(fkfyStr);
// 钱包优惠金额
String qbyhjeStr = getCellStringValue(row, 19);
bankbillHistory.setCQbyhje(qbyhjeStr);
// 商户优惠金额
String shyhjeStr = getCellStringValue(row, 20);
bankbillHistory.setCShyhje(shyhjeStr);
// 发卡行
String fkhStr = getCellStringValue(row, 21);
bankbillHistory.setCFkh(fkhStr);
// 分店简称
String fdjcStr = getCellStringValue(row, 22);
bankbillHistory.setCFdjc(fdjcStr);
// 其他优惠金额
String qtyhjeStr = getCellStringValue(row, 23);
bankbillHistory.setCQtyhje(qtyhjeStr);
// 分期期数
String fqqsStr = getCellStringValue(row, 24);
bankbillHistory.setCFqqs(fqqsStr);
// 分期手续费
String fqsxfStr = getCellStringValue(row, 25);
bankbillHistory.setCFqsxf(fqsxfStr);
// 分期服务方
String fqfwfStr = getCellStringValue(row, 26);
bankbillHistory.setCFqfwf(fqfwfStr);
// 分期付息方
String fqfxfStr = getCellStringValue(row, 27);
bankbillHistory.setCFqfxf(fqfxfStr);
// 子订单号
String zddhStr = getCellStringValue(row, 28);
bankbillHistory.setCZddh(zddhStr);
// 表名
bankbillHistory.setBillTableName(bill_table_name);
list.add(bankbillHistory);
}
responseMap.put("list", list);
} else {
System.out.println("执行失败,原因:路径" + ftp_path + "下无下载文件" + ftp_file_name);
errCode = "999";
errMsg = "执行失败,原因:路径" + ftp_path + "下无下载文件" + ftp_file_name;
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("执行失败,原因:" + e.getMessage());
errCode = "999";
errMsg = "执行失败,原因:" + e.getMessage();
} finally {
try {
if (sheets != null) {
sheets.close();
}
} catch (Exception ie) {
ie.printStackTrace();
}
}
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
/**
* @description: 获取银行端商户POS对账数据
* @author thuang
* @date 2021/9/22 13:57
* @version 1.0
*/
@PostMapping("/getBankDataBySHPOS")
@ResponseBody
public HashMap<Object, Object> getBankDataBySHPOS(@RequestBody HashMap<Object, Object> map) {
HashMap<Object, Object> responseMap = new HashMap<>();
String errCode = "0";
String errMsg = "";
// 先下载文件
String host = StringDUtil.changeNullToEmpty(map.get("FTP_HOST"));
String portStr = StringDUtil.changeNullToEmpty(map.get("FTP_PORT"));
int port = Integer.parseInt("".equals(portStr) ? "21" : portStr);
String username = StringDUtil.changeNullToEmpty(map.get("FTP_USER"));
String password = StringDUtil.changeNullToEmpty(map.get("FTP_PASSWORD"));
String localPath = StringDUtil.changeNullToEmpty(map.get("LOCAL_PATH"));
String mch_id = StringDUtil.changeNullToEmpty(map.get("MCH_ID"));
String ftp_path = StringDUtil.changeNullToEmpty(map.get("FTP_PATH"));
String ftp_file_name = StringDUtil.changeNullToEmpty(map.get("FTP_FILE_NAME"));
String bill_table_name = StringDUtil.changeNullToEmpty(map.get("BILL_TABLE_NAME"));
String thirdConfigId = StringDUtil.changeNullToEmpty(map.get("ID"));
String trade_date = StringDUtil.changeNullToEmpty(map.get("trade_date"));
HSSFWorkbook sheets = null;
try {
// 下载文件
log.info("开始下载FTP文件: " + ftp_file_name);
boolean b = DownloadFtpUtil.downloadFtpFile(host, username, password, port, ftp_path, localPath, ftp_file_name);
// 判断是否下载到文件
if (!b) {
log.error("FTP文件下载失败: " + ftp_file_name);
errCode = "1";
errMsg = "FTP文件下载失败请检查FTP连接参数和文件是否存在";
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
// 判断本地是否有文件
File file = new File(localPath + "/" + ftp_file_name);
if (file.exists()) {
// 存在 开始解析 存入数据库
FileInputStream fileInputStream = new FileInputStream(localPath + "/" + ftp_file_name);
sheets = new HSSFWorkbook(fileInputStream);
HSSFSheet sheet = sheets.getSheetAt(0);
// 获取sheet中第一行行号
int firstRowNum = sheet.getFirstRowNum();
// 获取sheet中最后一行行号
int lastRowNum = sheet.getLastRowNum();
List<BankbillHistory> list = new ArrayList<>();
for (int i = firstRowNum + 3; i <= lastRowNum - 4; i++) {
log.info("正在解析第" + i + "行数据");// 因为表格中第一行为说明,第二行为列标题
HSSFRow row = sheet.getRow(i);
if (row == null) {
continue;
}
BankbillHistory bankbillHistory = new BankbillHistory();
// 清算日期
String qsrqStr = getCellStringValue(row, 0);
// 拿第一个字段判断这条记录是否为空 如果为空直接跳出 一般这字段为空就是数据结束了或根本没有
if ("".equals(qsrqStr) || "汇总信息".equals(qsrqStr)) {
break;
}
bankbillHistory.setCQsrq(qsrqStr);
// 交易日期
String jyrqStr = getCellDateValue(row, 1);
bankbillHistory.setCJyrq(jyrqStr);
if (i == firstRowNum + 3) {
trade_date = jyrqStr;
}
// 交易时间
String jysjStr = getCellStringValue(row, 2);
bankbillHistory.setCJysj(jysjStr);
// 终端号
String zdhStr = getCellStringValue(row, 3);
bankbillHistory.setCZdh(zdhStr);
// 卡号
String khStr = getCellStringValue(row, 4);
bankbillHistory.setCCard(khStr);
// 交易类型
String jylxStr = getCellStringValue(row, 5);
bankbillHistory.setCJylx(jylxStr);
// 交易金额
String jyjeStr = getCellStringValue(row, 6);
log.info("jyjeStr:" + jyjeStr);
bankbillHistory.setCJyje(jyjeStr);
// 清算金额
String qsjeStr = getCellStringValue(row, 7);
bankbillHistory.setCQsje(qsjeStr);
// 手续费
String sxfStr = getCellStringValue(row, 8);
bankbillHistory.setCSxf(sxfStr);
// 参考号
String ckhStr = getCellStringValue(row, 9);
bankbillHistory.setCCkh(ckhStr);
// 流水号
String lshStr = getCellStringValue(row, 10);
bankbillHistory.setCLsh(lshStr);
// 卡类型
String klxStr = getCellStringValue(row, 11);
bankbillHistory.setCKlx(klxStr);
// 发卡行
String fkhStr = getCellStringValue(row, 12);
bankbillHistory.setCFkh(fkhStr);
// 支付方式
String zffsStr = getCellStringValue(row, 13);
bankbillHistory.setCZffs(zffsStr);
// 银商订单号
String ysddhStr = getCellStringValue(row, 15);
log.info("ysddhStr:" + ysddhStr);
bankbillHistory.setCYsddh(ysddhStr);
// 商户订单号
String shddhStr = getCellStringValue(row, 16);
bankbillHistory.setCShddh(shddhStr);
// 备注字段
String bzzdStr = getCellStringValue(row, 18);
bankbillHistory.setCBzzd(bzzdStr);
// 钱包优惠金额
String fdmcjjStr = getCellStringValue(row, 19);
bankbillHistory.setCFdjc(fdmcjjStr);
// 表名
bankbillHistory.setBillTableName(bill_table_name);
list.add(bankbillHistory);
}
responseMap.put("list", list);
} else {
System.out.println("执行失败,原因:路径" + ftp_path + "下无下载文件" + ftp_file_name);
errCode = "999";
errMsg = "执行失败,原因:路径" + ftp_path + "下无下载文件" + ftp_file_name;
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("执行失败,原因:" + e.getMessage());
errCode = "999";
errMsg = "执行失败,原因:" + e.getMessage();
} finally {
try {
if (sheets != null) {
sheets.close();
}
} catch (Exception ie) {
ie.printStackTrace();
}
}
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
/**
* @description: 获取银行端商户银联卡对账数据
* @author thuang
* @date 2021/9/22 13:57
* @version 1.0
*/
@PostMapping("/getBankDataBySHYLK")
@ResponseBody
public HashMap<Object, Object> getBankDataBySHYLK(@RequestBody HashMap<Object, Object> map) {
HashMap<Object, Object> responseMap = new HashMap<>();
String errCode = "0";
String errMsg = "";
// 先下载文件
String host = StringDUtil.changeNullToEmpty(map.get("FTP_HOST"));
String portStr = StringDUtil.changeNullToEmpty(map.get("FTP_PORT"));
int port = Integer.parseInt("".equals(portStr) ? "21" : portStr);
String username = StringDUtil.changeNullToEmpty(map.get("FTP_USER"));
String password = StringDUtil.changeNullToEmpty(map.get("FTP_PASSWORD"));
String localPath = StringDUtil.changeNullToEmpty(map.get("LOCAL_PATH"));
String mch_id = StringDUtil.changeNullToEmpty(map.get("MCH_ID"));
String ftp_path = StringDUtil.changeNullToEmpty(map.get("FTP_PATH"));
String ftp_file_name = StringDUtil.changeNullToEmpty(map.get("FTP_FILE_NAME"));
String bill_table_name = StringDUtil.changeNullToEmpty(map.get("BILL_TABLE_NAME"));
String thirdConfigId = StringDUtil.changeNullToEmpty(map.get("ID"));
String trade_date = StringDUtil.changeNullToEmpty(map.get("trade_date"));
HSSFWorkbook sheets = null;
try {
// 下载文件
log.info("开始下载FTP文件: " + ftp_file_name);
boolean b = DownloadFtpUtil.downloadFtpFile(host, username, password, port, ftp_path, localPath, ftp_file_name);
// 判断是否下载到文件
if (!b) {
log.error("FTP文件下载失败: " + ftp_file_name);
errCode = "1";
errMsg = "FTP文件下载失败请检查FTP连接参数和文件是否存在";
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
// 判断本地是否有文件
File file = new File(localPath + "/" + ftp_file_name);
if (file.exists()) {
// 存在 开始解析 存入数据库
FileInputStream fileInputStream = new FileInputStream(localPath + "/" + ftp_file_name);
sheets = new HSSFWorkbook(fileInputStream);
HSSFSheet sheet = sheets.getSheetAt(0);
// 获取sheet中第一行行号
int firstRowNum = sheet.getFirstRowNum();
// 获取sheet中最后一行行号
int lastRowNum = sheet.getLastRowNum();
List<BankbillHistory> list = new ArrayList<>();
for (int i = firstRowNum + 3; i <= lastRowNum - 2; i++) {// 因为表格中第一行为说明,第二行为列标题
HSSFRow row = sheet.getRow(i);
if (row == null) {
continue;
}
BankbillHistory bankbillHistory = new BankbillHistory();
// 清算日期
String qsrqStr = getCellStringValue(row, 0);
// 拿第一个字段判断这条记录是否为空 如果为空直接跳出 一般这字段为空就是数据结束了或根本没有
if ("".equals(qsrqStr) || "合计".equals(qsrqStr)) {
break;
}
bankbillHistory.setCQsrq(qsrqStr);
// 交易日期
String jyrqStr = getCellDateValue(row, 1);
bankbillHistory.setCJyrq(jyrqStr);
if (i == firstRowNum + 3) {
trade_date = jyrqStr;
}
// 交易时间
String jysjStr = getCellStringValue(row, 2);
bankbillHistory.setCJysj(jysjStr);
// 终端号
String zdhStr = getCellStringValue(row, 3);
bankbillHistory.setCZdh(zdhStr);
// 卡号
String khStr = getCellStringValue(row, 4);
bankbillHistory.setCCard(khStr);
// 交易类型
String jylxStr = getCellStringValue(row, 5);
bankbillHistory.setCJylx(jylxStr);
// 交易金额
String jyjeStr = getCellStringValue(row, 6);
bankbillHistory.setCJyje(jyjeStr);
// 清算金额
String qsjeStr = getCellStringValue(row, 7);
bankbillHistory.setCQsje(qsjeStr);
// 手续费
String sxfStr = getCellStringValue(row, 8);
bankbillHistory.setCSxf(sxfStr);
// 流水号
String lshStr = getCellStringValue(row, 9);
bankbillHistory.setCLsh(lshStr);
// 卡类型
String klxStr = getCellStringValue(row, 10);
bankbillHistory.setCKlx(klxStr);
// 发卡行
String fkhStr = getCellStringValue(row, 11);
bankbillHistory.setCFkh(fkhStr);
// 系统参考号 (对应银商订单号)
String xtckhStr = getCellStringValue(row, 12);
// 支付方式
bankbillHistory.setCZffs("银行卡支付");
// 银商订单号
bankbillHistory.setCYsddh(xtckhStr);
// 表名
bankbillHistory.setBillTableName(bill_table_name);
list.add(bankbillHistory);
}
responseMap.put("list", list);
} else {
System.out.println("执行失败,原因:路径" + ftp_path + "下无下载文件" + ftp_file_name);
errCode = "999";
errMsg = "执行失败,原因:路径" + ftp_path + "下无下载文件" + ftp_file_name;
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("执行失败,原因:" + e.getMessage());
errCode = "999";
errMsg = "执行失败,原因:" + e.getMessage();
} finally {
try {
if (sheets != null) {
sheets.close();
}
} catch (Exception ie) {
ie.printStackTrace();
}
}
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
/**
* @description: 获取银行端商户银联外卡对账数据
* @author yuan
* @date 2025/7/18 13:57
* @version 1.0
*/
@PostMapping("/getBankDataBySHYLWK")
@ResponseBody
public HashMap<Object, Object> getBankDataBySHYLWK(@RequestBody HashMap<Object, Object> map) {
HashMap<Object, Object> responseMap = new HashMap<>();
String errCode = "0";
String errMsg = "";
// 先下载文件
String host = StringDUtil.changeNullToEmpty(map.get("FTP_HOST"));
String portStr = StringDUtil.changeNullToEmpty(map.get("FTP_PORT"));
int port = Integer.parseInt("".equals(portStr) ? "21" : portStr);
String username = StringDUtil.changeNullToEmpty(map.get("FTP_USER"));
String password = StringDUtil.changeNullToEmpty(map.get("FTP_PASSWORD"));
String localPath = StringDUtil.changeNullToEmpty(map.get("LOCAL_PATH"));
String mch_id = StringDUtil.changeNullToEmpty(map.get("MCH_ID"));
String ftp_path = StringDUtil.changeNullToEmpty(map.get("FTP_PATH"));
String ftp_file_name = StringDUtil.changeNullToEmpty(map.get("FTP_FILE_NAME"));
String bill_table_name = StringDUtil.changeNullToEmpty(map.get("BILL_TABLE_NAME"));
String thirdConfigId = StringDUtil.changeNullToEmpty(map.get("ID"));
String trade_date = StringDUtil.changeNullToEmpty(map.get("trade_date"));
HSSFWorkbook sheets = null;
try {
// 下载文件
log.info("开始下载FTP文件: " + ftp_file_name);
boolean b = DownloadFtpUtil.downloadFtpFile(host, username, password, port, ftp_path, localPath, ftp_file_name);
// 判断是否下载到文件
if (!b) {
log.error("FTP文件下载失败: " + ftp_file_name);
errCode = "1";
errMsg = "FTP文件下载失败请检查FTP连接参数和文件是否存在";
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
// 判断本地是否有文件
File file = new File(localPath + "/" + ftp_file_name);
if (file.exists()) {
// 存在 开始解析 存入数据库
FileInputStream fileInputStream = new FileInputStream(localPath + "/" + ftp_file_name);
sheets = new HSSFWorkbook(fileInputStream);
HSSFSheet sheet = sheets.getSheetAt(0);
// 获取sheet中第一行行号
int firstRowNum = sheet.getFirstRowNum();
// 获取sheet中最后一行行号
int lastRowNum = sheet.getLastRowNum();
List<BankbillHistory> list = new ArrayList<>();
// 银联外卡对账单从第4行开始解析数据前3行是标题和表头
for (int i = firstRowNum + 3; i <= lastRowNum - 2; i++) {
HSSFRow row = sheet.getRow(i);
if (row == null) {
continue;
}
BankbillHistory bankbillHistory = new BankbillHistory();
// 清算日期
String qsrqStr = getCellStringValue(row, 0);
// 拿第一个字段判断这条记录是否为空 如果为空直接跳出
if ("".equals(qsrqStr) || "合计".equals(qsrqStr)) {
break;
}
bankbillHistory.setCQsrq(qsrqStr);
// 交易日期
String jyrqStr = getCellDateValue(row, 1);
bankbillHistory.setCJyrq(jyrqStr);
// 交易时间
String jysjStr = getCellStringValue(row, 2);
bankbillHistory.setCJysj(jysjStr);
// 终端号
String zdhStr = getCellStringValue(row, 3);
bankbillHistory.setCZdh(zdhStr);
// 卡号
String khStr = getCellStringValue(row, 4);
bankbillHistory.setCCard(khStr);
// 交易类型
String jylxStr = getCellStringValue(row, 5);
bankbillHistory.setCJylx(jylxStr);
// 交易金额
String jyjeStr = getCellStringValue(row, 6);
bankbillHistory.setCJyje(jyjeStr);
// 清算金额
String qsjeStr = getCellStringValue(row, 7);
bankbillHistory.setCQsje(qsjeStr);
// 手续费
String sxfStr = getCellStringValue(row, 8);
bankbillHistory.setCSxf(sxfStr);
// 参考号
String ckhStr = getCellStringValue(row, 9);
bankbillHistory.setCCkh(ckhStr);
// 流水号
String lshStr = getCellStringValue(row, 10);
bankbillHistory.setCLsh(lshStr);
// 卡类型
String klxStr = getCellStringValue(row, 11);
bankbillHistory.setCKlx(klxStr);
// 授权码
String sqmStr = getCellStringValue(row, 12);
bankbillHistory.setCBzzd(sqmStr); // 使用备注字段存储授权码
// 分店名称
String fdmcStr = getCellStringValue(row, 13);
bankbillHistory.setCFdjc(fdmcStr);
// 设置支付方式
bankbillHistory.setCZffs("银联外卡支付");
// 设置表名
bankbillHistory.setBillTableName(bill_table_name);
list.add(bankbillHistory);
}
responseMap.put("list", list);
} else {
System.out.println("执行失败,原因:路径" + ftp_path + "下无下载文件" + ftp_file_name);
errCode = "999";
errMsg = "执行失败,原因:路径" + ftp_path + "下无下载文件" + ftp_file_name;
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("执行失败,原因:" + e.getMessage());
errCode = "999";
errMsg = "执行失败,原因:" + e.getMessage();
} finally {
try {
if (sheets != null) {
sheets.close();
}
} catch (Exception ie) {
ie.printStackTrace();
}
}
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
/**
* @description: 获取微信支付对账数据
* @author thuang
* @date 2021/9/22 13:57
* @version 1.0
*/
@PostMapping("/getBankDataByWXAPI")
@ResponseBody
public HashMap<Object, Object> getBankDataByWXAPI(@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"));
2025-09-25 16:08:34 +08:00
log.info("开始获取微信账单,参数: mch_id={}, trade_date={}", mch_id, trade_date);
2025-09-15 18:52:59 +08:00
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);
2025-09-25 16:08:34 +08:00
log.info("微信账单接口返回数据: {}", body1);
2025-09-15 18:52:59 +08:00
// 检查微信接口返回状态
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;
}
2025-12-23 09:29:57 +08:00
// 将原始账单内容落地,便于后续人工核对或重复导入
try {
File csvFile = FileUtil.file(localPath, trade_date + ".csv");
File txtFile = FileUtil.file(localPath, trade_date + ".txt");
FileUtil.mkParentDirs(csvFile);
FileUtil.writeUtf8String(body1, csvFile);
FileUtil.writeUtf8String(body1, txtFile);
log.info("微信账单已保存到本地: {}, {}", csvFile.getAbsolutePath(), txtFile.getAbsolutePath());
} catch (IORuntimeException e) {
log.error("微信账单保存本地失败,路径: {}, 错误: {}", localPath, e.getMessage(), e);
errCode = "999";
errMsg = "微信账单保存本地失败:" + e.getMessage();
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
2025-09-15 18:52:59 +08:00
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: // 订单金额
2025-09-25 16:08:34 +08:00
// 只有在非退款状态时才设置订单金额
if (flag >= 0) {
2025-09-15 18:52:59 +08:00
bankbillHistory.setCJyje(value);
}
break;
case 20: // 商品名称
bankbillHistory.setCBzzd(value);
break;
case 22: // 手续费
bankbillHistory.setCSxf(value);
break;
2025-09-25 16:08:34 +08:00
case 14: // 微信退款单号
2025-09-15 18:52:59 +08:00
bankbillHistory.setCThddh(value);
break;
2025-09-25 16:08:34 +08:00
case 15: // 商户退款单号
2025-09-15 18:52:59 +08:00
bankbillHistory.setCYjylsh(value);
break;
2025-09-25 16:08:34 +08:00
case 25: // 申请退款金额
if (!"0.00".equals(value) && !value.isEmpty()) {
2025-09-15 18:52:59 +08:00
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;
// log.info("微信账单签名:" + signYBString);
// String signYB = SecureUtil.md5(signYBString).toUpperCase();
// 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>";
// 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("`", ""));
// if (row.get(46).replaceAll("`", "").equals("0.00")) {
// continue;
// }
// if (row.get(45).replaceAll("`", "").equals("REFUND")) {
// bankbillHistory.setCJyje("-" + row.get(46).replaceAll("`", ""));
// } else {
// bankbillHistory.setCJyje(row.get(46).replaceAll("`", ""));
// }
// bankbillHistory.setBillTableName("微信支付账单");
// list.add(bankbillHistory);
// }
// }
// 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) {
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;
}
}
// public static void main(String[] args) {
//
// String a = "?交易时间,公众账号ID,商户号,特约商户号,设备号,微信订单号,商户订单号,用户标识,交易类型,交易状态,付款银行,货币种类,应结订单金额,代金券金额,微信退款单号,商户退款单号,退款金额,充值券退款金额,退款类型,退款状态,商品名称,商户数据包,手续费,费率,订单金额,申请退款金额,费率备注\n" +
// "`2024-08-09 17:55:10,`wx83bc9715be856b14,`1648728329,`0,`,`4200002314202408091169938410,`JJ20240809175501,`o-ZxO47Otvo5Rsq7kN-4PHvZIOt8,`JSAPI,`SUCCESS,`ICBC_DEBIT,`CNY,`61.00,`0.00,`0,`0,`0.00,`0.00,`,`,`库尔勒市妇幼保健院-门诊付款,`{\\\"patid\\\":\\\"385606\\\"\\ \\\"sjh\\\":\\\"20240809yypt120016\\\"\\ \\\"ysje\\\":\\\"61.0000\\\"\\ \\\"zfje\\\":\\\"61.0000\\\"\\ \\\"zje\\\":\\\"61.0000\\\"},`0.00000,`0.00%,`61.00,`0.00,`\n" +
// "`2024-08-09 19:09:18,`wx83bc9715be856b14,`1648728329,`0,`,`4200002314202408091169938410,`JJ20240809175501,`o-ZxO47Otvo5Rsq7kN-4PHvZIOt8,`JSAPI,`REFUND,`ICBC_DEBIT,`CNY,`0.00,`0.00,`50303000492024080988526514493,`C0_20240809yypt120016,`61.00,`0.00,`ORIGINAL,`SUCCESS,`库尔勒市妇幼保健院-门诊付款,`{\\\"patid\\\":\\\"385606\\\"\\ \\\"sjh\\\":\\\"20240809yypt120016\\\"\\ \\\"ysje\\\":\\\"61.0000\\\"\\ \\\"zfje\\\":\\\"61.0000\\\"\\ \\\"zje\\\":\\\"61.0000\\\"},`0.00000,`0.00%,`0.00,`61.00,`\n" +
// "`2024-08-09 18:07:51,`wx83bc9715be856b14,`1648728329,`0,`,`4200002320202408095363202348,`JJ20240809180744,`o-ZxO47Otvo5Rsq7kN-4PHvZIOt8,`JSAPI,`SUCCESS,`ICBC_DEBIT,`CNY,`104.00,`0.00,`0,`0,`0.00,`0.00,`,`,`库尔勒市妇幼保健院-门诊付款,`{\\\"patid\\\":\\\"447719\\\"\\ \\\"sjh\\\":\\\"20240809yypt120017\\\"\\ \\\"ysje\\\":\\\"104.0000\\\"\\ \\\"zfje\\\":\\\"104.0000\\\"\\ \\\"zje\\\":\\\"104.0000\\\"},`0.00000,`0.00%,`104.00,`0.00,`\n" +
// "`2024-08-09 19:07:39,`wx83bc9715be856b14,`1648728329,`0,`,`4200002320202408095363202348,`JJ20240809180744,`o-ZxO47Otvo5Rsq7kN-4PHvZIOt8,`JSAPI,`REFUND,`ICBC_DEBIT,`CNY,`0.00,`0.00,`50303500422024080937274513002,`C0_20240809yypt120017,`104.00,`0.00,`ORIGINAL,`SUCCESS,`库尔勒市妇幼保健院-门诊付款,`{\\\"patid\\\":\\\"447719\\\"\\ \\\"sjh\\\":\\\"20240809yypt120017\\\"\\ \\\"ysje\\\":\\\"104.0000\\\"\\ \\\"zfje\\\":\\\"104.0000\\\"\\ \\\"zje\\\":\\\"104.0000\\\"},`0.00000,`0.00%,`0.00,`104.00,`\n" +
// "`2024-08-09 17:54:18,`wx83bc9715be856b14,`1648728329,`0,`,`4200002326202408099114331548,`JJ20240809175411,`o-ZxO47Otvo5Rsq7kN-4PHvZIOt8,`JSAPI,`SUCCESS,`ICBC_DEBIT,`CNY,`298.38,`0.00,`0,`0,`0.00,`0.00,`,`,`库尔勒市妇幼保健院-门诊付款,`{\\\"patid\\\":\\\"447719\\\"\\ \\\"sjh\\\":\\\"20240809yypt120015\\\"\\ \\\"ysje\\\":\\\"298.3800\\\"\\ \\\"zfje\\\":\\\"298.3800\\\"\\ \\\"zje\\\":\\\"298.3800\\\"},`0.00000,`0.00%,`298.38,`0.00,`\n" +
// "`2024-08-09 19:47:02,`wx83bc9715be856b14,`1648728329,`0,`,`4200002326202408099114331548,`JJ20240809175411,`o-ZxO47Otvo5Rsq7kN-4PHvZIOt8,`JSAPI,`REFUND,`ICBC_DEBIT,`CNY,`0.00,`0.00,`50303500342024080940745293001,`C0_20240809yypt120015,`298.38,`0.00,`ORIGINAL,`SUCCESS,`库尔勒市妇幼保健院-门诊付款,`{\\\"patid\\\":\\\"447719\\\"\\ \\\"sjh\\\":\\\"20240809yypt120015\\\"\\ \\\"ysje\\\":\\\"298.3800\\\"\\ \\\"zfje\\\":\\\"298.3800\\\"\\ \\\"zje\\\":\\\"298.3800\\\"},`0.00000,`0.00%,`0.00,`298.38,`\n" +
// "总交易单数,应结订单总金额,退款总金额,充值券退款总金额,手续费总金额,订单总金额,申请退款总金额\n" +
// "`6,`463.38,`463.38,`0.00,`0.00000,`463.38,`463.38";
// String[] split = a.split("\n");
// for (int i = 1; i < split.length - 2; i++) {
// String[] split1 = split[i].split(",");
// for (int j = 0; j < split1.length; j++) {
//
// System.out.println("==============");
// System.out.println("第" + j + "个:");
// System.out.println(split1[j]);
// System.out.println("==============");
// if (j == 21) {
// String s = split1[j].replaceAll("`", "");
// String s1 = s.replaceAll(" ", ",").replaceAll("\\\\", "");
// JSONObject entries = JSONUtil.parseObj(s1);
// Object zfje = entries.get("zfje");
//
// System.out.println(zfje.toString().substring(0, 5));
//
// }
// }
// }
// System.out.println();
// }
2025-10-31 09:08:46 +08:00
/**
* 发送对账结果微信消息推送
* @param tradeDate 对账时间
* @param operationResult 操作结果
* @param reconcileResult 对账结果
* @param operatorName 操作人
* @param openid 用户openid
* @return 推送结果
*/
public int SendNotifyYJJ(String tradeDate, String operationResult, String reconcileResult, String operatorName, String openid) {
try {
//第一步 获取token
String accessUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&" +
"&appid=" + WX_APP_ID + "&secret=" + WX_SECRET;
String accessTokenStr = HttpClientUtil.doGet(accessUrl, null);
log.info("step 1 get accesstoken:" + accessTokenStr);
if (accessTokenStr == null || accessTokenStr.isEmpty()) {
log.error("获取微信access_token失败响应为空");
return -1;
}
JSONObject jsonObject = JSON.parseObject(accessTokenStr);
if (jsonObject == null) {
log.error("解析微信access_token响应失败无法解析JSON");
return -1;
}
Object accessTokenObj = jsonObject.get("access_token");
if (accessTokenObj == null) {
log.error("微信access_token响应中没有access_token字段响应内容: {}", accessTokenStr);
return -1;
}
String accessToken = accessTokenObj.toString();
String sendUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
JSONObject sendPara = new JSONObject();
JSONObject dataPara = new JSONObject();
// 对账时间
JSONObject time2 = new JSONObject();
time2.put("value", tradeDate);
time2.put("color", "#173177");
// 操作结果
JSONObject const3 = new JSONObject();
const3.put("value", operationResult);
const3.put("color", "#173177");
// 对账结果
JSONObject const4 = new JSONObject();
const4.put("value", reconcileResult);
const4.put("color", "#173177");
// 操作人和时间
JSONObject character_string5 = new JSONObject();
character_string5.put("value", operatorName + " " + DateDUtil.DateToStr(DateDUtil.yyyy_MM_dd_HH_mm_ss, new Date()));
character_string5.put("color", "#173177");
dataPara.put("time2", time2);
dataPara.put("const3", const3);
dataPara.put("const4", const4);
dataPara.put("character_string5", character_string5);
sendPara.put("touser", openid);
sendPara.put("template_id", "sbzMHunU1zmB_Hg4LRAs7BSmYPw6CtxFuBHMXllxZB0");
sendPara.put("url", "https://nxwj.btlsoln.com/nxwj-gzh/#/reconciliation");
sendPara.put("data", dataPara);
String sendRes = HttpClientUtil.doPost(sendUrl, sendPara);
log.info("step 2 send notify:" + sendRes);
if (sendRes == null || sendRes.isEmpty()) {
log.error("发送微信消息失败,响应为空");
return -1;
}
JSONObject jsonSend = JSON.parseObject(sendRes);
if (jsonSend != null && jsonSend.containsKey("errcode")) {
Integer errcode = jsonSend.getInteger("errcode");
String errmsg = jsonSend.getString("errmsg");
if (errcode != null && errcode == 0) {
log.info("微信消息发送成功");
return 0;
} else {
// 根据不同错误码提供具体的错误信息
switch (errcode) {
case 43004:
log.error("微信消息发送失败用户未关注公众号无法接收模板消息。errcode: {}, errmsg: {}", errcode, errmsg);
return -2; // 特殊返回码表示用户未关注
case 40001:
log.error("微信消息发送失败access_token无效。errcode: {}, errmsg: {}", errcode, errmsg);
return -3;
case 40003:
log.error("微信消息发送失败openid无效。errcode: {}, errmsg: {}", errcode, errmsg);
return -4;
case 41030:
log.error("微信消息发送失败页面不存在或者小程序没有关联公众号。errcode: {}, errmsg: {}", errcode, errmsg);
return -5;
default:
log.error("微信消息发送失败errcode: {}, errmsg: {}", errcode, errmsg);
return -1;
}
}
}
return 0;
} catch (Exception e) {
log.error("发送微信消息异常", e);
return -1;
}
}
/**
* 测试对账结果微信消息推送接口
* @param map 包含对账信息和openid的参数
* @return 推送结果
*/
@PostMapping("/sendNotifyYJJ")
@ResponseBody
public HashMap<Object, Object> sendNotifyYJJ(@RequestBody HashMap<Object, Object> map) {
HashMap<Object, Object> responseMap = new HashMap<>();
String errCode = "0";
String errMsg = "";
try {
// 从请求参数中获取数据
String tradeDate = StringDUtil.changeNullToEmpty(map.get("tradeDate"));
String operationResult = StringDUtil.changeNullToEmpty(map.get("operationResult"));
String reconcileResult = StringDUtil.changeNullToEmpty(map.get("reconcileResult"));
String operatorName = StringDUtil.changeNullToEmpty(map.get("operatorName"));
String openid = StringDUtil.changeNullToEmpty(map.get("openid"));
// 参数校验
if (tradeDate.isEmpty()) {
errCode = "1";
errMsg = "对账时间不能为空";
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
if (openid.isEmpty()) {
errCode = "1";
errMsg = "openid不能为空";
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
// 设置默认值
if (operationResult.isEmpty()) {
operationResult = "操作完成!";
}
if (reconcileResult.isEmpty()) {
reconcileResult = "对账完成!";
}
if (operatorName.isEmpty()) {
operatorName = "系统";
}
// 调用推送方法
int result = SendNotifyYJJ(tradeDate, operationResult, reconcileResult, operatorName, openid);
if (result == 0) {
errMsg = "对账结果消息推送成功";
} else {
errCode = "1";
// 根据返回码提供具体的错误信息
switch (result) {
case -2:
errMsg = "消息推送失败:用户未关注公众号,无法接收模板消息";
break;
case -3:
errMsg = "消息推送失败微信access_token无效";
break;
case -4:
errMsg = "消息推送失败用户openid无效";
break;
case -5:
errMsg = "消息推送失败:页面不存在或小程序未关联公众号";
break;
default:
errMsg = "对账结果消息推送失败";
break;
}
}
} catch (Exception e) {
log.error("微信消息推送异常", e);
errCode = "999";
errMsg = "微信消息推送异常: " + e.getMessage();
}
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
/**
* 检查用户是否关注公众号
* @param openid 用户openid
* @return true-已关注false-未关注
*/
public boolean checkUserSubscribe(String openid) {
try {
// 获取access_token
String accessUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&" +
"&appid=" + WX_APP_ID + "&secret=" + WX_SECRET;
String accessTokenStr = HttpClientUtil.doGet(accessUrl, null);
if (accessTokenStr == null || accessTokenStr.isEmpty()) {
log.error("获取access_token失败");
return false;
}
JSONObject tokenJson = JSON.parseObject(accessTokenStr);
Object accessTokenObj = tokenJson.get("access_token");
if (accessTokenObj == null) {
log.error("access_token响应中没有access_token字段");
return false;
}
String accessToken = accessTokenObj.toString();
// 获取用户信息
String userInfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openid;
String userInfoResponse = HttpClientUtil.doGet(userInfoUrl, null);
log.info("用户信息响应: {}", userInfoResponse);
if (userInfoResponse != null && !userInfoResponse.isEmpty()) {
JSONObject userInfo = JSON.parseObject(userInfoResponse);
if (userInfo.containsKey("subscribe")) {
Integer subscribe = userInfo.getInteger("subscribe");
return subscribe != null && subscribe == 1;
}
}
} catch (Exception e) {
log.error("检查用户关注状态异常", e);
}
return false;
}
/**
* 根据验证码和手机号获取openid
* @param yz 验证码
* @param phone 手机号
* @return openid如果获取失败返回null
*/
public String getUserOpenIdByPhone(String yz, String phone) {
try {
String url = "http://172.16.21.21:8443/nxgzh/userInfo/getUserOpenIdByPhone?yz=" + yz + "&phone=" + phone;
String response = HttpClientUtil.doPost(url, null);
log.info("获取openid请求URL: {}", url);
log.info("获取openid响应: {}", response);
if (response != null && !response.isEmpty()) {
JSONObject jsonResponse = JSON.parseObject(response);
log.info("解析后的JSON对象: {}", jsonResponse);
// 返回格式为 {"code": 200, "message": "执行成功", "refreshToken": null, "data": "o4MF86KDH-v1Rh5ryVj4TAeLs2JY"}
// 检查code是否为200
Integer code = jsonResponse.getInteger("code");
log.info("响应code: {}", code);
if (code != null && code == 200) {
// data字段直接是openid字符串
if (jsonResponse.containsKey("data")) {
String openid = jsonResponse.getString("data");
log.info("获取到的openid: {}", openid);
if (openid != null && !openid.isEmpty() && !"null".equals(openid)) {
log.info("成功获取openid手机号: {}, openid: {}", phone, openid);
return openid;
} else {
log.warn("openid为空或null手机号: {}, data值: {}", phone, openid);
}
} else {
log.warn("响应中不包含data字段手机号: {}", phone);
}
} else {
String message = jsonResponse.getString("message");
log.warn("获取openid失败手机号: {}, code: {}, 返回信息: {}", phone, code, message);
}
} else {
log.warn("响应为空,手机号: {}", phone);
}
} catch (Exception e) {
log.error("获取openid失败验证码: {}, 手机号: {}, 错误: {}", yz, phone, e.getMessage(), e);
}
return null;
}
/**
* 获取用户openid的REST接口
* @param map 包含yz和phone参数的请求体
* @return 包含openid的响应结果
*/
@PostMapping("/getUserOpenId")
@ResponseBody
public HashMap<Object, Object> getUserOpenId(@RequestBody HashMap<Object, Object> map) {
HashMap<Object, Object> responseMap = new HashMap<>();
String errCode = "0";
String errMsg = "";
try {
// 从请求参数中获取验证码和手机号
String yz = StringDUtil.changeNullToEmpty(map.get("yz"));
String phone = StringDUtil.changeNullToEmpty(map.get("phone"));
log.info("请求获取openidyz: {}, phone: {}", yz, phone);
if (yz.isEmpty()) {
errCode = "1";
errMsg = "验证码不能为空";
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
if (phone.isEmpty()) {
errCode = "1";
errMsg = "手机号不能为空";
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
// 调用获取openid的方法
String openid = getUserOpenIdByPhone(yz, phone);
if (openid != null && !openid.isEmpty()) {
responseMap.put("openid", openid);
errMsg = "获取openid成功";
} else {
errCode = "1";
errMsg = "获取openid失败验证码或手机号错误或网络异常";
}
} catch (Exception e) {
log.error("获取openid异常", e);
errCode = "999";
errMsg = "获取openid异常: " + e.getMessage();
}
responseMap.put("errCode", errCode);
responseMap.put("errMsg", errMsg);
return responseMap;
}
/**
* 下载ZIP文件接口
* 调用远程服务下载文件并将字节流返回给客户端
* @param fileName 文件名通过路径参数传递
* @return 文件字节流
*/
@GetMapping("/download/{fileName}")
public ResponseEntity<InputStreamResource> downloadFile(@PathVariable String fileName) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
try {
log.info("开始调用远程下载接口,文件名: {}", fileName);
// 构建远程下载URL
String remoteUrl = "http://172.16.21.21:8443/nxgzh/find/download/" + fileName;
log.info("远程下载URL: {}", remoteUrl);
// 创建HTTP客户端
httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(remoteUrl);
// 执行请求
response = httpClient.execute(httpGet);
int statusCode = response.getStatusLine().getStatusCode();
log.info("远程接口响应状态码: {}", statusCode);
if (statusCode == 200) {
// 获取响应的输入流
InputStream inputStream = response.getEntity().getContent();
InputStreamResource resource = new InputStreamResource(inputStream);
// 获取文件大小
long contentLength = response.getEntity().getContentLength();
// 构造响应头
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
if (contentLength > 0) {
headers.setContentLength(contentLength);
}
log.info("文件下载成功,文件名: {}, 大小: {} bytes", fileName, contentLength);
return ResponseEntity.ok()
.headers(headers)
.body(resource);
} else if (statusCode == 404) {
log.error("远程文件不存在: {}", fileName);
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.header("X-Error", "File not found: " + fileName)
.body(null);
} else {
log.error("远程接口返回错误状态码: {}", statusCode);
return ResponseEntity.status(statusCode)
.header("X-Error", "Remote server error: " + statusCode)
.body(null);
}
} catch (Exception e) {
log.error("下载文件异常,文件名: {}, 错误: {}", fileName, e.getMessage(), e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.header("X-Error", "Download failed: " + e.getMessage())
.body(null);
} finally {
// 注意不要关闭response和httpClient因为流还在被读取
// Spring会在响应完成后自动处理资源清理
}
}
2025-11-17 17:27:12 +08:00
@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("`", ""));
2025-12-10 18:31:38 +08:00
bankbillHistory.setCShddh(row.get(25).replaceAll("`", ""));
2025-11-17 17:27:12 +08:00
bankbillHistory.setCCard(row.get(7).replaceAll("`", ""));
2025-12-10 18:31:38 +08:00
bankbillHistory.setCYsddh(row.get(6).replaceAll("`", ""));
2025-11-17 17:27:12 +08:00
// 处理交易金额不跳过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;
}
}
2025-09-15 18:52:59 +08:00
}
2025-11-17 17:27:12 +08:00