SpringBoot整合阿里云SMS短信服务 并实现发送短信验证码的功能 Redis Java 短信验证码

阿里云SMS短信服务 并实现发送短信验证码的功能SpringBoot整合阿里云SMS

简单简介

短信服务(Short Message Service)是广大企业客户快速触达手机用户所优选使用的通信能力。
调用API或用群发助手,即可发送验证码、通知类和营销短信;
国内验证短信秒级触达,到达率99%;
国际/港澳台短信覆盖200多个国家和地区,安全稳定,广受出海企业选用。

本次用到的技术

  • 需要熟悉 Spring Boot 操作流程

  • 会使用 Maven

  • 懂得基本的 Redis 操作

  • HTML 基础

废话不说,直接开启正题!

首先需要去 阿里云官网获取您的 AccessKey 和 AccessKey Secert

传送门 获取AccessKey教程地址

准备工作

  • 打开阿里云的 sms 控制台

传送门 阿里云SMS控制台

  • 可以 先在控制台中选择 快速 学习先看下基本的操作 可以测试基本短信发送 !

    刚进来的时候这里会显示几个 小圈圈 然后你点那几个圈就可以进行学习

img

国内消息 => 签名管理 => 添加签名

img

注意事项

申请说明不能随便写! 否则不能通过审核!!

国内消息 => 签名管理 =>创建模板

img

注意事项

${xxxx}代表参数 可以使用 java进行传入

申请说明不能随便写! 否则不能通过审核!!

两个都申请完成之后 去喝杯茶 大概10分钟左右就审核完成了 最多超不过小时

申请成功之后

记住签名的名称 和模板Code

待会要使用

img img

最好先在阿里云冲几块钱 要不然短信可能发不出去!!


开始整合

  • 创建SpringBoot项目 ~~
  • 打开 pom.xml 文件 添加依赖 本次demo能用到的依赖
  • 阿里云的 sdk依赖可在阿里云帮助文档中进行获取
 <!--Aliyun sms Begin-->
<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.67</version>
</dependency>
<!--Aliyun sms end-->

<!--Redis Begin-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--Redis End-->

测试:可以先打开 Test 测试一下

package cn.yufire.sms;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashMap;
import java.util.Map;

@SpringBootTest
class AliyunSmsDemoApplicationTests {
    
    

    @Test
    void sendSms() {
    
    

        // 指定地域名称 短信API的就是 cn-hangzhou 不能改变  后边填写您的  accessKey 和 accessKey Secret
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "您的accesskey", "您的accessKeySecret");
        IAcsClient client = new DefaultAcsClient(profile);

        // 创建通用的请求对象
        CommonRequest request = new CommonRequest();
        // 指定请求方式
        request.setMethod(MethodType.POST);
        // 短信api的请求地址  固定
        request.setDomain("dysmsapi.aliyuncs.com");
        // 签名算法版本  固定
        request.setVersion("2017-05-25");
        //请求 API 的名称。
        request.setAction("SendSms");
        // 上边已经指定过了 这里不用再指定地域名称
//        request.putQueryParameter("RegionId", "cn-hangzhou");
        // 您的申请签名
        request.putQueryParameter("SignName", "您的签名名称");
        // 您申请的模板 code
        request.putQueryParameter("TemplateCode", "您的模板code");
        // 要给哪个手机号发送短信  指定手机号
        request.putQueryParameter("PhoneNumbers", "要发送的手机号");

        // 创建参数集合
        Map<String, Object> params = new HashMap<>();
        // 生成短信的验证码  
        String code = String.valueOf(Math.random()).substring(3, 9);
        // 这里的key就是短信模板中的 ${xxxx}
        params.put("code", code);

        // 放入参数  需要把 map转换为json格式  使用fastJson进行转换
        request.putQueryParameter("TemplateParam", JSON.toJSONString(params));

        try {
    
    
            // 发送请求 获得响应体
            CommonResponse response = client.getCommonResponse(request);
            // 打印响应体数据
            System.out.println(response.getData());
            // 打印 请求状态 是否成功
            System.out.println(response.getHttpResponse().isSuccess());
        } catch (ServerException e) {
    
    
            e.printStackTrace();
        } catch (ClientException e) {
    
    
            e.printStackTrace();
        }

    }


}

