Bladeren bron

催收收费全体通知

cgy 2 maanden geleden
bovenliggende
commit
df1d301477

+ 9 - 0
zhsw-common/src/main/java/com/rongwei/zhsw/system/dao/SwBillManagementUnpaidDao.java

@@ -6,8 +6,10 @@ import com.rongwe.zhsw.system.domain.SwBillManagementUnpaidDo;
 import com.rongwe.zhsw.system.dto.TransferAccountDo;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.MapKey;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 账单管理(按年分表)(预收,未缴)(SwBillManagementUnpaid)表数据库访问层
@@ -23,6 +25,13 @@ public interface SwBillManagementUnpaidDao extends BaseMapper<SwBillManagementUn
 
     int deleteByIds(@Param("idList") List<String> idList);
 
+    /**
+     * 获取水费欠费用户信息
+     *
+     * @return 欠费用户信息列表
+     */
+    @MapKey("ID")
+    List<Map<String, Object>> getWaterFeeArrearsInfo();
 
 }
 

+ 18 - 5
zhsw-common/src/main/java/com/rongwei/zhsw/system/utils/WxMessageUtils.java

@@ -42,12 +42,18 @@ public class WxMessageUtils {
      */
     public static boolean sendTemplateMessage(String appId, String appSecret, String templateId, String openId, Map<String, Object> data) {
         try {
+            // 检查openId参数
+            if (openId == null || openId.isEmpty() || "null".equalsIgnoreCase(openId)) {
+                logger.error("发送模板消息失败:openId为null或空");
+                return false;
+            }
+            
             String accessToken = getAccessToken(appId, appSecret);
             if (accessToken == null) {
                 logger.error("获取access_token失败");
                 return false;
             }
-            logger.error("获取access_token成功", accessToken);
+            logger.info("获取access_token成功: {}", accessToken);
 
             Map<String, Object> params = new HashMap<>();
             params.put("touser", openId);
@@ -66,12 +72,19 @@ public class WxMessageUtils {
                     HttpEntity entity = response.getEntity();
                     String result = EntityUtils.toString(entity, "UTF-8");
                     JSONObject jsonResult = JSON.parseObject(result);
-                    logger.error("消息发送成功:",jsonResult);
-                    return jsonResult.getInteger("errcode") == 0;
+                    
+                    if (jsonResult.getInteger("errcode") == 0) {
+                        logger.info("微信模板消息发送成功,openId: {}", openId);
+                        return true;
+                    } else {
+                        logger.error("微信模板消息发送失败,openId: {}, 错误码: {}, 错误信息: {}", 
+                                    openId, jsonResult.getInteger("errcode"), jsonResult.getString("errmsg"));
+                        return false;
+                    }
                 }
             }
         } catch (Exception e) {
-            logger.error("发送模板消息失败", e);
+            logger.error("发送模板消息异常,openId: {}", openId, e);
         }
         return false;
     }
