linwe
2024-09-03 764d883b5ea3bdc06abbec548b6df0511e567978
src/main/java/org/springblade/modules/sms/service/impl/SmsSendServiceImpl.java
@@ -16,30 +16,47 @@
 */
package org.springblade.modules.sms.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.common.config.SmsConfig;
import org.springblade.common.utils.HttpClientUtils;
import org.springblade.common.utils.SpringUtils;
import org.springblade.common.utils.UtilRandom;
import org.springblade.common.utils.sms.AlipaySignature;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.modules.resource.entity.Sms;
import org.springblade.modules.resource.service.ISmsService;
import org.springblade.modules.sms.entity.SmsRecordEntity;
import org.springblade.modules.sms.entity.SmsTemplateEntity;
import org.springblade.modules.sms.mapper.SmsTemplateMapper;
import org.springblade.modules.sms.service.ISmsRecordService;
import org.springblade.modules.sms.service.ISmsSendService;
import org.springblade.modules.sms.service.ISmsTemplateService;
import org.springblade.modules.smsTask.entity.SmsTaskEntity;
import org.springblade.modules.smsTask.service.ISmsTaskService;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springblade.modules.system.vo.UserVO;
import org.springblade.modules.task.entity.TaskPlaceSelfCheckEntity;
import org.springblade.modules.task.entity.TaskResidencePermitApplyEntity;
import org.springblade.modules.task.service.ITaskPlaceSelfCheckService;
import org.springblade.modules.task.service.ITaskResidencePermitApplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * 短信模版表 服务实现类
@@ -50,78 +67,417 @@
@Service
public class SmsSendServiceImpl extends ServiceImpl<SmsTemplateMapper, SmsTemplateEntity> implements ISmsSendService {
   @Autowired
   private  BladeRedis redisTemplate;
   private BladeRedis redisTemplate;
   private static Logger logger = LoggerFactory.getLogger(SmsSendServiceImpl.class);
   // 确保这些字符串被适当地定义和管理
   public static final String SMS_VALIDATE_PHONE = "sms:validate:code:";
   public static final String SMS_VALIDATE_PHONE_NUM = "sms:validate:phone:";
   private static final String SMS_SEND_FAILED = "短信发送失败!";
   private static final String MESSAGE_SOP_EQUALS_MES_RESPONSE_CODE = "message_sop_equalsMes_response";
   private static final DateTimeFormatter SECOND_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//   @Autowired
//   private SmsConfig smsConfig;
   @Autowired
   private ISmsService iSmsService;
   @Override
   public Boolean smsSend(String phone) {
   @Autowired
   private ISmsTemplateService iSmsTemplateService;
      Sms serviceOne = iSmsService.getOne(Wrappers.<Sms>lambdaQuery().eq(Sms::getSmsCode, "106575361457"));
   @Override
   public Boolean sendVerificationCode(String phone) {
      if (phone == null || phone.length() != 11) {
         logger.error("手机号格式错误");
         return false;
      }
      if (redisTemplate.exists(SMS_VALIDATE_PHONE_NUM + phone)) {
         logger.error("同一个手机号一分钟内只能发送一条记录");
         return false;
      }
      Sms serviceOne = iSmsService.getOne(Wrappers.<Sms>lambdaQuery().eq(Sms::getStatus, 2));
      if (serviceOne == null) {
         logger.error("未找到状态为2的Sms服务");
         return false;
      }
      SmsTemplateEntity smsTemplateEntity = iSmsTemplateService.getOne(Wrappers.<SmsTemplateEntity>lambdaQuery()
         .eq(SmsTemplateEntity::getId, serviceOne.getTemplateId()));
      if (smsTemplateEntity == null) {
         logger.error("未找到对应的短信模板");
         return false;
      }
      //发送的手机号
      List<Map> phonesList = new ArrayList<>();
      Map phoneMap = new HashMap();
      phoneMap.put("phone", phone);
      List<String> varList = new ArrayList<>();
      Integer code = UtilRandom.randomCount(111111, 999999);
      varList.add(code.toString());
      phoneMap.put("varList", varList);
      phonesList.add(phoneMap);
      //短信主题
      String subject = "对外接口不同内容发送-动态模板";
      //短信内容
      String content = "您正在验证投票操作,验证码:#P_1#。如非本人操作,则密码可能已泄露,建议立即修改密码或联系客服。";
//        String content = "尊敬的#P_1#,你得工资#P_2#,测试#P_3#";
      //短信模板
      String template_id = null;
      String content = smsTemplateEntity.getContent();
      //发送时间
      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      String send_time = df.format(new Date());
      //优先级,高级=5,中级=3,低级=1
      String priority = "1";
      //不同内容发送类型,1=动态模板发送,2=文件内容发送
      String type = "1";
      LocalDateTime nowDateTime = LocalDateTime.now();
      String send_time = nowDateTime.format(SECOND_FORMATTER);
      Map params = new HashMap();
      params.put("phones", phonesList);
      params.put("subject", subject);
      //短信主题
      params.put("subject", "对外接口不同内容发送-动态模板");
      params.put("content", content);
      params.put("template_id", template_id);
      //短信模板
      params.put("template_id", null);
      // 发送时间
      params.put("send_time", send_time);
      params.put("priority", priority);
      params.put("type", type);
      //优先级,高级=5,中级=3,低级=1
      params.put("priority", "1");
      //不同内容发送类型,1=动态模板发送,2=文件内容发送
      params.put("type", "1");
      //创建人主键
      params.put("sop_create_by", serviceOne.getSmsCode());
      String s = null;
      //短信发送记录
      saveSmsRecord(phone, serviceOne, code.toString(), content);
      Boolean aBoolean = sendSmsGet(serviceOne, params);
      if (aBoolean) {
         // 将验证码存入redis,其中phone为手机号,code为验证码
         // SMS_VALIDATE_PHONE 为前缀,通过phone和code在redis中设置一个过期的键值对
         redisTemplate.setEx(SMS_VALIDATE_PHONE + phone, code, 300L);
         // 同时,为了记录该手机短时间内已接收的验证码次数,使用另一个键值对进行计数
         // SMS_VALIDATE_PHONE_NUM 为计数器的前缀,过期时间为60秒
         redisTemplate.setEx(SMS_VALIDATE_PHONE_NUM + phone, 1, 60L);
      }
      return aBoolean;
   }
   /**
    * @param templateId
    * @param residenceId
    * @return
    */
   @Override
   public Boolean sendNotice(Long templateId, Long residenceId) {
      Sms serviceOne = iSmsService.getOne(Wrappers.<Sms>lambdaQuery().eq(Sms::getStatus, 2));
      if (serviceOne == null) {
         logger.error("未找到状态为2的Sms服务");
         return false;
      }
      SmsTemplateEntity smsTemplateEntity = iSmsTemplateService.getOne(Wrappers.<SmsTemplateEntity>lambdaQuery()
         .eq(SmsTemplateEntity::getId, templateId));
      if (smsTemplateEntity == null) {
         logger.error("未找到对应的短信模板");
         return false;
      }
      ITaskResidencePermitApplyService bean = SpringUtils.getBean(ITaskResidencePermitApplyService.class);
      TaskResidencePermitApplyEntity residencePermitApplyEntity = bean.getById(residenceId);
      String phone = residencePermitApplyEntity.getPhone();
      //发送的手机号
      List<Map> phonesList = new ArrayList<>();
      Map phoneMap = new HashMap();
      phoneMap.put("phone", phone);
      List<String> varList = new ArrayList<>();
      // 设置参数
      varList.add(residencePermitApplyEntity.getName());
      phoneMap.put("varList", varList);
      phonesList.add(phoneMap);
      //短信内容
      String content = smsTemplateEntity.getContent();
      //发送时间
      LocalDateTime nowDateTime = LocalDateTime.now();
      String send_time = nowDateTime.format(SECOND_FORMATTER);
      Map params = new HashMap();
      params.put("phones", phonesList);
      //短信主题
      params.put("subject", "对外接口不同内容发送-动态模板");
      params.put("content", content);
      //短信模板
      params.put("template_id", null);
      // 发送时间
      params.put("send_time", send_time);
      //优先级,高级=5,中级=3,低级=1
      params.put("priority", "1");
      //不同内容发送类型,1=动态模板发送,2=文件内容发送
      params.put("type", "1");
      //创建人主键
      params.put("sop_create_by", serviceOne.getSmsCode());
      //短信发送记录
      saveSmsRecord(phone, serviceOne, residencePermitApplyEntity.getName(), content);
      Boolean aBoolean = sendSmsGet(serviceOne, params);
      return aBoolean;
   }
   /**
    * @param templateId
    * @param placeSelfCheckId
    * @return
    */
   @Override
   public Boolean sendRectificationNotice(Long templateId, Long placeSelfCheckId) {
      Sms serviceOne = iSmsService.getOne(Wrappers.<Sms>lambdaQuery().eq(Sms::getStatus, 2));
      if (serviceOne == null) {
         logger.error("未找到状态为2的Sms服务");
         return false;
      }
      SmsTemplateEntity smsTemplateEntity = iSmsTemplateService.getOne(Wrappers.<SmsTemplateEntity>lambdaQuery()
         .eq(SmsTemplateEntity::getId, templateId));
      if (smsTemplateEntity == null) {
         logger.error("未找到对应的短信模板");
         return false;
      }
      ITaskPlaceSelfCheckService bean = SpringUtils.getBean(ITaskPlaceSelfCheckService.class);
      TaskPlaceSelfCheckEntity placeSelfCheckEntity = bean.getById(placeSelfCheckId);
      IUserService userService = SpringUtils.getBean(IUserService.class);
      UserVO userVO = userService.getuserById(placeSelfCheckEntity.getId());
      String phone = userVO.getPhone();
      //发送的手机号
      List<Map> phonesList = new ArrayList<>();
      Map phoneMap = new HashMap();
      phoneMap.put("phone", phone);
      List<String> varList = new ArrayList<>();
      // 设置参数
      varList.add(userVO.getName());
      varList.add(placeSelfCheckEntity.getPlaceName());
      phoneMap.put("varList", varList);
      phonesList.add(phoneMap);
      //短信内容
      String content = smsTemplateEntity.getContent();
      //发送时间
      LocalDateTime nowDateTime = LocalDateTime.now();
      String send_time = nowDateTime.format(SECOND_FORMATTER);
      Map params = new HashMap();
      params.put("phones", phonesList);
      //短信主题
      params.put("subject", "对外接口不同内容发送-动态模板");
      params.put("content", content);
      //短信模板
      params.put("template_id", null);
      // 发送时间
      params.put("send_time", send_time);
      //优先级,高级=5,中级=3,低级=1
      params.put("priority", "1");
      //不同内容发送类型,1=动态模板发送,2=文件内容发送
      params.put("type", "1");
      //创建人主键
      params.put("sop_create_by", serviceOne.getSmsCode());
      //短信发送记录
      saveSmsRecord(phone, serviceOne, placeSelfCheckEntity.getPlaceName(), content);
      Boolean aBoolean = sendSmsGet(serviceOne, params);
      return aBoolean;
   }
   @Override
   public Boolean loginSendVerificationCode(String phone) {
      if (phone == null || phone.length() != 11) {
         logger.error("手机号格式错误");
         return false;
      }
      if (redisTemplate.exists(SMS_VALIDATE_PHONE_NUM + phone)) {
         logger.error("同一个手机号一分钟内只能发送一条记录");
         return false;
      }
      Sms serviceOne = iSmsService.getOne(Wrappers.<Sms>lambdaQuery().eq(Sms::getStatus, 2));
      if (serviceOne == null) {
         logger.error("未找到状态为2的Sms服务");
         return false;
      }
      SmsTemplateEntity smsTemplateEntity = iSmsTemplateService.getOne(Wrappers.<SmsTemplateEntity>lambdaQuery()
         .eq(SmsTemplateEntity::getId, "1783764287897939969"));
      if (smsTemplateEntity == null) {
         logger.error("未找到对应的短信模板");
         return false;
      }
      //发送的手机号
      List<Map> phonesList = new ArrayList<>();
      Map phoneMap = new HashMap();
      phoneMap.put("phone", phone);
      List<String> varList = new ArrayList<>();
      Integer code = UtilRandom.randomCount(111111, 999999);
      varList.add(code.toString());
      phoneMap.put("varList", varList);
      phonesList.add(phoneMap);
      //短信内容
      String content = smsTemplateEntity.getContent();
      //发送时间
      LocalDateTime nowDateTime = LocalDateTime.now();
      String send_time = nowDateTime.format(SECOND_FORMATTER);
      Map params = new HashMap();
      params.put("phones", phonesList);
      //短信主题
      params.put("subject", "对外接口不同内容发送-动态模板");
      params.put("content", content);
      //短信模板
      params.put("template_id", null);
      // 发送时间
      params.put("send_time", send_time);
      //优先级,高级=5,中级=3,低级=1
      params.put("priority", "1");
      //不同内容发送类型,1=动态模板发送,2=文件内容发送
      params.put("type", "1");
      //创建人主键
      params.put("sop_create_by", serviceOne.getSmsCode());
      //短信发送记录
      saveSmsRecord(phone, serviceOne, code.toString(), content);
      Boolean aBoolean = sendSmsGet(serviceOne, params);
      if (aBoolean) {
         // 将验证码存入redis,其中phone为手机号,code为验证码
         // SMS_VALIDATE_PHONE 为前缀,通过phone和code在redis中设置一个过期的键值对
         redisTemplate.setEx(SMS_VALIDATE_PHONE + phone, code, 300L);
         // 同时,为了记录该手机短时间内已接收的验证码次数,使用另一个键值对进行计数
         // SMS_VALIDATE_PHONE_NUM 为计数器的前缀,过期时间为60秒
         redisTemplate.setEx(SMS_VALIDATE_PHONE_NUM + phone, 1, 60L);
      }
      return aBoolean;
   }
   @Override
   public String checkCode(String phone, String code) {
      if (StringUtils.isNotBlank(phone)) {
         if (StringUtils.isBlank(code)) {
            return "验证码不能为空!";
         }
         Object validateCode = redisTemplate.get(SMS_VALIDATE_PHONE + phone);
         if (validateCode == null) {
            return "验证码不存在或已过期";
         }
         if (!validateCode.toString().equals(code)) {
            return "验证码错误";
         }
         //删除验证码
         redisTemplate.del(SMS_VALIDATE_PHONE + phone);
      }
      return "";
   }
   @Override
   public Boolean batchSendNotice(Long smsTaskId) {
      ISmsTaskService taskService = SpringUtils.getBean(ISmsTaskService.class);
      SmsTaskEntity smsTaskEntity = taskService.getById(smsTaskId);
      List<User> phoneList = taskService.selectSmsTaskListByPhone(smsTaskEntity);
      if (CollectionUtil.isEmpty(phoneList)) {
         logger.error("未查询到电话号码!");
         return false;
      }
      Sms serviceOne = iSmsService.getOne(Wrappers.<Sms>lambdaQuery().eq(Sms::getStatus, 2));
      if (serviceOne == null) {
         logger.error("未找到状态为2的Sms服务");
         return false;
      }
      SmsTemplateEntity smsTemplateEntity = iSmsTemplateService.getOne(Wrappers.<SmsTemplateEntity>lambdaQuery()
         .eq(SmsTemplateEntity::getId, smsTaskEntity.getSmsTemplate()));
      if (smsTemplateEntity == null) {
         logger.error("未找到对应的短信模板");
         return false;
      }
      ISmsRecordService smsRecordService = SpringUtils.getBean(ISmsRecordService.class);
      Boolean aBoolean = false;
      for (User user : phoneList) {
         // 发送的手机号
         List<Map> phonesList = new ArrayList<>();
         Map phoneMap = new HashMap();
         phoneMap.put("phone", user.getPhone());
         List<String> varList = new ArrayList<>();
         // 设置参数
         phoneMap.put("varList", varList);
         phonesList.add(phoneMap);
         // 短信内容
         String content = smsTemplateEntity.getContent();
         // 发送时间
         LocalDateTime nowDateTime = LocalDateTime.now();
         String send_time = nowDateTime.format(SECOND_FORMATTER);
         Map params = new HashMap();
         params.put("phones", phonesList);
         // 短信主题
         params.put("subject", "对外接口不同内容发送-动态模板");
         params.put("content", content);
         // 短信模板
         params.put("template_id", null);
         // 发送时间
         params.put("send_time", send_time);
         // 优先级,高级=5,中级=3,低级=1
         params.put("priority", "1");
         // 不同内容发送类型,1=动态模板发送,2=文件内容发送
         params.put("type", "1");
         // 创建人主键
         params.put("sop_create_by", serviceOne.getSmsCode());
         // 短信发送记录
         SmsRecordEntity smsRecordEntity = saveSmsRecord(user.getPhone(), serviceOne, user.getName(), content);
         aBoolean = false; //sendSmsGet(serviceOne, params);
         if (aBoolean){
            smsRecordEntity.setStatus(2);
            smsRecordService.updateById(smsRecordEntity);
         }
      }
      return aBoolean;
   }
   /**
    * 发送短信并获取发送结果。
    *
    * @param serviceOne 用于发送短信的服务对象
    * @param params     发送短信所需的参数映射
    * @return 如果短信发送成功,则返回true;否则返回false。
    */
   @NotNull
   private Boolean sendSmsGet(Sms serviceOne, Map params) {
      try {
         s = testGet(params, "message.sop.differentMes",serviceOne);
         JSONObject jsonObject = JSON.parseObject(s);
         JSONObject messageSopEqualsMesResponse = (JSONObject) jsonObject.get("message_sop_equalsMes_response");
         // 尝试发送短信并解析响应结果
         String result = sendSms(params, "message.sop.differentMes", serviceOne);
         JSONObject jsonObject = JSON.parseObject(result);
         JSONObject messageSopEqualsMesResponse = (JSONObject) jsonObject.get(MESSAGE_SOP_EQUALS_MES_RESPONSE_CODE);
         if (messageSopEqualsMesResponse.get("code").equals(200)) {
            // 将验证码存入redis
            redisTemplate.setEx(SMS_VALIDATE_PHONE + phone, code, 300L);
            redisTemplate.setEx(SMS_VALIDATE_PHONE_NUM + phone, 1, 60L);
            // 如果响应代码为200,表示短信发送成功
            return true;
         } else {
            // 记录短信发送失败的日志
            logger.error("短信发送失败!");
         }
      } catch (Exception e) {
         logger.error("短信发送失败!", e);
         // 记录发送短信过程中出现的异常
         logger.error(SMS_SEND_FAILED, e);
         throw new RuntimeException(e);
      }
      // 如果执行到这里,表示短信发送失败或出现异常
      return false;
   }
   public String testGet(Object bizContent, String method,Sms serviceOne) throws Exception {
   /**
    * 保存短信发送记录
    *
    * @param phone      接收短信的手机号码
    * @param serviceOne 发送短信所使用的服务
    * @param code       短信中的验证码
    * @param content    短信内容,其中可能包含占位符"#P_1#"用于被验证码替换
    */
   private static SmsRecordEntity saveSmsRecord(String phone, Sms serviceOne, String code, String content) {
      // 通过Spring工具类获取短信记录服务的实例
      ISmsRecordService smsRecordService = SpringUtils.getBean(ISmsRecordService.class);
      // 创建一个新的短信记录实体
      SmsRecordEntity smsRecordEntity = new SmsRecordEntity();
      // 设置短信内容,将占位符"#P_1#"替换为验证码
      smsRecordEntity.setContent(content.replace("#P_1#", code));
      // 设置手机号码
      smsRecordEntity.setPhone(phone);
      // 设置短信模板ID
      smsRecordEntity.setTemplateId(Long.valueOf(serviceOne.getTemplateId()));
      // 设置创建用户ID,来自认证工具类
      smsRecordEntity.setCreateUser(AuthUtil.getUserId());
      // 保存短信记录实体
      smsRecordService.save(smsRecordEntity);
      return smsRecordEntity;
   }
   public String sendSms(Object bizContent, String method, Sms serviceOne) throws Exception {
      // 公共请求参数
      Map<String, String> params = new HashMap<String, String>();
@@ -138,17 +494,9 @@
      String content = AlipaySignature.getSignContent(params);
      String sign = AlipaySignature.rsa256Sign(content, serviceOne.getSecretKey(), "utf-8");
      params.put("sign", sign);
      System.out.println("----------- 请求信息 -----------");
      System.out.println("请求参数:" + buildParamQuery(params));
      System.out.println("商户秘钥:" + serviceOne.getSecretKey());
      System.out.println("待签名内容:" + content);
      System.out.println("签名(sign):" + sign);
      System.out.println("URL参数:" + buildUrlQuery(params));
      System.out.println("----------- 返回结果 -----------");
      logger.info("短信请求参数:" + buildParamQuery(params));
      String responseData = HttpClientUtils.doGet(serviceOne.getRemark(), params);// 发送请求
      System.out.println("返回数据" + responseData);
      logger.info("短信响应结果:" + responseData);
      return responseData;
   }