浏览代码

优化-改造短信发送模块

xiaof 2 年之前
父节点
当前提交
a13a2ce12b

+ 0 - 69
paper-library-business/src/main/java/com/qmth/paper/library/business/util/SmsUtils.java

@@ -1,69 +0,0 @@
-package com.qmth.paper.library.business.util;
-
-import com.aliyuncs.DefaultAcsClient;
-import com.aliyuncs.IAcsClient;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
-import com.aliyuncs.exceptions.ClientException;
-import com.aliyuncs.http.MethodType;
-import com.aliyuncs.profile.DefaultProfile;
-import com.aliyuncs.profile.IClientProfile;
-import com.qmth.paper.library.common.config.DictionaryConfig;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-
-/**
- * @Date: 2021/11/5.
- */
-@Component
-public class SmsUtils {
-
-    @Resource
-    private DictionaryConfig dictionaryConfig;
-
-    /**
-     * 发送短信
-     *
-     * @param mobileNumber
-     * @param templateCode
-     * @param variableParams
-     * @return
-     * @throws ClientException
-     */
-    public SendSmsResponse sendSms(String mobileNumber, String templateCode, String variableParams) throws ClientException {
-        System.setProperty("sun.net.client.defaultConnectTimeout", "180000");
-        System.setProperty("sun.net.client.defaultReadTimeout", "18000");
-        // 初始化ascClient需要的几个参数
-        final String product = "Dysmsapi";// 短信API产品名称(短信产品名固定,无需修改)
-        final String domain = "dysmsapi.aliyuncs.com";// 短信API产品域名(接口地址固定,无需修改)
-        // 替换成你的AK
-        final String accessKeyId = dictionaryConfig.smsDomain().getAliyunSMSKey();// 你的accessKeyId,参考本文档步骤2
-        final String accessKeySecret = dictionaryConfig.smsDomain().getAliyunSMSSecret();// 你的accessKeySecret,参考本文档步骤2
-        // 初始化ascClient,暂时不支持多region(请勿修改)
-        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
-        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
-        IAcsClient acsClient = new DefaultAcsClient(profile);
-        // 组装请求对象
-        SendSmsRequest request = new SendSmsRequest();
-        // 使用post提交
-        request.setMethod(MethodType.POST);
-        // 必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为00+国际区号+号码,如“0085200000000”
-        request.setPhoneNumbers(mobileNumber);
-        // 必填:短信签名-可在短信控制台中找到
-        request.setSignName(dictionaryConfig.smsDomain().getAliyunSMSSignName());
-        // 必填:短信模板-可在短信控制台中找到
-        request.setTemplateCode(templateCode);
-        // 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
-        // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
-        request.setTemplateParam(variableParams);
-        // 可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
-        // request.setSmsUpExtendCode("90997");
-        // 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
-//             request.setOutId("yourOutId");
-        // 请求失败这里会抛ClientException异常
-
-        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
-        return sendSmsResponse;
-    }
-}

+ 4 - 0
paper-library-common/pom.xml

@@ -22,6 +22,10 @@
             <groupId>com.qmth.boot</groupId>
             <artifactId>core-fss</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.qmth.boot</groupId>
+            <artifactId>core-sms</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.qmth.boot</groupId>
             <artifactId>tools-device</artifactId>

+ 4 - 5
paper-library-common/src/main/java/com/qmth/paper/library/common/config/DictionaryConfig.java

