首先想要使用阿里短信服务必须获取到阿里的AccessKey
获取短信服务的签名以及模板
SmsUtils
@Component
public class SmSUtil {
private static final Logger logger = LoggerFactory.getLogger(SendSmsServiceImpl.class);
@Value("${aliyun.accessKeyID}") //从yml文件中获取到accessKeyID
private String accessKeyID;
@Value("${aliyun.accessKeySecret}") //从yml文件中获取accessKeySecret
private String accessKeySecret;
public boolean sendSms(String phoneNum, String code) {
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyID, accessKeySecret);
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
request.setMethod(MethodType.POST);
request.setDomain("dysmsapi.aliyuncs.com"); //短信API产品域名(接口地址固定,无需修改)
request.setVersion("2017-05-25"); //版本时间,由于阿里早期开发sdk混乱,一般使用这个版本
request.setAction("SendSms");
request.putQueryParameter("RegionId", "cn-hangzhou");
request.putQueryParameter("SignName", "XXX"); //签名,就是从阿里短信服务获取到的签名
request.putQueryParameter("PhoneNumbers", phoneNum); //接收短信者的手机号
request.putQueryParameter("TemplateCode", "SMS_209190486"); //短信模板 发送国际/港澳台消息时,请使用国际/港澳台短信模版
Map<String, Object> params = new HashMap<>();
params.put("code", code); //发送到手机的验证码
request.putQueryParameter("TemplateParam", JSON.toJSONString(params));
try {
CommonResponse response = client.getCommonResponse(request);
// System.out.println(response.getData()); // 返回的消息
logger.info(JSON.parseObject(response.getData(), Map.class).get("Message").toString());
return response.getHttpResponse().isSuccess();
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
return false;
}
}
SendSmsService
public interface SendSmsService {
/**
* 发送短信验证码的接口
*
* @param phoneNum 手机号
* @return
*/
boolean sendSms(@Param("phoneNum") String phoneNum);
/**
* 验证验证码是否正确
* @param code
* @param phone
* @return
*/
boolean checkSmsCode(String code,String phone) ;
SendSmsServiceImpl
@Service
@Data
public class SendSmsServiceImpl implements SendSmsService {
@Resource
private RedisTemplate<String, String> redisTemplate;
@Resource
private SmSUtil smSUtil;
@Override
public boolean sendSms(String phoneNum) {
// 获取到操作String的对象
ValueOperations<String, String> stringR = redisTemplate.opsForValue();
// 根据手机号进行查询
String phone = stringR.get(phoneNum);
// 如果手机号在redis中不存在的话才进行发送验证码操作
if (StringUtils.isEmpty(phone)) {
// 生成6位随机数
String securityCode = String.valueOf(Math.random()).substring(3, 9);
// 调用业务层接口 发送验证码
boolean sendSmsFlag = smSUtil.sendSms(phoneNum, securityCode);
if (sendSmsFlag) {
// 发送成功之后往redis中存入该手机号以及验证码 并设置超时时间 5 分钟
stringR.set(phoneNum, securityCode, 5, TimeUnit.MINUTES);
}
return true;
} else {
return false;
}
}
@Override
public boolean checkSmsCode(String code, String phone) {
// 获取到操作String的对象
ValueOperations<String, String> stringR = redisTemplate.opsForValue();
// 根据Key进行查询
String redisCode = stringR.get(phone);
if (StringUtils.isEmpty(redisCode)) {
return false;
}
if (code.equals(redisCode)) {
return true;
}
return false;
}
}
SendSmsController
@RestController
@AllArgsConstructor
@RequestMapping("sms")
@Api(value = "短信验证", tags = "短信验证")
@CrossOrigin // 跨域支持
public class SendSmsController {
@Resource
private SendSmsService sendSmsService;
@GetMapping("/sendSms")
public R sendSms(@RequestParam("phoneNum") String phoneNum) {
//验证手机号格式是否合理存在
boolean chinaPhoneLegal = PhoneFormatCheckUtils.isChinaPhoneLegal(phoneNum);
//如果手机号格式正确,发送短信,否则要求重新填写手机号
if (chinaPhoneLegal) {
boolean result = sendSmsService.sendSms(phoneNum);
if (result) {
return R.data("发送成功请注意查看手机");
}
return R.fail("发送失败请重新尝试");
}
return R.fail("请输入正确的18位手机号");
}
@GetMapping("/checkCode/")
public R checkCode(String phone, String code) {
boolean result = sendSmsService.checkSmsCode(code, phone);
if (result) {
return R.data("登录成功");
} else {
return R.fail("验证码已过期或错误请重试");
}
}
}
注意阿里云中的AccessKey,短信服务签名以及短信模板一定要审核通过正确
另外,一个小时内同一个手机号短信只能收到5次,会报
触发小时级流控Permits:5