基于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使用
- 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);
}
}
- 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("短信验证码校验成功");
}
网友评论