@@ -8,11 +8,7 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
 /**
- * @Description: 数据字典
- * @Param:
- * @return:
- * @Author: wangliang
- * @Date: 2020/4/10
+ * 数据字典
  */
 @Configuration
 public class DictionaryConfig {
@@ -35,6 +31,9 @@ public class DictionaryConfig {
         return new SmsDomain();
     }
 
+    /**
+     * fss配置
+     */
     @Bean
     @ConfigurationProperties(prefix = "com.qmth.fss", ignoreUnknownFields = false)
     public FssDomain fssDomain() {

+ 2 - 0
paper-library-common/src/main/java/com/qmth/paper/library/common/contant/SysSettingConstant.java

@@ -10,6 +10,8 @@ public class SysSettingConstant {
     public static final String SYS_INIT_PASSWORD = "initPassword";
     public static final String SYS_FILE_HOST_URL = "fileHostUrl";
     public static final String SYS_VERIFICATION_CODE_LOGIN_ENABLE = "verificationCodeLoginEnable";
+    public static final String SYS_VERIFICATION_CODE_EXPIRED_TIME = "verificationCodeExpiredTime";
+    public static final String SYS_VERIFICATION_CODE_SEND_INTERVAL = "verificationCodeSendInterval";
     public static final String SYS_SMS_NOTIFICATION_ENABLE = "SMSNotificationEnable";
     public static final String SYS_TXT_CHARSET = "txtCharset";
     public static final String OCR_OPEN = "openOcr";

+ 12 - 46
paper-library-common/src/main/java/com/qmth/paper/library/common/domain/SmsDomain.java

@@ -6,12 +6,10 @@ package com.qmth.paper.library.common.domain;
 public class SmsDomain {
 
     String smsNormalCode;
-    Integer codeExpiredTime;
-    Integer codeSendInterval;
-    String aliyunSMSKey;
-    String aliyunSMSSecret;
-    String aliyunSMSSignName;
-    String aliyunSMSTplCode;
+
+    String smsSignName;
+
+    String verificationCode;
 
     public String getSmsNormalCode() {
         return smsNormalCode;
@@ -21,51 +19,19 @@ public class SmsDomain {
         this.smsNormalCode = smsNormalCode;
     }
 
-    public Integer getCodeExpiredTime() {
-        return codeExpiredTime;
-    }
-
-    public void setCodeExpiredTime(Integer codeExpiredTime) {
-        this.codeExpiredTime = codeExpiredTime;
-    }
-
-    public Integer getCodeSendInterval() {
-        return codeSendInterval;
-    }
-
-    public void setCodeSendInterval(Integer codeSendInterval) {
-        this.codeSendInterval = codeSendInterval;
-    }
-
-    public String getAliyunSMSKey() {
-        return aliyunSMSKey;
-    }
-
-    public void setAliyunSMSKey(String aliyunSMSKey) {
-        this.aliyunSMSKey = aliyunSMSKey;
-    }
-
-    public String getAliyunSMSSecret() {
-        return aliyunSMSSecret;
-    }
-
-    public void setAliyunSMSSecret(String aliyunSMSSecret) {
-        this.aliyunSMSSecret = aliyunSMSSecret;
-    }
-
-    public String getAliyunSMSSignName() {
-        return aliyunSMSSignName;
+    public String getSmsSignName() {
+        return smsSignName;
     }
 
-    public void setAliyunSMSSignName(String aliyunSMSSignName) {
-        this.aliyunSMSSignName = aliyunSMSSignName;
+    public void setSmsSignName(String smsSignName) {
+        this.smsSignName = smsSignName;
     }
 
-    public String getAliyunSMSTplCode() {
-        return aliyunSMSTplCode;
+    public String getVerificationCode() {
+        return verificationCode;
     }
 
-    public void setAliyunSMSTplCode(String aliyunSMSTplCode) {
-        this.aliyunSMSTplCode = aliyunSMSTplCode;
+    public void setVerificationCode(String verificationCode) {
+        this.verificationCode = verificationCode;
     }
 }

+ 9 - 3
paper-library-common/src/main/java/com/qmth/paper/library/common/entity/SysSettingGlobal.java

@@ -49,12 +49,18 @@ public class SysSettingGlobal extends BaseEntity implements Serializable {
         settingObjects.add(new SettingObject("系统设置", 1, simpleObjects1));
 
         List<SimpleObject> simpleObjects2 = new ArrayList<>();
-        simpleObjects2.add(new SimpleObject(SysSettingConstant.OCR_APP_ID, "OCR AppId", "", 2, true));
-        simpleObjects2.add(new SimpleObject(SysSettingConstant.OCR_APP_KEY, "OCR AppKey", "", 3, true));
-        simpleObjects2.add(new SimpleObject(SysSettingConstant.OCR_APP_SECRET, "OCR AppSecret", "", 4, true));
+        simpleObjects2.add(new SimpleObject(SysSettingConstant.OCR_APP_ID, "OCR AppId", "", 1, true));
+        simpleObjects2.add(new SimpleObject(SysSettingConstant.OCR_APP_KEY, "OCR AppKey", "", 2, true));
+        simpleObjects2.add(new SimpleObject(SysSettingConstant.OCR_APP_SECRET, "OCR AppSecret", "", 3, true));
 
         settingObjects.add(new SettingObject("OCR参数设置", 2, simpleObjects2));
 
+        List<SimpleObject> simpleObjects3 = new ArrayList<>();
+        simpleObjects3.add(new SimpleObject(SysSettingConstant.SYS_VERIFICATION_CODE_EXPIRED_TIME, "验证码有效时间(分钟)", "2", 1, true));
+        simpleObjects3.add(new SimpleObject(SysSettingConstant.SYS_VERIFICATION_CODE_SEND_INTERVAL, "验证码发送频率(秒)", "60", 2, true));
+
+        settingObjects.add(new SettingObject("短信参数设置", 3, simpleObjects3));
+
         SysSettingGlobal sysSetting = new SysSettingGlobal();
         sysSetting.setParameterObject(JSON.toJSONString(settingObjects));
         return sysSetting;

+ 2 - 0
paper-library-common/src/main/java/com/qmth/paper/library/common/enums/ExceptionResultEnum.java

@@ -67,6 +67,8 @@ public enum ExceptionResultEnum {
 
     ATTACHMENT_IS_NULL(HttpStatus.INTERNAL_SERVER_ERROR, 50000024, "找不到附件"),
 
+    SIGN_NAME_NOT_SETTING(HttpStatus.INTERNAL_SERVER_ERROR, 5000025, "短信签名未配置"),
+
     EXAM_TASK_IS_NULL(HttpStatus.INTERNAL_SERVER_ERROR, 50000029, "命题任务为空"),
 
     NO_DATA(HttpStatus.INTERNAL_SERVER_ERROR, 5000030, "没有数据"),

+ 20 - 56
paper-library-common/src/main/java/com/qmth/paper/library/common/service/impl/BasicVerifyCodeServiceImpl.java

@@ -1,13 +1,5 @@
 package com.qmth.paper.library.common.service.impl;
 
-import com.aliyuncs.DefaultAcsClient;
-import com.aliyuncs.IAcsClient;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
-import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
-import com.aliyuncs.exceptions.ClientException;
-import com.aliyuncs.http.MethodType;
-import com.aliyuncs.profile.DefaultProfile;
-import com.aliyuncs.profile.IClientProfile;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.paper.library.common.config.DictionaryConfig;
@@ -18,30 +10,33 @@ import com.qmth.paper.library.common.enums.ExceptionResultEnum;
 import com.qmth.paper.library.common.mapper.BasicVerifyCodeMapper;
 import com.qmth.paper.library.common.service.BasicVerifyCodeService;
 import com.qmth.paper.library.common.service.CommonCacheService;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.qmth.paper.library.common.util.SmsSendUtil;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.util.Calendar;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * <p>
  * 短信验证码记录表 服务实现类
  * </p>
- *
- * @author xf
- * @since 2021-03-23
  */
 @Service
 public class BasicVerifyCodeServiceImpl extends ServiceImpl<BasicVerifyCodeMapper, BasicVerifyCode> implements BasicVerifyCodeService {
 
-    @Autowired
+    @Resource
     private DictionaryConfig dictionaryConfig;
 
     @Resource
     private CommonCacheService commonCacheService;
 
+    @Resource
+    private SmsSendUtil smsSendUtil;
+
     @Override
     public void sendVeirfyCode(String mobileNumber, SysUser sysUser) {
         String verificationCodeLoginEnable = commonCacheService.getSysSettingGlobal().get(SysSettingConstant.SYS_VERIFICATION_CODE_LOGIN_ENABLE);
@@ -56,49 +51,25 @@ public class BasicVerifyCodeServiceImpl extends ServiceImpl<BasicVerifyCodeMappe
         BasicVerifyCode basicVerifyCode = this.getOne(wrapper);
         if (basicVerifyCode != null) {
             Date oldCreateTime = new Date(basicVerifyCode.getCreateTime());
-            Integer sendInterval = dictionaryConfig.smsDomain().getCodeSendInterval();
+            Integer sendInterval = Integer.valueOf(commonCacheService.getSysSettingGlobal().get(SysSettingConstant.SYS_VERIFICATION_CODE_SEND_INTERVAL));
             if ((System.currentTimeMillis() - oldCreateTime.getTime()) < sendInterval * 1000) {
                 throw ExceptionResultEnum.ERROR.exception("发送验证码过于频繁,请" + sendInterval + "秒之后再试");
             }
         }
         try {
+            // 验证码
             StringBuilder sb = new StringBuilder();
             sb.append((int) ((Math.random() * 9 + 1) * 1000));
             String verifyCode = sb.toString();
-            System.setProperty("sun.net.client.defaultConnectTimeout", "180000");
-            System.setProperty("sun.net.client.defaultReadTimeout", "18000");
-            // 初始化ascClient需要的几个参数
-            final String product = "Dysmsapi";// 短信API产品名称(短信产品名固定,无需修改)
-            final String domain = "dysmsapi.aliyuncs.com";// 短信API产品域名(接口地址固定,无需修改)
-            // 替换成你的AK
-            final String accessKeyId = dictionaryConfig.smsDomain().getAliyunSMSKey();// 你的accessKeyId,参考本文档步骤2
-            final String accessKeySecret = dictionaryConfig.smsDomain().getAliyunSMSSecret();// 你的accessKeySecret,参考本文档步骤2
-            // 初始化ascClient,暂时不支持多region(请勿修改)
-            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
-            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
-            IAcsClient acsClient = new DefaultAcsClient(profile);
-            // 组装请求对象
-            SendSmsRequest request = new SendSmsRequest();
-            // 使用post提交
-            request.setMethod(MethodType.POST);
-            // 必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为00+国际区号+号码,如“0085200000000”
-            request.setPhoneNumbers(mobileNumber);
-            // 必填:短信签名-可在短信控制台中找到
-            request.setSignName(dictionaryConfig.smsDomain().getAliyunSMSSignName());
-            // 必填:短信模板-可在短信控制台中找到
-            request.setTemplateCode(dictionaryConfig.smsDomain().getAliyunSMSTplCode());
-            // 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
-            // 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
-            request.setTemplateParam("{\"code\":\"" + verifyCode + "\"}");
-            // 可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
-            // request.setSmsUpExtendCode("90997");
-            // 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
-            // request.setOutId("yourOutId");
-            // 请求失败这里会抛ClientException异常
-            SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
-            if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {
+
+            String templateCode = dictionaryConfig.smsDomain().getVerificationCode();
+            Map<String, Object> templateParam = new HashMap<>();
+            templateParam.put("code", verifyCode);
+            String bizId = smsSendUtil.sendSms(mobileNumber, templateCode, templateParam);
+
+            if (StringUtils.isNotBlank(bizId)) {
                 // 请求成功
-                Integer codeExpiredTime = dictionaryConfig.smsDomain().getCodeExpiredTime();
+                Integer codeExpiredTime = Integer.valueOf(commonCacheService.getSysSettingGlobal().get(SysSettingConstant.SYS_VERIFICATION_CODE_EXPIRED_TIME));
                 if (basicVerifyCode == null) {
                     basicVerifyCode = new BasicVerifyCode();
                     basicVerifyCode.setUserId(sysUser.getId());
@@ -118,16 +89,9 @@ public class BasicVerifyCodeServiceImpl extends ServiceImpl<BasicVerifyCodeMappe
                     basicVerifyCode.setUpdateTime(System.currentTimeMillis());
                     this.updateById(basicVerifyCode);
                 }
-            } else {
-                if("isv.MOBILE_NUMBER_ILLEGAL".equals(sendSmsResponse.getCode())){
-                    throw ExceptionResultEnum.ERROR.exception("非法手机号");
-                }else {
-                    throw ExceptionResultEnum.ERROR.exception(sendSmsResponse.getMessage());
-                }
             }
-        } catch (ClientException e) {
-            String error = e.getMessage();
-            throw ExceptionResultEnum.ERROR.exception("请重新获取验证码");
+        } catch (Exception e) {
+            throw ExceptionResultEnum.ERROR.exception("请重新获取验证码:" + e.getMessage());
         }
     }
 

+ 2 - 0
paper-library-common/src/main/java/com/qmth/paper/library/common/service/impl/SysUserServiceImpl.java

@@ -92,6 +92,8 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
     @Resource
     CommonCacheService commonCacheService;
 
+
+
     @Override
     public IPage<UserDto> listForPrintSystem(String userInfo, Long orgId, String roleId, Boolean enable, Integer pageNumber, Integer pageSize) {
         Long schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());

+ 72 - 0
paper-library-common/src/main/java/com/qmth/paper/library/common/util/SmsSendUtil.java

@@ -0,0 +1,72 @@
+package com.qmth.paper.library.common.util;
+
+import com.qmth.boot.core.sms.model.SmsSendRequest;
+import com.qmth.boot.core.sms.model.SmsSendResponse;
+import com.qmth.boot.core.sms.service.SmsService;
+import com.qmth.paper.library.common.config.DictionaryConfig;
+import com.qmth.paper.library.common.enums.ExceptionResultEnum;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Map;
+
+/**
+ * 短信发送工具类
+ */
+@Component
+public class SmsSendUtil {
+    private final static Logger log = LoggerFactory.getLogger(SmsSendUtil.class);
+
+    @Resource
+    private SmsService smsService;
+
+    @Resource
+    DictionaryConfig dictionaryConfig;
+
+
+    /**
+     * 短信发送接口
+     *
+     * @param phoneNumber   发送手机号
+     * @param templateCode  短信模版编号
+     * @param templateParam 模版变量
+     * @return bizId 本次操作业务标识
+     */
+    public String sendSms(String phoneNumber, String templateCode, Map<String, Object> templateParam) {
+        validDictionaryConfig(dictionaryConfig);
+        SmsSendRequest smsSendRequest = new SmsSendRequest();
+        // 必填,发送手机号
+        smsSendRequest.setPhoneNumber(phoneNumber);
+        // 必填,短信签名
+        smsSendRequest.setSignName(dictionaryConfig.smsDomain().getSmsSignName());
+        // 必填,短信模版编号
+        smsSendRequest.setTemplateCode(templateCode);
+        //模版变量,可选
+        if (templateParam != null && !templateParam.isEmpty()) {
+            smsSendRequest.setTemplateParam(templateParam);
+        }
+
+        SmsSendResponse smsSendResponse = smsService.sendSms(smsSendRequest);
+        if (smsSendResponse == null) {
+            throw ExceptionResultEnum.ERROR.exception("短信发送失败");
+        }
+        return smsSendResponse.getBizId();
+    }
+
+    /**
+     * 校验文件存储配置参数
+     *
+     * @param dictionaryConfig dictionaryConfig
+     */
+    private void validDictionaryConfig(DictionaryConfig dictionaryConfig) {
+        if (dictionaryConfig != null) {
+            if (StringUtils.isBlank(dictionaryConfig.smsDomain().getSmsSignName())) {
+                throw ExceptionResultEnum.SIGN_NAME_NOT_SETTING.exception();
+            }
+        }
+    }
+
+}

+ 4 - 6
paper-library/src/main/resources/application.properties

@@ -50,10 +50,8 @@ spring.cache.ehcache.config=classpath:ehcache/ehcache.xml
 spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
 spring.jackson.time-zone=GMT+8
 
+#-----------------sms config--------------
+com.qmth.sms.server=https://solar.qmth.com.cn
 sms.config.smsNormalCode=qmth
-sms.config.codeExpiredTime=2
-sms.config.codeSendInterval=60
-sms.config.aliyunSMSKey=LTAI4Fi8jVRYT49QBXU9x5QX
-sms.config.aliyunSMSSecret=97aBLBfkQR5mzCiQa82yWLAH57eUd8
-sms.config.aliyunSMSSignName=\u9038\u6559\u4E91
-sms.config.aliyunSMSTplCode=SMS_147416565
+sms.config.smsSignName=\u9038\u6559\u4E91
+sms.config.verificationCode=SMS_147416565

+ 5 - 0
pom.xml

@@ -92,6 +92,11 @@
                 <artifactId>core-fss</artifactId>
                 <version>${qmth.boot.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.qmth.boot</groupId>
+                <artifactId>core-sms</artifactId>
+                <version>${qmth.boot.version}</version>
+            </dependency>
             <dependency>
                 <groupId>com.qmth.boot</groupId>
                 <artifactId>data-mybatis-plus</artifactId>