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

1899 lines
85 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.saye.hgddmz.commons.date.DateDUtil;
import com.saye.hgddmz.commons.string.StringDUtil;
import com.saye.hgddmz.entity.BankbillHistory;
import com.saye.hgddmz.util.DownloadFtpUtil;
import com.saye.hgddmz.util.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
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.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
/**
* @author thuang
* @version 1.0
* @description: TODO
* @date 2021/9/22 13:55
*/
@Controller
@Slf4j
public class GetDateController {
// Yuan
private static String grant_type = "client_credential";
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";
private static String WX_SECRET = "895b90585c4698485c07e113711eac85";
/**
* 安全获取单元格字符串值
* @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"));
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;
}
// 将原始账单内容落地,便于后续人工核对或重复导入
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;
}
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);
if (value != null && value.startsWith("YC")) {
bankbillHistory.setIsInpatient("1");
} else {
bankbillHistory.setIsInpatient("0");
}
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;
// 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();
// }
/**
* 发送对账结果微信消息推送
* @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会在响应完成后自动处理资源清理
}
}
@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(25).replaceAll("`", ""));
bankbillHistory.setCCard(row.get(7).replaceAll("`", ""));
bankbillHistory.setCYsddh(row.get(6).replaceAll("`", ""));
String shddh = row.get(25).replaceAll("`", "");
if (shddh != null && shddh.startsWith("YC")) {
bankbillHistory.setIsInpatient("1");
} else {
bankbillHistory.setIsInpatient("0");
}
// 处理交易金额不跳过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;
}
}
}