diff --git a/mh-admin/src/main/resources/application-dev.yml b/mh-admin/src/main/resources/application-dev.yml index 63c74ba..d1a085c 100644 --- a/mh-admin/src/main/resources/application-dev.yml +++ b/mh-admin/src/main/resources/application-dev.yml @@ -216,3 +216,17 @@ control: topic: mh_control/events_upload/devices/dev amap: key: fc4e79719daca2d0b8a11ba3124e1bd5 + +wechat: + mpAppId: wx5653d0f930e98414 + mpAppSecret: 3473cbd80e891e4e7da1b1b71ae3a5a2 + redirectUri: https://35gm72cu2458.vicp.fun/wechat/userInfo + # 生成微信授权 + authorizedUrl: https://open.weixin.qq.com/connect/oauth2/authorize?appid=mpAppId&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect + # 获取code后,请求以下链接获取access_token + access_token: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET + # 拉取用户信息(需scope为 snsapi_userinfo) + userinfo: https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN + # 消息推送url + pushUrl: https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN + baseUrl: https://35gm72cu2458.vicp.fun diff --git a/mh-admin/src/main/resources/application-prod.yml b/mh-admin/src/main/resources/application-prod.yml index b4e31c9..6dbe62e 100644 --- a/mh-admin/src/main/resources/application-prod.yml +++ b/mh-admin/src/main/resources/application-prod.yml @@ -211,3 +211,17 @@ control: topic: mh_control/events_upload/devices amap: key: fc4e79719daca2d0b8a11ba3124e1bd5 + +wechat: + mpAppId: wx5653d0f930e98414 + mpAppSecret: 3473cbd80e891e4e7da1b1b71ae3a5a2 + redirectUri: http://jnd2.mhwsh.net:8766/wechat/userInfo + # 生成微信授权 + authorizedUrl: https://open.weixin.qq.com/connect/oauth2/authorize?appid=mpAppId&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect + # 获取code后,请求以下链接获取access_token + access_token: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET + # 拉取用户信息(需scope为 snsapi_userinfo) + userinfo: https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN + # 消息推送url + pushUrl: https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN + baseUrl: http://jnd2.mhwsh.net:8766 diff --git a/mh-admin/src/main/resources/application-test.yml b/mh-admin/src/main/resources/application-test.yml index 098d3eb..005f26d 100644 --- a/mh-admin/src/main/resources/application-test.yml +++ b/mh-admin/src/main/resources/application-test.yml @@ -210,3 +210,17 @@ control: topic: mh_control/events_upload/devices/test amap: key: fc4e79719daca2d0b8a11ba3124e1bd5 + +wechat: + mpAppId: wx5653d0f930e98414 + mpAppSecret: 3473cbd80e891e4e7da1b1b71ae3a5a2 + redirectUri: https://35gm72cu2458.vicp.fun/wechat/userInfo + # 生成微信授权 + authorizedUrl: https://open.weixin.qq.com/connect/oauth2/authorize?appid=mpAppId&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect + # 获取code后,请求以下链接获取access_token + access_token: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET + # 拉取用户信息(需scope为 snsapi_userinfo) + userinfo: https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN + # 消息推送url + pushUrl: https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN + baseUrl: https://35gm72cu2458.vicp.fun diff --git a/mh-common/pom.xml b/mh-common/pom.xml index 0947baa..0c59ee5 100644 --- a/mh-common/pom.xml +++ b/mh-common/pom.xml @@ -160,6 +160,13 @@ lombok + + + com.github.binarywang + weixin-java-mp + 4.7.6.B + + \ No newline at end of file diff --git a/mh-common/src/main/java/com/mh/common/config/wechat/RestTemplateConfig.java b/mh-common/src/main/java/com/mh/common/config/wechat/RestTemplateConfig.java new file mode 100644 index 0000000..dbde6b3 --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/config/wechat/RestTemplateConfig.java @@ -0,0 +1,28 @@ +package com.mh.common.config.wechat; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.BufferingClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +/** + * @author LJF + * @version 1.0 + * @project EEMCS + * @description restTemplate配置 + * @date 2025-06-30 14:35:10 + */ +@Configuration +public class RestTemplateConfig { + + // 配置类中定义Bean(全局禁用分块传输) + @Bean + public RestTemplate restTemplate() { + return new RestTemplateBuilder() + .requestFactory(() -> new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory())) + .build(); + } + +} diff --git a/mh-common/src/main/java/com/mh/common/config/wechat/WechatMpConfig.java b/mh-common/src/main/java/com/mh/common/config/wechat/WechatMpConfig.java new file mode 100644 index 0000000..ebf4d3b --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/config/wechat/WechatMpConfig.java @@ -0,0 +1,94 @@ +package com.mh.common.config.wechat; + +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import me.chanjar.weixin.mp.config.WxMpConfigStorage; +import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +import java.net.URLEncoder; + +/** + * @author chison + * @date 2020-04-03 15:42 + * @Description 微信网页授权信息配置类 + */ +@Component +@Configuration +public class WechatMpConfig { + + @Value("${wechat.mpAppId}") + private String mpAppId; + @Value("${wechat.mpAppSecret}") + private String mpAppSecret; + @Value("${wechat.redirectUri}") + private String redirectUri; + @Value("${wechat.authorizedUrl}") + private String authorizedUrl; + @Value("${wechat.access_token}") + private String accessToken; + @Value("${wechat.userinfo}") + private String userinfo; + @Value("${wechat.pushUrl}") + private String pushUrl; + @Value("${wechat.baseUrl}") + private String baseUrl; + + public String getBaseUrl() { + return baseUrl; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + public String getAuthorizedUrl() { + return authorizedUrl.replace("mpAppId", mpAppId).replace("REDIRECT_URI", URLEncoder.encode(redirectUri)); + } + + public String getAccessTokenUrl() { + return accessToken.replace("APPID", mpAppId).replace("SECRET", mpAppSecret); + } + + public String getUserInfo(String accessToken, String openId) { + return userinfo.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId); + } + + public String getPushMsgUrl(String accessToken) { + return pushUrl.replace("ACCESS_TOKEN", accessToken); + } + + public String getMpAppId() { + return mpAppId; + } + + public String getMpAppSecret() { + return mpAppSecret; + } + + /** + * 配置WxMpService所需信息 + * + * @return + */ + @Bean // 此注解指定在Spring容器启动时,就执行该方法并将该方法返回的对象交由Spring容器管理 + public WxMpService wxMpService() { + WxMpService wxMpService = new WxMpServiceImpl(); + // 设置配置信息的存储位置 + wxMpService.setWxMpConfigStorage(wxMpConfigStorage()); + + return wxMpService; + } + + public WxMpConfigStorage wxMpConfigStorage() { + // 使用这个实现类则表示将配置信息存储在内存中 + WxMpDefaultConfigImpl wxMpInMemoryConfigStorage = new WxMpDefaultConfigImpl(); + wxMpInMemoryConfigStorage.setAppId(getMpAppId()); + wxMpInMemoryConfigStorage.setSecret(getMpAppSecret()); + + return wxMpInMemoryConfigStorage; + } +} diff --git a/mh-common/src/main/java/com/mh/common/config/wechat/WechatSignUtil.java b/mh-common/src/main/java/com/mh/common/config/wechat/WechatSignUtil.java new file mode 100644 index 0000000..1cc7f9d --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/config/wechat/WechatSignUtil.java @@ -0,0 +1,62 @@ +package com.mh.common.config.wechat; + +import lombok.extern.slf4j.Slf4j; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.Map; +import java.util.TreeMap; + +/** + * @Author : Rainbow + * @date : 2024-09-14 + */ +@Slf4j +public class WechatSignUtil { + + /** + * SHA-1加密 + * @param params + * @return + */ + public static String generateSignature(Map params) { + // 使用TreeMap进行自然排序(按照key的ASCII码排序) + TreeMap sortedParams = new TreeMap<>(params); + + // 拼接字符串 + StringBuilder stringBuilder = new StringBuilder(); + for (Map.Entry entry : sortedParams.entrySet()) { + if (stringBuilder.length() > 0) { + stringBuilder.append("&"); + } + stringBuilder.append(entry.getKey()).append("=").append(entry.getValue()); + } + String string1 = stringBuilder.toString(); + + // SHA-1加密 + try { + // 获取SHA-1实例 + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + + // 将输入字符串转换为字节数组 + byte[] encodedHash = digest.digest(string1.getBytes()); + + // 可选:将字节数组转换为Base64字符串,便于显示和传输 + String base64Encoded = Base64.getEncoder().encodeToString(encodedHash); + log.info("SHA-1 (Base64 Encoded): {}", base64Encoded); + + // 或者,直接以16进制形式输出 + StringBuilder hexString = new StringBuilder(); + for (byte b : encodedHash) { + String hex = Integer.toHexString(0xff & b); + if(hex.length() == 1) hexString.append('0'); + hexString.append(hex); + } + log.info("SHA-1 (Hexadecimal): {}", hexString); + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("SHA-1 algorithm not found", e); + } + } +} diff --git a/mh-common/src/main/java/com/mh/common/core/domain/entity/AlarmRecords.java b/mh-common/src/main/java/com/mh/common/core/domain/entity/AlarmRecords.java index eff4cd9..45d38aa 100644 --- a/mh-common/src/main/java/com/mh/common/core/domain/entity/AlarmRecords.java +++ b/mh-common/src/main/java/com/mh/common/core/domain/entity/AlarmRecords.java @@ -83,6 +83,19 @@ public class AlarmRecords implements Serializable { */ private int status; + /** + * 是否发送通知 0:未发送 1:已发送 + */ + private int isSend; + + public int getIsSend() { + return isSend; + } + + public void setIsSend(int isSend) { + this.isSend = isSend; + } + public int getStatus() { return status; } diff --git a/mh-common/src/main/java/com/mh/common/core/domain/wechat/First.java b/mh-common/src/main/java/com/mh/common/core/domain/wechat/First.java new file mode 100644 index 0000000..d8fd48a --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/core/domain/wechat/First.java @@ -0,0 +1,35 @@ +package com.mh.common.core.domain.wechat; + +/** + * @author chison + * @date 2020-09-14 10:59 + * @Description + */ +public class First { + public String value; + public String color; + + public First() { + } + + public First(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } +} diff --git a/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key1.java b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key1.java new file mode 100644 index 0000000..627614f --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key1.java @@ -0,0 +1,35 @@ +package com.mh.common.core.domain.wechat; + +/** + * @author chison + * @date 2020-09-14 10:59 + * @Description + */ +public class Key1 { + public String value; + public String color; + + public Key1() { + } + + public Key1(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } +} diff --git a/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key2.java b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key2.java new file mode 100644 index 0000000..370b41c --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key2.java @@ -0,0 +1,36 @@ +package com.mh.common.core.domain.wechat; + +/** + * @author chison + * @date 2020-09-14 10:59 + * @Description + */ +public class Key2 { + + public String value; + public String color; + + public Key2() { + } + + public Key2(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } +} diff --git a/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key3.java b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key3.java new file mode 100644 index 0000000..41a823b --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key3.java @@ -0,0 +1,36 @@ +package com.mh.common.core.domain.wechat; + +/** + * @author chison + * @date 2020-09-14 11:00 + * @Description + */ +public class Key3 { + + public String value; + public String color; + + public Key3() { + } + + public Key3(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } +} diff --git a/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key4.java b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key4.java new file mode 100644 index 0000000..aeb8893 --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key4.java @@ -0,0 +1,36 @@ +package com.mh.common.core.domain.wechat; + +/** + * @author chison + * @date 2020-09-14 11:00 + * @Description + */ +public class Key4 { + + public String value; + public String color; + + public Key4() { + } + + public Key4(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } +} diff --git a/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key5.java b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key5.java new file mode 100644 index 0000000..e35e095 --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Key5.java @@ -0,0 +1,36 @@ +package com.mh.common.core.domain.wechat; + +/** + * @author chison + * @date 2020-09-14 11:00 + * @Description + */ +public class Key5 { + + public String value; + public String color; + + public Key5() { + } + + public Key5(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } +} diff --git a/mh-common/src/main/java/com/mh/common/core/domain/wechat/PushMsgEntity.java b/mh-common/src/main/java/com/mh/common/core/domain/wechat/PushMsgEntity.java new file mode 100644 index 0000000..8031f9c --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/core/domain/wechat/PushMsgEntity.java @@ -0,0 +1,115 @@ +package com.mh.common.core.domain.wechat; + +/** + * @author chison + * @date 2020-09-14 10:58 + * @Description 推送消息实体类 + */ +public class PushMsgEntity { + public String touser; //接收人 + public String templateId; //微信提供模板id + public String url; //消息推送消息url + public First first; //消息头消息 + public Key1 key1; + public Key2 key2; + public Key3 key3; + public Key4 key4; + public Key5 key5; + public Remark remark; + + public String getTouser() { + return touser; + } + + public void setTouser(String touser) { + this.touser = touser; + } + + public String getTemplateId() { + return templateId; + } + + public void setTemplateId(String templateId) { + this.templateId = templateId; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public First getFirst() { + return first; + } + + public void setFirst(First first) { + this.first = first; + } + + public Key1 getKey1() { + return key1; + } + + public void setKey1(Key1 key1) { + this.key1 = key1; + } + + public Key2 getKey2() { + return key2; + } + + public void setKey2(Key2 key2) { + this.key2 = key2; + } + + public Key3 getKey3() { + return key3; + } + + public void setKey3(Key3 key3) { + this.key3 = key3; + } + + public Key4 getKey4() { + return key4; + } + + public void setKey4(Key4 key4) { + this.key4 = key4; + } + + public Key5 getKey5() { + return key5; + } + + public void setKey5(Key5 key5) { + this.key5 = key5; + } + + public Remark getRemark() { + return remark; + } + + public void setRemark(Remark remark) { + this.remark = remark; + } + + @Override + public String toString() { + return "PushMsgEntity{" + + "touser='" + touser + '\'' + + ", templateId='" + templateId + '\'' + + ", url='" + url + '\'' + + ", first=" + first + + ", key1=" + key1 + + ", key2=" + key2 + + ", key3=" + key3 + + ", key4=" + key4 + + ", key5=" + key5 + + ", remark=" + remark + + '}'; + } +} diff --git a/mh-common/src/main/java/com/mh/common/core/domain/wechat/Remark.java b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Remark.java new file mode 100644 index 0000000..d4f7b91 --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/core/domain/wechat/Remark.java @@ -0,0 +1,36 @@ +package com.mh.common.core.domain.wechat; + +/** + * @author chison + * @date 2020-09-14 15:47 + * @Description + */ +public class Remark { + + public String value; + public String color; + + public Remark() { + } + + public Remark(String value, String color) { + this.value = value; + this.color = color; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } +} diff --git a/mh-common/src/main/java/com/mh/common/core/domain/wechat/WechatTemplate.java b/mh-common/src/main/java/com/mh/common/core/domain/wechat/WechatTemplate.java new file mode 100644 index 0000000..d9d0d24 --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/core/domain/wechat/WechatTemplate.java @@ -0,0 +1,70 @@ +package com.mh.common.core.domain.wechat; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import java.util.Date; + +/** + * @author LJF + * @version 1.0 + * @project EEMCS + * @description 微信模板 + * @date 2025-06-27 11:43:54 + */ +@Data +@TableName("wechat_template") +public class WechatTemplate { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String templateId; + + private String templateName; + + private String title; + + private String content1; + + private String content2; + + private String content3; + + private String content4; + + private String content5; + + private String remark; + + private Date createTime; + + private Date updateTime; + + /** + * 0:正常 1:不使用 + */ + private int grade; + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("id", id) + .append("templateId", templateId) + .append("templateName", templateName) + .append("title", title) + .append("content1", content1) + .append("content2", content2) + .append("content3", content3) + .append("content4", content4) + .append("content5", content5) + .append("remark", remark) + .append("createTime", createTime) + .append("updateTime", updateTime) + .append("grade", grade) + .toString(); + } +} diff --git a/mh-common/src/main/java/com/mh/common/core/domain/wechat/WechatTemplateProject.java b/mh-common/src/main/java/com/mh/common/core/domain/wechat/WechatTemplateProject.java new file mode 100644 index 0000000..38428f7 --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/core/domain/wechat/WechatTemplateProject.java @@ -0,0 +1,52 @@ +package com.mh.common.core.domain.wechat; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import org.apache.commons.lang3.builder.ToStringBuilder; + +import java.util.Date; + +/** + * @author LJF + * @version 1.0 + * @project EEMCS + * @description 微信模板 + * @date 2025-06-27 11:43:54 + */ +@Data +@TableName("wechat_template_project") +public class WechatTemplateProject { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private Long templateId; + + private Long projectId; + + private Long wechatUserId; + + private Date createTime; + + private Date updateTime; + + /** + * 0:正常 1:不使用 + */ + private int grade; + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("id", id) + .append("templateId", templateId) + .append("projectId", projectId) + .append("wechatUserId", wechatUserId) + .append("createTime", createTime) + .append("updateTime", updateTime) + .append("grade", grade) + .toString(); + } +} diff --git a/mh-common/src/main/java/com/mh/common/core/domain/wechat/WechatUserInfo.java b/mh-common/src/main/java/com/mh/common/core/domain/wechat/WechatUserInfo.java new file mode 100644 index 0000000..1435719 --- /dev/null +++ b/mh-common/src/main/java/com/mh/common/core/domain/wechat/WechatUserInfo.java @@ -0,0 +1,172 @@ +package com.mh.common.core.domain.wechat; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import java.util.Date; + +/** + * @author LJF + * @version 1.0 + * @project mh_esi + * @description 微信用户实体类 + * @date 2024-11-27 16:58:55 + */ +@TableName("wechat_user_info") +public class WechatUserInfo { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private String userName; + + private String telNum; + + private String openId; + + private String nickName; + + private int sex; + + private String province; + + private String city; + + private String country; + + private String headimgurl; + + private int isStatus; + + private Date createTime; + + private Date updateTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getTelNum() { + return telNum; + } + + public void setTelNum(String telNum) { + this.telNum = telNum; + } + + public String getOpenId() { + return openId; + } + + public void setOpenId(String openId) { + this.openId = openId; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public int getSex() { + return sex; + } + + public void setSex(Integer sex) { + this.sex = sex; + } + + public String getProvince() { + return province; + } + + public void setProvince(String province) { + this.province = province; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public void setSex(int sex) { + this.sex = sex; + } + + public String getHeadimgurl() { + return headimgurl; + } + + public void setHeadimgurl(String headimgurl) { + this.headimgurl = headimgurl; + } + + public int getIsStatus() { + return isStatus; + } + + public void setIsStatus(int isStatus) { + this.isStatus = isStatus; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + @Override + public String toString() { + return "WechatUserInfoEntity{" + + "id=" + id + + ", userName='" + userName + '\'' + + ", telNum='" + telNum + '\'' + + ", openId='" + openId + '\'' + + ", nickName='" + nickName + '\'' + + ", sex=" + sex + + ", province='" + province + '\'' + + ", city='" + city + '\'' + + ", country='" + country + '\'' + + ", headimgurl='" + headimgurl + '\'' + + ", isStatus=" + isStatus + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + '}'; + } +} diff --git a/mh-quartz/src/main/java/com/mh/quartz/task/PushDataToWechatTask.java b/mh-quartz/src/main/java/com/mh/quartz/task/PushDataToWechatTask.java new file mode 100644 index 0000000..c28a22e --- /dev/null +++ b/mh-quartz/src/main/java/com/mh/quartz/task/PushDataToWechatTask.java @@ -0,0 +1,126 @@ +package com.mh.quartz.task; + +import com.mh.common.constant.Constants; +import com.mh.common.core.domain.entity.AlarmRecords; +import com.mh.common.core.domain.wechat.*; +import com.mh.common.utils.DateUtils; +import com.mh.common.utils.DictUtils; +import com.mh.system.service.IWechatService; +import com.mh.system.service.operation.IAlarmRecordsService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author LJF + * @version 1.0 + * @project EEMCS + * @description 微信推送数据 + * @date 2025-06-27 10:54:23 + */ +@Slf4j +@Component("pushDataToWechatTask") +public class PushDataToWechatTask { + + @Resource + private IAlarmRecordsService alarmRecordsService; + + @Resource + private IWechatService wechatService; + + public void pushDataToWechat() { + // 查询报警内容 + AlarmRecords alarmRecords = new AlarmRecords(); + alarmRecords.setStatus(0); + alarmRecords.setIsSend(0); + Map param = new HashMap<>(); + param.put("beginTime", DateUtils.dateToString(new Date(), "yyyy-MM-dd 00:00:00")); + param.put("endTime", DateUtils.dateToString(new Date(), "yyyy-MM-dd 23:59:59")); + alarmRecords.setParams(param); + List alarmRecords1 = alarmRecordsService.selectAlarmRecordsList(alarmRecords); + if (null == alarmRecords1 || alarmRecords1.isEmpty()) { + return; + } + alarmRecords1.forEach(alarmRecords2 -> { + // 查询需要推送的微信用户 + List> wechatUserList = wechatService.queryWechatUser(0); + if (null == wechatUserList || wechatUserList.isEmpty()) { + log.info("没有查询到微信用户"); + } + // 开始推送数据 + for (Map map : wechatUserList) { + PushMsgEntity pushMsgEntity = new PushMsgEntity(); + try { + // 判断模板id种类 + switch (map.get("template_id").toString()) { + case "fqAXCFXSBCqHLJjBLIjD-Wr_dN8RLsTcsatUQa3Ktx4": + // 设备异常告警提醒 + pushDeviceExceptionParams(map, pushMsgEntity, alarmRecords2); + break; + case "qG3Odr74o4BRx8QigZuoil3l3ZC2aAdDeO49robRLC8": + // 推送用电量、用冷量、EER数据 + // pushAllParams(projectInfoEntity, map, pushMsgEntity, energyDataEntity); + break; + default: + break; + } + + } catch (Exception e) { + throw new RuntimeException(e); + } + if (!pushMsgEntity.getTouser().isEmpty()) { + String result = wechatService.pushMsg(pushMsgEntity); + if (Constants.SUCCESS.equals(result)) { + // 更新数据:已发送通知 + alarmRecordsService.updateAlarmRecordById(alarmRecords2.getId(), 1); + } + } + } + }); + } + + /** + * 推送设备异常告警提醒 + * @param map + * @param pushMsgEntity + * @param alarmRecords2 + */ + private void pushDeviceExceptionParams(Map map, PushMsgEntity pushMsgEntity, AlarmRecords alarmRecords2) { + pushMsgEntity.setTouser(map.get("open_id").toString()); + pushMsgEntity.setTemplateId(map.get("template_id").toString()); + pushMsgEntity.setUrl("http://jnd2.mhwsh.net:8765/"); + First first = new First(); + first.setValue("设备异常告警提醒"); + pushMsgEntity.setFirst(first); + Key1 key1 = new Key1(); + key1.setValue(alarmRecords2.getDeviceName()); + pushMsgEntity.setKey1(key1); + + Key2 key2 = new Key2(); + // 通过告警等级id得到value值 + String alarmLevel = alarmRecords2.getAlarmLevel(); + String alarmLevel1 = DictUtils.getDictLabel("alarm_level", alarmLevel); + key2.setValue(alarmLevel1); + pushMsgEntity.setKey2(key2); + + Key3 key3 = new Key3(); + // 通过告警类型id得到value值 + String alarmType = alarmRecords2.getAlarmType(); + String alarmType1 = DictUtils.getDictLabel( "alarm_type", alarmType); + key3.setValue(alarmType1); + pushMsgEntity.setKey3(key3); + + Key4 key4 = new Key4(); + key4.setValue(alarmRecords2.getContent().substring(0, 20)); + pushMsgEntity.setKey4(key4); + + Key5 key5 = new Key5(); + key5.setValue(DateUtils.dateToString(alarmRecords2.getCreateTime(), "yyyy-MM-dd HH:mm:ss")); + pushMsgEntity.setKey5(key5); + } +} diff --git a/mh-system/src/main/java/com/mh/system/mapper/WechatMapper.java b/mh-system/src/main/java/com/mh/system/mapper/WechatMapper.java new file mode 100644 index 0000000..df25e9a --- /dev/null +++ b/mh-system/src/main/java/com/mh/system/mapper/WechatMapper.java @@ -0,0 +1,26 @@ +package com.mh.system.mapper; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; +import java.util.Map; + +/** + * @author LJF + * @version 1.0 + * @project EEMCS + * @description 微信相关mapper + * @date 2025-06-27 14:02:37 + */ +@Mapper +public interface WechatMapper { + + + @Select("select wt.template_id, wui.open_id from wechat_template_project wtp " + + " join wechat_template wt on wtp.template_id = wt.id " + + " join wechat_user_info wui on wtp.wechat_user_id = wui.id" + + " where wtp.grade = #{grade} and wui.is_status = 1 ") + List> queryWechatUser(@Param("grade") int grade); +} diff --git a/mh-system/src/main/java/com/mh/system/mapper/operation/AlarmRecordsMapper.java b/mh-system/src/main/java/com/mh/system/mapper/operation/AlarmRecordsMapper.java index a1212b5..d0df964 100644 --- a/mh-system/src/main/java/com/mh/system/mapper/operation/AlarmRecordsMapper.java +++ b/mh-system/src/main/java/com/mh/system/mapper/operation/AlarmRecordsMapper.java @@ -3,6 +3,7 @@ package com.mh.system.mapper.operation; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.mh.common.core.domain.entity.AlarmRecords; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Update; /** * @author LJF @@ -13,4 +14,7 @@ import org.apache.ibatis.annotations.Mapper; */ @Mapper public interface AlarmRecordsMapper extends BaseMapper { + + @Update("update alarm_records set is_send = #{isSend} where id = #{id} ") + void updateIsSendById(String id, int isSend); } diff --git a/mh-system/src/main/java/com/mh/system/service/IWechatService.java b/mh-system/src/main/java/com/mh/system/service/IWechatService.java new file mode 100644 index 0000000..bf4ad8a --- /dev/null +++ b/mh-system/src/main/java/com/mh/system/service/IWechatService.java @@ -0,0 +1,20 @@ +package com.mh.system.service; + +import com.mh.common.core.domain.wechat.PushMsgEntity; + +import java.util.List; +import java.util.Map; + +/** + * @author LJF + * @version 1.0 + * @project EEMCS + * @description 微信相关服务类 + * @date 2025-06-27 13:48:09 + */ +public interface IWechatService { + + List> queryWechatUser(int grade); + + String pushMsg(PushMsgEntity pushMsgEntity); +} diff --git a/mh-system/src/main/java/com/mh/system/service/impl/WechatServiceImpl.java b/mh-system/src/main/java/com/mh/system/service/impl/WechatServiceImpl.java new file mode 100644 index 0000000..c95f32f --- /dev/null +++ b/mh-system/src/main/java/com/mh/system/service/impl/WechatServiceImpl.java @@ -0,0 +1,169 @@ +package com.mh.system.service.impl; + +import com.alibaba.fastjson2.JSONObject; +import com.mh.common.config.wechat.WechatMpConfig; +import com.mh.common.constant.Constants; +import com.mh.common.core.domain.wechat.PushMsgEntity; +import com.mh.common.core.redis.RedisCache; +import com.mh.system.mapper.WechatMapper; +import com.mh.system.service.IWechatService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.*; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.zip.GZIPOutputStream; + +/** + * @author LJF + * @version 1.0 + * @project EEMCS + * @description 微信服务实现类 + * @date 2025-06-27 13:48:32 + */ +@Slf4j +@Service +public class WechatServiceImpl implements IWechatService { + + @Autowired + private WechatMapper wechatMapper; + + @Autowired + private WechatMpConfig wechatMpConfig; + + @Autowired + private RedisCache redisCache; + + @Autowired + private RestTemplate restTemplate; + + @Override + public List> queryWechatUser(int grade) { + return wechatMapper.queryWechatUser(grade); + } + public String getAccessToken() { + String tokenResult = restTemplate.getForObject(wechatMpConfig.getAccessTokenUrl(),String.class); + JSONObject jsonObj = JSONObject.parseObject(tokenResult); + if (jsonObj == null || !jsonObj.containsKey("access_token")) { + return ""; + } + String accessToken = jsonObj.get("access_token").toString(); + log.info("获取access_token==>{}", accessToken); + redisCache.setCacheObject("accessToken", accessToken , 7000, TimeUnit.SECONDS); + return accessToken; + } + + @Override + public String pushMsg(PushMsgEntity pushMsgEntity) { + String result = Constants.FAIL; + // 判断cache中是否存在access_token + String accessToken = ""; + if (redisCache.hasKey("accessToken")) { + log.info("ConcurrentHashMap中存在access_token的cache,直接使用"); + // 再次判断是否存在access_token + if (!redisCache.hasKey("accessToken")) { + log.info("cache中不存在access_token,重新获取"); + accessToken = getAccessToken(); + } else { + accessToken = Objects.requireNonNull(redisCache.getCacheObject("accessToken")).toString(); + } + } else { + + String tokenResult = restTemplate.getForObject(wechatMpConfig.getAccessTokenUrl(), String.class); + JSONObject jsonObj = JSONObject.parseObject(tokenResult); + if (jsonObj == null || !jsonObj.containsKey("access_token")) { + return result; + } + accessToken = getAccessToken(); + } + if (accessToken.isEmpty()) { + return result; + } + // 封装推送内容 + JSONObject jsonObject = new JSONObject(); + jsonObject.put("touser", pushMsgEntity.getTouser()); + jsonObject.put("template_id", pushMsgEntity.getTemplateId()); + jsonObject.put("url", pushMsgEntity.getUrl()); + JSONObject data = new JSONObject(); + + // 判断模板id属于哪一个,切换对应的参数 + switch (pushMsgEntity.getTemplateId()) { + case "fqAXCFXSBCqHLJjBLIjD-Wr_dN8RLsTcsatUQa3Ktx4": + // 设备名称 + data.put("thing11", pushMsgEntity.getKey1()); + // 告警等级 + data.put("thing4", pushMsgEntity.getKey2()); +// // 告警类型 +// data.put("thing3", pushMsgEntity.getKey3()); + // 告警明细 + data.put("thing6", pushMsgEntity.getKey4()); + // 告警时间 + data.put("time5", pushMsgEntity.getKey5()); + break; + default: + break; + + } + data.put("remark", pushMsgEntity.getRemark()); + jsonObject.put("data", data); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + // 使用StringHttpMessageConverter来处理请求体 + String requestBody = jsonObject.toJSONString(); + HttpEntity entity = new HttpEntity<>(requestBody, headers); + + String requestUrl = wechatMpConfig.getPushMsgUrl(accessToken); + log.info("请求URL: {}", requestUrl); + log.info("请求体: {}", requestBody); + + try { + // 使用配置了StringHttpMessageConverter的RestTemplate + RestTemplate restTemplate = new RestTemplate(); + restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); + + ResponseEntity response = restTemplate.exchange( + requestUrl, + HttpMethod.POST, + entity, + String.class + ); + + String resultBody = response.getBody(); + + // 可以检查响应状态码 + if (!response.getStatusCode().is2xxSuccessful()) { + log.error("微信推送失败,状态码: {}", response.getStatusCode()); + } + + // { + // "errcode": 0, + // "errmsg": "ok", + // "msgid": 4054699362939830276 + //} + // 增加判断逻辑,判断errcode=0,errmsg=ok,返回success + JSONObject resultJson = JSONObject.parseObject(resultBody); + assert resultJson != null; + if (resultJson.getInteger("errcode") != 0) { + log.error("微信推送失败,错误码: {}", resultBody); + } else { + result = Constants.SUCCESS; + } + } catch (RestClientException e) { + log.error("推送消息失败", e); + } + return result; + } +} diff --git a/mh-system/src/main/java/com/mh/system/service/operation/IAlarmRecordsService.java b/mh-system/src/main/java/com/mh/system/service/operation/IAlarmRecordsService.java index 52a8f5a..56cacb8 100644 --- a/mh-system/src/main/java/com/mh/system/service/operation/IAlarmRecordsService.java +++ b/mh-system/src/main/java/com/mh/system/service/operation/IAlarmRecordsService.java @@ -24,4 +24,6 @@ public interface IAlarmRecordsService { AlarmRecords selectAlarmRecordsById(String acdId); int deleteAlarmRecordsByIds(String[] acdIds); + + void updateAlarmRecordById(String id, int i); } diff --git a/mh-system/src/main/java/com/mh/system/service/operation/impl/AlarmRecordsServiceImpl.java b/mh-system/src/main/java/com/mh/system/service/operation/impl/AlarmRecordsServiceImpl.java index 16bcdf9..0ceaf32 100644 --- a/mh-system/src/main/java/com/mh/system/service/operation/impl/AlarmRecordsServiceImpl.java +++ b/mh-system/src/main/java/com/mh/system/service/operation/impl/AlarmRecordsServiceImpl.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; @@ -79,13 +80,16 @@ public class AlarmRecordsServiceImpl implements IAlarmRecordsService { String beginTimeStr = (String) alarmRecords.getParams().get("beginTime"); String endTimeStr = (String) alarmRecords.getParams().get("endTime"); - if (StringUtils.isNotEmpty(beginTimeStr) && StringUtils.isNotEmpty(endTimeStr)) { - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - LocalDate beginTime = LocalDate.parse(beginTimeStr, formatter); - LocalDate endTime = LocalDate.parse(endTimeStr, formatter).plusDays(1); + String beginDateOnly = beginTimeStr.split(" ")[0]; + String endDateOnly = endTimeStr.split(" ")[0]; + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + LocalDate beginTime = LocalDate.parse(beginDateOnly, formatter); + LocalDate endTime = LocalDate.parse(endDateOnly, formatter).plusDays(1); + + queryWrapper.between("create_time", java.sql.Date.valueOf(beginTime), java.sql.Date.valueOf(endTime)); - queryWrapper.between("create_time", java.sql.Date.valueOf(beginTime), java.sql.Date.valueOf(endTime)); - } } // 台账id if (!StringUtils.isEmpty(alarmRecords.getLedgerId())) { @@ -106,6 +110,9 @@ public class AlarmRecordsServiceImpl implements IAlarmRecordsService { // 是否已处理,0:未处理,1:已处理 queryWrapper.eq("status", alarmRecords.getStatus()); + // 是否已经发送短信,0:未发送,1:已发送 + queryWrapper.eq("is_send", alarmRecords.getIsSend()); + queryWrapper.orderByDesc("create_time"); return alarmRecordsMapper.selectList(queryWrapper); } @@ -125,4 +132,9 @@ public class AlarmRecordsServiceImpl implements IAlarmRecordsService { } return 0; } + + @Override + public void updateAlarmRecordById(String id, int isSend) { + alarmRecordsMapper.updateIsSendById(id, isSend); + } }