wuxw
2020-02-10 e082aabd2035e45bf0004424611483551e9d0209
加入验证码发送功能
2个文件已修改
7个文件已添加
603 ■■■■■ 已修改文件
Api/src/main/java/com/java110/api/listener/owner/AppUserBindingOwnerListener.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Api/src/main/java/com/java110/api/listener/user/UserSendSmsListener.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CommonService/src/main/java/com/java110/common/smo/impl/SmsInnerServiceSMOImpl.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-bean/src/main/java/com/java110/dto/msg/SmsDto.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-core/src/main/java/com/java110/core/factory/SendSmsFactory.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-core/src/main/java/com/java110/core/factory/TencentSendMessageFactory.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-core/src/main/java/com/java110/core/smo/common/ISmsInnerServiceSMO.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-utils/src/main/java/com/java110/utils/constant/ServiceCodeConstant.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-utils/src/main/java/com/java110/utils/util/ValidatorUtil.java 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Api/src/main/java/com/java110/api/listener/owner/AppUserBindingOwnerListener.java
@@ -5,17 +5,20 @@
import com.java110.api.listener.AbstractServiceApiListener;
import com.java110.core.annotation.Java110Listener;
import com.java110.core.context.DataFlowContext;
import com.java110.core.smo.common.ISmsInnerServiceSMO;
import com.java110.core.smo.community.ICommunityInnerServiceSMO;
import com.java110.core.smo.file.IFileInnerServiceSMO;
import com.java110.core.smo.owner.IOwnerAppUserInnerServiceSMO;
import com.java110.core.smo.owner.IOwnerInnerServiceSMO;
import com.java110.core.smo.user.IUserInnerServiceSMO;
import com.java110.dto.msg.SmsDto;
import com.java110.dto.user.UserDto;
import com.java110.dto.community.CommunityDto;
import com.java110.dto.owner.OwnerAppUserDto;
import com.java110.dto.owner.OwnerDto;
import com.java110.entity.center.AppService;
import com.java110.event.service.api.ServiceDataFlowEvent;
import com.java110.utils.cache.MappingCache;
import com.java110.utils.constant.*;
import com.java110.utils.util.Assert;
import com.java110.utils.util.BeanConvertUtil;
@@ -48,6 +51,9 @@
    private IFileInnerServiceSMO fileInnerServiceSMOImpl;
    @Autowired
    private ISmsInnerServiceSMO smsInnerServiceSMOImpl;
    @Autowired
    private ICommunityInnerServiceSMO communityInnerServiceSMOImpl;
    @Autowired
@@ -78,10 +84,20 @@
        Assert.hasKeyAndValue(reqJson, "appUserName", "未包含用户名称");
        Assert.hasKeyAndValue(reqJson, "idCard", "未包含身份证号");
        Assert.hasKeyAndValue(reqJson, "link", "未包含联系电话");
        Assert.hasKeyAndValue(reqJson, "msgCode", "未包含联系电话验证码");
        //判断是否有用户ID
        Map<String, String> headers = event.getDataFlowContext().getRequestCurrentHeaders();
        Assert.hasKeyAndValue(headers, "user_id", "请求头中未包含用户信息");
        SmsDto smsDto = new SmsDto();
        smsDto.setTel(reqJson.getString("link"));
        smsDto.setCode(reqJson.getString("msgCode"));
        smsDto = smsInnerServiceSMOImpl.validateCode(smsDto);
        if (!smsDto.isSuccess() && "ON".equals(MappingCache.getValue("APP_USER_BINDING_OWNER_SMS"))) {
            throw new IllegalArgumentException(smsDto.getMsg());
        }
    }
    @Override
@@ -102,7 +118,7 @@
        Assert.hasLength(openId, "该用户不是能力开放用户");
        OwnerAppUserDto ownerAppUserDto = BeanConvertUtil.covertBean(reqJson,OwnerAppUserDto.class);
        OwnerAppUserDto ownerAppUserDto = BeanConvertUtil.covertBean(reqJson, OwnerAppUserDto.class);
        ownerAppUserDto.setStates(new String[]{"10000", "12000"});
        List<OwnerAppUserDto> ownerAppUserDtos = ownerAppUserInnerServiceSMOImpl.queryOwnerAppUsers(ownerAppUserDto);
