2 コミット 1b23ba3279 ... b856aaffeb

作者 SHA1 メッセージ 日付
  xuzhancheng b856aaffeb Merge remote-tracking branch 'origin/dev' into dev 3 日 前
  xuzhancheng 695cd18a82 约检确认单消息推送 3 日 前

+ 114 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/appointmentconfirmorder/AppointmentConfirmOrderServiceImpl.java

@@ -2,9 +2,12 @@ package cn.start.tz.module.pressure2.service.appointmentconfirmorder;
 
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.start.tz.framework.common.enums.TerminalEnum;
+import cn.start.tz.framework.common.exception.ErrorCode;
 import cn.start.tz.framework.common.exception.ServiceException;
 import cn.start.tz.framework.common.exception.ServiceException;
 import cn.start.tz.framework.common.pojo.PageResult;
 import cn.start.tz.framework.common.pojo.PageResult;
 import cn.start.tz.framework.common.util.object.BeanUtils;
 import cn.start.tz.framework.common.util.object.BeanUtils;
+import cn.start.tz.framework.env.core.enums.EnvEnum;
 import cn.start.tz.framework.ip.core.Area;
 import cn.start.tz.framework.ip.core.Area;
 import cn.start.tz.framework.ip.core.utils.AreaUtils;
 import cn.start.tz.framework.ip.core.utils.AreaUtils;
 import cn.start.tz.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.start.tz.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -19,6 +22,10 @@ import cn.start.tz.module.bpm.enums.task.BpmTaskStatusEnum;
 import cn.start.tz.module.member.api.templatesendlog.TemplateSendLogApi;
 import cn.start.tz.module.member.api.templatesendlog.TemplateSendLogApi;
 import cn.start.tz.module.member.api.templatesendlog.dto.TemplateSendLogDto;
 import cn.start.tz.module.member.api.templatesendlog.dto.TemplateSendLogDto;
 import cn.start.tz.module.member.api.templatesendlog.dto.TemplateSendLogRespDto;
 import cn.start.tz.module.member.api.templatesendlog.dto.TemplateSendLogRespDto;
+import cn.start.tz.module.member.api.user.dto.MemberUserReqVo;
+import cn.start.tz.module.member.api.user.dto.MemberUserRespDTO;
+import cn.start.tz.module.member.api.user.dto.SendAppMpMessageReqDTO;
+import cn.start.tz.module.member.api.user.dto.WxMpTemplateDataReqDto;
 import cn.start.tz.module.pressure2.dal.dataobject.acceptorder.AcceptOrderDO;
 import cn.start.tz.module.pressure2.dal.dataobject.acceptorder.AcceptOrderDO;
 import cn.start.tz.module.pressure2.enums.RedisKeyEnums;
 import cn.start.tz.module.pressure2.enums.RedisKeyEnums;
 import cn.start.tz.module.pressure2.controller.admin.appointmentconfirmorder.vo.*;
 import cn.start.tz.module.pressure2.controller.admin.appointmentconfirmorder.vo.*;
@@ -50,6 +57,11 @@ import cn.start.tz.module.pressure2.dal.mysql.equipboilerschedulingitem.EquipBoi
 import cn.start.tz.module.pressure2.service.acceptorder.AcceptOrderService;
 import cn.start.tz.module.pressure2.service.acceptorder.AcceptOrderService;
 import cn.start.tz.module.pressure2.service.common.RedisService;
 import cn.start.tz.module.pressure2.service.common.RedisService;
 import cn.start.tz.module.pressure2.service.equipboilerschedulingcheck.EquipBoilerSchedulingCheckService;
 import cn.start.tz.module.pressure2.service.equipboilerschedulingcheck.EquipBoilerSchedulingCheckService;
+import cn.start.tz.module.pressure2.service.member.MemberRemoteService;
+import cn.start.tz.module.pressure2.service.member.vo.MemberUserCreateReqVO;
+import cn.start.tz.module.pressure2.service.member.vo.MemberUserRespVO;
+import cn.start.tz.module.pressure2.service.membermessage.MemberMessageRemoteService;
+import cn.start.tz.module.pressure2.service.membermessage.vo.SendMpMessageReqVO;
 import cn.start.tz.module.pressure2.service.orderreport.OrderReportService;
 import cn.start.tz.module.pressure2.service.orderreport.OrderReportService;
 import cn.start.tz.module.system.api.dept.DeptApi;
 import cn.start.tz.module.system.api.dept.DeptApi;
 import cn.start.tz.module.system.api.dept.dto.DeptRespDTO;
 import cn.start.tz.module.system.api.dept.dto.DeptRespDTO;
