发送手机或者邮箱验证码的通用功能

ConmmonController层

@ApiOperation(value = "发送验证码V2")
    @ApiImplicitParam(name = "param", value = "发送验证码参数", required = true, dataType = "SendCodeParam", paramType = "body")
    @PostMapping("send_code/v2")
    //@RequestHeader(Constant.LANGUAGE_HEADER) String language 语言功能并没有用上
    public ResponseData<String> sendCodeV2(@RequestBody @Valid SendCodeParamV2 param, BindingResult bindingResult,
                                           @RequestHeader(Constant.LANGUAGE_HEADER) String language) {
        if (bindingResult.hasErrors()) {
            return errorMsg(bindingResult);
        }
        boolean isEmail = false;
        boolean isPhone = false;
        //注意这里的ReUtil类是package cn.hutool.core.util;
        if (ReUtil.isMatch(Constant.PHONE_REGEXP, param.getPhone())) {
            isPhone = true;
        }
        if (ReUtil.isMatch(Constant.EMAIL_REGEXP, param.getPhone())) {
            isEmail = true;
        }
        if (!isEmail && !isPhone) {
            throw new BusinessException(ApiResult.PARAM_IS_ILLEGAL);
        }
        if(isPhone){
            commonService.sendSms(param.getType(), param.getPhone(), null);
            return ResponseData.okMsg("验证码已发送至" + StringUtils.overlay(param.getPhone(), "****", 3, 7) + "手机上");
        }else {
            commonService.sendEmailCode(param.getType(), param.getPhone(), null);
            return ResponseData.okMsg("验证码已发送至" + StringUtils.overlay(param.getPhone(), "****", 3, 7) + "邮箱上");
        }
    }

ConmmonService层

发送短信功能:

@Override
    public ApiResult sendSms(Integer type, String phone, Map<String, Object> templateParam) {
        String sendCodePrefix;
        Example example = Example.builder(User.class).andWhere(Sqls.custom().andEqualTo("username", phone).andEqualTo("deleted", false)).build();
        User user = userMapper.selectOneByExample(example);
        //通用的发送验证码的接口 不论数据库里面是否有用户 都有发送验证码的情况(没有用户:注册;有用户:修改密码忘记密码绑定手机号)
        if (Objects.nonNull(user)) {
            //发送短信的类型:目的是为了注册 那用户为空则已经注册
            if (type.equals(SendCodeType.REGISTER.ordinal())) {
                throw new BusinessException(ApiResult.USERNAME_IS_REGISTERED);
            }
            //用户注册过 但是被锁定
            if (user.getStatus().equals(UserStatus.LOCKED.ordinal())) {
                throw new BusinessException(ApiResult.BE_LOCKED);
            }
            if (type.equals(SendCodeType.FORGET_PWD.ordinal())) {
                sendCodePrefix = RedisKeyPrefix.USER_FORGET_PWD_PREFIX + phone;
            } else if (type.equals(SendCodeType.BIND.ordinal())) {
                // 手机号被绑定,无法发送
                Example userAuthExample = Example.builder(UserAuth.class).where(Sqls.custom().andEqualTo("userId", user.getId())).build();
                if (userAuthMapper.selectCountByExample(userAuthExample) > 0) {
                    throw new BusinessException(ApiResult.USER_AUTH_BIND);
                }

                sendCodePrefix = RedisKeyPrefix.USER_BIND_PHONE_PREFIX + phone;
            } else {
                sendCodePrefix = RedisKeyPrefix.USER_UPDATE_PREFIX + phone;
            }
        } else {
            //用户为空
            if (type.equals(SendCodeType.FORGET_PWD.ordinal())) {
                throw new BusinessException(ApiResult.USERNAME_IS_NOT_EXIST);
            } else if (type.equals(SendCodeType.BIND.ordinal())) {
                sendCodePrefix = RedisKeyPrefix.USER_BIND_PHONE_PREFIX + phone;
            } else {
                sendCodePrefix = RedisKeyPrefix.USER_REGISTER_PREFIX + phone;
            }
        }
        if (templateParam == null) {
            //设置初始容量
            templateParam = new HashMap<>(2);
        }
        Long nowTime = System.currentTimeMillis();
        String code;
        List<Object> list = redisTemplate.boundHashOps(sendCodePrefix).multiGet(Arrays.asList(CODE, "lastSendTime"));
        if (Objects.isNull(list.get(0)) || Objects.isNull(list.get(1))) {
            code = getSixRandom();
            Map<String, Object> map = ImmutableMap.of(CODE, code, "lastSendTime", String.valueOf(nowTime));
            redisTemplate.opsForHash().putAll(sendCodePrefix, map);
        } else {
            Long lastSendTime = Long.valueOf((String) list.get(1));
            // 一分钟发送一次
            if (nowTime - lastSendTime < 60000L) {
                throw new BusinessException(ApiResult.SEND_SMS_FREQUENTLY);
            }
            redisTemplate.opsForHash().put(sendCodePrefix, "lastSendTime", String.valueOf(nowTime));
            code = (String) redisTemplate.opsForHash().get(sendCodePrefix, CODE);
        }
        // 5分钟后失效
        redisTemplate.expireAt(sendCodePrefix, DateUtils.addMinutes(new Date(), 5));
        templateParam.put(CODE, code);
        List<String> phoneList = new ArrayList<>();
        phoneList.add(phone);
        //调用sdk
        String result = smsCore.send("智能炒锅", SendCodeType.values()[type].getTemplateCode(), templateParam, phoneList, null);
        if (result != null) {
            return ApiResult.SUCCESS;
        } else {
            throw new BusinessException(ApiResult.SEND_MAX_SMS);
        }
    }


