美文网首页
基于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