@@ -61,6 +73,7 @@ import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.validation.annotation.Validated;
@@ -69,11 +82,14 @@ import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.*;
 import java.util.function.Function;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
+import static cn.start.tz.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.start.tz.framework.common.util.servlet.ServletUtils.getClientIP;
 import static cn.start.tz.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.start.tz.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
 
 
 
@@ -141,6 +157,15 @@ public class AppointmentConfirmOrderServiceImpl implements AppointmentConfirmOrd
     @Resource
     @Resource
     private OrgContactApi orgContactApi;
     private OrgContactApi orgContactApi;
 
 
+    @Value("${tz.env.name}")
+    private String env;
+
+    @Resource
+    private MemberRemoteService memberRemoteService;
+
+    @Resource
+    private MemberMessageRemoteService memberMessageRemoteService;
+
     @Resource
     @Resource
     private BpmProcessInstanceApi processInstanceApi;
     private BpmProcessInstanceApi processInstanceApi;
 
 
@@ -890,6 +915,95 @@ public class AppointmentConfirmOrderServiceImpl implements AppointmentConfirmOrd
 
 
     @Override
     @Override
     public void sendTemplateMessage(SendTemplateMessageVO sendTemplateMessageVO) {
     public void sendTemplateMessage(SendTemplateMessageVO sendTemplateMessageVO) {
+        AppointmentConfirmOrderDO appointmentConfirmOrderDO = appointmentConfirmOrderMapper.selectById(sendTemplateMessageVO.getId());
+        if (appointmentConfirmOrderDO == null) {
+            throw new ServiceException(404, "约检单不存在");
+        }
+
+        LambdaQueryWrapperX<BoilerAppointmentConfirmOrderItemDO> queryConfirmOrderItemWrapper = new LambdaQueryWrapperX<>();
+        queryConfirmOrderItemWrapper.eq(BoilerAppointmentConfirmOrderItemDO::getOrderId, appointmentConfirmOrderDO.getId());
+        List<BoilerAppointmentConfirmOrderItemDO> appointmentConfirmOrderItemDOS = appointmentConfirmOrderItemMapper.selectList(queryConfirmOrderItemWrapper);
+        if (CollUtil.isEmpty(appointmentConfirmOrderItemDOS)) {
+            throw new ServiceException(404, "约检确认单设备项目不存在");
+        }
+
+        List<String> equipIds = appointmentConfirmOrderItemDOS.stream().map(BoilerAppointmentConfirmOrderItemDO::getEquipId).toList();
+        LambdaQueryWrapperX<EquipBoilerDO> queryEquipBoiler = new LambdaQueryWrapperX<>();
+        queryEquipBoiler.in(EquipBoilerDO::getId, equipIds);
+        List<EquipBoilerDO> equipBoilerDOS = equipBoilerMapper.selectList(queryEquipBoiler);
+        if (CollUtil.isEmpty(equipBoilerDOS)) {
+            throw new ServiceException(404, "约检确认联系人不存在");
+        }
+
+//        List<String> contactPhones = equipBoilerDOS.stream().map(EquipBoilerDO::getContactPhone).distinct().toList();
+        List<String> contactPhones = Collections.singletonList(appointmentConfirmOrderDO.getUnitPhone());
+        if (CollUtil.isEmpty(contactPhones)) {
+            return;
+        }
+
+        String unitName = appointmentConfirmOrderDO.getUnitName();
+        String unitCode = appointmentConfirmOrderDO.getUnitCode();
+
+        String checkType = "内部检验";
+        if (appointmentConfirmOrderDO.getCheckType() == 200) {
+            checkType = "外部检验";
+        } else if (appointmentConfirmOrderDO.getCheckType() == 300) {
+            checkType = "耐压检验";
+        }
+
+
+        LocalDate appointmentDate = appointmentConfirmOrderDO.getAppointmentDate();
+        String date = appointmentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+        Long count = appointmentConfirmOrderItemMapper.selectCount(BoilerAppointmentConfirmOrderItemDO::getOrderId, sendTemplateMessageVO.getId());
+        String thing = String.format("%s|%s|%s", checkType, "锅炉", count);
+//        List<String> memberIds = clientUnitApi.getChargeMember(unitName).getCheckedData();
+//        if(memberIds == null){
+//            return;
+//        }
+
+        log.info("contactPhones:{}", contactPhones);
+        contactPhones.forEach(contactPhone -> {
+            SendMpMessageReqVO param = new SendMpMessageReqVO();
+            MemberUserRespVO memberUser = memberRemoteService.getUserByMobile(contactPhone);
+
+            // 获取不到平台用户信息是创建一个平台用户账号
+            if (ObjectUtil.isEmpty(memberUser)) {
+                MemberUserCreateReqVO memberUserReqVo = new MemberUserCreateReqVO();
+                memberUserReqVo.setMobile(contactPhone);
+                memberUserReqVo.setName(contactPhone);
+                memberUserReqVo.setRegisterIp(getClientIP());
+
+                memberUser = memberRemoteService.createUser(memberUserReqVo);
+                if (ObjectUtil.isEmpty(memberUser)) {
+                    throw exception(new ErrorCode(1007,"创建用户失败"));
+                }
+            }
+
+            param.setMemberId(memberUser.getId());
+            // 	3f-xg-UmbhgSb0QrU_3QYoN70uFWPfbhkBMhObgr3CE
+            if (EnvEnum.HSD.getEnvName().equals(env)) {
+                param.setTemplateId("3f-xg-UmbhgSb0QrU_3QYoN70uFWPfbhkBMhObgr3CE");
+            } else if (EnvEnum.UAT.getEnvName().equals(env)) {
+                param.setTemplateId("roTC0SQzXdla8FZJLyl3X84cSbrOsLMikD9lpmPD3YY");
+            }
+            List<SendMpMessageReqVO.TemplateData> list = new ArrayList<>();
+
+            list.add(new SendMpMessageReqVO.TemplateData("thing49", unitName, null));
+            list.add(new SendMpMessageReqVO.TemplateData("thing13", thing, null));
+            list.add(new SendMpMessageReqVO.TemplateData("time45", date, null));
+
+            param.setTemplateDataList(list);
+
+            // if(sendTemplateMessageVO.getPage()){
+            SendMpMessageReqVO.MiniProgram mini = new SendMpMessageReqVO.MiniProgram();
+            mini.setPagePath(String.format("pages/boiler/appointment-confirm/index?id=%s", sendTemplateMessageVO.getId()));
+            mini.setUsePath(true);
+            param.setMiniProgram(mini);
+            //}
+            param.setBusinessId(appointmentConfirmOrderDO.getId());
+            param.setBusinessType(0);
+            memberMessageRemoteService.sendMpMessage(param);
+        });
 
 
     }
     }
 
 