@Override
    public ApiResult sendEmailCode(Integer type, String email, Map<String, Object> templateParam) {
        String sendCodePrefix;
        Example example =Example.builder(User.class).andWhere(Sqls.custom().andEqualTo("email",email).andEqualTo("deleted",false)).build();
        User user = userMapper.selectOneByExample(example);
        if(Objects.nonNull(user)){
            //发送短信的类型:目的是为了注册 那用户为空则已经注册
            if (type.equals(SendCodeType.REGISTER.ordinal())) {
                throw new BusinessException(ApiResult.USERNAME_IS_REGISTERED);
            }
            //用户注册过 但是被锁定
            if (user.getStatus().equals(UserStatus.LOCKED.ordinal())) {
                throw new BusinessException(ApiResult.BE_LOCKED);
            }

            if (type.equals(SendCodeType.FORGET_PWD.ordinal())) {
                sendCodePrefix = RedisKeyPrefix.USER_FORGET_PWD_PREFIX + email;
            } else if (type.equals(SendCodeType.BIND.ordinal())) {
                // 手机号被绑定,无法发送
                Example userAuthExample = Example.builder(UserAuth.class).where(Sqls.custom().andEqualTo("userId", user.getId())).build();
                if (userAuthMapper.selectCountByExample(userAuthExample) > 0) {
                    throw new BusinessException(ApiResult.USER_AUTH_BIND);
                }

                sendCodePrefix = RedisKeyPrefix.USER_BIND_PHONE_PREFIX + email;
            } else {
                sendCodePrefix = RedisKeyPrefix.USER_UPDATE_PREFIX + email;
            }
        }else {
            //用户为空
            if (type.equals(SendCodeType.FORGET_PWD.ordinal())) {
                throw new BusinessException(ApiResult.USERNAME_IS_NOT_EXIST);
            } else if (type.equals(SendCodeType.BIND.ordinal())) {
                sendCodePrefix = RedisKeyPrefix.USER_BIND_PHONE_PREFIX + email;
            } else {
                sendCodePrefix = RedisKeyPrefix.USER_REGISTER_PREFIX + email;
            }
        }
        if (templateParam == null) {
            //设置初始容量
            templateParam = new HashMap<>(2);
        }
        Long nowTime = System.currentTimeMillis();
        String code;
        List<Object> list = redisTemplate.boundHashOps(sendCodePrefix).multiGet(Arrays.asList(CODE, "lastSendTime"));
        if (Objects.isNull(list.get(0)) || Objects.isNull(list.get(1))) {
            code = getSixRandom();
            Map<String, Object> map = ImmutableMap.of(CODE, code, "lastSendTime", String.valueOf(nowTime));
            redisTemplate.opsForHash().putAll(sendCodePrefix, map);
        } else {
            Long lastSendTime = Long.valueOf((String) list.get(1));
            // 一分钟发送一次
//            if (nowTime - lastSendTime < 60000L) {
//                throw new BusinessException(ApiResult.SEND_SMS_FREQUENTLY);
//            }

            redisTemplate.opsForHash().put(sendCodePrefix, "lastSendTime", String.valueOf(nowTime));
            code = (String) redisTemplate.opsForHash().get(sendCodePrefix, CODE);
        }
        // 5分钟后失效
        redisTemplate.expireAt(sendCodePrefix, DateUtils.addMinutes(new Date(), 5));
        templateParam.put(CODE, code);
        //调用发送邮件接口
        String result = emailService.sendCodeMail(email, code, "5", type, "zh");
        if(result!=null){
            return ApiResult.SUCCESS;
        }
        return ApiResult.BUSINESS_FAIL;
    }

