短信服务(Short Message Service)是指通过调用短信发送API,将指定短信内容发送给指定手机用户。用户收到的短信来自106开头的号码,短信的内容多用于企业向用户传递验证码、系统通知、会员服务等信息。在业务场景中使用的越来越广泛,这里我们选用阿里云的短信服务,当然也有很多的短信发送服务商,自行选择即可。
I 导入所需要的依赖
使用阿里云的服务当然少不了它的官方文档了
↓↓↓↓↓↓↓
点我呀
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.1</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.0.0</version>
</dependency>
application.yml 相关配置 因为我们要把验证码存入redis中 这里需要配置redis
redis 使用问题可以看我上一篇文档
redis:
host: 127.0.0.1
port: 6379
timeout: 180000
lettuce:
pool:
max-active: 20
max-wait: -1
max-idle: 5
min-idle: 0
#这里我们自定义一个配置
aliyun:
sms:
Key: L*****************jr
Serect: c*********************o
SignName: 你的签名名称
TemplateCode: 你的模板编号
II 开通短信发送服务以及申请模板签名
a. 开通短信服务
开通过就会管理控制台的按钮,进去后点击添加签名
根据自己的需求填写相关内容,填写完后等待官方审核,未通过重写添加申请即可
添加需要的短信模板
与签名相同,申请通过后会在自己的列表中找到申请的模板
有了签名,和模板就可以在代码中使用了。
III 短信发送基础
a. 在项目中使用,采用官方文档的示例代码进行修改,封装为工具类方便调用
/**
* @Author Yang_Vincent
* @Date 2020/7/20 23:07
*/
public class SendSmsStatusUtils {
//发送短息方法抽取
public static Boolean sendSmsBySatus(Map<String, Object> map, String phoneNum) {
// AccessKey ID和AccessKey Secret是访问阿里云API的密钥,具有该账户完全的权限。
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", MsmProperties.KEY, MsmProperties.SERECT);
//创建一个可以发送到阿里云的对象
IAcsClient client = new DefaultAcsClient(profile);
//设置固定参数
CommonRequest request = new CommonRequest();
//request.setProtocol(ProtocolType.HTTPS);
request.setSysMethod(MethodType.POST);
request.setSysDomain("dysmsapi.aliyuncs.com");
request.setSysVersion("2017-05-25");
request.setSysAction("SendSms");
//设置发送服务的相关参数
request.putQueryParameter("PhoneNumbers", phoneNum); //设置手机号
request.putQueryParameter("SignName", MsmProperties.SIGNNAME); //设置阿里云的签名名称
request.putQueryParameter("TemplateCode", MsmProperties.TEMPLATECODE); //阿里云的模拟code
//(传入的数据需要为json格式,所以封装成map集合合适)map转换成json格式数据的方法JSONObject.toJSONString(map)
request.putQueryParameter("TemplateParam", JSONObject.toJSONString(map)); //设置要发送的验证码
//使用对象进行最终发送
try {
CommonResponse response = client.getCommonResponse(request);
boolean success = response.getHttpResponse().isSuccess();
return success;
} catch (ClientException e) {
e.printStackTrace();
return false;
}
}
}
我们将所需要的短信秘钥、名称、签名、模板写入application.yml中,我们自定义一个类去读取它
/**
* @Author Yang_Vincent
* @Date 2020/7/20 21:24
*/
@Component
public class MsmProperties implements InitializingBean {
//这里为配置文件写入的前缀 变量名要和配置文件中的保持一致,以此类推
@Value("${aliyun.sms.Key}")
private String Key;
@Value("${aliyun.sms.Serect}")
private String Serect;
@Value("${aliyun.sms.SignName}")
private String SignName;
@Value("${aliyun.sms.TemplateCode}")
private String TemplateCode;
public static String KEY;
public static String SERECT;
public static String SIGNNAME;
public static String TEMPLATECODE;
@Override
public void afterPropertiesSet() throws Exception {
KEY = this.Key;
SERECT = this.Serect;
SIGNNAME = this.SignName;
TEMPLATECODE = this.TemplateCode;
}
}
读取配置文件的方法有很多这里只演示一种
b.模拟业务场景发送验证码
/**
* @Author Yang_Vincent
* @Date 2020/7/20 21:10
*/
@Service
public class MsmServiceImpl implements MsmService {
@Override
public Boolean send(Map<String, Object> map, String phoneNum) {
if (CollectionUtils.isEmpty(map)) {
return false;
}
Boolean status = SendSmsStatusUtils.sendSmsBySatus(map, phoneNum);
return status;
}
}
c. 结合redis实现验证码的有效时间
根据自己业务场景的需求实现结合用户注册,这里只做演示
/**
* @Author Yang_Vincent
* @Date 2020/7/20 21:10
*/
@RestController
@CrossOrigin
@RequestMapping("/edumsm/msm")
public class MsmController {
//redis存储前缀
static final String KEY_PREFIX = "user:code:phone:";
@Autowired
private MsmService msmService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@GetMapping("/send/{phoneNum}")
public R sendVerifyCode(@PathVariable("phoneNum") String phoneNum) {
String code = stringRedisTemplate.opsForValue().get(KEY_PREFIX + phoneNum);
if (StringUtils.isNotBlank(code)) {
return R.ok();
}
code = RandomUtil.getSixBitRandom();
Map<String, Object> map = new HashMap<>();
map.put("code", code);
Boolean isSuccess = this.msmService.send(map, phoneNum);
if (isSuccess) {
this.stringRedisTemplate.opsForValue().set(KEY_PREFIX + phoneNum, code, 5, TimeUnit.MINUTES);
return R.ok();
}
return R.error().message("发送失败,请重试!");
}
}
这里定义一个静态常量的前缀结合需要发送验证码的手机号写入到redis中设置好时效即可
IV 测试短信服务
因为项目中使用swagger 就用它来测试了
看了看手机短信也收到了,OK就写到这里吧