阿里大于发送短信(用户微服务--消息微服务)

Posted 只因为你而温柔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阿里大于发送短信(用户微服务--消息微服务)相关的知识,希望对你有一定的参考价值。

阿里大于官网

  1. 官网流程文档:

    https://help.aliyun.com/document_detail/55284.html?spm=a2c4g.11186623.6.567.77f914d1QWnwjX

    1. 登录阿里大于: https://dayu.aliyun.com/

    2. 去短信服务

      https://dysms.console.aliyun.com/dysms.htm?spm=5176.12818093.0.ddysms.6eac16d0SKkGSC#/domestic/text/template

    3. 设置签名模板(需要审核)

    4. 拿到 AccessKey


    5. 申请短信模板

    6. 总结需要的东西
      短信签名,短信模板 id,AccessKey,AccessKey Secret,version(版本信息,有点坑), Action(SendSms)关键的还有一个 jar 包(依赖)

    用户微服务

    1. pom.xml(需要用到消息微服务的api----因为AliSmsModel类在消息api中)

      <dependency>
        <groupId>com.xiaoge</groupId>
        <artifactId>message-api</artifactId>
        <version>1.0-SNAPSHOT</version>
       </dependency>
      
    2. RedisCacheConfig(有这个配置启动类上必须加@EnableCaching注解, 把缓存叫给redis, 用redis客户端查看也不会乱码)

      package com.xiaoge.config;
      
      import org.springframework.boot.autoconfigure.cache.CacheProperties;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.data.redis.cache.RedisCacheConfiguration;
      import org.springframework.data.redis.serializer.RedisSerializationContext;
      import org.springframework.data.redis.serializer.RedisSerializer;
      
      @Configuration
      public class RedisCacheConfig 
      
          //使用了cache的注解,需要手动设置序列化
          private CacheProperties cacheProperties;
      
          /**
           * 该配置类被构造时,它里面的参数,将有Spring 的ioc 容器提供
           *
           * @param cacheProperties
           */
          public RedisCacheConfig(CacheProperties cacheProperties) 
              this.cacheProperties = cacheProperties;
          
      
      
          /**
           * 定义Redis缓存的序列化的形式
           * 在这个RedisSerializer类里面提交了3 种常用的序列化形式
           * 1 java  jdk的序列化 (默认的形式)
           * 2 json  jackson (我们可以手动切换)
           * 3 String String的序列化(主要用在字符串的存储,不是对象) 对key 一般使用的是String的序列化
           */
          @Bean
          public RedisCacheConfiguration redisCacheConfiguration() 
              CacheProperties.Redis redisProperties = this.cacheProperties.getRedis();
              RedisCacheConfiguration config = RedisCacheConfiguration
                      .defaultCacheConfig();
      
              config = config.serializeValuesWith(
                      RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()));
              // 缓存的过期时间,一般我们在配置文件里面设置
              if (redisProperties.getTimeToLive() != null) 
                  config = config.entryTtl(redisProperties.getTimeToLive());
              
              // 是否给缓存添加前缀
              if (redisProperties.getKeyPrefix() != null) 
                  config = config.prefixKeysWith(redisProperties.getKeyPrefix());
              
              // 空值的缓存
              if (!redisProperties.isCacheNullValues()) 
                  config = config.disableCachingNullValues();
              
              //禁用key
              if (!redisProperties.isUseKeyPrefix()) 
                  config = config.disableKeyPrefix();
              
              return config;
          
      
      
    3. 启动类

      @SpringBootApplication
      @EnableEurekaClient
      @EnableCaching
      public class MemberServiceApplication 
      
          public static void main(String[] args) 
              SpringApplication.run(MemberServiceApplication.class, args);
          
      
      
      
    4. UserController

      package com.xiaoge.controller;
      
      import com.xiaoge.domain.User;
      import com.xiaoge.domain.UserCollection;
      import com.xiaoge.service.UserCollectionService;
      import com.xiaoge.service.UserService;
      import io.swagger.annotations.Api;
      import io.swagger.annotations.ApiImplicitParam;
      import io.swagger.annotations.ApiImplicitParams;
      import io.swagger.annotations.ApiOperation;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.http.ResponseEntity;
      import org.springframework.security.core.context.SecurityContextHolder;
      import org.springframework.web.bind.annotation.*;
      
      import java.util.Map;
      
      /**
       * @Classname UserController
       * @Date 2022/6/6 下午8:23
       * @Created by xiaoge
       * @Description TODO
       */
      @Api(tags = "前台用户管理接口")
      @RestController
      @RequestMapping
      public class UserController 
      
          @Autowired
          private UserService userService;
      
      
          @ApiImplicitParams(
                  @ApiImplicitParam(name = "phoneNum", value = "用户手机号, 验证码")
          )
          @ApiOperation("修改用户信息")
          @PostMapping("p/sms/send")
          public ResponseEntity<Void> bindPhoneNum(@RequestBody Map<String, String> phoneNum) 
              String openId = SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString();
              userService.bindPhoneNum(openId, phoneNum);
              return ResponseEntity.ok().build();
          
      
      
      
      
      
      
    5. UserService

      package com.xiaoge.service;
      
      import com.baomidou.mybatisplus.extension.service.IService;
      import com.xiaoge.domain.User;
      
      import java.util.Map;
      
      /**
      * @Classname UserService
      * @Date 2022/6/6 下午7:00
      * @Created by xiaoge
      * @Description TODO
      */
      public interface UserService extends IService<User>
      
      
          /**
           * 用户绑定手机号
           * @param openId
           * @param phoneNum
           */
          Boolean bindPhoneNum(String openId, Map<String, String> phoneNum);
      
      
      
    6. UserServiceImpl

    7. package com.xiaoge.service.impl;
      
      import com.alibaba.fastjson.JSON;
      import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
      import com.xiaoge.constant.QueueConstant;
      import com.xiaoge.domain.User;
      import com.xiaoge.mapper.UserMapper;
      import com.xiaoge.model.AliSmsModel;
      import com.xiaoge.service.UserService;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.amqp.rabbit.core.RabbitTemplate;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.data.redis.core.RedisTemplate;
      import org.springframework.stereotype.Service;
      import org.springframework.transaction.annotation.Transactional;
      
      import java.time.Duration;
      import java.util.HashMap;
      import java.util.Map;
      
      /**
       * @Classname UserServiceImpl
       * @Date 2022/6/6 下午7:00
       * @Created by xiaoge
       * @Description TODO
       */
      @Slf4j
      @Service
      public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService
      
          @Autowired
          private RabbitTemplate rabbitTemplate;
      
          @Autowired
          private RedisTemplate redisTemplate;
      
          /**
           * 用户绑定手机号
           * 1. 生成一个code
           * 2. 放在redis
           * 3. 设置一个过期时间 5min
           * 4. 组装参数
           * 5. 放入mq
           * 6. 返回
           * @param openId
           * @param phoneNum
           */
          @Override
          public Boolean bindPhoneNum(String openId, Map<String, String> phoneNum) 
              String phonenum = phoneNum.get("phonenum");
      
              // 生成验证码
              String code = createCode();
      
              // 放入redis
              redisTemplate.opsForValue().set(phonenum, code, Duration.ofMinutes(5));
      
              // 组装参数 放mq 短信的签名 短信的模板,短信的code
              AliSmsModel aliSmsModel = new AliSmsModel();
              aliSmsModel.setPhoneNumbers(phonenum);
              aliSmsModel.setSignName("ego商城");
              aliSmsModel.setTemplateCode("SMS_203185255");
              Map<String, String> map = new HashMap<>(2);
              map.put("code", code);
              aliSmsModel.setTemplateParam(JSON.toJSONString(map));
      
              // 发送消息
              rabbitTemplate.convertAndSend(QueueConstant.PHONE_CHANGE_EX, QueueConstant.PHONE_CHANGE_KEY, JSON.toJSONString(aliSmsModel));
      
              return true;
          
      
      
          /**
           * 生成验证码
           * @return
           */
          private String createCode() 
              // 位数 4  6  8多一点
              // 随机生成验证码
              return "88888888";
          
      
      
      

    消息微服务

    1. message-api中模型类 用户微服务用到了该模型类

      package com.whsxt.model;
      
      import io.swagger.annotations.ApiModel;
      import io.swagger.annotations.ApiModelProperty;
      import lombok.AllArgsConstructor;
      import lombok.Builder;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      
      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      @Builder
      @ApiModel("发送阿里大于短信的实体类")
      public class AliSmsModel 
      
          @ApiModelProperty("手机号")
          private String phoneNumbers;
      
          @ApiModelProperty("签名")
          private String signName;
      
          @ApiModelProperty("模板id")
          private String templateCode;
      
          @ApiModelProperty("参数")
          private String templateParam;
      
          @ApiModelProperty("短信扩展码")
          private String smsUpExtendCode;
      
          @ApiModelProperty("外部流水扩展字段")
          private String outId;
      
      
      
      
    2. pom.xml

        <dependency>
          <groupId>com.aliyun</groupId>
          <artifactId>aliyun-java-sdk-core</artifactId>
          <version>4.0.6</version> <!-- 注:如提示报错,先升级基础包版,无法解决可联系技术支持 -->
         </dependency>
      
    3. RabbitMQConfig(发送短信mq配置 PHONE_CHANGE_QUEUE都是自己随便定义的常量值)

      package com.xiaoge.config;
      
      import com.xiaoge.constant.QueueConstant;
      import org.springframework.amqp.core.Binding;
      import org.springframework.amqp.core.BindingBuilder;
      import org.springframework.amqp.core.DirectExchange;
      import org.springframework.amqp.core.Queue;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      
      /**
       * @Classname RabbitMQConfig
       * @Date 2022/6/25 下午2:56
       * @Created by xiaoge
       * @Description TODO
       */
      @Configuration
      public class RabbitMQConfig 
      
      
          /*  短信mq配置  */
          @Bean
          public Queue phoneChangeQueue() 
              return new Queue(QueueConstant.PHONE_CHANGE_QUEUE);
          
      
      
          @Bean
          public DirectExchange phoneChangeExchange() 
              return new DirectExchange(QueueConstant.PHONE_CHANGE_EX);
          
      
          @Bean
          public Binding bind() 
              return BindingBuilder
                      .bind(phoneChangeQueue())
                      .to(phoneChangeExchange())
                      .with(QueueConstant.PHONE_CHANGE_KEY);
          
      
      
      
      
    4. application.yml

      # 阿里大于短信模版
      sms:
        region-id: cn-hangzhou
        access-key-id: LTAIkRdZIaLMBGKw
        access-secret: ZPuDXJKxZ0ZNndDXlWkO8WAcZK26n7
        sys-domain: dysmsapi.aliyuncs.com
        version: 2017-05-25
      
    5. SmsProperties

      package com.xiaoge.config;
      
      import lombok.Data;
      import org.springframework.boot.context.properties.ConfigurationProperties;
      
      /**
       * @Classname Sms
       * @Date 2022/6/25 下午3:56
       * @Created by xiaoge
       * @Description TODO
       */
      @Data
      @ConfigurationProperties(prefix = "sms")
      public class SmsProperties 
      
          private String regionId;
      
          private String accessKeyId;
      
          private String accessSecret;
      
          private String version;
      
      
      
    6. SmsAutoConfiguration

      package com.xiaoge.config;
      
      import com.aliyuncs.DefaultAcsClient;
      import com.aliyuncs.IAcsClient;
      import com.aliyuncs.profile.DefaultProfile;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.boot.context.properties.EnableConfigurationProperties;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      
      /**
       * @Classname SmsAutoConfiguration
       * @Date 2022/6/25 下午4:00
       * @Created by xiaoge
       * @Description TODO
       */
      @Configuration
      @EnableConfigurationProperties(value = SmsProperties.class)
      public class SmsAutoConfiguration 
      
          @Autowired
          private SmsProperties smsProperties;
      
      
          /**
           * 初始化阿里的客户端
           * 阿里的不是直接给一个url 你直接请求就可以
           * 他是需要你自己写一个客户端的配置
           * 你自己调用客户客户端的配置来发请求
           *
           * @return
           */
          @Bean
          public IAcsClient iAcsClient() 
              DefaultProfile profile = DefaultProfile.getProfile(smsProperties.getRegionId(),
                      smsProperties.getAccessKeyId(),
                      smsProperties.getAccessSecret()
              );
              IAcsClient acsClient = new DefaultAcsClient(profile);
              return acsClient;
          
      
      
      
      
    7. SmsListener(监听器, 并且发送短信)

      package com.xiaoge.listener;
      
      import com.alibaba.fastjson.

      异步发送邮件短信微信

      用户创建订单的按钮点击后,服务器存储这个订单信息后,调用发送短信、邮件、微信的接口,发送消息。而发送短信、邮件、微信都要涉及第三方的处理,服务器又要发送一个新的包裹给一个新的服务器,告诉他帮我发一个信息出去。这往往是一个漫长、且不可测的过程。

       

      因此势必增加异步操作,先返回给客户订单创建成功,然后慢慢发送信息出去。

       

      1、先记录要发送的内容、地址

      2、通知发件模块

      3、发件模块读取发送内容、地址,发送信息

      4、更新发送结果到系统。

      5、回掉发送完成后的一些善后任务。

      以上是关于阿里大于发送短信(用户微服务--消息微服务)的主要内容,如果未能解决你的问题,请参考以下文章

      微服务架构下消息服务多通道设计思路

      消息推送之微信模板消息

      微信小程序提示短信配置没有填写

      阿里云微消息队列(MQTT)的基本使用

      实践 | 如何通过微信服务号推送Zabbix告警(附赠源码)

      夜间监测微博用户动态并发送短信提示该睡觉了