发送邮件EmailService

@Override
    public String sendCodeMail(String email, String code, String minute, Integer type, String language) {
        String result = null;
        if (type.equals(SendCodeType.REGISTER.ordinal())) {
            result = sendRegisteredMail(email, code, minute, type, language);
        }
        if (type.equals(SendCodeType.UPDATE_PWS.ordinal())) {

            result = sendUpdatePwdMail(email, code, minute, type, language);
        }
        if (type.equals(SendCodeType.FORGET_PWD.ordinal())) {

            result = sendUpdatePwdMail(email, code, minute, type, language);
        }
        if (Objects.isNull(result)) {
            throw new BusinessException(ApiResult.FAILED_TO_SEND_MAIL);
        }
        return result;
    }


String sendUpdatePwdMail(String email, String code, String minute, Integer type, String language) {
        boolean ch = FeiyueUtils.languageIsCh(language);
        StringBuilder content = new StringBuilder();
        if (ch) {
            content.append("您正在尝试修改登录密码,验证码为:[").
                    append(code).
                    append("],有效期为[").
                    append(minute).
                    append("分钟],请妥善保管账户信息!");
            String bzId = MailUtil.send(mailAccount, email, "密码修改", content.toString(), false);
            log.info("\n----------发送邮件成功,业务编号:{}", bzId);
            if (StrUtil.isNotBlank(bzId)) {
                return "验证码已发送至" + email + "邮箱上";
            }
        }
        content.append("You are trying to modify the login password, the verification code is: [").
                append(code).
                append("], the validity period is[").
                append(minute).
                append(" minutes],please keep your account information properly!");
        String bzId = MailUtil.send(mailEnAccount, email, "ChangePassword", content.toString(), false);
        if (StrUtil.isNotBlank(bzId)) {
            return "The verification code has been sent to the " + email + " mailbox";
        }
        return null;
    }

String sendRegisteredMail(String email, String code, String minute, Integer type, String language) {
        boolean ch = FeiyueUtils.languageIsCh(language);
        StringBuilder content = new StringBuilder();
        if (ch) {
            content.append("您正在注册成为智能炒锅新用户,验证码为:[").
                    append(code).
                    append("],有效期为[").
                    append(minute).
                    append("分钟],感谢您的支持!");
            String bzId = MailUtil.send(mailAccount, email, "注册验证", content.toString(), false);
            log.info("\n----------发送邮件成功,业务编号:{}", bzId);
            if (StrUtil.isNotBlank(bzId)) {
                return "验证码已发送至" + email + "邮箱上";
            }
        }
        content.append("You are registering as a new WorldValue user, the verification code is: [").
                append(code).
                append("], the validity period is [").
                append(minute).
                append(" minutes],thank you for your support!");
        String bzId = MailUtil.send(mailEnAccount, email, "RegistrationVerification", content.toString(), false);
        log.info("\n----------发送邮件成功,业务编号:{}", bzId);
        if (StrUtil.isNotBlank(bzId)) {
            return "The verification code has been sent to the " + email + " mailbox";
        }
        return null;
    }
package com.zskj.smart_wok.service.properties;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.extra.mail.MailAccount;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeUtility;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;

/**
 * @author dongyao
 * @date 2020/12/15 15:40
 */
@Getter
@Setter
@Slf4j
@Configuration
@ConfigurationProperties(prefix = "service.email")
@EnableConfigurationProperties(ServiceEmailProperties.class)
public class ServiceEmailProperties{
    /**
     * # 邮件服务器的SMTP地址,可选,默认为smtp.<发件人邮箱后缀>
     * host = c1.icoremail.net
     * # 邮件服务器的SMTP端口,可选,默认25
     * port = 25
     * # 发件人(必须正确,否则发送失败)
     * from = *********
     * user = 
     * # 密码(注意,某些邮箱需要为SMTP服务单独设置授权码,详情查看相关帮助)
     * # pass = FbMjkjbNwa5RPdbj
     * pass = Kg2W3h5UT0%0!Pm=
     * # 使用SSL安全连接
     * # sslEnable = true
     */
    private String host;