Api/src/main/java/com/java110/api/listener/user/UserSendSmsListener.java
New file
@@ -0,0 +1,104 @@
package com.java110.api.listener.user;
import com.alibaba.fastjson.JSONObject;
import com.java110.api.listener.AbstractServiceApiListener;
import com.java110.core.annotation.Java110Listener;
import com.java110.core.context.DataFlowContext;
import com.java110.core.factory.SendSmsFactory;
import com.java110.core.smo.common.ISmsInnerServiceSMO;
import com.java110.core.smo.user.IUserInnerServiceSMO;
import com.java110.dto.msg.SmsDto;
import com.java110.dto.user.UserDto;
import com.java110.event.service.api.ServiceDataFlowEvent;
import com.java110.utils.cache.CommonCache;
import com.java110.utils.constant.ServiceCodeConstant;
import com.java110.utils.util.Assert;
import com.java110.utils.util.BeanConvertUtil;
import com.java110.utils.util.DateUtil;
import com.java110.utils.util.StringUtil;
import com.java110.utils.util.ValidatorUtil;
import com.java110.vo.api.user.ApiUserDataVo;
import com.java110.vo.api.user.ApiUserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * 用户发送短信
 */
@Java110Listener("userSendSmsListener")
public class UserSendSmsListener extends AbstractServiceApiListener {
    @Autowired
    private IUserInnerServiceSMO userInnerServiceSMOImpl;
    @Autowired
    private ISmsInnerServiceSMO smsInnerServiceSMOImpl;
    @Override
    public String getServiceCode() {
        return ServiceCodeConstant.USER_SEND_SMS;
    }
    @Override
    public HttpMethod getHttpMethod() {
        return HttpMethod.POST;
    }
    @Override
    public int getOrder() {
        return DEFAULT_ORDER;
    }
    public IUserInnerServiceSMO getUserInnerServiceSMOImpl() {
        return userInnerServiceSMOImpl;
    }
    public void setUserInnerServiceSMOImpl(IUserInnerServiceSMO userInnerServiceSMOImpl) {
        this.userInnerServiceSMOImpl = userInnerServiceSMOImpl;
    }
    @Override
    protected void validate(ServiceDataFlowEvent event, JSONObject reqJson) {
        //super.validatePageInfo(reqJson);
        Assert.hasKeyAndValue(reqJson, "tel", "必填,请填写手机号");
        if (!ValidatorUtil.isMobile(reqJson.getString("tel"))) {
            throw new IllegalArgumentException("手机号格式错误");
        }
        //校验是否有有效的验证码
        String smsCode = CommonCache.getValue(reqJson.getString("tel") + SendSmsFactory.VALIDATE_CODE);
        if (!StringUtil.isEmpty(smsCode) && smsCode.contains("-")) {
            long oldTime = Long.parseLong(smsCode.substring(smsCode.indexOf("-"), smsCode.length()));
            long nowTime = new Date().getTime();
            if (nowTime - oldTime < 1000 * 60 * 2) {
                throw new IllegalArgumentException("请不要重复发送验证码");
            }
        }
    }
    @Override
    protected void doSoService(ServiceDataFlowEvent event, DataFlowContext context, JSONObject reqJson) {
        String tel = reqJson.getString("tel");
        //校验是否传了 分页信息
        String msgCode = SendSmsFactory.generateMessageCode(6);
        SmsDto smsDto = new SmsDto();
        smsDto.setTel(tel);
        smsDto.setCode(msgCode);
        smsDto = smsInnerServiceSMOImpl.send(smsDto);
        ResponseEntity<String> sendMessageResult = new ResponseEntity<String>(smsDto.getMsg(), smsDto.isSuccess() ? HttpStatus.OK : HttpStatus.BAD_REQUEST);
        context.setResponseEntity(sendMessageResult);
    }
}
CommonService/src/main/java/com/java110/common/smo/impl/SmsInnerServiceSMOImpl.java
New file
@@ -0,0 +1,103 @@
package com.java110.common.smo.impl;
import com.java110.common.dao.IMsgServiceDao;
import com.java110.core.base.smo.BaseServiceSMO;
import com.java110.core.factory.SendSmsFactory;
import com.java110.core.smo.common.IMsgInnerServiceSMO;
import com.java110.core.smo.common.ISmsInnerServiceSMO;
import com.java110.core.smo.user.IUserInnerServiceSMO;
import com.java110.dto.PageDto;
import com.java110.dto.msg.MsgDto;
import com.java110.dto.msg.SmsDto;
import com.java110.utils.cache.CommonCache;
import com.java110.utils.util.BeanConvertUtil;
import com.java110.utils.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.List;
/**
 * @ClassName FloorInnerServiceSMOImpl
 * @Description 消息内部服务实现类
 * @Author wuxw
 * @Date 2019/4/24 9:20
 * @Version 1.0
 * add by wuxw 2019/4/24
 **/