+ 109 - 1
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/appointmentconfirmorder/PipeAppointmentConfirmOrderServiceImpl.java

@@ -2,9 +2,12 @@ package cn.start.tz.module.pressure2.service.appointmentconfirmorder;
 
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.start.tz.framework.common.enums.TerminalEnum;
+import cn.start.tz.framework.common.exception.ErrorCode;
 import cn.start.tz.framework.common.exception.ServiceException;
 import cn.start.tz.framework.common.exception.ServiceException;
 import cn.start.tz.framework.common.pojo.PageResult;
 import cn.start.tz.framework.common.pojo.PageResult;
 import cn.start.tz.framework.common.util.object.BeanUtils;
 import cn.start.tz.framework.common.util.object.BeanUtils;
+import cn.start.tz.framework.env.core.enums.EnvEnum;
 import cn.start.tz.framework.ip.core.Area;
 import cn.start.tz.framework.ip.core.Area;
 import cn.start.tz.framework.ip.core.utils.AreaUtils;
 import cn.start.tz.framework.ip.core.utils.AreaUtils;
 import cn.start.tz.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.start.tz.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -17,6 +20,10 @@ import cn.start.tz.module.bpm.enums.boiler.BoilerBpmModelConstants;
 import cn.start.tz.module.bpm.enums.pipe.PipeBpmModelConstants;
 import cn.start.tz.module.bpm.enums.pipe.PipeBpmModelConstants;
 import cn.start.tz.module.bpm.enums.task.BpmTaskStatusEnum;
 import cn.start.tz.module.bpm.enums.task.BpmTaskStatusEnum;
 import cn.start.tz.module.member.api.templatesendlog.TemplateSendLogApi;
 import cn.start.tz.module.member.api.templatesendlog.TemplateSendLogApi;