    private Integer port;

    private String from;

    private String fromEn;

    private String fromInfo;

    private String user;

    private String pass;
    private Boolean auth;
    private Boolean sslEnable;
    private Long timeout;
    private Long connectionTimeout;
    private String socketFactoryClass;
    private Boolean socketFactoryFallback;
    private Integer socketFactoryPort;

    @PostConstruct
    @Bean(name = "mailAccount")
    public MailAccount mailAccount() {
        log.info("\n-------初始化mailAccount");
        MailAccount account = new MailAccount();
        account.setHost(this.host);
        account.setPort(this.port);
        account.setFrom(this.from);
        account.setUser(this.user);
        account.setPass(this.pass);
        account.setAuth(this.auth);
        account.setSslEnable(this.sslEnable);
        account.setTimeout(this.timeout);
        account.setConnectionTimeout(this.connectionTimeout);
        account.setStarttlsEnable(true);
//        account.setSocketFactoryClass(this.socketFactoryClass);
//        account.setSocketFactoryFallback(this.socketFactoryFallback);
//        account.setSocketFactoryPort(this.socketFactoryPort);
        return account;
    }

    @PostConstruct
    @Bean(name = "mailEnAccount")
    public MailAccount mailEnAccount() {
        log.info("\n-------初始化mailEnAccount");
        MailAccount account = new MailAccount();
        account.setHost(this.host);
        account.setPort(this.port);
        account.setFrom(this.fromEn);
        account.setUser(this.user);
        account.setPass(this.pass);
        account.setAuth(this.auth);
        account.setSslEnable(this.sslEnable);
        account.setTimeout(this.timeout);
        account.setConnectionTimeout(this.connectionTimeout);
        account.setStarttlsEnable(true);
//        account.setSocketFactoryClass(this.socketFactoryClass);
//        account.setSocketFactoryFallback(this.socketFactoryFallback);
//        account.setSocketFactoryPort(this.socketFactoryPort);
        return account;
    }

    @PostConstruct
    @Bean(name = "mailInfoAccount")
    public MailAccount mailInfoAccount() {
        log.info("\n-------初始化mailInfoAccount");
        MailAccount account = new MailAccount();
        account.setHost(this.host);
        account.setPort(this.port);
        account.setFrom(this.fromInfo);
        account.setUser(this.user);
        account.setPass(this.pass);
        account.setAuth(this.auth);
        account.setSslEnable(this.sslEnable);
        account.setTimeout(this.timeout);
        account.setConnectionTimeout(this.connectionTimeout);
        account.setStarttlsEnable(true);
//        account.setSocketFactoryClass(this.socketFactoryClass);
//        account.setSocketFactoryFallback(this.socketFactoryFallback);
//        account.setSocketFactoryPort(this.socketFactoryPort);
        return account;
    }

}
spring.profiles.active=dev
spring.jackson.default-property-inclusion=non_null
spring.jackson.time-zone=GMT+8
#freemarker
spring.freemarker.suffix=.html
spring.freemarker.content-type=text/html
spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.charset=utf-8
spring.freemarker.checkTemplateLocation=true

mybatis.config-location=classpath:mybatis-config.xml
mybatis.mapper-locations=classpath:mapper/*.xml

wx.app-id=wxb989b47d3af39aca
wx.app-secret=1486b350bfa4a5b7e2705cd1ff31159e

spring.messages.basename=static/i18n/messages


# 邮件服务器的SMTP地址,可选,默认为smtp.<发件人邮箱后缀>
service.email.host=smtp.qq.com
# 邮件服务器的SMTP端口,可选,默认25
service.email.port=465
# 发件人(必须正确,否则发送失败)
service.email.from=xxxx<11*****11@qq.com>
service.email.from-info=xxxx<11******11@qq.com>
service.email.from-en=WorldValueUserService<11*******11@qq.com>
# 用户名,默认为发件人邮箱前缀
service.email.user=11*****11
# 密码(注意,某些邮箱需要为SMTP服务单独设置授权码,详情查看相关帮助)
service.email.pass=lxbtxlyoycboifjf
service.email.ssl-enable=true
service.email.auth=true
service.email.timeout=25000
service.email.connection-timeout=25000
service.email.socket-factory-class=javax.net.ssl.SSLSocketFactory
#service.email.socket-factory-fallback=false
#service.email.socket-factory-port=465

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值