init:宁夏武警获取建行账单

This commit is contained in:
Yuan
2025-10-31 09:08:46 +08:00
parent c7aa65a373
commit 62676cf59b
4 changed files with 568 additions and 3 deletions

View File

@@ -77,6 +77,10 @@
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- excel -->
<dependency>
<groupId>org.apache.poi</groupId>

View File

@@ -6,18 +6,28 @@ import cn.hutool.http.HttpUtil;
import com.saye.hgddmz.commons.date.DateDUtil;
import com.saye.hgddmz.commons.string.StringDUtil;
import com.saye.hgddmz.entity.BankbillHistory;
import com.saye.hgddmz.entity.UserOrder;
import com.saye.hgddmz.util.DownloadFtpUtil;
import com.saye.hgddmz.util.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
/**
@@ -36,6 +46,10 @@ public class GetDateController {
private static String appid = "wx45acd2b4907cb8f4";
private static String secret = "895b90585c4698485c07e113711eac85";
private static String key = "Nxwj20250903Jojubanking12091209x";
// 微信消息推送相关常量
private static String WX_APP_ID = "wx45acd2b4907cb8f4";
private static String WX_SECRET = "895b90585c4698485c07e113711eac85";
/**
* 安全获取单元格字符串值
@@ -1111,4 +1125,429 @@ public class GetDateController {
// }
// 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会在响应完成后自动处理资源清理
}
}
}

View File

@@ -0,0 +1,39 @@
package com.saye.hgddmz.entity;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* 用户订单实体类
* @author thuang
* @version 1.0
* @date 2025/01/15
*/
@Getter
@Setter
public class UserOrder implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 医院编号
*/
private String hosnum;
/**
* 订单金额
*/
private Double money;
/**
* 成功时间
*/
private String successtime;
/**
* 订单编号
*/
private String code;
}

View File

@@ -0,0 +1,83 @@
package com.saye.hgddmz.util;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* HTTP客户端工具类
* @author thuang
* @version 1.0
* @date 2025/01/15
*/
@Slf4j
public class HttpClientUtil {
/**
* 发送GET请求
* @param url 请求URL
* @param headers 请求头
* @return 响应结果
*/
public static String doGet(String url, java.util.Map<String, String> headers) {
HttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
// 设置请求头
if (headers != null) {
headers.forEach(httpGet::setHeader);
}
try {
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
log.debug("GET请求响应: {}", result);
return result;
} catch (IOException e) {
log.error("GET请求失败: {}", e.getMessage(), e);
return null;
}
}
/**
* 发送POST请求
* @param url 请求URL
* @param params 请求参数JSON格式
* @return 响应结果
*/
public static String doPost(String url, Object params) {
HttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
try {
// 设置请求头
httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
// 设置请求体
String jsonParams = JSON.toJSONString(params);
StringEntity entity = new StringEntity(jsonParams, StandardCharsets.UTF_8);
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
String result = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
log.debug("POST请求响应: {}", result);
return result;
} catch (IOException e) {
log.error("POST请求失败: {}", e.getMessage(), e);
return null;
}
}
}