需求:当有需要审批的业务时,给审批负责人发送短信提醒。
实现方式:定时任务
首先要确定发送短信的内容,给谁发送什么内容的短信。
@PostConstruct
@Scheduled(cron = "0 0 9 * * ?")
public void sendForToBeAudited() {
log.info("发送提醒审核短信定时任务开始");
if (Constants.SWITCH_ON.equals(timerService.getSwitchValue(TimerEnum.SEND_FOR_TO_BE_AUDITED.getTimerCode()))) {
LocalDate today = LocalDate.now();
LocalDate auditDate = today.minusDays(Long.parseLong(timerService.getSwitchValue("audit_time")));
//查询待审核的工单
List<ZyToBeAuditedDto> list = zyMessageSendRecordMapper.selectToBeAudited(auditDate);
//数据整合
List<ZyToBeAuditedDto> resultList = getZyToBeAuditedDtos(list);
for (ZyToBeAuditedDto zyToBeAuditedDto : resultList) {
//每个对象就是一条短信内容
checkIsSend(today, zyToBeAuditedDto);
}
} else {
log.info("发送短信开关为关,无法发送短信");
}
}
要建立一张表用来记录短信的发送记录,字段包括但不限于日期,接收人,短信内容,短信模板id等(每条短信对应有相应的模板)
发送短信前要判断是否发送短信
/**
* 校验是否需要发送短信
*
* @param today
* @param zyToBeAuditedDto
*/
private void checkIsSend(LocalDate today, ZyToBeAuditedDto zyToBeAuditedDto) {
//查询人员信息
ZyMonthPlanSms zyMonthPlanSms = zyMessageSendRecordMapper.selectUserInfo(zyToBeAuditedDto.getCreateUserName());
if (ObjectUtils.isEmpty(zyMonthPlanSms)) {
log.error("审核人不存在:" + zyToBeAuditedDto.getCreateUserName());
} else {
ZyMessageSendRecord zyMessageSend = zyMessageSendRecordMapper.selectOne(new LambdaQueryWrapper<ZyMessageSendRecord>().eq(ZyMessageSendRecord::getUserName, zyMonthPlanSms.getUserName()).eq(ZyMessageSendRecord::getDate, today).eq(ZyMessageSendRecord::getSmsTemplateId, toBeAuditedAlertsTemplateId));
if (ObjectUtils.isEmpty(zyMessageSend)) {
StringBuilder monthPlanName = new StringBuilder();
for (int i = 0; i <= zyToBeAuditedDto.getBizNameList().size() - 1; i++) {
if (i != zyToBeAuditedDto.getBizNameList().size() - 1) {
monthPlanName.append(zyToBeAuditedDto.getBizNameList().get(i)).append("、");
} else {
monthPlanName.append(zyToBeAuditedDto.getBizNameList().get(i));
}
}
String monthPlanNames = monthPlanName.toString();
if (monthPlanNames.length() > Integer.parseInt(timerService.getSwitchValue("message_length_limit"))) {
monthPlanNames = monthPlanNames.substring(0, Integer.parseInt(timerService.getSwitchValue("message_length_show"))-1) + "...等";
}
zyMonthPlanSms.setMonthPlanName(monthPlanNames);
//发送短信
sendAudit(zyMonthPlanSms);
ZyMessageSendRecord zyMessageSendRecord = new ZyMessageSendRecord();
zyMessageSendRecord.setDate(today);
zyMessageSendRecord.setSmsContent(zyMonthPlanSms.getUserRealName() + "你好,您有" + zyMonthPlanSms.getMonthPlanName() + "作业计划需要您尽快进行审批,请尽快登陆智能运维机器人平台审批确认。");
zyMessageSendRecord.setSmsTemplateId(toBeAuditedAlertsTemplateId);
zyMessageSendRecord.setUserName(zyMonthPlanSms.getUserName());
zyMessageSendRecord.setUserRealName(zyMonthPlanSms.getUserRealName());
zyMessageSendRecordService.save(zyMessageSendRecord);
}
}
}
接下来是发送短信的通用方法:
//有些信息是固定的
@Value("${sms.url}")
private String url;
@Value("${sms.appId}")
private String appId;
@Value("${sms.appKey}")
private String appKey;
@Value("${sms.province}")
private String province;
@Value("${sms.toBeAuditedAlerts.templateId}")
private String toBeAuditedAlertsTemplateId;
//发送短信方法
private void sendAudit(ZyMonthPlanSms zyMonthPlanSms) {
SmsDto smsDto = new SmsDto();
smsDto.setPhone(zyMonthPlanSms.getPhone());
smsDto.setTemplateId(toBeAuditedAlertsTemplateId);
Map<String, Object> templateMap = new HashMap<>();
templateMap.put("name", zyMonthPlanSms.getUserRealName());
templateMap.put("plans", zyMonthPlanSms.getMonthPlanName());
initSms(smsDto, templateMap);
String json = JSON.toJSONString(smsDto);
log.info("调用发送短信服务入参为:{}", json);
OkHttpUtils.post(url, json, Constants.CODE_FORMAT, new SmsCallback());
}
//内部方法
private void initSms(SmsDto smsDto, Map<String, Object> templateMap) {
smsDto.setAppId(appId);
smsDto.setProvince(province);
String salt = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
smsDto.setSalt(salt);
smsDto.setSign(sign(appKey, salt));
Map<String, Object> textMap = new HashMap<>();
textMap.put("templateId", smsDto.getTemplateId());
//通过脱敏算法进行信息遮盖
templateMap.put("mobile", DataSensitiveUtil.maskData(smsDto.getPhone(), 3, 4));
textMap.put("templateParam", templateMap);
smsDto.setText(textMap);
}
//这个没看懂,就直接照抄了
private String sign(String appKey, String salt) {
try {
String str = salt + "\n" + appKey;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(appKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] signData = mac.doFinal(str.getBytes(StandardCharsets.UTF_8));
return URLEncoder.encode(Base64.getEncoder().encodeToString(signData), Constants.CODE_FORMAT);
} catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
log.error(e.getMessage());
return e.getMessage();
} catch (InvalidKeyException e2) {
log.error(e2.getMessage());
return e2.getMessage();
}
}
//短信发送结果
public static class SmsCallback implements Callback {
@Override
public void onFailure(Call call, IOException e) {
log.error("短信接口回调失败", e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
ResponseBody responseBody = response.body();
String resp = responseBody == null ? "" : responseBody.string();
log.info("短信接口回调成功:{}", resp);
}
}
实体类信息:
public class SmsDto{
private String phone;
private String account;
private String province;
private Map<String,Object> text;
private String templateId;
private String appId;
private String salt;
private String sign;
}
希望能帮到你...