+import cn.start.tz.module.member.api.user.dto.MemberUserReqVo;
+import cn.start.tz.module.member.api.user.dto.MemberUserRespDTO;
+import cn.start.tz.module.member.api.user.dto.SendAppMpMessageReqDTO;
+import cn.start.tz.module.member.api.user.dto.WxMpTemplateDataReqDto;
 import cn.start.tz.module.pressure2.dal.dataobject.boileracceptorderuser.BoilerAcceptOrderUserDO;
 import cn.start.tz.module.pressure2.dal.dataobject.boileracceptorderuser.BoilerAcceptOrderUserDO;
 import cn.start.tz.module.pressure2.dal.dataobject.boilerappointmentconfirmorderuser.BoilerAppointmentConfirmOrderUserDO;
 import cn.start.tz.module.pressure2.dal.dataobject.boilerappointmentconfirmorderuser.BoilerAppointmentConfirmOrderUserDO;
 import cn.start.tz.module.pressure2.enums.RedisKeyEnums;
 import cn.start.tz.module.pressure2.enums.RedisKeyEnums;
@@ -63,6 +70,11 @@ import cn.start.tz.module.pressure2.dal.mysql.pipeorderexception.PipeOrderExcept
 import cn.start.tz.module.pressure2.service.acceptorder.PipeAcceptOrderService;
 import cn.start.tz.module.pressure2.service.acceptorder.PipeAcceptOrderService;
 import cn.start.tz.module.pressure2.service.common.RedisService;
 import cn.start.tz.module.pressure2.service.common.RedisService;
 import cn.start.tz.module.pressure2.service.equippipeschedulingcheck.EquipPipeSchedulingCheckService;
 import cn.start.tz.module.pressure2.service.equippipeschedulingcheck.EquipPipeSchedulingCheckService;
+import cn.start.tz.module.pressure2.service.member.MemberRemoteService;
+import cn.start.tz.module.pressure2.service.member.vo.MemberUserCreateReqVO;
+import cn.start.tz.module.pressure2.service.member.vo.MemberUserRespVO;
+import cn.start.tz.module.pressure2.service.membermessage.MemberMessageRemoteService;
+import cn.start.tz.module.pressure2.service.membermessage.vo.SendMpMessageReqVO;
 import cn.start.tz.module.pressure2.service.orderreport.OrderReportService;
 import cn.start.tz.module.pressure2.service.orderreport.OrderReportService;
 import cn.start.tz.module.system.api.dept.DeptApi;
 import cn.start.tz.module.system.api.dept.DeptApi;
 import cn.start.tz.module.system.api.orgcontact.OrgContactApi;
 import cn.start.tz.module.system.api.orgcontact.OrgContactApi;
@@ -73,6 +85,7 @@ import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.validation.annotation.Validated;
@@ -82,11 +95,14 @@ import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Function;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
+import static cn.start.tz.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.start.tz.framework.common.util.servlet.ServletUtils.getClientIP;
 import static cn.start.tz.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.start.tz.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
 
 
 
@@ -162,7 +178,12 @@ public class PipeAppointmentConfirmOrderServiceImpl implements PipeAppointmentCo
 
 
     @Resource
     @Resource
     private AppointmentConfirmRefuseYearItemMapper appointmentConfirmRefuseYearItemMapper;
     private AppointmentConfirmRefuseYearItemMapper appointmentConfirmRefuseYearItemMapper;
-
+    @Value("${tz.env.name}")
+    private String env;
+    @Resource
+    private MemberRemoteService memberRemoteService;
+    @Resource
+    private MemberMessageRemoteService memberMessageRemoteService;
     @Resource
     @Resource
     private AppointmentConfirmOrderRefuseItemMapper appointmentConfirmOrderRefuseItemMapper;
     private AppointmentConfirmOrderRefuseItemMapper appointmentConfirmOrderRefuseItemMapper;
 
 
