java短信发送工具类,使用Redis缓存及校验

bootstrap.yml

#微服务启动参数
spring:
  redis:
    host: 192.168.200.129
    port: 6379 #端口号
    password: password # 密码
  application:
    name: user-service
  main:
    allow-bean-definition-overriding: true # Spring Boot 2.1 需要设定
  cloud:
    sentinel:
      transport:
        dashboard: 192.168.200.129:8858 #sentinel控制台地址
    nacos:
      discovery:      #配置注册中心
        server-addr: 192.168.200.129:8848
        namespace: public
        group: ${group.name}
      config:         #配置中心
        server-addr: 192.168.200.129:8848
        namespace: public
        group: ${group.name}
        file-extension: properties
        shared-configs:
          - dataId: mp-config.properties
            group: ${group.name}
          - dataId: spring-druid-config.properties
            group: ${group.name}
          - dataId: feign-config.properties
            group: ${group.name}
          - dataId: ribbon-config.properties
            group: ${group.name}
  profiles:           # 激活配置环境
    active: dev

# 组名称
group:
  name: xc-group

# 日志文件配置路径
logging:
  config: classpath:log4j2-dev.xml

SmsUitl(发短信的工具类)

package com.xuecheng.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;

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

@Slf4j
public class SmsUtil {


    /**
     * 发送短信验证码
     *
     * @param phone 手机号码
     * @return 是否发送成功  成功:返回验证码   失败:返回null;
     */
    public static String sendVerificationCode(String phone) {
        // 创建DefaultAcsClient实例并传递Profile对象
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "LTAI5tEPVSc57i7Z4wzvAuxg", "zkzRKsdgNm1Km0Szb6dmBhIgvMiD1t");
        IAcsClient client = new DefaultAcsClient(profile);

        // 创建SendSmsRequest请求对象并设置请求参数
        SendSmsRequest request = new SendSmsRequest();
        request.setSignName("传智教育"); // 短信签名
        request.setTemplateCode("SMS_461140079"); // 短信模板code
        request.setPhoneNumbers(phone); // 测试号的号码(其它号码需要添加测试号先)
        //短信模板
        Map<String, Object> map = new HashMap<>();
        String verifyCode = RandomStringUtils.random(6, "123456789"); // 获取六位验证码
        map.put("code", verifyCode);
        request.setTemplateParam(JSONObject.toJSONString(map)); // 发送短信信息内容(因为这里是验证码,格式为:{"code":"4-6位数字"})

        try {
            SendSmsResponse response = client.getAcsResponse(request); // 发送短信请求,获取响应
            log.info(JSON.toJSONString(response)); // 打印响应信息
            boolean isOk = response.getCode() != null && response.getCode().equals("OK");// 判断短信是否发送成功
            if (isOk) {
                return verifyCode;
            }
//
//            //todo
            return verifyCode;
        } catch (ServerException e) { // 服务端异常
            e.printStackTrace(); // 打印异常信息
        } catch (ClientException e) { // 客户端异常
            log.error("ErrCode:" + e.getErrCode()); // 打印错误码
            log.error("ErrMsg:" + e.getErrMsg()); // 打印错误信息
            log.error("RequestId:" + e.getRequestId()); // 打印请求ID
        }
        return null; // 默认返回短信发送失败
    }

}
RandomStringUtil(随机字符串工具)
package com.xuecheng.common.util;


import java.util.Random;

/**
 * 随机字符串工具
 *
 * @author scq
 *
 */
public class RandomStringUtil {
        /**
         * 获取指定长度随机字符串
         *
         * @param length
         * @return
         */
        public static String getRandomString(int length) {
            Random random = new Random();
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < length; i++) {
                int number = random.nextInt(3);
                long result = 0;
                switch (number) {
                    case 0:
                        result = Math.round(Math.random() * 25 + 65);
                        sb.append(String.valueOf((char) result));
                        break;
                    case 1:
                        result = Math.round(Math.random() * 25 + 97);
                        sb.append(String.valueOf((char) result));
                        break;
                    case 2:
                        sb.append(String.valueOf(new Random().nextInt(10)));
                        break;
                }
            }
            return sb.toString();
        }

        /**
         * 测试验证
         *
         * @param args
         */
        //public static void main(String[] args) {
        //    System.out.println(RandomStringUtil.getRandomString(5));
        //    String  str2 = RandomStringUtils.random(12,"123456789");
        //    System.out.println(str2);
        //}


}

