改造短信发送接口

This commit is contained in:
geng.tang@qq.com
2024-01-02 21:33:52 +08:00
parent 2a38f01da7
commit 31edb4775a
32 changed files with 623 additions and 111 deletions

View File

@@ -1,5 +1,6 @@
package com.gxwebsoft.common.core.config;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -102,4 +103,6 @@ public class ConfigProperties {
private String bucketName;
private String bucketDomain;
@ApiModelProperty("项目默认租户")
private Integer tenantId;
}

View File

@@ -8,8 +8,8 @@ public class OrderConstants {
public static final String PAY_METHOD_OTHER = "40"; // 其他支付
// 付款状态
public static final Integer PAY_STATUS_NO_PAY = 10; // 未付款
public static final Integer PAY_STATUS_SUCCESS = 20; // 已付款
public static final int PAY_STATUS_NO_PAY = 10; // 未付款
public static final int PAY_STATUS_SUCCESS = 20; // 已付款
// 发货状态
public static final Integer DELIVERY_STATUS_NO = 10; // 未发货

View File

@@ -0,0 +1,18 @@
package com.gxwebsoft.common.core.enums;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum ESmsType {
LOGIN("SMS_290002047"),
RECEIPT("SMS_290002047"),
ALERT("SMS_464505085"),
OVERDUE("SMS_464525076");
@ApiModelProperty("短信模版编号")
private String templateId;
}

View File

@@ -3,15 +3,23 @@ package com.gxwebsoft.common.core.exception;
import com.gxwebsoft.common.core.Constants;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 全局异常处理器
@@ -19,11 +27,10 @@ import javax.servlet.http.HttpServletResponse;
* @author WebSoft
* @since 2018-02-22 11:29:30
*/
@ControllerAdvice
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
private final Logger logger = LoggerFactory.getLogger(getClass());
@ResponseBody
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public ApiResult<?> methodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException e,
HttpServletResponse response) {
@@ -31,26 +38,33 @@ public class GlobalExceptionHandler {
return new ApiResult<>(Constants.RESULT_ERROR_CODE, "请求方式不正确").setError(e.toString());
}
@ResponseBody
@ExceptionHandler(AccessDeniedException.class)
public ApiResult<?> accessDeniedExceptionHandler(AccessDeniedException e, HttpServletResponse response) {
CommonUtil.addCrossHeaders(response);
return new ApiResult<>(Constants.UNAUTHORIZED_CODE, Constants.UNAUTHORIZED_MSG).setError(e.toString());
}
@ResponseBody
@ExceptionHandler(BusinessException.class)
public ApiResult<?> businessExceptionHandler(BusinessException e, HttpServletResponse response) {
CommonUtil.addCrossHeaders(response);
return new ApiResult<>(e.getCode(), e.getMessage());
}
@ResponseBody
@ExceptionHandler(Throwable.class)
public ApiResult<?> exceptionHandler(Throwable e, HttpServletResponse response) {
logger.error(e.getMessage(), e);
log.error(e.getMessage(), e);
CommonUtil.addCrossHeaders(response);
return new ApiResult<>(Constants.RESULT_ERROR_CODE, Constants.RESULT_ERROR_MSG).setError(e.toString());
}
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public ApiResult<?> MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e)
{
//获取实体类定义的校验注解字段上的message作为异常信息@NotBlank(message = "用户密码不能为空!")异常信息即为"用户密码不能为空!"
List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
String message = allErrors.stream().map(s -> s.getDefaultMessage()).collect(Collectors.joining(";"));
List<String> msgList = Arrays.asList(message.split(";"));
return new ApiResult<>(Constants.RESULT_ERROR_CODE, msgList.get(0));
}
}

View File