@@ -1058,6 +1079,93 @@ public class PipeAppointmentConfirmOrderServiceImpl implements PipeAppointmentCo
 
 
     @Override
     @Override
     public void sendTemplateMessage(SendTemplateMessageVO sendTemplateMessageVO) {
     public void sendTemplateMessage(SendTemplateMessageVO sendTemplateMessageVO) {
+        AppointmentConfirmOrderDO appointmentConfirmOrderDO = appointmentConfirmOrderMapper.selectById(sendTemplateMessageVO.getId());
+        if (appointmentConfirmOrderDO == null) {
+            throw new ServiceException(404, "约检单不存在");
+        }
+
+        LambdaQueryWrapperX<PipeAppointmentConfirmOrderItemDO> queryConfirmOrderItemWrapper = new LambdaQueryWrapperX<>();
+        queryConfirmOrderItemWrapper.eq(PipeAppointmentConfirmOrderItemDO::getOrderId, appointmentConfirmOrderDO.getId());
+        List<PipeAppointmentConfirmOrderItemDO> appointmentConfirmOrderItemDOS = appointmentConfirmOrderItemMapper.selectList(queryConfirmOrderItemWrapper);
+        if (CollUtil.isEmpty(appointmentConfirmOrderItemDOS)) {
+            throw new ServiceException(404, "约检确认单设备项目不存在");
+        }
+
+        List<String> equipIds = appointmentConfirmOrderItemDOS.stream().map(PipeAppointmentConfirmOrderItemDO::getEquipId).toList();
+        LambdaQueryWrapperX<EquipPipeDO> queryEquipPipe = new LambdaQueryWrapperX<>();
+        queryEquipPipe.in(EquipPipeDO::getId, equipIds);
+        List<EquipPipeDO> equipPipeDOS = equipPipeMapper.selectList(queryEquipPipe);
+        if (CollUtil.isEmpty(equipPipeDOS)) {
+            throw new ServiceException(404, "约检确认联系人不存在");
+        }
+
+//        List<String> contactPhones = equipPipeDOS.stream().map(EquipPipeDO::getContactPhone).distinct().toList();
+        List<String> contactPhones = Collections.singletonList(appointmentConfirmOrderDO.getUnitPhone());
+        if (CollUtil.isEmpty(contactPhones)) {
+            return;
+        }
+
+        String unitName = appointmentConfirmOrderDO.getUnitName();
+        String unitCode = appointmentConfirmOrderDO.getUnitCode();
+
+        String checkType = "定期检验";
+        if (appointmentConfirmOrderDO.getCheckType() == 200) {
+            checkType = "年度检验";
+        }
+
+
+        LocalDate appointmentDate = appointmentConfirmOrderDO.getAppointmentDate();
+        String date = appointmentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+        Long count = appointmentConfirmOrderItemMapper.selectCount(PipeAppointmentConfirmOrderItemDO::getOrderId, sendTemplateMessageVO.getId());
+        String thing = String.format("%s|%s|%s", checkType, "压力管道", count);
+//        List<String> memberIds = clientUnitApi.getChargeMember(unitName).getCheckedData();
+//        if(memberIds == null){
+//            return;
+//        }
+
+        log.info("contactPhones:{}", contactPhones);
+        contactPhones.forEach(contactPhone -> {
+            SendMpMessageReqVO param = new SendMpMessageReqVO();
+            MemberUserRespVO memberUser = memberRemoteService.getUserByMobile(contactPhone);
+
+            // 获取不到平台用户信息是创建一个平台用户账号
+            if (ObjectUtil.isEmpty(memberUser)) {
+                MemberUserCreateReqVO memberUserReqVo = new MemberUserCreateReqVO();
+                memberUserReqVo.setMobile(contactPhone);
+                memberUserReqVo.setName(contactPhone);
+                memberUserReqVo.setRegisterIp(getClientIP());
+
+                memberUser = memberRemoteService.createUser(memberUserReqVo);
+                if (ObjectUtil.isEmpty(memberUser)) {
+                    throw exception(new ErrorCode(1007,"创建用户失败"));
+                }
+            }
+
+            param.setMemberId(memberUser.getId());
+            // 	3f-xg-UmbhgSb0QrU_3QYoN70uFWPfbhkBMhObgr3CE
+            if (EnvEnum.HSD.getEnvName().equals(env)) {
+                param.setTemplateId("3f-xg-UmbhgSb0QrU_3QYoN70uFWPfbhkBMhObgr3CE");
+            } else if (EnvEnum.UAT.getEnvName().equals(env)) {
+                param.setTemplateId("roTC0SQzXdla8FZJLyl3X84cSbrOsLMikD9lpmPD3YY");
+            }
+            List<SendMpMessageReqVO.TemplateData> list = new ArrayList<>();
+
+            list.add(new SendMpMessageReqVO.TemplateData("thing49", unitName, null));
+            list.add(new SendMpMessageReqVO.TemplateData("thing13", thing, null));
+            list.add(new SendMpMessageReqVO.TemplateData("time45", date, null));
+
+            param.setTemplateDataList(list);
+
+            // if(sendTemplateMessageVO.getPage()){
+            SendMpMessageReqVO.MiniProgram mini = new SendMpMessageReqVO.MiniProgram();
+            mini.setPagePath(String.format("pages/pipe/appointment-confirm/index?id=%s", sendTemplateMessageVO.getId()));
+            mini.setUsePath(true);
+            param.setMiniProgram(mini);
+            //}
+            param.setBusinessId(appointmentConfirmOrderDO.getId());
+            param.setBusinessType(0);
+            memberMessageRemoteService.sendMpMessage(param);
+        });
 
 
     }
     }
 
 

+ 31 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/member/MemberRemoteService.java

@@ -0,0 +1,31 @@
+package cn.start.tz.module.pressure2.service.member;
+
+import cn.start.tz.module.pressure2.service.member.vo.MemberUserCreateReqVO;
+import cn.start.tz.module.pressure2.service.member.vo.MemberUserRespVO;
+
+/**
+ * 平台用户远程服务接口
+ * <p>
+ * 提供平台用户的远程调用服务,包括用户创建和查询功能
+ *
+ * @author 系统管理员
+ */
+public interface MemberRemoteService {
+
+    /**
+     * 创建平台用户
+     *
+     * @param reqVO 平台用户创建请求对象,包含用户基本信息
+     * @return 创建成功的平台用户响应对象,包含用户ID和详细信息
+     */
+    MemberUserRespVO createUser(MemberUserCreateReqVO reqVO);
+
+    /**
+     * 根据手机号查询平台用户
+     *
+     * @param mobile 手机号码,用于唯一标识用户
+     * @return 平台用户响应对象,如果用户不存在则返回null
+     */
+    MemberUserRespVO getUserByMobile(String mobile);
+
+}

+ 134 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/member/MemberRemoteServiceImpl.java

@@ -0,0 +1,134 @@
+package cn.start.tz.module.pressure2.service.member;
+
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.crypto.digest.DigestUtil;
+import cn.start.tz.framework.common.pojo.CommonResult;
+import cn.start.tz.framework.common.util.json.JsonUtils;
+import cn.start.tz.module.pressure2.service.member.vo.MemberUserCreateReqVO;
+import cn.start.tz.module.pressure2.service.member.vo.MemberUserRespVO;
+import com.fasterxml.jackson.core.type.TypeReference;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.http.*;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import jakarta.annotation.Resource;
+import java.time.Duration;
+
+@Slf4j
+@Service
+public class MemberRemoteServiceImpl implements MemberRemoteService {
+
+    /**
+     * nonce Redis Key 模板: member_remote_nonce:{appId}:{nonce}
+     */
+    private static final String NONCE_KEY_FORMAT = "member_remote_nonce:%s:%s";
+
+    private static final TypeReference<CommonResult<MemberUserRespVO>> USER_RESULT_TYPE =
+            new TypeReference<CommonResult<MemberUserRespVO>>() {};
+
+    @Resource
+    private RestTemplate restTemplate;
+
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Value("${app-auth.base-url:http://localhost:48080}")
+    private String baseUrl;
+
+    @Value("${app-auth.app-id:xxxxxx}")
+    private String appId;
+
+    @Value("${app-auth.app-secret:yyyyyy}")
+    private String appSecret;
+
+    @Override
+    public MemberUserRespVO createUser(MemberUserCreateReqVO reqVO) {
+        long timestamp = System.currentTimeMillis();
+        String nonce = IdUtil.fastSimpleUUID();
+
+        // 请求体序列化
+        String bodyJson = JsonUtils.toJsonString(reqVO);
+
+        // 签名计算:第1步(查询参数为空)+ 第2步(请求体)+ 第3步(Header排序)+ appSecret
+        String signString = buildSignString("", bodyJson, timestamp, nonce);
+        String sign = DigestUtil.sha256Hex(signString);
+
+        // nonce 存 Redis 防重放
+        String nonceKey = String.format(NONCE_KEY_FORMAT, appId, nonce);
+        stringRedisTemplate.opsForValue().set(nonceKey, "1", Duration.ofSeconds(120));
+
+        HttpHeaders headers = buildSignHeaders(timestamp, nonce, sign);
+        headers.setContentType(MediaType.APPLICATION_JSON);
+
+        HttpEntity<String> entity = new HttpEntity<>(bodyJson, headers);
+
+        String url = baseUrl + "/external-api/member/user/create";
+        ResponseEntity<String> response = restTemplate.exchange(
+                url, HttpMethod.POST, entity, String.class);
+
+        return parseResponse(response);
+    }
+
+    @Override
+    public MemberUserRespVO getUserByMobile(String mobile) {
+        long timestamp = System.currentTimeMillis();
+        String nonce = IdUtil.fastSimpleUUID();
+
+        // 查询参数按 key 字典序拼接: mobile={mobile}
+        String queryStr = "mobile=" + mobile;
+
+        // 签名计算:第1步(查询参数)+ 第2步(空)+ 第3步(Header排序)+ appSecret
+        String signString = buildSignString(queryStr, "", timestamp, nonce);
+        String sign = DigestUtil.sha256Hex(signString);
+
+        // nonce 存 Redis 防重放
+        String nonceKey = String.format(NONCE_KEY_FORMAT, appId, nonce);
+        stringRedisTemplate.opsForValue().set(nonceKey, "1", Duration.ofSeconds(120));
+
+        HttpHeaders headers = buildSignHeaders(timestamp, nonce, sign);
+        HttpEntity<Void> entity = new HttpEntity<>(headers);
+
+        String url = baseUrl + "/external-api/member/user/getByMobile?mobile=" + mobile;
+        ResponseEntity<String> response = restTemplate.exchange(
+                url, HttpMethod.GET, entity, String.class);
+
+        return parseResponse(response);
+    }
+
+    private String buildSignString(String queryParams, String requestBody, long timestamp, String nonce) {
+        // 第1步 + 第2步 + 第3步(Header按key字典序: appId < nonce < timestamp) + appSecret
+        return queryParams
+                + requestBody
+                + "appId=" + appId + "&nonce=" + nonce + "&timestamp=" + timestamp
+                + appSecret;
+    }
+
+    private HttpHeaders buildSignHeaders(long timestamp, String nonce, String sign) {
+        HttpHeaders headers = new HttpHeaders();
+        headers.set("appId", appId);
+        headers.set("timestamp", String.valueOf(timestamp));
+        headers.set("nonce", nonce);
+        headers.set("sign", sign);
+        return headers;
+    }
+
+    private MemberUserRespVO parseResponse(ResponseEntity<String> response) {
+        if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
+            CommonResult<MemberUserRespVO> result = JsonUtils.parseObject(
+                    response.getBody(), USER_RESULT_TYPE);
+            if (result != null && result.isSuccess()) {
+                return result.getData();
+            }
+            log.warn("[parseResponse][接口返回失败: code={}, msg={}]",
+                    result != null ? result.getCode() : null,
+                    result != null ? result.getMsg() : null);
+            return null;
+        }
+        log.warn("[parseResponse][HTTP状态异常: {}]", response.getStatusCode());
+        return null;
+    }
+
+}

+ 17 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/member/vo/MemberUserCreateReqVO.java

@@ -0,0 +1,17 @@
+package cn.start.tz.module.pressure2.service.member.vo;
+
+import lombok.Data;
+
+@Data
+public class MemberUserCreateReqVO {
+
+    private String mobile;
+    private String nickname;
+    private String name;
+    private String avatar;
+    private Integer sex;
+    private String kszxOpenid;
+    private String registerIp;
+    private Integer registerTerminal;
+
+}

+ 20 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/member/vo/MemberUserRespVO.java

@@ -0,0 +1,20 @@
+package cn.start.tz.module.pressure2.service.member.vo;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import lombok.Data;
+
+@Data
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class MemberUserRespVO {
+
+    private String id;
+    private String mobile;
+    private String nickname;
+    private String name;
+    private String avatar;
+    private Integer sex;
+    private Integer status;
+    private String kszxOpenid;
+    private String createTime;
+
+}

+ 14 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/membermessage/MemberMessageRemoteService.java

@@ -0,0 +1,14 @@
+package cn.start.tz.module.pressure2.service.membermessage;
+
+import cn.start.tz.module.pressure2.service.membermessage.vo.SendMpMessageReqVO;
+
+public interface MemberMessageRemoteService {
+
+    /**
+     * 推送微信公众号模版消息
+     *
+     * @return 推送结果: 0=成功, 1=用户拒绝接收, 3=推送失败
+     */
+    Integer sendMpMessage(SendMpMessageReqVO reqVO);
+
+}

+ 92 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/membermessage/MemberMessageRemoteServiceImpl.java

@@ -0,0 +1,92 @@
+package cn.start.tz.module.pressure2.service.membermessage;
+
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.crypto.digest.DigestUtil;
+import cn.start.tz.framework.common.pojo.CommonResult;
+import cn.start.tz.framework.common.util.json.JsonUtils;
+import cn.start.tz.module.pressure2.service.membermessage.vo.SendMpMessageReqVO;
+import com.fasterxml.jackson.core.type.TypeReference;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.http.*;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import jakarta.annotation.Resource;
+import java.time.Duration;
+
+@Slf4j
+@Service
+public class MemberMessageRemoteServiceImpl implements MemberMessageRemoteService {
+
+    private static final String NONCE_KEY_FORMAT = "member_message_nonce:%s:%s";
+
+    private static final TypeReference<CommonResult<Integer>> RESULT_TYPE =
+            new TypeReference<CommonResult<Integer>>() {};
+
+    @Resource
+    private RestTemplate restTemplate;
+
+    @Resource
+    private StringRedisTemplate stringRedisTemplate;
+
+    @Value("${app-auth.base-url:http://localhost:48080}")
+    private String baseUrl;
+
+    @Value("${app-auth.app-id:xxxxxx}")
+    private String appId;
+
+    @Value("${app-auth.app-secret:yyyyyy}")
+    private String appSecret;
+
+    @Override
+    public Integer sendMpMessage(SendMpMessageReqVO reqVO) {
+        long timestamp = System.currentTimeMillis();
+        String nonce = IdUtil.fastSimpleUUID();
+
+        // 请求体序列化
+        String bodyJson = JsonUtils.toJsonString(reqVO);
+
+        // 签名:第1步(查询参数空) + 第2步(请求体) + 第3步(Header按key字典序) + appSecret
+        String signString = bodyJson
+                + "appId=" + appId + "&nonce=" + nonce + "&timestamp=" + timestamp
+                + appSecret;
+        String sign = DigestUtil.sha256Hex(signString);
+
+        // nonce 存 Redis 防重放
+        String nonceKey = String.format(NONCE_KEY_FORMAT, appId, nonce);
+        stringRedisTemplate.opsForValue().set(nonceKey, "1", Duration.ofSeconds(120));
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        headers.set("appId", appId);
+        headers.set("timestamp", String.valueOf(timestamp));
+        headers.set("nonce", nonce);
+        headers.set("sign", sign);
+
+        HttpEntity<String> entity = new HttpEntity<>(bodyJson, headers);
+
+        String url = baseUrl + "/external-api/member/message/send-mp-message";
+        ResponseEntity<String> response = restTemplate.exchange(
+                url, HttpMethod.POST, entity, String.class);
+
+        if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
+            CommonResult<Integer> result = JsonUtils.parseObject(
+                    response.getBody(), RESULT_TYPE);
+            if (result != null && result.isSuccess()) {
+                log.info("[sendMpMessage][推送完成, memberId={}, templateId={}, result={}]",
+                        reqVO.getMemberId(), reqVO.getTemplateId(), result.getData());
+                return result.getData();
+            }
+            log.warn("[sendMpMessage][接口返回失败: code={}, msg={}]",
+                    result != null ? result.getCode() : null,
+                    result != null ? result.getMsg() : null);
+            return 3;
+        }
+
+        log.warn("[sendMpMessage][HTTP状态异常: {}]", response.getStatusCode());
+        return 3;
+    }
+
+}

+ 39 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/membermessage/vo/SendMpMessageReqVO.java

@@ -0,0 +1,39 @@
+package cn.start.tz.module.pressure2.service.membermessage.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+@Data
+public class SendMpMessageReqVO {
+
+    private String memberId;
+    private String templateId;
+    private List<TemplateData> templateDataList;
+    private MiniProgram miniProgram;
+    private String businessId;
+    private Integer businessType;
+
+    @Data
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class TemplateData {
+
+        private String name;
+        private String value;
+        private String color;
+
+    }
+
+    @Data
+    public static class MiniProgram {
+
+        private String appid;
+        private String pagePath;
+        private Boolean usePath;
+
+    }
+
+}