近况

害,软考学不动啊,我感觉自己连学习都不会了,难道看看别人的软考博客,看几道例题就算学会了?
如果是自己把别人的笔记再整理一下的话,又觉得自己是在自我感动,对学习知识本身没什么用处
所以学习到底怎么学,又有可能是我想的太多做的太少,确实,现在的自己感觉太没有动力了,没有激情
牛逼的人对生活总是充满着激情,如果是因为提升自己才能收获激情,那我就是很久没有提升自己了
长时间的感觉没有提升,自然对于生活没有动力,这个星期六星期天一定要去学习,一定要有收获啊!!!

今天再水一篇关于配置阿里云的短信服务的,短信服务在很多场景都用到过,最常见的场景就是登录,注册,找回密码
正好公司让我去实现这个需求,所以去学习了一下怎么使用阿里云的短信服务
整个流程思路:

1.用户输入手机号,点击发送验证码
2.后端接收到请求,生成一个随机数,将该手机号和随机数保存在redis中,过期时间配置在配置类上
	如果redis数据保存成功则调用阿里云短信接口发送短信,如果失败,则通知前端
	根据返回json中body的code字段来判断成功还是失败
3.前端收到发送成功的结果后,用户会收到短信,用户输入验证码,前端将该用户的手机号和用户输入的验证码都发送到后端
	后端根据用户手机号从redis中查询存在redis中的验证码,如果查询为空,则可能验证码过期,再将该验证码与用户输入的验证码进行对比,判断是否输入正确。

调用阿里云发送短信接口返回的数据,如果失败,则body中code为其他,但是statusCode值仍为200.

下面是配置阿里云短信服务流程

  • 登录阿里云,申请短信签名和模板

    申请通过后,我们需要的是签名名称和模板CODE两个字段的值,搞定后,需要再去配置一个阿里云AccessKey AccessKey相当于token,通过api请求阿里的接口就需要这个accessKey,页面右上角鼠标悬浮就能看到AccessKey管理
  • 导入依赖

    <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>dysmsapi20170525</artifactId>
      <version>2.0.23</version>
    </dependency>
  • 在项目配置文件上填上上面配置,并写好相应的配置类

    • application.yaml

      jeecg :
        sms-config:
          #阿里云配置
          accessKeyId: ${ACCESS_KEY_ID:xxxxxxxxxxx}
          accessKeySecret: ${ACCESS_KEY_SECRET:xxxxxxxxxxx}
          #短信模板
          templateCode: ${TEMPLATE_CODE:xxxxxxxx}
          #短信签名
          signName: ${SIGN_NAME:xxxxxxxxx}
          #验证码有效时间,单位默认为分钟
          validTime: ${VALID_TIME:5}
    • SmsSendConfig

      @Data
      @Configuration
      @ConfigurationProperties(prefix = "jeecg.sms-config")
      public class SmsSendConfig {
          /**
           * 访问阿里云的公钥
           */
          private String accessKeyId;
      
          /**
           * 访问阿里云的私钥
           */
          private String accessKeySecret;
      
          /**
           * 模板标识
           */
          private String templateCode;
      
          /**
           * 短信签名名称
           */
          private String signName;
      
          /**
           * 验证码有效时间,单位默认分钟
           * @return
           * @throws Exception
           */
          private Integer validTime;
      
          @Bean("SMSClient")
          public Client createClient() throws Exception{
              Config config = new Config()
                      .setAccessKeyId(accessKeyId)
                      .setAccessKeySecret(accessKeySecret)
                      .setEndpoint("dysmsapi.aliyuncs.com");
              return new Client(config);
          }
      }
  • LoginController

    @Autowired
    private SmsSendConfig smsSendConfig;
    
    @Autowired
    @Qualifier("SMSClient")
    private Client smsClient;
    
    private String  getRandomString(Integer num){
      String alphanumeric = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
      StringBuilder sb = new StringBuilder(num);
      SecureRandom random = new SecureRandom();
      for (int i = 0; i < num; i++) {
        sb.append(alphanumeric.charAt(random.nextInt(alphanumeric.length())));
      }
      return sb.toString();
    }
    
    @ApiOperation("发送短信接口")
    @RequestMapping(value = "/sendSMS", method = RequestMethod.POST)
    public Result<Object> sendSMS(@RequestBody JSONObject jsonObject){
      //0.参数获取和手机号格式校验
      String phone = jsonObject.get("phone").toString();
      //手机号模式,0:登录,2:忘记密码
      String mode = jsonObject.get("mode").toString();
      if (ObjectUtil.isEmpty(phone)|| !phone.matches(phoneRegex)){
        return Result.error("手机号码格式不正确");
      }
    
      //1.登录和忘记密码都必须要求用户已经绑定手机号,目前系统没有注册功能
      SysUser sysUser = sysUserService.getUserByPhone(phone);
      if (ObjectUtil.isEmpty(sysUser)){
        return Result.error("该用户不存在或未绑定手机号");
      }
      String redisKey = phone+"-"+mode;
      //检查验证码是否有效,有效则直接返回
      Object object = redisUtil.get(redisKey);
      if (object != null) {
        return Result.error("当前验证码仍然有效!");
      }
    
      //2.生成验证码code,配置必要的请求参数
      HashMap<String, String> map = new HashMap<>();
      String code = getRandomString(6);
      map.put("code",code);
      String param = JSONObject.toJSONString(map);
      SendSmsRequest sendSmsRequest = new SendSmsRequest();
      sendSmsRequest
        .setPhoneNumbers(phone)
        .setSignName(smsSendConfig.getSignName())
        .setTemplateCode(smsSendConfig.getTemplateCode())
        .setTemplateParam(param);
    
      //3.发送验证码
      try {
        SendSmsResponse sendSmsResponse = smsClient.sendSms(sendSmsRequest);
        if (ObjectUtil.equals(sendSmsResponse.getBody().getCode(),200)){
      redisTemplate.opsForValue().set(redisKey,code,smsSendConfig.getValidTime(),TimeUnit.MINUTES);
          return Result.OK("验证码发送成功");
        }
      }catch (TeaException error) {
        // 如有需要,请打印 error
        com.aliyun.teautil.Common.assertAsString(error.message);
      } catch (Exception _error) {
        TeaException error = new TeaException(_error.getMessage(), _error);
        // 如有需要,请打印 error
        com.aliyun.teautil.Common.assertAsString(error.message);
      }
      return Result.error("短信验证码发送失败,请稍后重试");
    }