@RestController
public class SmsInnerServiceSMOImpl extends BaseServiceSMO implements ISmsInnerServiceSMO {
    private static final Logger logger = LoggerFactory.getLogger(SmsInnerServiceSMOImpl.class);
    @Autowired
    private IMsgServiceDao msgServiceDaoImpl;
    @Autowired
    private IUserInnerServiceSMO userInnerServiceSMOImpl;
    @Override
    public SmsDto send(@RequestBody SmsDto smsDto) {
        try {
            SendSmsFactory.sendSms(smsDto.getTel(), smsDto.getCode());
            //将验证码存入Redis中
            CommonCache.setValue(smsDto.getTel() + SendSmsFactory.VALIDATE_CODE, smsDto.getCode().toLowerCase() + "-" + new Date().getTime(), CommonCache.defaultExpireTime);
            smsDto.setSuccess(true);
            smsDto.setMsg("成功");
        } catch (Exception e) {
            logger.error("发送短信验证码失败", e);
            smsDto.setSuccess(false);
            smsDto.setMsg(e.getMessage());
        }
        return smsDto;
    }
    @Override
    public SmsDto validateCode(@RequestBody SmsDto smsDto) {
        //校验是否有有效的验证码
        String smsCode = CommonCache.getValue(smsDto.getTel() + SendSmsFactory.VALIDATE_CODE);
        if (!StringUtil.isEmpty(smsCode) && smsCode.contains("-")) {
            smsCode = smsCode.substring(0, smsCode.indexOf("-"));
        }
        if (smsCode.equals(smsCode)) {
            smsDto.setSuccess(true);
            smsDto.setMsg("校验成功");
            return smsDto;
        }
        smsDto.setSuccess(false);
        smsDto.setMsg("校验码不存在或不正确");
        return smsDto;
    }
    public IMsgServiceDao getMsgServiceDaoImpl() {
        return msgServiceDaoImpl;
    }
    public void setMsgServiceDaoImpl(IMsgServiceDao msgServiceDaoImpl) {
        this.msgServiceDaoImpl = msgServiceDaoImpl;
    }
    public IUserInnerServiceSMO getUserInnerServiceSMOImpl() {
        return userInnerServiceSMOImpl;
    }
    public void setUserInnerServiceSMOImpl(IUserInnerServiceSMO userInnerServiceSMOImpl) {
        this.userInnerServiceSMOImpl = userInnerServiceSMOImpl;
    }
}
java110-bean/src/main/java/com/java110/dto/msg/SmsDto.java
New file
@@ -0,0 +1,54 @@
package com.java110.dto.msg;
import com.java110.dto.PageDto;
import java.io.Serializable;
import java.util.Date;
/**
 * @ClassName FloorDto
 * @Description 消息数据层封装
 * @Author wuxw
 * @Date 2019/4/24 8:52
 * @Version 1.0
 * add by wuxw 2019/4/24
 **/
