美文网首页
基于springBoot短信验证码接入

基于springBoot短信验证码接入

作者: Raral | 来源:发表于2021-03-17 13:30 被阅读0次

    基于springBoot短信验证码接入

    实现思路

    1. 通过明网科技注册账号,找到对应的账号信息
    2. 根据文档说明,写一个工具类 目的发送信息参数处理
    3. 借助redis 控制 验证码的失效时间和临时存储,校验验证码是否正确
    
    2.png

    工具类

    package com.cms2.common.utils.sms;
    
    import com.cms2.common.constant.ExceptionCode;
    import com.cms2.common.exception.DpException;
    
    import java.io.BufferedReader;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.URL;
    import java.net.URLConnection;
    import java.net.URLDecoder;
    import java.net.URLEncoder;
    import java.util.Random;
    
    /**
     * @description: 推送消息工具类
     */
    public class SendSmsUtil {
        private final static String UTF8 = "UTF-8";
        private final static String GB2312 = "GB2312";
        private final static String SMS_URL = "http://37037.com/sms.aspx";// 短信通道-URL
        private final static String QYID = "";// 短信通道-企业ID
        private final static String ZH = "";// 短信通道-账号
        private final static String MM = "";// 短信通道-密码
    
        /**
         * <p>
         * 作用描述:发送短信
         * </p>
         * <p>
         * 修改说明: 1 发送短信成功(其他请求代表成功) -1 账号无效或未开户 -2 账号密码错误 -3 下发手机号为空 -4 下发短信内容为空 -5
         * 指定短信企业ID为空 -6 账户或密码错误 -7 账户被冻结 -8 下发短信内容包含非法关键词 -9 账户没有充值或指定企业ID错误 -10
         * 下发短信内容长度超出规定限制,限制为350字符 -11 下发账号余额不足 -20 服务器连接异常 -21 当前短信隶属106营销短信
         * 必须加“尊称”、“退订回复T” -99 系统未知错误
         * </p>
         *
         * @param tel
         * @param content
         * @return
         */
    
        public static boolean sendNote(String tel, String content) {
            DataOutputStream server = null;
            BufferedReader in = null;
            InputStreamReader is = null;
            boolean flag = false;
            try {
                String urlencContent = URLEncoder.encode(content, UTF8);
                String postData = "action=send" + "&userid=" + QYID + "&account="
                        + ZH + "&password=" + MM + "&mobile=" + tel + "&content="
                        + urlencContent + "&sendTime=&extno=";
                URL myurl = new URL(SMS_URL);
                URLConnection urlc = myurl.openConnection();
                urlc.setReadTimeout(1000 * 30);
                urlc.setDoOutput(true);
                urlc.setDoInput(true);
                urlc.setAllowUserInteraction(false);
                server = new DataOutputStream(urlc.getOutputStream());
                server.write(postData.getBytes(UTF8));
                server.close();
                server = null;
    
                is = new InputStreamReader(urlc.getInputStream(), UTF8);
                in = new BufferedReader(is);
                String resXml = "", s = "";
                while ((s = in.readLine()) != null) {
                    resXml = resXml + s + "\r\n";
                }
                in.close();
                in = null;
                is.close();
                is = null;
                String respon = URLDecoder.decode(resXml, UTF8).replaceAll("\r|\n",
                        "");
                System.out.println("短信下发返回结果=" + respon);
                if (null != respon && !"".equals(respon)
                        && respon.contains("Success")) {
                    flag = true;
                }
                return flag;
            } catch (Exception e) {
                throw new DpException(ExceptionCode.SMS_ERROR, e);
            } finally {
                try {
                    if (null != server) {
                        server.close();
                        server = null;
                    }
                    if (null != in) {
                        in.close();
                        in = null;
                    }
                    if (null != is) {
                        is.close();
                        is = null;
                    }
                } catch (IOException e) {
                    throw new DpException(ExceptionCode.SMS_ERROR, e);
                }
            }
        }
    
        public static synchronized String zcCode() {
            int max = 10000;
            int min = 1000;
            Random random = new Random();
            int s = random.nextInt(max) % (max - min + 1) + min;
            return "" + s;
        }
    
    }
    
    

    redis使用

    1. service层-- RedisServiceImpl
    package com.cms2.system.service.impl;
    
    import com.cms2.system.service.IRedisService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.*;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    import org.springframework.stereotype.Service;
    
    import java.io.Serializable;
    import java.util.List;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @description: redis 读写,过期时间
     */
    @Service
    public class RedisServiceImpl implements IRedisService {
        @Autowired
        private RedisTemplate redisTemplate;
    
        @Autowired(required = false)
        @Override
        public void setRedisTemplate(RedisTemplate redisTemplate) {
            RedisSerializer stringSerializer = new StringRedisSerializer();
            redisTemplate.setKeySerializer(stringSerializer);
            redisTemplate.setValueSerializer(stringSerializer);
            redisTemplate.setHashKeySerializer(stringSerializer);
            redisTemplate.setHashValueSerializer(stringSerializer);
            this.redisTemplate = redisTemplate;
        }
    
        /**
         * 写入缓存
         * @param key
         * @param value
         * @return
         */
        @Override
        public boolean set(final String key, Object value) {
            boolean result = false;
            try {
                ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
                operations.set(key, value);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
        /**
         * 写入缓存设置时效时间
         * @param key
         * @param value
         * @return
         */
        @Override
        public boolean set(final String key, Object value, Long expireTime) {
            boolean result = false;
            try {
                ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
                operations.set(key, value);
                redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
        /**
         * 批量删除对应的value
         * @param keys
         */
        @Override
        public void remove(final String... keys) {
            for (String key : keys) {
                remove(key);
            }
        }
    
        /**
         * 批量删除key
         * @param pattern
         */
        @Override
        public void removePattern(final String pattern) {
            Set<Serializable> keys = redisTemplate.keys(pattern);
            if (keys.size() > 0) {
                redisTemplate.delete(keys);
            }
        }
        /**
         * 删除对应的value
         * @param key
         */
        @Override
        public void remove(final String key) {
            if (exists(key)) {
                redisTemplate.delete(key);
            }
        }
        /**
         * 判断缓存中是否有对应的value
         * @param key
         * @return
         */
        @Override
        public boolean exists(final String key) {
            return redisTemplate.hasKey(key);
        }
        /**
         * 读取缓存
         * @param key
         * @return
         */
        @Override
        public Object get(final String key) {
            Object result = null;
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            result = operations.get(key);
            return result;
        }
        /**
         * 哈希 添加
         * @param key
         * @param hashKey
         * @param value
         */
        @Override
        public void hmSet(String key, Object hashKey, Object value){
            HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
            hash.put(key,hashKey,value);
        }
    
        /**
         * 哈希获取数据
         * @param key
         * @param hashKey
         * @return
         */
        @Override
        public Object hmGet(String key, Object hashKey){
            HashOperations<String, Object, Object>  hash = redisTemplate.opsForHash();
            return hash.get(key,hashKey);
        }
    
        /**
         * 列表添加
         * @param k
         * @param v
         */
        @Override
        public void lPush(String k,Object v){
            ListOperations<String, Object> list = redisTemplate.opsForList();
            list.rightPush(k,v);
        }
    
        /**
         * 列表获取
         * @param k
         * @param l
         * @param l1
         * @return
         */
        @Override
        public List<Object> lRange(String k, long l, long l1){
            ListOperations<String, Object> list = redisTemplate.opsForList();
            return list.range(k,l,l1);
        }
    
        /**
         * 集合添加
         * @param key
         * @param value
         */
        @Override
        public void add(String key,Object value){
            SetOperations<String, Object> set = redisTemplate.opsForSet();
            set.add(key,value);
        }
    
        /**
         * 集合获取
         * @param key
         * @return
         */
        @Override
        public Set<Object> setMembers(String key){
            SetOperations<String, Object> set = redisTemplate.opsForSet();
            return set.members(key);
        }
    
        /**
         * 有序集合添加
         * @param key
         * @param value
         * @param scoure
         */
        @Override
        public void zAdd(String key,Object value,double scoure){
            ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
            zset.add(key,value,scoure);
        }
    
        /**
         * 有序集合获取
         * @param key
         * @param scoure
         * @param scoure1
         * @return
         */
        @Override
        public Set<Object> rangeByScore(String key,double scoure,double scoure1){
            ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
            return zset.rangeByScore(key, scoure, scoure1);
        }
    }
    
    
    1. redis基于springboot配置信息
    spring:
        redis:
            host: 127.0.0.1
            port: 6379
            password:
            database: 
            lettuce:
              pool:
                max-active: 32
                max-wait: 300ms
                max-idle: 16
                min-idle: 8
            timeout: 300ms
    

    service层 SmsServiveImpl 发送短信业务逻辑

    package com.cms2.system.service.impl;
    
    import com.cms2.common.utils.StringUtils;
    import com.cms2.common.utils.sms.SendSmsUtil;
    import com.cms2.system.service.IRedisService;
    import com.cms2.system.service.ISmsService;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    
    /**
     * @description:
     */
    @Service
    public class SmsServiceImpl implements ISmsService {
        @Resource
        private IRedisService redisService;
    
        @Override
        public Object sendSms(String phoneNums, String templeteCode, String templateParam) throws Exception {
            return null;
        }
    
        @Override
        public Object querySendDetails(String phoneNumber, String bizId) throws Exception {
            return null;
        }
    
        @Override
        public String sendMessage(String mobile, int type) {
            //首先判断验证码是否存在 如果存在 则修改验证码过期时间延长至180S
            String verifyCode = (String)redisService.get(mobile);
            if(StringUtils.isBlank(verifyCode)){
                //如果验证码为空 则新增验证码
                verifyCode = SendSmsUtil.zcCode();
            }
            //redis存储验证码并设置180S的过期时间 过期redis自动删除
            redisService.set(mobile,verifyCode,180L);
            //短信发送验证码 异步发送
            String content = null;
            switch(type){
                case 0:
                    //发送登录验证码
                    content = "【项目名称】您的注册验证码为:%s,请在3分钟内验证!";
                    content = String.format(content,verifyCode);
                    break;
                case 1:
                    //发送找回密码验证码
                    content = "【项目名称】您正在进行找回密码操作,验证码为:%s,请在3分钟内验证!";
                    content = String.format(content,verifyCode);
                    break;
                case 2:
                    //验证码登录
                    content = "【项目名称】您正在登录项目名称,验证码为:%s,请在3分钟内验证!";
                    content = String.format(content,verifyCode);
                    break;
                case 3:
                    //绑定手机号
                    content = "【项目名称】您正在进行绑定手机号操作,验证码为:%s,请在3分钟内验证!";
                    content = String.format(content,verifyCode);
                    break;
                case 4:
                    //解绑手机号
                    content = "【项目名称】您正在进行解绑手机号操作,验证码为:%s,请在3分钟内验证!";
                    content = String.format(content,verifyCode);
                    break;
                default:break;
            }
            SendSmsUtil.sendNote(mobile,content);
            return verifyCode;
    
        }
    
        //校验
        @Override
        public Boolean checkIsCorrectCode(String mobile, String identifyCode) {
            boolean success = false;
            //首先判断验证码是否存在 如果存在 则修改验证码过期时间延长至180S
            String verifyCode = (String)redisService.get(mobile);
            if(StringUtils.isNotBlank(verifyCode) && verifyCode.equals(identifyCode)) {
                success = true;
            }
            return success;
        }
    }
    
    

    controller层

    @RestController
    @RequestMapping("/api/common")
    public class ApiCommonController extends BaseController {
    
        @Autowired
        private ISmsService smsService;
    
        @PostMapping(value = "/sms/send")
        public AjaxResult getPhoneCode(@Valid @RequestBody VerifyCodeDto codeDto) {
    // 如果需求是:  "type": 0 注册验证码 1为找回密码 2为验证码登录 3为绑定手机号
            if(codeDto.getType() < 3 && codeDto.getType() > 0) {
                // 先判断用户是不是已经注册过了
                AccUser user = new AccUser();
                user.setUsername(codeDto.getPhone());
                List<AccUser> list =  userService.selectAccUserList(user);
                if(list.isEmpty()){
                    return AjaxResult.error("该手机号尚未注册该项目");
                }
            }else if(codeDto.getType() == 3) {
                //处理绑定手机号
                AccUser user = new AccUser();
                user.setUsername(codeDto.getPhone());
                List<AccUser> list =  userService.selectAccUserList(user);
                if(!list.isEmpty()){
                    Long id = list.get(0).getId();
                    AccUserCredential userCredentialCheck = new AccUserCredential();
                    userCredentialCheck.setUserId(id);
                    userCredentialCheck.setLoginType(1);
                    List<AccUserCredential> userCredentials = userCredentialService.selectAccUserCredentialList(userCredentialCheck);
                    if (userCredentials.size()!=0){
                    return AjaxResult.error("该手机号已经注册该项目!");
                    }
                }
            }
            //正常放送短信
            String code = smsService.sendMessage(codeDto.getPhone(),codeDto.getType());
            if(StringUtils.isBlank(code)){
                return AjaxResult.error("短信发送失败");
            }
            Map<String,String> map = new HashMap<>();
            map.put("code",code);
            return AjaxResult.success(map);
        }
    
    }
    
    
    
    
        /**
         * 验证短信验证码是否正确
         * 第一层在APP端已经验证成功
         */
        @EncryptIgnore
        @DecryptIgnore
        @PostMapping(value = "/sms/verify")
        public AjaxResult verifyPhoneCode(@Valid @RequestBody VerifyCodeReq codeReq){
            boolean flag =  smsService.checkIsCorrectCode(codeReq.getPhone(),codeReq.getCode());
            if(!flag){
                return AjaxResult.error("短信验证码校验失败");
            }
            return AjaxResult.success("短信验证码校验成功");
        }
    
    

    相关文章

      网友评论

          本文标题:基于springBoot短信验证码接入

          本文链接:https://www.haomeiwen.com/subject/ljzscltx.html