RedisTemplate(实例化:在config中或者启动类)

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        //创建RedisTemplate实例
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        //设置Redis连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //设置键的序列化器为  字符串redis序列化器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置值的序列化器为  JSON序列化器
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        //设置哈希键的序列化器为 字符串redis序列化器
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        //设置哈希值的序列化器为 JSON序列化器
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        //完成序列化的初始化
        redisTemplate.afterPropertiesSet();
        //返回实例
        return redisTemplate;
    }

Smscontroller

package com.shanjupay.user.controller;

import com.shanjupay.user.api.SmsService;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.exception.BusinessException;
import com.xuecheng.common.util.PhoneUtil;
import com.xuecheng.common.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;


@Api(value = "短信通知相关", tags = "短信验证码发送校验")
@RestController
@RequestMapping("/sms")
@Slf4j
public class SmsController {

    @Resource
    private SmsService smsService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @ApiOperation("发送短信验证码")
    @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String", paramType = "query")
    @GetMapping("/sendMessage")
    public RestResponse sendMessage(@RequestParam String phone) {
        //判断手机号是否为空
        if (StringUtils.isAnyBlank(phone)) {
            //手机号为空
            throw new BusinessException(CommonErrorCode.E_100112);//手机号为空
        }
        //校验手机号格式
        if (!PhoneUtil.isMatches(phone)) {
            //校验手机号格式
            throw new BusinessException(CommonErrorCode.E_100109);//手机号格式不正确
        }

        //从Redis中获取短信验证码
        String verifyCode = redisTemplate.opsForValue().get(phone);
        //如果redis中有,则短信验证码已发送,并且有效,直接再次返回该验证码
        if (!StringUtil.isBlank(verifyCode)) {
            throw new BusinessException(CommonErrorCode.E_100117);//验证码已发送,请查看短信或检查是否被拦截,或检查手机号码是否正确!
        }

        //如果Redis 中没有查到则调用业务实现类去生成并发送
        smsService.sendMessage(phone);
        return RestResponse.success("短信发送成功");
    }


    @ApiOperation("校验短信验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "verifyCode", value = "验证码", required = true, dataType = "String", paramType = "query")
    })
    @GetMapping("/verify")
    public RestResponse sendMessage(String phone, String verifyCode) {
        smsService.verificationMessageCode(phone, verifyCode);
        return RestResponse.success("短信验证成功");
    }

}
SmsService
package com.shanjupay.user.api;

import java.util.Map;

/**
 *  短信服务
 */
public interface SmsService {

    /**
     * 发送短信验证码
     * @param phone
     * @return
     */
    Boolean sendMessage(String phone);


    /**
     * 校验手机验证码
     * @param phone
     * @param verifyCode
     */
     Map verificationMessageCode(String phone, String verifyCode);

}
SmsServiceImpl
package com.shanjupay.user.service;

import com.shanjupay.user.api.SmsService;
import com.shanjupay.user.mapper.AccountMapper;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.exception.BusinessException;
import com.xuecheng.common.util.SmsUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Description:
 * @Version: V1.0
 */
@Slf4j
@Service
public class SmsServiceImpl implements SmsService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private AccountMapper accountMapper;

    @Override
    public Boolean sendMessage(String phone) {
        String verifyCode = SmsUtil.sendVerificationCode(phone);
        if (!StringUtils.isBlank(verifyCode)) {
            redisTemplate.opsForValue().set(phone, verifyCode, 60, TimeUnit.SECONDS);
            return true;
        }
        return false;

    }

    /**
     * 校验验证码
     *
     * @param phone
     * @param verifyCode
     * @return
     */
    @Override
    public Map verificationMessageCode(String phone, String verifyCode) {
        //2校验手机号在数据库中是否存在
        int mobileCount = accountMapper.selectAccountByMobile(phone);
        log.info("mobileCount{}", mobileCount);
        if (mobileCount < 1) {
            throw new BusinessException(CommonErrorCode.E_100119);//没有该用户,请注册后重新登录!
        }
        //2.获取Redis中的验证码
        String redisPhoneCode = redisTemplate.opsForValue().get(phone);
        //3.用户一直没有校验导致Redis超时销毁
        if (StringUtils.isBlank(redisPhoneCode)) {
            throw new BusinessException(CommonErrorCode.E_100120);//验证码已过期,请重新获取.   或检查有没有点击'获取验证码'按钮.
        }
        //校验验证码
        if (!redisPhoneCode.equals(verifyCode)) {
            //验证码错误
            throw new BusinessException(CommonErrorCode.E_100102);//验证码错误
        }
        Map<String, Object> map = new HashMap<>();
        map.put("手机号:", phone);
        map.put("验证码:", verifyCode);
        return map;
    }
}

猜你喜欢

转载自blog.csdn.net/anyi2351033836/article/details/131260161