Commit a97367b2 authored by licc's avatar licc

短信接口

parent d0d606e1
...@@ -2,7 +2,7 @@ package cn.wisenergy.mapper; ...@@ -2,7 +2,7 @@ package cn.wisenergy.mapper;
import cn.wisenergy.model.app.SchemeQueryRecord; import cn.wisenergy.model.app.SchemeQueryRecord;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import io.lettuce.core.dynamic.annotation.Param; import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -14,6 +14,7 @@ public interface SchemeRecordMapper extends BaseMapper<SchemeQueryRecord> { ...@@ -14,6 +14,7 @@ public interface SchemeRecordMapper extends BaseMapper<SchemeQueryRecord> {
/** /**
* 添加方案记录 * 添加方案记录
*
* @param schemeQueryRecord 方案记录信息 * @param schemeQueryRecord 方案记录信息
* @return 方案记录信息 * @return 方案记录信息
*/ */
...@@ -21,6 +22,7 @@ public interface SchemeRecordMapper extends BaseMapper<SchemeQueryRecord> { ...@@ -21,6 +22,7 @@ public interface SchemeRecordMapper extends BaseMapper<SchemeQueryRecord> {
/** /**
* 编辑方案记录 * 编辑方案记录
*
* @param schemeQueryRecord 方案记录信息 * @param schemeQueryRecord 方案记录信息
* @return 0 失败 1 成功 * @return 0 失败 1 成功
*/ */
...@@ -28,6 +30,7 @@ public interface SchemeRecordMapper extends BaseMapper<SchemeQueryRecord> { ...@@ -28,6 +30,7 @@ public interface SchemeRecordMapper extends BaseMapper<SchemeQueryRecord> {
/** /**
* 获取方案记录信息 * 获取方案记录信息
*
* @param id 方案记录id * @param id 方案记录id
* @return * @return
*/ */
...@@ -35,17 +38,18 @@ public interface SchemeRecordMapper extends BaseMapper<SchemeQueryRecord> { ...@@ -35,17 +38,18 @@ public interface SchemeRecordMapper extends BaseMapper<SchemeQueryRecord> {
/** /**
* 统计方案记录条数 * 统计方案记录条数
*
* @param map 统计条件 * @param map 统计条件
* @return 记录条数 * @return 记录条数
*/ */
int count(Map<String, Object> map); int count(Map<String, Object> map);
/** /**
*
* @param userId 用户id * @param userId 用户id
* @param startNum 开始数 * @param startNum 开始数
* @param endNum 结束数 * @param endNum 结束数
* @return 列表 * @return 列表
*/ */
List<SchemeQueryRecord> getByUserId(Integer userId,Integer startNum,Integer endNum ); List<SchemeQueryRecord> getByUserId(@Param("userId") Integer userId, @Param("startNum") Integer startNum,
@Param("endNum") Integer endNum);
} }
package cn.wisenergy.model.enums;
/**
* @author 86187
* @ Description: 短信模板编号枚举
* @ Author : 86187
* @ Date : 2021/1/26 15:37
*/
public enum TemplateType {
;
private Integer code;
private String desc;
TemplateType(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
package cn.wisenergy.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @author 86187
* @ Description: 发送短信验证码Vo
* @ Author : 86187
* @ Date : 2021/1/26 15:06
*/
@Data
@ApiModel(value = "SendSmsVo")
public class SendSmsVo implements Serializable {
private static final long serialVersionUID = -1072677301838222102L;
/**
* 手机号码
*/
@ApiModelProperty(value = "手机号码", name = "phone")
private String phone;
/**
* 来源 PC/APP
*/
@ApiModelProperty(value = "来源 PC/APP", name = "source")
private String source;
/**
* 场景 1:短信登录 2:短信注册 3:短信修改密码 4:短信找回密码 5:短信重置密码
*/
@ApiModelProperty(value = "场景 1:短信登录 2:短信注册 3:短信修改密码 4:短信找回密码 5:短信重置密码", name = "scene")
private Integer scene;
}
...@@ -39,6 +39,13 @@ ...@@ -39,6 +39,13 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- 短信-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.3</version>
</dependency>
</dependencies> </dependencies>
......
package cn.wisenergy.service.app; package cn.wisenergy.service.app;
import cn.wisenergy.common.utils.R; import cn.wisenergy.common.utils.R;
import cn.wisenergy.model.vo.SendSmsVo;
/** /**
* @author 86187 * @author 86187
...@@ -9,23 +10,14 @@ import cn.wisenergy.common.utils.R; ...@@ -9,23 +10,14 @@ import cn.wisenergy.common.utils.R;
* @ Date : 2021/1/15 15:44 * @ Date : 2021/1/15 15:44
*/ */
public interface SendSmsSerVice { public interface SendSmsSerVice {
/** /**
* 发送短信验证码 * 发送短信验证码
* * @param sendSmsVo 入参信息
* @param phone 手机号
* @return true 成功 false 失败 * @return true 成功 false 失败
* @throws Exception 异常
*/ */
R<Boolean> sendSmCode(String phone) throws Exception; R<Boolean> sendSmCode(SendSmsVo sendSmsVo) throws Exception;
/**
* 在缓存中记录验证码
*
* @param phone 手机号
* @param code 短信验证码
* @param type 场景类型 1:验证码登录 2:手机注册 3:修改密码 4:找回密码
* @return 是否成功
*/
R<String> record(String phone, String code, Integer type);
/** /**
* 验证手机验证码:外部调用 * 验证手机验证码:外部调用
......
package cn.wisenergy.service.app.impl;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import java.util.HashMap;
import java.util.Map;
public class SendSms {
public static void main(String[] args) {
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "LTAIuFVMscvCNpMU", "AvotjHvvGzEm8sX9vZaUhVypnZfUk7");
IAcsClient client = new DefaultAcsClient(profile);
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("dysmsapi.aliyuncs.com");
request.setSysVersion("2017-05-25");
request.setSysAction("SendSms");
Map<String,Object> map=new HashMap<>();
map.put("code",123456);
request.putQueryParameter("RegionId", "cn-hangzhou");
request.putQueryParameter("PhoneNumbers", "18757121665");
request.putQueryParameter("SignName", "遵义群智科技有限公司");
request.putQueryParameter("TemplateCode", "SMS_157970381");
request.putQueryParameter("TemplateParam", JSON.toJSONString(map));
try {
CommonResponse response = client.getCommonResponse(request);
System.out.println(response.getData());
} catch (ClientException e) {
e.printStackTrace();
}
}
}
...@@ -2,23 +2,32 @@ package cn.wisenergy.service.app.impl; ...@@ -2,23 +2,32 @@ package cn.wisenergy.service.app.impl;
import cn.wisenergy.common.utils.R; import cn.wisenergy.common.utils.R;
import cn.wisenergy.model.enums.SceneType; import cn.wisenergy.model.enums.SceneType;
import cn.wisenergy.model.vo.SendSmsVo;
import cn.wisenergy.service.app.SendSmsSerVice; import cn.wisenergy.service.app.SendSmsSerVice;
import cn.wisenergy.service.cache.Cache; import cn.wisenergy.service.cache.Cache;
import cn.wisenergy.service.cache.RedisService;
import cn.wisenergy.service.common.CachePrefix; import cn.wisenergy.service.common.CachePrefix;
import cn.wisenergy.service.common.Common; import cn.wisenergy.service.common.Common;
import cn.wisenergy.service.util.SmsSign; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.SimpleFormatter;
/** /**
* @author 86187 * @author 86187
* @ Description: 短信验证码接口实现 * @ Description: 短信验证码接口实现
...@@ -31,45 +40,77 @@ public class SendSmsSerViceImpl implements SendSmsSerVice { ...@@ -31,45 +40,77 @@ public class SendSmsSerViceImpl implements SendSmsSerVice {
@Autowired @Autowired
private Cache cache; private Cache cache;
@Autowired
private RedisService redisService;
@Autowired @Autowired
private RestTemplate restTemplate; private RestTemplate restTemplate;
private static final String SMS_RESULT = "OK";
@Override @Override
public R<Boolean> sendSmCode(String phone) throws Exception { public R<Boolean> sendSmCode(SendSmsVo sendSmsVo) throws Exception {
log.info("volunteer-service[]SendSmsSerViceImpl[]sendSmCode[]input.param.phone:" + phone); log.info("volunteer-service[]SendSmsSerViceImpl[]sendSmCode[]input.param.sendSmsVo:" + sendSmsVo);
if (StringUtils.isBlank(phone)) { if (null == sendSmsVo || StringUtils.isBlank(sendSmsVo.getPhone()) ||
StringUtils.isBlank(sendSmsVo.getSource()) || null == sendSmsVo.getScene()) {
return R.error("入参不能为空!"); return R.error("入参不能为空!");
} }
final HttpHeaders requestHeaders = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
requestHeaders.setContentType(type);
String url = SmsSign.getUrl(); DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", Common.ACCESS_KEY_ID, Common.SMS_SECRET);
log.info("完成路径:"+url); IAcsClient client = new DefaultAcsClient(profile);
String responseEntity = this.restTemplate.getForObject(url, String.class);
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("dysmsapi.aliyuncs.com");
request.setSysVersion("2017-05-25");
request.setSysAction("SendSms");
return R.ok(); //生成六位随机数作为短信验证码
int code = (int) ((Math.random() * 9 + 1) * 100000);
Map<String, Object> map = new HashMap<>(4);
map.put("code", code);
request.putQueryParameter("RegionId", "cn-hangzhou");
request.putQueryParameter("PhoneNumbers", sendSmsVo.getPhone());
request.putQueryParameter("SignName", "遵义群智科技有限公司");
request.putQueryParameter("TemplateCode", "SMS_157970381");
request.putQueryParameter("TemplateParam", JSON.toJSONString(map));
try {
//发送验证码
CommonResponse response = client.getCommonResponse(request);
} catch (ClientException e) {
e.printStackTrace();
} }
@Override //保存验证到缓存,以便做验证
public R<String> record(String phone, String code, Integer scene) { String value = SceneType.getNameByCode(sendSmsVo.getScene());
String value = SceneType.getNameByCode(scene); boolean bool = redisService.set(CachePrefix.SMS_CODE.getPrefix() + value + "_" + sendSmsVo.getPhone(), code, Common.SMS_TIMEOUT);
cache.put(CachePrefix.SMS_CODE.getPrefix() + value + "_" + phone, code, Common.SMS_TIMEOUT); log.info("短信缓存前缀:" + CachePrefix.SMS_CODE.getPrefix());
return R.ok("缓存验证码成功!"); log.info("场景名字:" + value);
return R.ok(bool);
} }
@Override @Override
public R<Boolean> valid(String phone, String code, Integer type) { public R<Boolean> valid(String phone, String code, Integer type) {
String value = SceneType.getNameByCode(type); String value = SceneType.getNameByCode(type);
//获取短信验证码key //获取短信验证码key
String valCode = CachePrefix.SMS_CODE.getPrefix() + value + "_" + phone; String key = CachePrefix.SMS_CODE.getPrefix() + value + "_" + phone;
//判断缓存是否过期
long time = redisService.getExpire(key);
if (time < 0) {
return R.error("验证码已过期!");
}
//redis中获取验证码 //redis中获取验证码
Object obj = cache.get(valCode); Object obj = redisService.get(key);
if (obj != null && obj.equals(code)) { if (obj != null) {
String smCode = obj.toString();
if (code.equals(smCode)) {
//验证码存在,校验通过,清除验证码缓存 //验证码存在,校验通过,清除验证码缓存
cache.remove(valCode); redisService.del(key);
return R.ok(0, true); return R.ok(0, true);
} }
}
return R.ok(1, false); return R.ok(1, false);
} }
...@@ -87,6 +128,4 @@ public class SendSmsSerViceImpl implements SendSmsSerVice { ...@@ -87,6 +128,4 @@ public class SendSmsSerViceImpl implements SendSmsSerVice {
// } // }
// return false; // return false;
} }
} }
package cn.wisenergy.service.common; package cn.wisenergy.service.common;
/** /**
* @author 86187
* @ Description : 对接接口调用公共参数封装 * @ Description : 对接接口调用公共参数封装
* @ Author : lcc * @ Author : lcc
* @ CreateDate : 2020/11/8 20:35 * @ CreateDate : 2020/11/8 20:35
...@@ -13,10 +14,16 @@ public class Common { ...@@ -13,10 +14,16 @@ public class Common {
public static final String RESET_PASSWORD_VALUE = "123456"; public static final String RESET_PASSWORD_VALUE = "123456";
/** /**
* 阿里云短信发送Url * 阿里云短信accessKeyId
*/ */
public static final String SEND_SMS_URL = "http://dysmsapi.aliyuncs.com/?Signature="; public static final String ACCESS_KEY_ID = "LTAIuFVMscvCNpMU";
public static final Integer SMS_TIMEOUT = 300;
/**
* 阿里云短信secret
*/
public static final String SMS_SECRET = "AvotjHvvGzEm8sX9vZaUhVypnZfUk7";
public static final long SMS_TIMEOUT = 300;
} }
package cn.wisenergy.service.util;
import cn.wisenergy.service.common.Common;
import java.util.HashMap;
import java.util.Map;
/**
* @author 86187
*/
public class SmsSign {
public static String getUrl() throws Exception {
String accessKeyId = "LTAIuFVMscvCNpMU";
String accessSecret = "AvotjHvvGzEm8sX9vZaUhVypnZfUk7";
java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
// 这里一定要设置GMT时区
df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
Map<String, String> paras = new HashMap<String, String>();
// 1. 系统参数
paras.put("SignatureMethod", "HMAC-SHA1");
paras.put("SignatureNonce", java.util.UUID.randomUUID().toString());
paras.put("AccessKeyId", accessKeyId);
paras.put("SignatureVersion", "1.0");
paras.put("Timestamp", df.format(new java.util.Date()));
paras.put("Format", "json");
// 2. 业务API参数
paras.put("Action", "SendSms");
paras.put("Version", "2021-01-25");
paras.put("RegionId", "cn-hangzhou");
paras.put("PhoneNumbers", "18757121665");
paras.put("SignName", "阿里云短信测试专用");
paras.put("TemplateParam", "{\"customer\":\"test\"}");
paras.put("TemplateCode", "SMS_157970381");
paras.put("OutId", "123");
// 3. 去除签名关键字Key
if (paras.containsKey("Signature")) {
paras.remove("Signature");
}
// 4. 参数KEY排序
java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>();
sortParas.putAll(paras);
// 5. 构造待签名的字符串
java.util.Iterator<String> it = sortParas.keySet().iterator();
StringBuilder sortQueryStringTmp = new StringBuilder();
while (it.hasNext()) {
String key = it.next();
sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key)));
}
// 去除第一个多余的&符号
String sortedQueryString = sortQueryStringTmp.substring(1);
StringBuilder stringToSign = new StringBuilder();
stringToSign.append("GET").append("&");
stringToSign.append(specialUrlEncode("/")).append("&");
stringToSign.append(specialUrlEncode(sortedQueryString));
String sign = sign(accessSecret + "&", stringToSign.toString());
// 6. 签名最后也要做特殊URL编码
String signature = specialUrlEncode(sign);
System.out.println(Common.SEND_SMS_URL + signature + sortQueryStringTmp);
return Common.SEND_SMS_URL + signature + sortQueryStringTmp;
}
public static String specialUrlEncode(String value) throws Exception {
return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
}
public static String sign(String accessSecret, String stringToSign) throws Exception {
javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
return new sun.misc.BASE64Encoder().encode(signData);
}
}
package cn.wisenergy.web.admin.controller.app; package cn.wisenergy.web.admin.controller.app;
import cn.wisenergy.common.utils.R; import cn.wisenergy.common.utils.R;
import cn.wisenergy.common.utils.StringUtil;
import cn.wisenergy.model.vo.SendSmsVo;
import cn.wisenergy.service.app.SendSmsSerVice; import cn.wisenergy.service.app.SendSmsSerVice;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
...@@ -15,6 +17,7 @@ import org.springframework.web.bind.annotation.*; ...@@ -15,6 +17,7 @@ import org.springframework.web.bind.annotation.*;
* @ Description: 短信管理 * @ Description: 短信管理
* @ Author : 86187 * @ Author : 86187
* @ Date : 2021/1/15 15:40 * @ Date : 2021/1/15 15:40
* @author 86187
*/ */
@RestController @RestController
@Api(tags = "短信管理") @Api(tags = "短信管理")
...@@ -24,32 +27,17 @@ public class SendSmsController { ...@@ -24,32 +27,17 @@ public class SendSmsController {
@Autowired @Autowired
private SendSmsSerVice sendSmsSerVice; private SendSmsSerVice sendSmsSerVice;
@ApiOperation(value = "发送短信验证码", notes = "发送短信验证码", httpMethod = "GET") @ApiOperation(value = "发送短信验证码", notes = "发送短信验证码", httpMethod = "POST")
@ApiImplicitParam(name = "phone", value = "手机号码", dataType = "String", required = true) @ApiImplicitParam(name = "sendSmsVo", value = "手机号码", dataType = "SendSmsVo")
@GetMapping("/sendSms") @PostMapping("/sendSms")
public R<Boolean> sendSms(String phone) throws Exception { public R<Boolean> sendSms(@RequestBody SendSmsVo sendSmsVo) throws Exception {
log.info("SendSmsController[]sendSms[]input.param:phone:" + phone); log.info("SendSmsController[]sendSms[]input.param.sendSmsVo:" + sendSmsVo);
if (StringUtils.isBlank(phone)) { if (null == sendSmsVo || StringUtils.isBlank(sendSmsVo.getPhone()) ||
StringUtils.isBlank(sendSmsVo.getSource()) || null == sendSmsVo.getScene()) {
return R.error("入参为空!"); return R.error("入参为空!");
} }
return sendSmsSerVice.sendSmCode(phone); return sendSmsSerVice.sendSmCode(sendSmsVo);
}
@ApiOperation(value = "在缓存中记录验证码", notes = "在缓存中记录验证码", httpMethod = "GET")
@ApiImplicitParams({
@ApiImplicitParam(name = "phone", value = "手机号码", dataType = "String", required = true),
@ApiImplicitParam(name = "code", value = "短信验证码", dataType = "String", required = true),
@ApiImplicitParam(name = "scene", value = "场景类型 1:验证码登录 2:手机注册 3:修改密码 4:找回密码", dataType = "int", required = true)
})
@GetMapping("/recode")
public R<String> recode(String phone, String code, Integer scene) {
log.info("SendSmsController[]recode[]input.param:phone,code,type" + phone, code, scene);
if (StringUtils.isBlank(phone) || StringUtils.isBlank(code) || null == scene) {
return R.error("入参为空!");
}
return sendSmsSerVice.record(phone, code, scene);
} }
@ApiOperation(value = "在缓存中记录验证码", notes = "在缓存中记录验证码", httpMethod = "GET") @ApiOperation(value = "在缓存中记录验证码", notes = "在缓存中记录验证码", httpMethod = "GET")
......
...@@ -44,18 +44,18 @@ spring: ...@@ -44,18 +44,18 @@ spring:
# 总限制 # 总限制
max-request-size: 10MB max-request-size: 10MB
# redis: redis:
# database: 0 database: 0
# host: localhost host: 192.168.110.165
# port: 6379 port: 6379
# password: root # 密码(默认为空) password: # 密码(默认为空)
# timeout: 6000ms # 连接超时时长(毫秒) timeout: 6000ms # 连接超时时长(毫秒)
# jedis: jedis:
# pool: pool:
# max-active: 1000 # 连接池最大连接数(使用负值表示没有限制) max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
# max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
# max-idle: 10 # 连接池中的最大空闲连接 max-idle: 10 # 连接池中的最大空闲连接
# min-idle: 5 # 连接池中的最小空闲连 min-idle: 5 # 连接池中的最小空闲连
###上传文件配置 :该配置可根据部署的系统或开发人员自定义路径,每次部署之前需要修改location ###上传文件配置 :该配置可根据部署的系统或开发人员自定义路径,每次部署之前需要修改location
uploadFile: uploadFile:
resourceHandler: /upload_flowChart/** #请求 url 中的资源映射也是保存到数据库中的父级路径 resourceHandler: /upload_flowChart/** #请求 url 中的资源映射也是保存到数据库中的父级路径
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment