SpringBoot 整合阿里云短信

1. pom.xml Maven依赖

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-core</artifactId>
    <version>4.5.17</version>
</dependency>

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
    <version>2.1.0</version>
</dependency>

 2. application.yml 配置文件

sms:
  common:
    code-length: 6
    code-period: 300
  aliyun:
    access-key-id: LTAISDdmjBtCU1CQ
    access-key-secret: beutUXdEqZCaaeKzwlXD79WSdsG243
    template:
      sign-name: dcy
      # 登录模板
      code-login: SMS_209131746
      # 重置密码模板
      code-reset-password: SMS_202631506
    error-code:
      isv:
        RAM_PERMISSION_DENY: RAM权限DENY
        OUT_OF_SERVICE: 业务停机
        PRODUCT_UN_SUBSCRIPT: 未开通云通信产品的阿里云客户
        PRODUCT_UNSUBSCRIBE: 产品未开通
        ACCOUNT_NOT_EXISTS: 账户不存在
        ACCOUNT_ABNORMAL: 账户异常
        SMS_TEMPLATE_ILLEGAL: 短信模板不合法
        SMS_SIGNATURE_ILLEGAL: 短信签名不合法
        INVALID_PARAMETERS: 参数异常
        SYSTEM_ERROR: 系统错误
        MOBILE_NUMBER_ILLEGAL: 非法手机号
        MOBILE_COUNT_OVER_LIMIT: 手机号码数量超过限制
        TEMPLATE_MISSING_PARAMETERS: 模板缺少变量
        BUSINESS_LIMIT_CONTROL: 业务限流
        INVALID_JSON_PARAM: JSON参数不合法,只接受字符串值
        BLACK_KEY_CONTROL_LIMIT: 黑名单管控
        PARAM_LENGTH_LIMIT: 参数超出长度限制
        PARAM_NOT_SUPPORT_URL: 不支持URL
        AMOUNT_NOT_ENOUGH: 账户余额不足

3. 配置类

package com.ruhuanxingyun.dcy.service.manage.config;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

/**
 * @description: 阿里云短信
 * @author: ruphie
 * @date: Create in 2021/4/17 9:24
 * @company: ruhuanxingyun
 */
@Configuration
@ConfigurationProperties(prefix = "sms")
@Data
public class AliyunSmsProvider {

    /**
     * 公共信息
     */
    private Common common = new Common();

    /**
     * 阿里云短信
     */
    private Aliyun aliyun = new Aliyun();

    @Data
    public class Common {

        /**
         * 验证码长度
         */
        private int codeLength;

        /**
         * 验证码有限期
         */
        private long codePeriod;

    }

    @Data
    public class Aliyun {

        /**
         * accessKeyId
         */
        private String accessKeyId;

        /**
         * accessKeySecret
         */
        private String accessKeySecret;

        /**
         * 模板
         */
        private Template template = new Template();

        /**
         * 错误码
         */
        private Map<String, String> errorCode;

        @Data
        public class Template {

            /**
             * 签名
             */
            private String signName;

            /**
             * 登录模板
             */
            private String codeLogin;

            /**
             * 重置密码模板
             */
            private String codeResetPassword;

        }

    }

    @Bean
    public IAcsClient acsClient() {
        // 设置超时时间
        System.setProperty("sun.net.client.defaultConnectTimeout", "5000");
        System.setProperty("sun.net.client.defaultReadTimeout", "5000");
        // 初始化ascClient
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", aliyun.getAccessKeyId(), aliyun.getAccessKeySecret());
        DefaultProfile.addEndpoint("cn-hangzhou", "Dysmsapi", "dysmsapi.aliyuncs.com");

        return new DefaultAcsClient(profile);
    }

}

4. 服务层

