Browse Source

小程序订阅

ops-management-platform-backend-dev
gjh 1 week ago
parent
commit
f036e10893
  1. 13
      ruoyi-modules/guoyan-platform/src/main/java/org/dromara/platform/config/AppConfig.java
  2. 270
      ruoyi-modules/guoyan-platform/src/main/java/org/dromara/platform/controller/WeChatController.java
  3. 18
      ruoyi-modules/guoyan-platform/src/main/java/org/dromara/platform/domain/app/WeComSubscribeDataItem.java
  4. 43
      ruoyi-modules/guoyan-platform/src/main/java/org/dromara/platform/domain/app/WeComSubscribeMessageRequest.java

13
ruoyi-modules/guoyan-platform/src/main/java/org/dromara/platform/config/AppConfig.java

@ -0,0 +1,13 @@
package org.dromara.platform.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

270
ruoyi-modules/guoyan-platform/src/main/java/org/dromara/platform/controller/WeChatController.java

@ -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;
}
}

18
ruoyi-modules/guoyan-platform/src/main/java/org/dromara/platform/domain/app/WeComSubscribeDataItem.java

@ -0,0 +1,18 @@
package org.dromara.platform.domain.app;
public class WeComSubscribeDataItem {
private String value;
public WeComSubscribeDataItem(String value) {
this.value = value;
}
// Getter and Setter
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

43
ruoyi-modules/guoyan-platform/src/main/java/org/dromara/platform/domain/app/WeComSubscribeMessageRequest.java

@ -0,0 +1,43 @@
package org.dromara.platform.domain.app;
import java.util.Map;
public class WeComSubscribeMessageRequest {
private String touser;
private String template_id;
private String page;
private Map<String, WeComSubscribeDataItem> data;
// Getter and Setter
public String getTouser() {
return touser;
}
public void setTouser(String touser) {
this.touser = touser;
}
public String getTemplate_id() {
return template_id;
}
public void setTemplate_id(String template_id) {
this.template_id = template_id;
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public Map<String, WeComSubscribeDataItem> getData() {
return data;
}
public void setData(Map<String, WeComSubscribeDataItem> data) {
this.data = data;
}
}
Loading…
Cancel
Save