测试结果

img

# 响应数据
{
    
    "Message":"OK","RequestId":"E18E096C-CF46-431C-B81E-14AD8F564994","BizId":"490017688565398557^0","Code":"OK"}
# 是否请求成功
true


可以创建Service和Controller 组成一个对外提供服务的接口\

  • application.yml 配置文件
server:
  port: 8080
spring:
  redis:
    host: 127.0.0.1
    port: 6379
aliyun:
  accessKeyID: 你的accessKeyID
  accessKeySecret: 你的accessKeySecret
  • 创建service层
package cn.yufire.sms.service;

public interface SendSmsService {
    
    

    /**
     * 发送短信验证码的接口
     *
     * @param phoneNum 手机号
     * @param code     验证码
     * @return
     */
    boolean sendSms(String phoneNum, String code);

}

  • 创建service的实现类
package cn.yufire.sms.service.impl;

import cn.yufire.sms.service.SendSmsService;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
@Data // lombok的注解
public class SendSmsServiceImpl implements SendSmsService {
    
    

    private static final Logger logger = LoggerFactory.getLogger(SendSmsServiceImpl.class);
    // 这里采用 注入的方式传递参数
    @Value("${aliyun.accessKeyID}")
    private String accessKeyID;
    @Value("${aliyun.accessKeySecret}")
    private String accessKeySecret;

    @Override
    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");
        request.setVersion("2017-05-25");
        request.setAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("SignName", "签名名称");
        request.putQueryParameter("PhoneNumbers", phoneNum);
        request.putQueryParameter("TemplateCode", "模板code");

        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;
    }
}

  • 创建 Controller
package cn.yufire.sms.controller;

import cn.yufire.sms.service.SendSmsService;
import com.aliyuncs.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.TimeUnit;

@RestController
@CrossOrigin // 跨域支持
public class SendSmsController {
    
    

    @Autowired
    private SendSmsService sendSmsService;

    // 注入redis操作模板
    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    @GetMapping("/sendSms")
    public String sendSms(@RequestParam("phoneNum") String phoneNum) {
    
    
        // 获取到操作String的对象
        ValueOperations<String, String> stringR = redisTemplate.opsForValue();

        // 根据手机号进行查询
        String phone = stringR.get(phoneNum);

        // 如果手机号在redis中不存在的话才进行发送验证码操作
        if (StringUtils.isEmpty(phone)) {
    
    
            // 生成6位随机数
            String code = String.valueOf(Math.random()).substring(3, 9);
            // 调用业务层接口 发送验证码
            boolean sendSmsFlag = sendSmsService.sendSms(phoneNum, code);
            if (sendSmsFlag) {
    
    
                // 发送成功之后往redis中存入该手机号以及验证码 并设置超时时间 5 分钟
                stringR.set(phoneNum, code, 5, TimeUnit.MINUTES);
            }
            return "发送验证码到:" + phoneNum + "成功! " + "Message:" + sendSmsFlag;
        } else {
    
    
            return "该手机号:" + phoneNum + " 剩余:" + redisTemplate.getExpire(phoneNum) + "秒后可再次进行发送!";
        }
    }

    @GetMapping("/checkCode/{key}/{code}")
    public String checkCode(@PathVariable("key") String number, @PathVariable("code") String code) {
    
    

        // 获取到操作String的对象
        ValueOperations<String, String> stringR = redisTemplate.opsForValue();
        // 根据Key进行查询
        String redisCode = stringR.get(number);
        if (code.equals(redisCode)) {
    
    
            return "成功";
        } else {
    
    
            return redisCode == null ? "请先获取验证码在进行校验!" : "错误";
        }
    }
}

请求访问接口

这里使用PostMan

测试成功!img

此时的手机上

img

此时的Redis里

img

注意事项

  • 千万千万不能把 阿里云的 accessKey 和 accessSecret 泄露了
  • 在 sms控制台内 可以设置 短信的安全 发送频率等等的设置
  • 在控制台内还有帮助文档!

img

完结撒花

作者:yufire © [email protected]

猜你喜欢

转载自blog.csdn.net/weixin_43420255/article/details/105916173