|
|
@ -0,0 +1,270 @@ |
|
|
|
package org.dromara.platform.controller; |
|
|
|
|
|
|
|
import com.alibaba.excel.EasyExcel; |
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException; |
|
|
|
import com.fasterxml.jackson.core.type.TypeReference; |
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper; |
|
|
|
import jakarta.annotation.Resource; |
|
|
|
import jakarta.servlet.http.HttpServletResponse; |
|
|
|
import jakarta.validation.constraints.NotNull; |
|
|
|
import lombok.RequiredArgsConstructor; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.dromara.common.core.domain.R; |
|
|
|
import org.dromara.common.core.validate.AddGroup; |
|
|
|
import org.dromara.common.idempotent.annotation.RepeatSubmit; |
|
|
|
import org.dromara.common.log.annotation.Log; |
|
|
|
import org.dromara.common.log.enums.BusinessType; |
|
|
|
import org.dromara.platform.domain.PerformanceManagement; |
|
|
|
import org.dromara.platform.domain.ProjectManager; |
|
|
|
import org.dromara.platform.domain.app.WeComSubscribeDataItem; |
|
|
|
import org.dromara.platform.domain.app.WeComSubscribeMessageRequest; |
|
|
|
import org.dromara.platform.domain.bo.PartyInfoBo; |
|
|
|
import org.dromara.platform.domain.vo.PartyInfoVo; |
|
|
|
import org.dromara.platform.domain.vo.WorkOrderInfoVo; |
|
|
|
import org.dromara.platform.listener.PerformanceManagementListener; |
|
|
|
import org.dromara.platform.listener.ProjectManagerListener; |
|
|
|
import org.dromara.platform.service.IPerformanceManagementService; |
|
|
|
import org.dromara.platform.service.IWorkOrderInfoService; |
|
|
|
import org.dromara.platform.service.ProjectManagerService; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.http.HttpEntity; |
|
|
|
import org.springframework.http.HttpHeaders; |
|
|
|
import org.springframework.http.MediaType; |
|
|
|
import org.springframework.http.ResponseEntity; |
|
|
|
import org.springframework.validation.annotation.Validated; |
|
|
|
import org.springframework.web.bind.annotation.*; |
|
|
|
import org.springframework.web.client.HttpClientErrorException; |
|
|
|
import org.springframework.web.client.RestTemplate; |
|
|
|
import org.springframework.web.multipart.MultipartFile; |
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
import java.net.URI; |
|
|
|
import java.net.URLEncoder; |
|
|
|
import java.net.http.HttpClient; |
|
|
|
import java.net.http.HttpRequest; |
|
|
|
import java.net.http.HttpResponse; |
|
|
|
import java.time.LocalDate; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
/** |
|
|
|
* @Author gejunhao |
|
|
|
* @Date 2025/1/10 14:11 |
|
|
|
* @Description: 测试接口 |
|
|
|
*/ |
|
|
|
@RequiredArgsConstructor |
|
|
|
@RestController |
|
|
|
@Slf4j |
|
|
|
@RequestMapping("/wechat") |
|
|
|
public class WeChatController { |
|
|
|
// 替换为你的 AppID 和 AppSecret
|
|
|
|
private static final String APP_ID = "wxe2eba8943d47678e"; |
|
|
|
private static final String APP_SECRET = "7af0a56aaa7780ad041ee4cda2359353"; |
|
|
|
private static final String APP_OPENID = "ohCQF7nRbdBVnk4GUD_TgTRv_IYs"; |
|
|
|
private static final String ACCESS_TOKEN = "93_Rdp-c-VBBN-2qNAxBQ1pmx3gvuxjoMk2A_BmczJinRcJ9G3IwJ-okucNWz30OY7bb_8tk44XjQ5pdaRf8-lvrb8blIUjuFDklcyLtjX-1g4Ik9Q1cUuzhP-O9DwLYPhAEASFW"; |
|
|
|
private static final String TEMPLATE_ID = "z9G-4dk8JHget0Ftm8ysEa6pT2mztklfDTYF9sYBDzM"; |
|
|
|
private static final String SUBSCRIBE_SEND_PREFIX = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="; |
|
|
|
|
|
|
|
|
|
|
|
@GetMapping("/hello") |
|
|
|
public void test(HttpServletResponse response) throws IOException { |
|
|
|
log.warn("hello word!"); |
|
|
|
response.setContentType("text/html;charset=utf8"); |
|
|
|
response.getWriter().println("调用接口成功!"); |
|
|
|
} |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private ObjectMapper objectMapper; |
|
|
|
@Resource |
|
|
|
private RestTemplate restTemplate; |
|
|
|
|
|
|
|
@GetMapping("/getOpenId") |
|
|
|
public R< Map<String, String>> getOpenId(String jsCode) throws JsonProcessingException { |
|
|
|
Map<String, String> result = getOpenIdForApp(jsCode); |
|
|
|
return R.ok("根据jsCode获取对应的openId", result); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@GetMapping("/getAccessToken") |
|
|
|
public R<Map<String, String>> getAccessToken() throws JsonProcessingException { |
|
|
|
Map<String, String> result = getAccessTokenForApp(); |
|
|
|
// 5. 返回给前端
|
|
|
|
return R.ok("获取对应的access_token",result); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@GetMapping("/sendSubscribeMsg") |
|
|
|
public ResponseEntity<String> sendSubscribeMessage(String openid, String accessToken) { |
|
|
|
// 使用默认值或传入参数
|
|
|
|
openid = openid == null ? APP_OPENID : openid; |
|
|
|
accessToken = accessToken == null ? ACCESS_TOKEN : accessToken; |
|
|
|
|
|
|
|
String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken; |
|
|
|
|
|
|
|
// 构建请求体
|
|
|
|
WeComSubscribeMessageRequest request = new WeComSubscribeMessageRequest(); |
|
|
|
request.setTouser(openid); |
|
|
|
request.setTemplate_id(TEMPLATE_ID); |
|
|
|
request.setPage("pages/index/index"); |
|
|
|
|
|
|
|
Map<String, WeComSubscribeDataItem> dataMap = new HashMap<>(); |
|
|
|
dataMap.put("character_string5", new WeComSubscribeDataItem("工单编号:123456")); |
|
|
|
dataMap.put("thing2", new WeComSubscribeDataItem("空调内部故障")); |
|
|
|
dataMap.put("time13", new WeComSubscribeDataItem("2025年6月20日")); |
|
|
|
dataMap.put("thing10", new WeComSubscribeDataItem("宁波国研机房")); |
|
|
|
dataMap.put("thing8", new WeComSubscribeDataItem("2025年6月21日")); |
|
|
|
|
|
|
|
request.setData(dataMap); |
|
|
|
|
|
|
|
// 打印格式化的 JSON 请求体
|
|
|
|
try { |
|
|
|
String formattedJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(request); |
|
|
|
String compactJson = objectMapper.writeValueAsString(request); |
|
|
|
System.out.println("🎯 请求地址: " + url); |
|
|
|
System.out.println("📥 请求体 JSON(紧凑格式):\n" + compactJson); |
|
|
|
System.out.println("📘 请求体 JSON(格式化):\n" + formattedJson); |
|
|
|
} catch (JsonProcessingException e) { |
|
|
|
System.err.println("⚠ JSON 序列化失败:" + e.getMessage()); |
|
|
|
} |
|
|
|
|
|
|
|
// 设置请求头并清除可能导致 412 的字段
|
|
|
|
HttpHeaders headers = new HttpHeaders(); |
|
|
|
headers.setContentType(MediaType.APPLICATION_JSON); |
|
|
|
|
|
|
|
// 显式移除 If-Match / If-None-Match(保险起见)
|
|
|
|
headers.remove("If-Match"); |
|
|
|
headers.remove("If-None-Match"); |
|
|
|
|
|
|
|
HttpEntity<WeComSubscribeMessageRequest> entity = new HttpEntity<>(request, headers); |
|
|
|
|
|
|
|
// 发送请求并捕获异常
|
|
|
|
try { |
|
|
|
ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class); |
|
|
|
|
|
|
|
// 打印响应结果(调试用)
|
|
|
|
System.out.println("📤 响应状态码: " + response.getStatusCode()); |
|
|
|
System.out.println("📤 响应内容: " + response.getBody()); |
|
|
|
|
|
|
|
return response; |
|
|
|
} catch (HttpClientErrorException e) { |
|
|
|
// 或者返回错误信息给前端
|
|
|
|
System.err.println("❌ HTTP 错误状态码: " + e.getStatusCode()); |
|
|
|
System.err.println("❌ 响应头: " + e.getResponseHeaders()); |
|
|
|
System.err.println("❌ 响应体: " + e.getResponseBodyAsString()); |
|
|
|
throw e; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
@GetMapping("/sendSubscribeMsgTest") |
|
|
|
public ResponseEntity<String> sendSubscribeMsgTest( |
|
|
|
@RequestParam(required = false) String openid, |
|
|
|
@RequestParam(required = false) String accessToken) { |
|
|
|
|
|
|
|
// 使用默认值或传入参数
|
|
|
|
openid = openid == null ? APP_OPENID : openid; |
|
|
|
accessToken = accessToken == null ? ACCESS_TOKEN : accessToken; |
|
|
|
|
|
|
|
String url = SUBSCRIBE_SEND_PREFIX + accessToken; |
|
|
|
|
|
|
|
// 构建请求体对象
|
|
|
|
WeComSubscribeMessageRequest request = new WeComSubscribeMessageRequest(); |
|
|
|
request.setTouser(openid); |
|
|
|
request.setTemplate_id(TEMPLATE_ID); |
|
|
|
request.setPage("pages/index/index"); |
|
|
|
|
|
|
|
Map<String, WeComSubscribeDataItem> dataMap = new HashMap<>(); |
|
|
|
dataMap.put("character_string5", new WeComSubscribeDataItem("工单编号:123456")); |
|
|
|
dataMap.put("thing2", new WeComSubscribeDataItem("空调内部故障")); |
|
|
|
dataMap.put("time13", new WeComSubscribeDataItem("2025年6月20日")); |
|
|
|
dataMap.put("thing10", new WeComSubscribeDataItem("宁波国研机房")); |
|
|
|
dataMap.put("thing8", new WeComSubscribeDataItem("2025年6月21日")); |
|
|
|
|
|
|
|
request.setData(dataMap); |
|
|
|
// 序列化 JSON 并记录日志
|
|
|
|
String jsonBody; |
|
|
|
try { |
|
|
|
jsonBody = objectMapper.writeValueAsString(request); |
|
|
|
} catch (JsonProcessingException e) { |
|
|
|
String errorMsg = "❌ JSON 构建失败:" + e.getMessage(); |
|
|
|
log.error(errorMsg, e); // 统一日志记录
|
|
|
|
return ResponseEntity.status(500).body(errorMsg); |
|
|
|
} |
|
|
|
|
|
|
|
// 打印调试信息(格式化 JSON)
|
|
|
|
try { |
|
|
|
String formattedJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(request); |
|
|
|
log.info("🎯 请求地址: {}", url); |
|
|
|
log.info("📘 请求体 JSON(格式化):\n{}", formattedJson); |
|
|
|
} catch (JsonProcessingException e) { |
|
|
|
log.warn("⚠️ 格式化 JSON 失败,跳过打印"); |
|
|
|
} |
|
|
|
|
|
|
|
// 创建 HttpClient 实例并发送 POST 请求
|
|
|
|
HttpClient client = HttpClient.newHttpClient(); |
|
|
|
|
|
|
|
HttpRequest httpRequest = HttpRequest.newBuilder() |
|
|
|
.uri(URI.create(url)) |
|
|
|
.header("Content-Type", "application/json") |
|
|
|
.POST(HttpRequest.BodyPublishers.ofString(jsonBody)) |
|
|
|
.build(); |
|
|
|
|
|
|
|
try { |
|
|
|
HttpResponse<String> response = client.send(httpRequest, HttpResponse.BodyHandlers.ofString()); |
|
|
|
|
|
|
|
// 记录响应结果
|
|
|
|
log.info("📤 响应状态码: {}", response.statusCode()); |
|
|
|
log.info("📤 响应内容: {}", response.body()); |
|
|
|
|
|
|
|
// 返回给前端
|
|
|
|
return ResponseEntity.status(response.statusCode()).body(response.body()); |
|
|
|
|
|
|
|
} catch (IOException | InterruptedException e) { |
|
|
|
String errorMsg = "❌ 请求发送失败:" + e.getMessage(); |
|
|
|
log.error(errorMsg, e); |
|
|
|
return ResponseEntity.status(500).body(errorMsg); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private Map<String, String> getAccessTokenForApp() throws JsonProcessingException { |
|
|
|
// 1. 构造请求 URL
|
|
|
|
String url = "https://api.weixin.qq.com/cgi-bin/token?" + |
|
|
|
"grant_type=client_credential&" + |
|
|
|
"appid={appid}&" + |
|
|
|
"secret={secret}"; |
|
|
|
|
|
|
|
// 2. 构造参数 Map
|
|
|
|
Map<String, String> uriVariables = new HashMap<>(); |
|
|
|
uriVariables.put("appid", APP_ID); |
|
|
|
uriVariables.put("secret", APP_SECRET); |
|
|
|
|
|
|
|
// 3. 发起请求
|
|
|
|
String response = restTemplate.getForObject(url, String.class, uriVariables); |
|
|
|
|
|
|
|
// 4. 解析 JSON 获取 access_token
|
|
|
|
Map<String, String> result = objectMapper.readValue(response, new TypeReference<Map<String, String>>() {}); |
|
|
|
String accessToken = result.get("access_token"); |
|
|
|
if (accessToken == null || accessToken.isEmpty()) { |
|
|
|
throw new RuntimeException("获取 access_token 失败: " + response); |
|
|
|
} |
|
|
|
log.info("获取access_token:{}",accessToken); |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Map<String, String> getOpenIdForApp(String jsCode) throws JsonProcessingException { |
|
|
|
String url = "https://api.weixin.qq.com/sns/jscode2session?appid={appid}&secret={secret}&js_code={jscode}&grant_type=authorization_code"; |
|
|
|
|
|
|
|
Map<String, String> uriVariables = new HashMap<>(); |
|
|
|
uriVariables.put("appid", APP_ID); |
|
|
|
uriVariables.put("secret", APP_SECRET); |
|
|
|
uriVariables.put("jscode", jsCode); |
|
|
|
|
|
|
|
// 发送 GET 请求并接收返回结果(微信返回的是 JSON)
|
|
|
|
String response = restTemplate.getForObject(url, String.class, uriVariables); |
|
|
|
|
|
|
|
// 这里你可以解析 response 获取 openid 等信息
|
|
|
|
log.info("微信返回结果:{}", response); |
|
|
|
Map<String, String> result = objectMapper.readValue(response, new TypeReference<Map<String, String>>() {}); |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |