From 764d883b5ea3bdc06abbec548b6df0511e567978 Mon Sep 17 00:00:00 2001
From: linwe <872216996@qq.com>
Date: Tue, 03 Sep 2024 09:46:05 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/binlog' into binlog

---
 src/main/java/org/springblade/modules/sms/service/impl/SmsSendServiceImpl.java |  411 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 372 insertions(+), 39 deletions(-)

diff --git a/src/main/java/org/springblade/modules/sms/service/impl/SmsSendServiceImpl.java b/src/main/java/org/springblade/modules/sms/service/impl/SmsSendServiceImpl.java
index 4c49e02..ea44fe0 100644
--- a/src/main/java/org/springblade/modules/sms/service/impl/SmsSendServiceImpl.java
+++ b/src/main/java/org/springblade/modules/sms/service/impl/SmsSendServiceImpl.java
@@ -16,31 +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;
 
 /**
  * 短信模版表 服务实现类
@@ -58,7 +74,7 @@
 	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 String SEND_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+	private static final DateTimeFormatter SECOND_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
 
 
 	@Autowired
@@ -68,7 +84,16 @@
 	private ISmsTemplateService iSmsTemplateService;
 
 	@Override
-	public Boolean smsSend(String phone) {
+	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) {
@@ -84,59 +109,375 @@
 
 		//发送的手机号
 		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 = smsTemplateEntity.getContent();
-		//短信模板
-		String template_id = null;
 		//发送时间
-		SimpleDateFormat df = new SimpleDateFormat(SEND_TIME_FORMAT);
-		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);
+			// 尝试发送短信并解析响应结果
+			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(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>();
@@ -153,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;
 	}
 

--
Gitblit v1.9.3