package com.ruhuanxingyun.dcy.service.manage.service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.ruhuanxingyun.dcy.service.manage.config.AliyunSmsProvider;
import com.ruhuanxingyun.dcy.service.manage.constant.RedisConstants;
import com.ruhuanxingyun.dcy.service.manage.constant.UserConstants;
import com.ruhuanxingyun.dcy.service.manage.enums.CodeEnum;
import com.ruhuanxingyun.dcy.service.manage.enums.StatusEnum;
import com.ruhuanxingyun.dcy.service.manage.model.dto.SmsDTO;
import com.ruhuanxingyun.dcy.service.manage.model.entity.system.User;
import com.ruhuanxingyun.dcy.service.manage.service.system.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @description: 短信 服务层
 * @author: ruphie
 * @date: Create in 2021/4/17 9:45
 * @company: ruhuanxingyun
 */
@Slf4j
@Service
public class SmsService {

    @Autowired
    private UserService userService;

    @Autowired
    private AliyunSmsProvider aliyunSmsProvider;

    @Autowired
    private IAcsClient acsClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 发送短信验证码
     *
     * @param smsDTO 短信信息
     * @return 状态
     */
    public String sendSmsCode(SmsDTO smsDTO) {
        String phone = smsDTO.getPhone();
        // 校验手机号
        String result = this.verifyPhone(phone);
        if (StrUtil.isNotBlank(result)) {
            return result;
        }

        AliyunSmsProvider.Common common = aliyunSmsProvider.getCommon();
        StringBuilder code = new StringBuilder();
        // 生成验证码
        for (int i = 0, len = common.getCodeLength(); i < len; i++) {
            code.append((int) (Math.random() * 10));
        }

        // 获取短信配置
        AliyunSmsProvider.Aliyun aliyun = aliyunSmsProvider.getAliyun();
        AliyunSmsProvider.Aliyun.Template template = aliyun.getTemplate();

        String templateCode;
        String codeType = smsDTO.getCodeType();
        if (StrUtil.equals("login", codeType)) {
            templateCode = template.getCodeLogin();
        } else if (StrUtil.equals("resetPwd", codeType)) {
            templateCode = template.getCodeResetPassword();
        } else {
            log.warn("手机号【{}】发送短信的验证码类型{}不存在", phone, codeType);

            return "验证码类型不存在";
        }

        // 组装请求对象
        SendSmsRequest request = new SendSmsRequest();
        request.setPhoneNumbers(phone);
        // 短信签名
        request.setSignName(template.getSignName());
        // 短信模板
        request.setTemplateCode(templateCode);
        Map<String, String> params = new HashMap<>(2);
        params.put("code", code.toString());
        // 变量替换
        request.setTemplateParam(JSONObject.toJSONString(params));

        try {
            // 执行请求
            SendSmsResponse response = acsClient.getAcsResponse(request);
            String smsCode = response.getCode();
            if (StrUtil.equals(HttpStatus.OK.getReasonPhrase(), smsCode)) {
                // 储存验证码
                stringRedisTemplate.opsForValue().set(String.format("dcy:service:manage:sms:%s:%s", codeType, phone), code.toString(), common.getCodePeriod(), TimeUnit.SECONDS);

                return null;
            }

            // 错误信息
            return aliyun.getErrorCode().get(smsCode);
        } catch (Exception e) {
            log.error("手机号【{}】发送类型【{}】的验证码失败", phone, codeType, e);

            return "验证码发送失败";
        }
    }

    /**
     * 校验手机号
     *
     * @param phone 手机号
     * @return 校验状态
     */
    private String verifyPhone(String phone) {
        User user = userService.lambdaQuery()
                .select(User::getIsDisabled)
                .eq(User::getPhone, phone)
                .one();
        if (ObjectUtil.isNull(user)) {
            return "账号不存在";
        }

        if (user.getIsDisabled() == 1) {
            return "账号已禁用";
        }

        return null;
    }

}

 

可参考:阿里云短信服务

posted @ 2020-07-10 10:33  如幻行云  阅读(652)  评论(0编辑  收藏  举报