你是否经常接到一些垃圾短信,这些短信是否使你厌烦?现在教给大家如何发送垃圾短信。
本文用例是采用了阿里云的短信服务
添加 Maven 依赖:
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.1.0</version>
</dependency>
编写阿里云短信工具类 SMSUtil.java
@Slf4j
@Component
public class SMSUtil {
@Autowired
private SMSPutLogMapper smsPutLogMapper;
private static SMSUtil smsUtil;
/**
* 静态调 Mapper
*/
@PostConstruct
public void init() {
smsUtil = this;
smsUtil.smsPutLogMapper = this.smsPutLogMapper;
}
private static final String accessKeyId = "accessKeyId";
private static final String secret = "secret";
/**
* 短信发送接口
*
* @param dto
* @return 发送回执ID
*/
public static String sendSMS(SMSDto dto) {
CommonRequest request = new CommonRequest();
//request.setProtocol(ProtocolType.HTTPS);
request.setMethod(MethodType.POST);
request.setDomain("dysmsapi.aliyuncs.com");
request.setVersion("2017-05-25");
request.setAction("SendSms");
request.putQueryParameter("PhoneNumbers", dto.getPhoneNumbers());
request.putQueryParameter("SignName", "SignName");
request.putQueryParameter("TemplateCode", dto.getTemplateCode());
if (!Strings.isNullOrEmpty(dto.getTemplateParam())) {
request.putQueryParameter("TemplateParam", dto.getTemplateParam());
}
String resData = baseSMS(request);
int saveRes = saveSMSLog(dto, resData);
String message = JSONObject.parseObject(resData).get("Message").toString();
String code = JSONObject.parseObject(resData).get("Code").toString();
if ("OK".equals(message) && "OK".equals(code)) {
return JSONObject.parseObject(resData).get("BizId").toString();
} else {
return code + message + "saveRes:" + saveRes;
}
}
/**
* 保存发送日志
*
* @param dto
* @param str
* @return
*/
private static int saveSMSLog(SMSDto dto, String str) {
String message = JSONObject.parseObject(str).get("Message").toString();
String code = JSONObject.parseObject(str).get("Code").toString();
String bizId = "error!", requestId = "error!";
if ("OK".equals(message) && "OK".equals(code)) {
bizId = JSONObject.parseObject(str).get("BizId").toString();
requestId = JSONObject.parseObject(str).get("RequestId").toString();
}
SMSPutLog log = new SMSPutLog();
log.setPutTime(LocalDateTime.now())
.setTemplateCode(dto.getTemplateCode())
.setSucNum(dto.getPhoneNumbers().split(",").length)
.setBizId(bizId)
.setRequestId(requestId);
return smsUtil.smsPutLogMapper.insert(log);
}
/**
* 查看短信发送记录和发送状态
*
* @param bizId 发送回执ID
* @param phoneNumber 接收短信的手机号码
* @param sendDate 短信发送日期,支持查询最近30天的记录, 格式为yyyyMMdd,默认当前时间
* @return SmsSendDetailDTOs
*/
public static String querySendDetails(String bizId, String phoneNumber, String sendDate) {
if (Strings.isNullOrEmpty(sendDate)) {
try {
sendDate = DateUtil.dateFormat(null, "yyyyMMdd");
} catch (ParseException e) {
e.printStackTrace();
}
}
CommonRequest request = new CommonRequest();
//request.setProtocol(ProtocolType.HTTPS);
request.setMethod(MethodType.POST);
request.setDomain("dysmsapi.aliyuncs.com");
request.setVersion("2017-05-25");
request.setAction("QuerySendDetails");
request.putQueryParameter("PhoneNumber", phoneNumber);
request.putQueryParameter("SendDate", sendDate);
request.putQueryParameter("PageSize", "10");
request.putQueryParameter("CurrentPage", "1");
request.putQueryParameter("BizId", bizId);
String resData = baseSMS(request);
String message = JSONObject.parseObject(resData).get("Message").toString();
String code = JSONObject.parseObject(resData).get("Code").toString();
if ("OK".equals(message) && "OK".equals(code)) {
return JSONObject.parseObject(resData).get("SmsSendDetailDTOs").toString();
} else {
return code + message;
}
}
private static String baseSMS(CommonRequest request) {
DefaultProfile profile = DefaultProfile.getProfile("default", accessKeyId, secret);
IAcsClient client = new DefaultAcsClient(profile);
try {
CommonResponse response = client.getCommonResponse(request);
log.info(response.getData());
return response.getData();
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
return "{\"Message\":\"ERROR\",\"Code\":\"ERROR\"}";
}
}
服务实现类代码如下:
public String sendSmsTask(SendSMSDto dto) {
try {
if (!Strings.isNullOrEmpty(dto.getPhoneNumbers())) {
String[] strs = dto.getPhoneNumbers().split(",");
// 填会员ID
if (strs[0].length() < 11) {
dto.setPhoneNumbers(getMemberPhonsById(strs));
}
// 填手机号(不变)
}
} catch (Exception e) {
return "输入异常";
}
String bizId = "";
SMSDto smsDto = new SMSDto();
smsDto.setPhoneNumbers(dto.getPhoneNumbers())
.setTemplateCode(dto.getTemplateCode())
.setTemplateParam(dto.getTemplateParam());
if (dto.getSendDateTime() == null) {
bizId = SMSUtil.sendSMS(smsDto);
} else {
Timer timer = new Timer();
timer.schedule(new SendSMSTask(smsDto), DateUtil.toDate(dto.getSendDateTime()));
bizId = "定时任务开启:发送时间" + dto.getSendDateTime().toString();
log.info("定时任务开启:发送时间" + dto.getSendDateTime().toString());
}
return bizId;
}
其中,SendSMSDto.java 模型如下:
@Data
@Accessors(chain = true)
public class SendSMSDto extends BaseSign {
@NotBlank(message = "手机号/会员ID 不能为空")
@ApiModelProperty("手机号/会员ID,多个逗号分隔")
private String phoneNumbers;
@NotBlank(message = "短信模板不能为空")
@ApiModelProperty("短信模板ID")
private String templateCode;
@ApiModelProperty("发送时间(yyyy-MM-dd HH:mm:ss)默认当前时间")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime sendDateTime;
@ApiModelProperty("短信模板参数(例:{\"code\":\"1111\"})")
private String templateParam;
}
SendSMSDto 中,继承的 BaseSign 为校验字段,防止其他人恶意调用接口。其中的规则可以自定义,且有时效性。
由于业务需求,发送短信接口可接受的参数包含手机号或会员的ID,如果输入的 phoneNumbers 为用户 ID 则会自动查表取出用户的手机号。
短信的模板和模板参数要对应,详见阿里云短信服务的接口简介。
除此之外,SendSMSDto 还接收一个 sendDateTime 参数,可以指定发送时间,这就用到了定时任务。由于之前的系列文章内没有单独讲过定时任务,在本文中会简单介绍下,将来会单独写一篇文章介绍定时任务。
如果发送时间不填写,则会直接执行 SMSUtil 里面的 sendSMS 方法。
返回参数示例:
名称 | 类型 | 示例值 | 描述 |
---|---|---|---|
BizId | String | 900619746936498440^0 | 发送回执ID,可根据该ID在接口QuerySendDetails中查询具体的发送状态。 |
Code | String | OK | 请求状态码。
|
Message | String | OK | 状态码的描述。 |
RequestId | String | F655A8D5-B967-440B-8683-DAD6FF8DE990 | 请求ID。 |
new Timer().schedule(new SendSMSTask(smsDto), DateUtil.toDate(dto.getSendDateTime()));
SendSMSTask.java:
@Slf4j
public class SendSMSTask extends TimerTask {
private SMSDto dto;
@Override
public void run() {
String bizId = SMSUtil.sendSMS(dto);
log.info("定时发送短信执行,回执:" + bizId);
}
public SendSMSTask(SMSDto dto) {
this.dto = dto;
}
}
到了指定的时间会自动执行 sendSMS 函数,并保存短信回执。