@@ -10,6 +10,7 @@ import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.system.entity.Setting;
import com.gxwebsoft.common.system.service.SettingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
@@ -20,6 +21,7 @@ import javax.annotation.Resource;
* @author leng
*
*/
@Slf4j
@Component
public class AlipayConfigUtil {
private final StringRedisTemplate stringRedisTemplate;
@@ -34,6 +36,7 @@ public class AlipayConfigUtil {
@Resource
private ConfigProperties pathConfig;
@Resource
private SettingService settingService;
public AlipayConfigUtil(StringRedisTemplate stringRedisTemplate){
@@ -69,9 +72,8 @@ public class AlipayConfigUtil {
* 获取支付宝秘钥
*/
public JSONObject payment(Integer tenantId) {
System.out.println("tenantId = " + tenantId);
String key = "setting:payment:" + tenantId;
System.out.println("key = " + key);
log.info("tenantId:{}, redis key:{}",tenantId, key);
String cache = stringRedisTemplate.opsForValue().get(key);
if (cache == null) {
Setting payment = settingService.getData("payment");

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.common.core.web;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.gxwebsoft.common.core.Constants;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
@@ -37,6 +38,10 @@ public class ApiResult<T> implements Serializable {
this(code, message, null);
}
public ApiResult(String message) {
this(Constants.RESULT_OK_CODE, message, null);
}
public ApiResult(Integer code, String message, T data) {
this(code, message, data, null);
}
@@ -84,4 +89,7 @@ public class ApiResult<T> implements Serializable {
return this;
}
public boolean isOk(){
return this.code == Constants.RESULT_OK_CODE;
}
}

View File

@@ -2,6 +2,7 @@ package com.gxwebsoft.common.system.controller;
import cn.hutool.core.util.StrUtil;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.enums.ESmsType;
import com.gxwebsoft.common.core.utils.CacheClient;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.web.*;
@@ -40,7 +41,7 @@ public class AccessKeyController extends BaseController {
final PageResult<AccessKey> accessKeyPageResult = accessKeyService.pageRel(param);
if (param.getCode() != null) {
// 短信验证码校验
String code = cacheClient.get(param.getPhone(), String.class);
String code = cacheClient.get(ESmsType.LOGIN.name() + ":" + param.getPhone(), String.class);
if (StrUtil.equals(code,param.getCode())) {
return success(accessKeyPageResult);
}

View File

@@ -7,13 +7,13 @@ import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.enums.ESmsType;
import com.gxwebsoft.common.core.security.JwtSubject;
import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.utils.CacheClient;
@@ -31,18 +31,23 @@ import com.gxwebsoft.common.system.param.UpdatePasswordParam;
import com.gxwebsoft.common.system.result.CaptchaResult;
import com.gxwebsoft.common.system.result.LoginResult;
import com.gxwebsoft.common.system.service.AccessKeyService;
import com.gxwebsoft.common.system.service.AliSmsService;
import com.gxwebsoft.common.system.service.LoginRecordService;
import com.gxwebsoft.common.system.service.RoleMenuService;
import com.gxwebsoft.common.system.service.UserService;
import com.wf.captcha.SpecCaptcha;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
@@ -59,6 +64,7 @@ import java.util.concurrent.TimeUnit;
@Api(tags = "登录认证")
@RestController
@RequestMapping("/api")
@Slf4j
public class MainController extends BaseController {
@Resource
private ConfigProperties configProperties;
@@ -71,9 +77,9 @@ public class MainController extends BaseController {
@Resource
private CacheClient cacheClient;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private AccessKeyService accessKeyService;
@Resource
private AliSmsService aliSmsService;
@ApiOperation("用户登录")
@PostMapping("/login")
@@ -205,41 +211,36 @@ public class MainController extends BaseController {
@ApiOperation("短信验证码")
@PostMapping("/sendSmsCaptcha")
public ApiResult<?> sendSmsCaptcha(@RequestBody SmsCaptchaParam param) {
DefaultProfile profile = DefaultProfile.getProfile("regionld", "LTAI5tBWM9dSmEAoQFhNqxqJ", "Dr0BqiKl7eaL1NNKoCd12qKsbgjnum");
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");
request.putQueryParameter("RegionId", "cn-hangzhou");
request.putQueryParameter("PhoneNumbers", param.getPhone());
request.putQueryParameter("SignName", "南宁网宿科技");
request.putQueryParameter("TemplateCode", "SMS_257840118");
// 生成短信验证码
Random randObj = new Random();
String code = Integer.toString(100000 + randObj.nextInt(900000));
request.putQueryParameter("TemplateParam", "{\"code\":" + code + "}");
try {
CommonResponse response = client.getCommonResponse(request);
String json = response.getData();
Gson g = new Gson();
HashMap result = g.fromJson(json, HashMap.class);
if("OK".equals(result.get("Message"))) {
cacheClient.set(param.getPhone(),code,5L,TimeUnit.MINUTES);
return success("发送成功",result.get("Message"));
}else{
return fail("发送失败");
public ApiResult<?> sendSmsCaptcha(@RequestBody @Valid SmsCaptchaParam param) {
try {
// User user = getLoginUser();
// param.setTenantId(user.getTenantId());
String code = RandomStringUtils.randomNumeric(6);
param.setTemplateParam("{\"code\":" + code + "}");
ApiResult ret = aliSmsService.sendSms(param);
if(ret.isOk()){
ESmsType type = ESmsType.valueOf(param.getType());
cacheClient.set(type.name() + ":" + param.getPhone(), code,5L,TimeUnit.MINUTES);
}
return success(ret);
} catch (ClientException e) {
log.error(e.getMessage(), e);
return fail("发送出错!");
}
} catch (ServerException e) {
e.printStackTrace();
} catch (ClientException e) {
e.printStackTrace();
}
return fail("发送失败");
}
// @ApiOperation("预警短信")
// @PostMapping("/sendSmsAlert")
// public ApiResult<?> sendSmsAlert(@RequestBody SmsCaptchaParam param) {
// try {
// return aliSmsService.sendSms(param);
// } catch (ClientException e) {
// log.error(e.getMessage(), e);
// return fail("发送出错!");
// }
// }
@OperationLog
@ApiOperation("重置密码")
@PutMapping("/password")
@@ -251,7 +252,7 @@ public class MainController extends BaseController {
return fail("验证码不能为空");
}
// 短信验证码校验
String code = cacheClient.get(user.getPhone(), String.class);
String code = cacheClient.get(ESmsType.LOGIN.name() + ":" + user.getPhone(), String.class);
if (!StrUtil.equals(code,user.getCode())) {
return fail("验证码不正确");
}

View File

@@ -1,10 +1,17 @@
package com.gxwebsoft.common.system.param;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.gxwebsoft.common.core.enums.ESmsType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
/**
@@ -14,18 +21,29 @@ import java.io.Serializable;
* @since 2021-08-30 17:35:16
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
//@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiModel(description = "发送短信验证码参数")
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Validated
public class SmsCaptchaParam implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("短信签名")
private String signName;
// @ApiModelProperty("短信签名")
// private String signName;
@ApiModelProperty("手机号码")
@ApiModelProperty(value = "手机号码", required = true)
@NotBlank(message = "手机号码不能为空!")
@Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
private String phone;
@ApiModelProperty("短信模板")
private String TemplateParam;
@ApiModelProperty("短信模板参数")
private String templateParam;
@ApiModelProperty("验证码类型")
private String type = ESmsType.LOGIN.name();
@ApiModelProperty(value = "租户id", hidden = true)
private Integer tenantId;
}

View File

@@ -0,0 +1,23 @@
package com.gxwebsoft.common.system.service;
import com.aliyuncs.exceptions.ClientException;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.system.param.SmsCaptchaParam;
/**
* 阿里短信服务层
*
* @author WebSoft
* @since 2018-12-24 16:10:41
*/
public interface AliSmsService {
/**
* 发送阿里短信
* @param param
* @return
*/
ApiResult sendSms(SmsCaptchaParam param) throws ClientException;
}

View File

@@ -50,6 +50,8 @@ public interface SettingService extends IService<Setting> {
Setting getData(String settingKey);
String getContent(String settingKey, Integer tenantId);
JSONObject getCache(String key);
void initConfig(Setting setting);

View File

@@ -0,0 +1,72 @@
package com.gxwebsoft.common.system.service.impl;
import cn.hutool.core.util.StrUtil;
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 com.google.gson.Gson;
import com.gxwebsoft.common.core.Constants;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.enums.ESmsType;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.system.param.SmsCaptchaParam;
import com.gxwebsoft.common.system.service.AliSmsService;
import com.gxwebsoft.common.system.service.SettingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.HashMap;
@Service
@Slf4j
@RequiredArgsConstructor
public class AliSmsServiceImpl implements AliSmsService {
private final SettingService settingService;
private final ConfigProperties configProperties;
@Override
public ApiResult sendSms(SmsCaptchaParam param) throws ClientException {
Integer tenantId = param.getTenantId();
if(null == tenantId){
tenantId = configProperties.getTenantId();
}
String smsConfig = settingService.getContent("sms", tenantId);
if(StrUtil.isBlank(smsConfig)){
return new ApiResult(Constants.RESULT_ERROR_CODE, "短信参数未配置!");
}
JSONObject smsConfigJson = JSON.parseObject(smsConfig);
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", smsConfigJson.getString("accessKeyId"), smsConfigJson.getString("accessKeySecret"));
IAcsClient client = new DefaultAcsClient(profile);
String signName = smsConfigJson.getString("sign");
ESmsType type = ESmsType.valueOf(param.getType());
CommonRequest request = new CommonRequest();
request.setSysMethod(MethodType.POST);
request.setSysDomain("dysmsapi.aliyuncs.com");
request.setSysVersion("2017-05-25");
request.setSysAction("SendSms");
request.putQueryParameter("RegionId", "cn-hangzhou");
String phone = param.getPhone();
request.putQueryParameter("PhoneNumbers", phone);
request.putQueryParameter("SignName", signName);
request.putQueryParameter("TemplateCode", type.getTemplateId());
request.putQueryParameter("TemplateParam", param.getTemplateParam());
CommonResponse response = client.getCommonResponse(request);
String json = response.getData();
Gson g = new Gson();
HashMap result = g.fromJson(json, HashMap.class);
if("OK".equals(result.get("Message"))) {
return new ApiResult("发送成功");
}
log.warn("阿里云短信发送失败!{}", json);
return new ApiResult(Constants.RESULT_ERROR_CODE, "发送失败");
}
}

View File

@@ -1,5 +1,6 @@
package com.gxwebsoft.common.system.service.impl;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -99,6 +100,32 @@ public class SettingServiceImpl extends ServiceImpl<SettingMapper, Setting> impl
return query().eq("setting_key", settingKey).one();
}
@Override
public String getContent(String settingKey, Integer tenantId) {
String redisKey = settingKey + ":";
if(null != tenantId){
redisKey += tenantId;
} else {
redisKey += -1;
}
if(stringRedisTemplate.hasKey(redisKey)){
return stringRedisTemplate.opsForValue().get(redisKey);
}
Setting setting = query().eq("setting_key", settingKey)
.eq(null != tenantId, "tenant_id", tenantId)
.eq("deleted", 0)
.orderByDesc("setting_id")
.last("limit 1")
.one();
if(null == setting){
return "";
}
String ret = setting.getContent();
stringRedisTemplate.opsForValue().set(redisKey, ret);
return ret;
}
@Override
public JSONObject getCache(String key) {
final String cache = stringRedisTemplate.opsForValue().get(key);