Procházet zdrojové kódy

公众号报修处理提醒

QAQ 陈 před 4 měsíci
rodič
revize
327e524bc5

+ 15 - 0
zhsw-common/pom.xml

@@ -44,6 +44,21 @@
             <artifactId>wechatpay-java-core</artifactId>
             <version>0.2.16</version>
         </dependency>
+        <dependency>
+            <groupId>com.alibaba.boot</groupId>
+            <artifactId>nacos-config-spring-boot-starter</artifactId>
+            <version>0.2.12</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.13</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.83</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 4 - 0
zhsw-common/src/main/java/com/rongwei/zhsw/system/dao/SwEnterpriseConfigInfoDao.java

@@ -16,6 +16,10 @@ import java.util.List;
 */
 public interface SwEnterpriseConfigInfoDao extends BaseMapper<SwEnterpriseConfigInfoDo> {
     List<SwEnterpriseConfigInfoDo> selectListByDsKey(@Param("dsKeys") List<String> dsKey);
+
+    SwEnterpriseConfigInfoDo getEnterpriseConfig();
+
+    String getUserOpenIdsByRoles(@Param("roleCodes") List<String> roleCodes);
 }
 
 

+ 128 - 0
zhsw-common/src/main/java/com/rongwei/zhsw/system/utils/WxMessageUtils.java

@@ -0,0 +1,128 @@
+package com.rongwei.zhsw.system.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.exception.NacosException;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+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.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 微信公众号消息推送工具类
+ */
+public class WxMessageUtils {
+    private static final Logger logger = LoggerFactory.getLogger(WxMessageUtils.class);
+    private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
+    private static final String TEMPLATE_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send";
+    private static String accessToken;
+    private static long tokenExpireTime;
+
+    /**
+     * 发送模板消息
+     *
+     * @param appId      公众号appId
+     * @param appSecret  公众号appSecret
+     * @param templateId 模板ID
+     * @param openId     用户openId
+     * @param data       模板数据
+     * @return 是否发送成功
+     */
+    public static boolean sendTemplateMessage(String appId, String appSecret, String templateId, String openId, Map<String, Object> data) {
+        try {
+            String accessToken = getAccessToken(appId, appSecret);
+            if (accessToken == null) {
+                logger.error("获取access_token失败");
+                return false;
+            }
+            logger.error("获取access_token成功", accessToken);
+
+            Map<String, Object> params = new HashMap<>();
+            params.put("touser", openId);
+            params.put("template_id", templateId);
+            params.put("data", data);
+
+            String jsonStr = JSON.toJSONString(params);
+            String url = TEMPLATE_MESSAGE_URL + "?access_token=" + accessToken;
+
+            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+                HttpPost httpPost = new HttpPost(url);
+                httpPost.setEntity(new StringEntity(jsonStr, "UTF-8"));
+                httpPost.setHeader("Content-Type", "application/json");
+
+                try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+                    HttpEntity entity = response.getEntity();
+                    String result = EntityUtils.toString(entity, "UTF-8");
+                    JSONObject jsonResult = JSON.parseObject(result);
+                    logger.error("消息发送成功:",jsonResult);
+                    return jsonResult.getInteger("errcode") == 0;
+                }
+            }
+        } catch (Exception e) {
+            logger.error("发送模板消息失败", e);
+        }
+        return false;
+    }
+
+    /**
+     * 获取access_token
+     */
+    private static String getAccessToken(String appId, String appSecret) {
+        // 如果access_token未过期,直接返回
+        if (accessToken != null && System.currentTimeMillis() < tokenExpireTime) {
+            return accessToken;
+        }
+
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            String url = String.format("%s?grant_type=client_credential&appid=%s&secret=%s",
+                    ACCESS_TOKEN_URL, appId, appSecret);
+            HttpGet httpGet = new HttpGet(url);
+
+            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
+                HttpEntity entity = response.getEntity();
+                String result = EntityUtils.toString(entity, "UTF-8");
+                JSONObject jsonResult = JSON.parseObject(result);
+
+                if (jsonResult.containsKey("access_token")) {
+                    accessToken = jsonResult.getString("access_token");
+                    logger.error("获取access_token成功", accessToken);
+
+                    // 设置过期时间,提前5分钟过期
+                    tokenExpireTime = System.currentTimeMillis() + (jsonResult.getLong("expires_in") - 300) * 1000;
+                    return accessToken;
+                } else {
+                    logger.error("获取access_token失败: {}", result);
+                    return null;
+                }
+            }
+        } catch (IOException e) {
+            logger.error("获取access_token异常", e);
+            return null;
+        }
+    }
+
+    /**
+     * 从Nacos获取配置
+     */
+    private static String getNacosConfig(String dataId, String group) {
+        try {
+            ConfigService configService = NacosFactory.createConfigService("127.0.0.1:8848");
+            return configService.getConfig(dataId, group, 5000);
+        } catch (NacosException e) {
+            logger.error("从Nacos获取配置失败", e);
+            return null;
+        }
+    }
+}

+ 24 - 1
zhsw-common/src/main/resources/mybatis/zhsw/SwEnterpriseConfigInfoDao.xml

@@ -14,4 +14,27 @@
             from ${dsKey}.sw_enterprise_config_info where DELETED='0'
         </foreach>
     </select>
-</mapper>
+
+    <select id="getEnterpriseConfig" resultType="com.rongwe.zhsw.system.domain.SwEnterpriseConfigInfoDo">
+        SELECT * FROM zhsw00001.sw_enterprise_config_info LIMIT 1
+    </select>
+
+    <select id="getUserOpenIdsByRoles" resultType="string">
+        SELECT
+        GROUP_CONCAT(QYWXUSERID SEPARATOR ',') AS userids
+        FROM
+        zhsw00001.sys_user u
+        LEFT JOIN
+        zhsw00001.sys_user_role ur ON u.id = ur.userid AND u.DELETED = 0
+        LEFT JOIN
+        zhsw00001.sys_role r ON ur.roleid = r.id AND r.DELETED = 0
+        WHERE
+        r.CODE IN
+        <foreach collection="roleCodes" item="roleCode" open="(" separator="," close=")">
+            #{roleCode}
+        </foreach>
+        AND u.DELETED = 0
+        AND r.DELETED = 0
+        AND u.QYWXUSERID IS NOT NULL
+    </select>
+</mapper>

+ 16 - 1
zhsw-entity/src/main/java/com/rongwe/zhsw/system/domain/SwEnterpriseConfigInfoDo.java

@@ -110,4 +110,19 @@ public class SwEnterpriseConfigInfoDo extends BaseDo implements Serializable {
      * 商户密钥
      */
     private String merchantsecretkey;
-}
+
+    /**
+     * 公众号ID
+     */
+    private String gzhapppid;
+
+    /**
+     * 公众号开发者密钥
+     */
+    private String gzappsecret;
+
+    /**
+     * 模板数据配置
+     */
+    private String templateconfiguration;
+}

+ 36 - 0
zhsw-entity/src/main/java/com/rongwe/zhsw/system/dto/WxMessage.java

@@ -0,0 +1,36 @@
+package com.rongwe.zhsw.system.dto;
+
+import lombok.Data;
+
+@Data
+public class WxMessage {
+    /**
+     * 接收者openid
+     */
+    private String toUser;
+
+    /**
+     * 消息类型
+     */
+    private String messageType;
+
+    /**
+     * 消息内容
+     */
+    private String content;
+
+    /**
+     * 模板ID(如果是模板消息)
+     */
+    private String templateId;
+
+    /**
+     * 跳转链接
+     */
+    private String url;
+
+    /**
+     * 消息标题
+     */
+    private String title;
+}

+ 135 - 0
zhsw-server/src/main/java/com/rongwei/zhsw/system/controller/WeChatOfficialController.java