public class SmsDto extends PageDto implements Serializable {
    private String tel;
    private String code;
    private boolean success; //true 成功 false 失败
    private String msg; //原因
    public String getTel() {
        return tel;
    }
    public void setTel(String tel) {
        this.tel = tel;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public boolean isSuccess() {
        return success;
    }
    public void setSuccess(boolean success) {
        this.success = success;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}
java110-core/src/main/java/com/java110/core/factory/SendSmsFactory.java
New file
@@ -0,0 +1,48 @@
package com.java110.core.factory;
import com.java110.utils.cache.MappingCache;
import java.util.Random;
/**
 * @ClassName SendSmsFactory
 * @Description 验证码短信发送接口
 * @Author wuxw
 * @Date 2020/2/10 10:14
 * @Version 1.0
 * add by wuxw 2020/2/10
 **/
public class SendSmsFactory {
    private static final String SMS_DOMAIN = "SMS_DOMAIN";
    private static final String SMS_COMPANY = "SMS_COMPANY";
    private static final String SMS_COMPANY_ALI = "ALI";
    private static final String SMS_COMPANY_TENCENT = "TENCENT";
    public static final String VALIDATE_CODE = "_validateTel";
    public static void sendSms(String tel, String code) {
        String smsCompany = MappingCache.getValue(SMS_DOMAIN, SMS_COMPANY);
        if (SMS_COMPANY_ALI.equals(smsCompany)) {
            AliSendMessageFactory.sendMessage(tel, code);
        } else {
            TencentSendMessageFactory.sendMessage(tel, code);
        }
    }
    /**
     * 生成验证码
     *
     * @param limit 位数
     * @return
     */
    public static String generateMessageCode(int limit) {
        Random random = new Random();
        String result = "";
        for (int i = 0; i < limit; i++) {
            result += random.nextInt(10);
        }
        return result;
    }
}
java110-core/src/main/java/com/java110/core/factory/TencentSendMessageFactory.java
New file
@@ -0,0 +1,89 @@
package com.java110.core.factory;
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.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.java110.utils.cache.MappingCache;
import com.java110.utils.factory.ApplicationContextFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.util.Random;
/*
pom.xml
<dependency>
  <groupId>com.aliyun</groupId>
  <artifactId>aliyun-java-sdk-core</artifactId>
  <version>4.0.3</version>
</dependency>
*/
/**
 * Created by wuxw on 2019/3/23.
 */
public class TencentSendMessageFactory {
    private final static String TENCENT_SMS_DOMAIN = "TENCENT_SMS";
    private final static Logger logger = LoggerFactory.getLogger(TencentSendMessageFactory.class);
    public final static int DEFAULT_MESSAGE_CODE_LENGTH = 6;
    private RestTemplate restTemplate;
    /**
     * 生成6位短信码
     *
     * @return
     */
    public static String generateMessageCode() {
        return generateMessageCode(DEFAULT_MESSAGE_CODE_LENGTH);
    }
    /**
     * 生成验证码
     *
     * @param limit 位数
     * @return
     */
    public static String generateMessageCode(int limit) {
        Random random = new Random();
        String result = "";
        for (int i = 0; i < limit; i++) {
            result += random.nextInt(10);
        }
        return result;
    }
    public static void sendMessage(String tel, String code) {
        //开始发送验证码
        logger.debug("发送号码为{},短信码为{}", tel, code);
        String url = "https://sms.tencentcloudapi.com/?Action=SendSms" +
                "&PhoneNumberSet.0=+86" + tel +
                "&TemplateID=" + MappingCache.getValue(TENCENT_SMS_DOMAIN, "TemplateID") +
                "&Sign=" + MappingCache.getValue(TENCENT_SMS_DOMAIN, "Sign") +
                "&TemplateParamSet.0=" + code +
                "&SmsSdkAppid=" + MappingCache.getValue(TENCENT_SMS_DOMAIN, "SmsSdkAppid") +
                "&Version=2019-07-11";
        ResponseEntity<String> responseEntity = getRestTemplate().getForEntity(url, String.class);
        logger.debug("腾讯短信验证码发送,请求报文" + url + ",返回日志" + responseEntity);
    }
    private static RestTemplate getRestTemplate() {
        return ApplicationContextFactory.getBean("restTemplate", RestTemplate.class);
    }
}
java110-core/src/main/java/com/java110/core/smo/common/ISmsInnerServiceSMO.java
New file
@@ -0,0 +1,42 @@
package com.java110.core.smo.common;
import com.java110.core.feign.FeignConfiguration;
import com.java110.dto.msg.MsgDto;
import com.java110.dto.msg.SmsDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
/**
 * @ClassName IMsgInnerServiceSMO
 * @Description 发送短信接口
 * @Author wuxw
 * @Date 2019/4/24 9:04
 * @Version 1.0
 * add by wuxw 2019/4/24
 **/
@FeignClient(name = "common-service", configuration = {FeignConfiguration.class})
@RequestMapping("/smsApi")
public interface ISmsInnerServiceSMO {
    /**
     * <p>查询小区楼信息</p>
     *
     * @param smsDto 短信信息
     * @return MsgDto 对象数据
     */
    @RequestMapping(value = "/send", method = RequestMethod.POST)
    SmsDto send(@RequestBody SmsDto smsDto);
    /**
     * 查询<p>小区楼</p>总记录数
     *
     * @param smsDto 短信信息
     * @return 小区下的小区楼记录数
     */
    @RequestMapping(value = "/validateCode", method = RequestMethod.POST)
    SmsDto validateCode(@RequestBody SmsDto smsDto);
}
java110-utils/src/main/java/com/java110/utils/constant/ServiceCodeConstant.java
@@ -123,6 +123,11 @@
    public static final String LIST_USERS = "user.listUsers";
    /**
     * 查询 组织管理
     */
    public static final String USER_SEND_SMS = "user.userSendSms";
    /**
     * 保存商户信息
     */
    public static final String SERVICE_CODE_SAVE_STORE_INFO = "save.store.info";
java110-utils/src/main/java/com/java110/utils/util/ValidatorUtil.java
New file
@@ -0,0 +1,140 @@
package com.java110.utils.util;
/**
 * @ClassName Vadator
 * @Description TODO
 * @Author wuxw
 * @Date 2020/2/10 11:00
 * @Version 1.0
 * add by wuxw 2020/2/10
 **/
import java.util.regex.Pattern;
/**
 * @program:
 * @description: 校验工具类
 * @author: xujingyang
 * @create: 2019-01-05 16:21
 **/
public class ValidatorUtil {
    /**
     * 正则表达式:验证用户名
     */
    public static final String REGEX_USERNAME = "^[a-zA-Z]\\w{5,20}$";
    /**
     * 正则表达式:验证密码
     */
    public static final String REGEX_PASSWORD = "^[a-zA-Z0-9]{6,20}$";
    /**
     * 正则表达式:验证手机号
     */
    public static final String REGEX_MOBILE = "^(1[0-9])\\d{9}$";
    /**
     * 正则表达式:验证邮箱
     */
    public static final String REGEX_EMAIL = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
    /**
     * 正则表达式:验证汉字
     */
    public static final String REGEX_CHINESE = "^[\u4e00-\u9fa5],{0,}$";
    /**
     * 正则表达式:验证身份证
     */
    public static final String REGEX_ID_CARD = "(^\\d{18}$)|(^\\d{15}$)";
    /**
     * 正则表达式:验证URL
     */
    public static final String REGEX_URL = "http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";
    /**
     * 正则表达式:验证IP地址
     */
    public static final String REGEX_IP_ADDR = "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)";
    /**
     * 校验用户名
     *
     * @param username
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isUsername(String username) {
        return Pattern.matches(REGEX_USERNAME, username);
    }
    /**
     * 校验密码
     *
     * @param password
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isPassword(String password) {
        return Pattern.matches(REGEX_PASSWORD, password);
    }
    /**
     * 校验手机号
     *
     * @param mobile
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isMobile(String mobile) {
        return Pattern.matches(REGEX_MOBILE, mobile);
    }
    /**
     * 校验邮箱
     *
     * @param email
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isEmail(String email) {
        return Pattern.matches(REGEX_EMAIL, email);
    }
    /**
     * 校验汉字
     *
     * @param chinese
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isChinese(String chinese) {
        return Pattern.matches(REGEX_CHINESE, chinese);
    }
    /**
     * 校验身份证
     *
     * @param idCard
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isIDCard(String idCard) {
        return Pattern.matches(REGEX_ID_CARD, idCard);
    }
    /**
     * 校验URL
     *
     * @param url
     * @return 校验通过返回true,否则返回false
     */
    public static boolean isUrl(String url) {
        return Pattern.matches(REGEX_URL, url);
    }
    /**
     * 校验IP地址
     *
     * @param ipAddr
     * @return
     */
    public static boolean isIPAddr(String ipAddr) {
        return Pattern.matches(REGEX_IP_ADDR, ipAddr);
    }
}