1899 lines
85 KiB
Java
1899 lines
85 KiB
Java
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("请求获取openid,yz: {}, 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;
|
||
}
|
||
}
|
||
}
|
||
|
||
|