@@ -0,0 +1,135 @@
+package com.rongwei.zhsw.system.controller;
+
+import com.rongwei.rwcommon.base.R;
+import com.rongwei.zhsw.system.dao.SwEnterpriseConfigInfoDao;
+import com.rongwei.zhsw.system.service.impl.SwEnterpriseConfigInfoServiceImpl;
+import com.rongwei.zhsw.system.utils.WxMessageUtils;
+import com.rongwe.zhsw.system.domain.SwEnterpriseConfigInfoDo;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import lombok.extern.slf4j.Slf4j;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.Arrays;
+
+@Slf4j
+@RestController
+@RequestMapping("/officialAccountReminder")
+public class WeChatOfficialController {
+    @Autowired
+    private SwEnterpriseConfigInfoServiceImpl swEnterpriseConfigInfoService;
+
+    @PostMapping("/sendRepairMessage")
+    public R sendRepairMessage(@RequestBody Map<String, Object> dataInfo) {
+        try {
+            log.info("开始处理报修消息提醒,消息内容:{}", dataInfo);
+
+            // 参数验证
+            if (dataInfo == null || !dataInfo.containsKey("mbtype") || !dataInfo.containsKey("receiverrole")) {
+                return R.error("请求参数不完整");
+            }
+
+            Map<String, String> mbtypeMap = (Map<String, String>) dataInfo.get("mbtype");
+            Map<String, String> receiverRoleMap = (Map<String, String>) dataInfo.get("receiverrole");
+
+            if (mbtypeMap == null || !mbtypeMap.containsKey("value") ||
+                receiverRoleMap == null || !receiverRoleMap.containsKey("value")) {
+                return R.error("请求参数格式不正确");
+            }
+
+            // 获取企业配置信息
+            SwEnterpriseConfigInfoDo config = swEnterpriseConfigInfoService.getBaseMapper().getEnterpriseConfig();
+            if (config == null) {
+                return R.error("未找到企业配置信息");
+            }
+
+            // 获取模板ID
+            String mbtype = mbtypeMap.get("value");
+            JSONObject templateConfig = JSON.parseObject(config.getTemplateconfiguration());
+            String templateId = templateConfig.getString(mbtype);
+            if (templateId == null) {
+                return R.error("未找到对应的模板ID");
+            }
+
+            // 获取接收者角色
+            String receiverRole = receiverRoleMap.get("value");
+            List<String> roleCodes = Arrays.asList(receiverRole.split(","));
+
+            // 获取用户OpenID
+            String openIds = swEnterpriseConfigInfoService.getBaseMapper().getUserOpenIdsByRoles(roleCodes);
+            if (openIds == null || openIds.isEmpty()) {
+                return R.error("未找到符合条件的接收者");
+            }
+
+            // 构建模板消息数据
+            Map<String, Object> data = new HashMap<>();
+
+            Map<String, String> firstMap = new HashMap<>();
+            firstMap.put("value", ((Map<String, String>) dataInfo.get("first")).get("value"));
+            data.put("first", firstMap);
+            Map<String, String> keyword1Map = new HashMap<>();
+            keyword1Map.put("value", ((Map<String, String>) dataInfo.get("keyword1")).get("value"));
+            data.put("keyword1", keyword1Map);
+            Map<String, String> keyword2Map = new HashMap<>();
+            keyword2Map.put("value", ((Map<String, String>) dataInfo.get("keyword2")).get("value"));
+            data.put("keyword2", keyword2Map);
+            Map<String, String> keyword3Map = new HashMap<>();
+            keyword3Map.put("value", ((Map<String, String>) dataInfo.get("keyword3")).get("value"));
+            data.put("keyword3", keyword3Map);
+            Map<String, String> keyword4Map = new HashMap<>();
+            keyword4Map.put("value", ((Map<String, String>) dataInfo.get("keyword4")).get("value"));
+            data.put("keyword4", keyword4Map);
+            Map<String, String> remarkMap = new HashMap<>();
+            remarkMap.put("value", "请尽快处理!");
+            data.put("remark", remarkMap);
+            // 发送消息给所有接收者
+            String[] openIdArray = openIds.split(",");
+            boolean allSuccess = true;
+            int successCount = 0;
+            int failCount = 0;
+
+            for (String openId : openIdArray) {
+                try {
+                    boolean result = WxMessageUtils.sendTemplateMessage(
+                            config.getGzhapppid(),
+                            config.getGzappsecret(),
+                            templateId,
+                            openId,
+                            data
+                    );
+
+                    if (!result) {
+                        allSuccess = false;
+                        failCount++;
+                        log.error("发送消息给用户 {} 失败", openId);
+                    } else {
+                        successCount++;
+                        log.info("成功发送消息给用户: {}", openId);
+                    }
+                } catch (Exception e) {
+                    allSuccess = false;
+                    failCount++;
+                    log.error("发送消息给用户 {} 时发生异常: {}", openId, e.getMessage());
+                }
+            }
+
+            if (allSuccess) {
+                log.info("所有消息发送成功,共发送{}条", successCount);
+                return R.ok("所有消息发送成功,共发送" + successCount + "条");
+            } else {
+                String message = String.format("部分消息发送失败,成功:%d条,失败:%d条,请检查日志", successCount, failCount);
+                log.warn(message);
+                return R.error(message);
+            }
+        } catch (Exception e) {
+            log.error("发送报修消息提醒失败", e);
+            return R.error("发送报修消息提醒失败:" + e.getMessage());
+        }
+    }
+}