SpringBoot集成腾讯云短信服务

前言

可以说现在一个成熟的软件基本上都会具有发送短信验证码的场景;比如在这些场景中:

  1. 用户使用手机号进行注册
  2. 用户使用短信验证码登录
  3. 用户忘记密码,通过发送手机验证码,进行重置密码
  4. 修改手机号
  5. 修改密码

在以上场景中,我们就需要集成短信服务。现在的短信服务众多,例如:腾讯云、阿里云等。
在这篇文章中将使用SpringBoot集成腾讯云的短信服务。

开始集成

准备阶段

我们需要先注册一个腾讯云的账号,然后在腾讯云的产品里面找到短信在这里插入图片描述
里面有相应的短信套餐可以选择,如果是新用户注册的话,会有一定的免费短信条数。
然后我们进入短信的控制台页面,我们先要创建一个短信签名,其中签名用途,签名类型和签名内容等根据自己的实际情况进行填写。
注意:签名内容为短信验证码【】中括号里面的内容,如:【xxx】1234为您的验证码,请于5分钟内输入。其签名内容就为 xxx。在这里插入图片描述
填写完成之后,确定即可。在签名管理中就可以看到刚刚创建的短信签名。当显示的状态变为已通过后该签名就可以使用了。
在这里插入图片描述
接下来我们需要创建短信的模板。选择创建正文模板选项,根据实际情况进行填写。填写完成,确定即可。其中短信内容部分{1}{2}等变量参数为动态参数,需要我们在代码中请求腾讯云短信服务时携带。
在这里插入图片描述
创建完成模板状态显示已通过即可使用。
在这里插入图片描述

Coding阶段

pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.junwei</groupId>
    <artifactId>smsdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>smsdemo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <qcloudsms.version>1.0.6</qcloudsms.version>
        <lombok.versino>1.18.8</lombok.versino>
        <httpclient.version>4.5.9</httpclient.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.qcloudsms</groupId>
            <artifactId>qcloudsms</artifactId>
            <version>${qcloudsms.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.versino}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>${httpclient.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

注意:需要使用redis缓存数据库

server:
  port: 9016

spring:
  application:
    name: sms-service

  redis:
    host: 127.0.0.1
    port: 6379

smsconfig:
  appId: 腾讯云短信应用id
  appkey: 腾讯云短信应用key
  smsSign: 腾讯云创建的短信签名
  templateid: 腾讯云短信模板id
  invalidtime: 验证码失效时间
  # redis存储前缀,根据不同类型做区分
  phone-prefix: LOGIN,REGIST,FORGET_PASSWORD,UPDATE_MOBILE,UPDATE_PASSWORD,WX_UN_TYING,UPDATE_NEW_MOBILE

logging:
  level:
    root: info

短信签名和短信模板id在以上配置成功后就可以看到;腾讯云AppId和AppKey在这里:
在这里插入图片描述

Controller

@RestController
@RequestMapping("sms")
public class SmsController {
    
    

    @Autowired
    private SmsService smsService;

    @PostMapping("send")
    public Result send(@RequestBody SendSmsDto sendSmsDto) {
    
    
        smsService.sendSmsCode(sendSmsDto);
        return Result.success("");
    }

    @PostMapping("verify")
    public Result verify(@RequestBody VerifyCodeDto verifyCodeDto) {
    
    
        smsService.verifyCode(verifyCodeDto);
        return Result.success("");
    }

}

SmsConfig

@Configuration
public class SmsConfig {
    
    
    /**
     * 初始化主账号名称
     **/
    @Value("${smsconfig.appkey}")
    private String APP_KEY;

    /**
     * 初始化应用ID
     **/
    @Value("${smsconfig.appId}")
    private int APP_ID;

    @Bean
    public SmsSingleSender ssender() {
    
    
        return new SmsSingleSender(APP_ID, APP_KEY);
    }
}

ServiceImpl

@Service
@Slf4j
public class SmsServiceImpl implements SmsService {
    
    

    @Autowired
    private SmsSingleSender smsSingleSender;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 短信模板ID
     **/
    @Value("${smsconfig.templateid}")
    private int TEMPLATE_ID;
    /**
     * 短信签名内容
     */
    @Value("${smsconfig.smsSign}")
    private String SMS_SIGN;

    @Value("${smsconfig.invalidtime}")
    private String INVALID_TIME;

    @Value("${smsconfig.phone-prefix}")
    private String PHONE_PREFIX;

    @Override
    public void sendSmsCode(SendSmsDto sendSmsDto) {
    
    
        // 可以在发送验证码之前对当前手机号做一些验证,如该手机号是否注册过
        // 为了防止短信轰炸可以根据业务需求在此做一些限制
        String code = SmsUtil.getCode();
        try {
    
    
            ArrayList<String> params = new ArrayList<>();
            params.add(code);
            params.add(INVALID_TIME);
            SmsSingleSenderResult senderResult = smsSingleSender
                    .sendWithParam("86", sendSmsDto.getMobile(),
                            TEMPLATE_ID, params, SMS_SIGN, "", "");
            int statusCode = senderResult.result;
            String statusMsg = senderResult.errMsg;
            log.info("发送短信,腾讯云返回状态码:" + statusCode);
            log.info("发送短信,腾讯云返回信息:" + statusMsg);
            // 过于频繁
            if (Constants.SEND_SMS_CODE_FREQUENT == statusCode) {
    
    
                throw new SmsException(R.USER_LOGIN_ERROR3, "");
            }
            // 达到上限
            if (Constants.SEND_SMS_CODE_UPPER == statusCode) {
    
    
                throw new SmsException(R.USER_CODE_TOOMANY, "");
            }
            if (Constants.SEND_SMS_CODE_SUCCESS != statusCode) {
    
    
                throw new SmsException(R.sms_send_error, "");
            }
            if (!redisUtil.setCacheObject(SmsUtil.map.get(sendSmsDto.getType()) + sendSmsDto.getMobile(),
                    code, 60 * Integer.parseInt(INVALID_TIME))) {
    
    
                throw new SmsException(R.sms_send_error, "");
            }
        } catch (Exception e) {
    
    
            throw new SmsException(R.sms_send_error, "");
        }
    }

    @Override
    public void verifyCode(VerifyCodeDto verifyCodeDto) {
    
    
        String redisCode = (String) redisUtil.getCacheObject(SmsUtil.map
                .get(verifyCodeDto.getType()) + verifyCodeDto.getMobile());
        AssertUtil.isNull(redisCode, R.USER_LOGIN_ERROR4);
        if (redisCode.equals(verifyCodeDto.getCode())) {
    
    
            redisUtil.delete(SmsUtil.map.get(verifyCodeDto.getType()) + verifyCodeDto.getMobile());
        } else {
    
    
            throw new SmsException(R.USER_CODE_ERROR, "");
        }
    }
}

文章中只展示了关键部分代码,需要详细代码,请clone该仓库:SpringBoot集成腾讯云短信服务

功能测试阶段

这里使用Postman对接口进行测试。
首先测试的是短信验证码发送接口:
根据接口及参数设置,这里使用post请求方式,需要传入手机号和短信验证码类型两个参数。测试请求成功。
在这里插入图片描述
发送成功,手机接收到验证码:
在这里插入图片描述

接下来我们测试校验验证码接口:
根据接口及参数设置,这里使用post请求方式,需要传入手机号,接收到的短信验证码以及短信验证码的类型三个参数,验证成功。
在这里插入图片描述
至此短信服务已经整合完毕,可以在发送短信前或后根据自己的业务需求做一些相应的处理。
最后奉上详细的代码的git地址:https://gitee.com/junweiw/tx_send_sms.git

猜你喜欢

转载自blog.csdn.net/wFitting/article/details/106242142