@@ -97,7 +110,7 @@ public class WxMessageUtils {
 
                 if (jsonResult.containsKey("access_token")) {
                     accessToken = jsonResult.getString("access_token");
-                    logger.error("获取access_token成功", accessToken);
+                    logger.info("获取access_token成功: {}", accessToken);
 
                     // 设置过期时间,提前5分钟过期
                     tokenExpireTime = System.currentTimeMillis() + (jsonResult.getLong("expires_in") - 300) * 1000;

+ 43 - 1
zhsw-common/src/main/resources/mybatis/zhsw/SwBillManagementUnpaidDao.xml

@@ -13,5 +13,47 @@
     </if>
     </delete>
 
+    <select id="getWaterFeeArrearsInfo" resultType="java.util.Map">
+        SELECT
+            '0' as DELETED,
+            um.ID,
+            um.VILLAGENAME,
+            um.USERNUMBER,
+            um.USERNAME,
+            um.USERTYPE,
+            um.ADDRESS,
+            um.WATERTYPE,
+            MIN(sbmu.THISMETERREADINGDATE) AS 'ARRDATE', -- 最早的欠费时间
+            GROUP_CONCAT(DISTINCT CONCAT(sbmu.YEAR, '-', sbmu.MONTH) ORDER BY sbmu.YEAR ASC, sbmu.MONTH ASC SEPARATOR '、') AS 'BLILYEARMONTH',
+            um.PHONENUMBER,
+            SUM(IFNULL(sbmu.THISMETERREADING, 0) - IFNULL(sbmu.LASTMETERREADING, 0)) AS 'TWC',
+            SUM(IFNULL(sbmu.OUGHTTOHAVEPAID, 0)) AS 'ODP',
+            SUM(IFNULL(sbmu.FEEWAIVER, 0)) AS 'TOTALABATMENT',
+            SUM(IFNULL(sbmu.ACTUALDUE, 0)) AS 'ACTPAY',
+            SUM(IFNULL(sbmu.ACTUALDUE, 0)) AS 'ARR',
+            suw.WECHATSIGN AS 'GZHOPENID'
+        FROM
+            sw_bill_management_unpaid sbmu
+        LEFT JOIN
+            sw_user_management um ON sbmu.USERNUMBER = um.USERNUMBER AND um.DELETED = '0' AND um.STATUS = 'enable'
+        LEFT JOIN
+            sw_user_wechat suw ON um.ID = suw.USERID AND suw.DELETED = '0'
+        WHERE
+            sbmu.DELETED = '0'
+            AND sbmu.ACTUALDUE > 0
+            AND (sbmu.STATUS = '2' OR sbmu.STATUS = '5')
+            AND um.USERNUMBER IS NOT NULL
+            AND suw.WECHATSIGN IS NOT NULL
+        GROUP BY
+            um.VILLAGENAME,
+            um.USERNUMBER,
+            um.USERNAME,
+            um.USERTYPE,
+            um.ADDRESS,
+            um.WATERTYPE,
+            um.PHONENUMBER,
+            um.ID,
+            suw.WECHATSIGN
+    </select>
 
-</mapper>
+</mapper>

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

@@ -1,6 +1,7 @@
 package com.rongwei.zhsw.system.controller;
 
 import com.rongwei.rwcommon.base.R;
+import com.rongwei.zhsw.system.dao.SwBillManagementUnpaidDao;
 import com.rongwei.zhsw.system.dao.SwEnterpriseConfigInfoDao;
 import com.rongwei.zhsw.system.service.impl.SwEnterpriseConfigInfoServiceImpl;
 import com.rongwei.zhsw.system.utils.WxMessageUtils;
@@ -25,6 +26,9 @@ public class WeChatOfficialController {
     @Autowired
     private SwEnterpriseConfigInfoServiceImpl swEnterpriseConfigInfoService;
 
+    @Autowired
+    private SwBillManagementUnpaidDao swBillManagementUnpaidDao;
+
     @PostMapping("/sendRepairMessage")
     public R sendRepairMessage(@RequestBody Map<String, Object> dataInfo) {
         try {
@@ -133,4 +137,151 @@ public class WeChatOfficialController {
             return R.error("发送报修消息提醒失败:" + e.getMessage());
         }
     }
+
+    /**
+     * 发送水费缴费通知消息
+     * 模板内容:
+     * - 标题: 水费缴费通知
+     * - 内容: 您有年月1、年月2水费账单未缴,请及时缴纳
+     * - 客户姓名: {{keyword1.DATA}}
+     * - 客户编号: {{keyword2.DATA}}
+     * - 用水地址: {{keyword3.DATA}}
+     * - 欠费笔数: {{keyword4.DATA}}
+     * - 欠费金额: {{keyword5.DATA}}
+     * - 备注: 请您及时缴费,可通过微信公众号进入用水宝小程序缴费,超期将停水。
+     */
+    @PostMapping("/sendFeeMessage")
+    public R sendFeeMessage(@RequestBody Map<String, Object> dataInfo) {
+        try {
+            log.info("开始处理水费缴费通知消息,消息内容:{}", dataInfo);
+
+            // 参数验证
+            if (dataInfo == null || !dataInfo.containsKey("mbtype")) {
+                return R.error("请求参数不完整");
+            }
+
+            // 获取模板类型,直接作为字符串使用
+            String mbtype = String.valueOf(dataInfo.get("mbtype"));
+            log.info("mbtype的值: {}, 类型: {}", mbtype, dataInfo.get("mbtype") != null ? dataInfo.get("mbtype").getClass().getName() : "null");
+            if (mbtype == null || mbtype.isEmpty()) {
+                return R.error("请求参数格式不正确");
+            }
+
+            // 获取企业配置信息
+            SwEnterpriseConfigInfoDo config = swEnterpriseConfigInfoService.getBaseMapper().getEnterpriseConfig();
+            if (config == null) {
+                return R.error("未找到企业配置信息");
+            }
+            log.info("企业配置信息: {}", config);
+
+            // 获取模板ID
+            JSONObject templateConfig = JSON.parseObject(config.getTemplateconfiguration());
+
+            boolean containsKey = templateConfig.containsKey(mbtype);
+
+            String templateId = templateConfig.getString(mbtype);
+
+            if (templateId == null) {
+                // 尝试手动获取
+                Object directValue = templateConfig.get(mbtype);
+                return R.error("未找到对应的模板ID");
+            }
+
+            // 判断是否为水费通知模板
+            if (!"cstz".equals(mbtype)) {
+                return R.error("不支持的模板类型");
+            }
+
+            // 查询欠费用户信息
+            List<Map<String, Object>> arrearsInfoList = swBillManagementUnpaidDao.getWaterFeeArrearsInfo();
+            if (arrearsInfoList == null || arrearsInfoList.isEmpty()) {
+                return R.error("未找到欠费用户信息");
+            }
+
+            int successCount = 0;
+            int failCount = 0;
+
+            // 循环发送消息给每个欠费用户
+            for (Map<String, Object> userInfo : arrearsInfoList) {
+                String userNumber = String.valueOf(userInfo.get("USERNUMBER"));
+                String userName = String.valueOf(userInfo.get("USERNAME"));
+
+                // 获取用户微信公众号ID
+                Object gzhOpenIdObj = userInfo.get("GZHOPENID");
+                String openId = (gzhOpenIdObj != null) ? String.valueOf(gzhOpenIdObj) : null;
+
+                // 严格检查openId是否为有效值
+                if (openId == null || openId.isEmpty() || "null".equalsIgnoreCase(openId)) {
+                    continue;
+                }
+                log.info("准备向用户 {} ({}) 发送消息,GZHOPENID: {}", userName, userNumber, openId);
+
+                try {
+                    // 构建模板消息数据
+                    Map<String, Object> data = new HashMap<>();
+
+                    Map<String, String> firstMap = new HashMap<>();
+                    String billMonths = (String) userInfo.get("BLILYEARMONTH");
+                    firstMap.put("value", "您有" + billMonths + "水费账单未缴,请及时缴纳");
+                    data.put("first", firstMap);
+
+                    Map<String, String> keyword1Map = new HashMap<>();
+                    keyword1Map.put("value", userName);
+                    data.put("keyword1", keyword1Map);
+
+                    Map<String, String> keyword2Map = new HashMap<>();
+                    keyword2Map.put("value", userNumber);
+                    data.put("keyword2", keyword2Map);
+
+                    Map<String, String> keyword3Map = new HashMap<>();
+                    keyword3Map.put("value", (String) userInfo.get("ADDRESS"));
+                    data.put("keyword3", keyword3Map);
+
+                    // 计算欠费笔数
+                    String billMonthsStr = (String) userInfo.get("BLILYEARMONTH");
+                    int billCount = billMonthsStr.split("、").length;
+
+                    Map<String, String> keyword4Map = new HashMap<>();
+                    keyword4Map.put("value", String.valueOf(billCount));
+                    data.put("keyword4", keyword4Map);
+
+                    Map<String, String> keyword5Map = new HashMap<>();
+                    keyword5Map.put("value", userInfo.get("ARR") + "元");
+                    data.put("keyword5", keyword5Map);
+
+                    Map<String, String> remarkMap = new HashMap<>();
+                    remarkMap.put("value", "请您及时缴费,可通过微信公众号进入用水宝小程序缴费,超期将停水。");
+                    data.put("remark", remarkMap);
+
+                    // 发送模板消息
+                    boolean result = WxMessageUtils.sendTemplateMessage(
+                            config.getGzhapppid(),
+                            config.getGzappsecret(),
+                            templateId,
+                            openId,
+                            data
+                    );
+
+                    if (result) {
+                        successCount++;
+                        log.info("成功发送水费缴费通知给用户: {}, 户号: {}", userName, userNumber);
+                    } else {
+                        failCount++;
+                        log.error("发送水费缴费通知给用户 {} ({}) 失败", userName, userNumber);
+                    }
+                } catch (Exception e) {
+                    failCount++;
+                    log.error("发送水费缴费通知给用户 {} ({}) 时发生异常: {}", userName, userNumber, e.getMessage());
+                }
+            }
+
+            String message = String.format("水费缴费通知发送完成,成功:%d条,失败:%d条", successCount, failCount);
+            log.info(message);
+            return R.ok(message);
+
+        } catch (Exception e) {
+            log.error("发送水费缴费通知失败", e);
+            return R.error("发送水费缴费通知失败:" + e.getMessage());
+        }
+    }
 }