当前位置:网站首页>阿里大于发送短信(用户微服务--消息微服务)
阿里大于发送短信(用户微服务--消息微服务)
2022-07-03 11:53:00 【只因为你而温柔】
阿里大于官网
官网流程文档:
https://help.aliyun.com/document_detail/55284.html?spm=a2c4g.11186623.6.567.77f914d1QWnwjX
登录阿里大于: https://dayu.aliyun.com/
去短信服务
https://dysms.console.aliyun.com/dysms.htm?spm=5176.12818093.0.ddysms.6eac16d0SKkGSC#/domestic/text/template
设置签名模板(需要审核)
拿到AccessKey
申请短信模板
总结需要的东西
短信签名,短信模板 id,AccessKey,AccessKey Secret,version(版本信息,有点坑), Action(SendSms)关键的还有一个 jar 包(依赖)
用户微服务
pom.xml(需要用到消息微服务的api----因为AliSmsModel类在消息api中)
<dependency> <groupId>com.xiaoge</groupId> <artifactId>message-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
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; } }
启动类
@SpringBootApplication @EnableEurekaClient @EnableCaching public class MemberServiceApplication { public static void main(String[] args) { SpringApplication.run(MemberServiceApplication.class, args); } }
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(); } }
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); }
UserServiceImpl
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"; } }
消息微服务
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; }
pom.xml
<dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.0.6</version> <!-- 注:如提示报错,先升级基础包版,无法解决可联系技术支持 --> </dependency>
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); } }
application.yml
# 阿里大于短信模版 sms: region-id: cn-hangzhou access-key-id: LTAIkRdZIaLMBGKw access-secret: ZPuDXJKxZ0ZNndDXlWkO8WAcZK26n7 sys-domain: dysmsapi.aliyuncs.com version: 2017-05-25
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; }
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; } }
SmsListener(监听器, 并且发送短信)
package com.xiaoge.listener; import com.alibaba.fastjson.JSON; import com.aliyuncs.CommonRequest; import com.aliyuncs.CommonResponse; import com.aliyuncs.IAcsClient; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.http.MethodType; import com.rabbitmq.client.Channel; import com.xiaoge.config.SmsProperties; import com.xiaoge.constant.QueueConstant; import com.xiaoge.model.AliSmsModel; import com.xiaoge.service.SmsLogService; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.Message; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * @Classname SmsListener * @Date 2022/6/25 下午3:52 * @Created by xiaoge * @Description TODO */ @Component @Slf4j public class SmsListener { @Autowired private SmsProperties smsProperties; @Autowired private IAcsClient iAcsClient; @Autowired private SmsLogService smsLogService; /** * 短信监听 concurrency 线程数量3-5个 */ @RabbitListener(queues = QueueConstant.PHONE_CHANGE_QUEUE, concurrency = "3-5") public void smsHandler(Message message, Channel channel){ // 拿到消息 String msg = new String(message.getBody()); // 需要发送的内容 AliSmsModel aliSmsModel = JSON.parseObject(msg, AliSmsModel.class); // 发短信了 try { CommonResponse commonResponse = realSendMsg(aliSmsModel); // 成功了 log.info("短信发送成功"); // 记录数据库 smsLogService.saveMsg(aliSmsModel, commonResponse); // 签收 channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); } catch (Exception e) { log.error("发送短信失败"); } } /** * 发送短信 * @param aliSmsModel * @return */ private CommonResponse realSendMsg(AliSmsModel aliSmsModel) throws ClientException { CommonRequest commonRequest = new CommonRequest(); // 基本参数 commonRequest.setVersion(smsProperties.getVersion()); commonRequest.setMethod(MethodType.POST); commonRequest.setRegionId(smsProperties.getRegionId()); commonRequest.setAction("SendSms"); commonRequest.setDomain("dysmsapi.aliyuncs.com"); // 给哪个手机号发 commonRequest.putQueryParameter("PhoneNumbers", aliSmsModel.getPhoneNumbers()); commonRequest.putQueryParameter("SignName", aliSmsModel.getSignName()); commonRequest.putQueryParameter("TemplateCode", aliSmsModel.getTemplateCode()); commonRequest.putQueryParameter("TemplateParam", aliSmsModel.getTemplateParam()); // 发请求 CommonResponse commonResponse = iAcsClient.getCommonResponse(commonRequest); System.out.println(commonResponse.getData()); System.out.println(commonResponse.getHttpStatus()); return commonResponse; } }
SmsLogService
package com.xiaoge.service; import com.aliyuncs.CommonResponse; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaoge.domain.SmsLog; import com.xiaoge.model.AliSmsModel; /** * @Classname SmsLogService * @Date 2022/6/25 下午3:19 * @Created by xiaoge * @Description TODO */ public interface SmsLogService extends IService<SmsLog>{ /** * 把短信信息保存进数据库 * @param aliSmsModel * @param commonResponse */ void saveMsg(AliSmsModel aliSmsModel, CommonResponse commonResponse); }
SmsLogServiceImpl(保存发送过的短信到数据库)
package com.xiaoge.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.aliyuncs.CommonResponse; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaoge.domain.SmsLog; import com.xiaoge.mapper.SmsLogMapper; import com.xiaoge.model.AliSmsModel; import com.xiaoge.service.SmsLogService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Date; /** * @Classname SmsLogServiceImpl * @Date 2022/6/25 下午3:19 * @Created by xiaoge * @Description TODO */ @Service public class SmsLogServiceImpl extends ServiceImpl<SmsLogMapper, SmsLog> implements SmsLogService{ @Autowired private SmsLogMapper smsLogMapper; /** * 把短信信息保存进数据库 * * @param aliSmsModel * @param commonResponse */ @Override public void saveMsg(AliSmsModel aliSmsModel, CommonResponse commonResponse) { String phoneNumbers = aliSmsModel.getPhoneNumbers(); String templateParam = aliSmsModel.getTemplateParam(); JSONObject jsonObject = JSON.parseObject(templateParam); String code = jsonObject.getString("code"); SmsLog smsLog = new SmsLog(); smsLog.setUserPhone(phoneNumbers); smsLog.setContent("尊敬的用户,您的注册会员动态密码为:" + code + ",请勿泄漏于他人!"); smsLog.setMobileCode(code); smsLog.setRecDate(new Date()); String data = commonResponse.getData(); JSONObject jsonObject1 = JSON.parseObject(data); String code1 = jsonObject1.getString("Code"); smsLog.setResponseCode(String.valueOf(commonResponse.getHttpStatus())); if (code1.equals("OK")) { smsLog.setStatus(1); } else { smsLog.setStatus(0); } smsLog.setType(2); // 插入数据库 smsLogMapper.insert(smsLog); } }
边栏推荐
- elastic_ L01_ summary
- Slf4j log facade
- Introduction to concurrent programming (I)
- LeetCode 0556. Next bigger element III - end of step 4
- Official website of Unicode query
- 347. Top k high frequency elements
- How to deploy web pages to Alibaba cloud
- 2.8 overview of ViewModel knowledge
- elastic_ L02_ install
- (construction notes) ADT and OOP
猜你喜欢
If you can't learn, you have to learn. Jetpack compose writes an im app (I)
ES6 standard
[MySQL special] read lock and write lock
QT OpenGL texture map
ES6新特性
Basic knowledge of OpenGL (sort it out according to your own understanding)
4000字超详解指针
C language improvement article (wchar_t) character type
Display time with message interval of more than 1 minute in wechat applet discussion area
laravel 时区问题timezone
随机推荐
2.9 overview of databinding knowledge points
写一个简单的nodejs脚本
Adult adult adult
Introduction to concurrent programming (I)
023 ([template] minimum spanning tree) (minimum spanning tree)
elastic_ L01_ summary
QT OpenGL texture map
01_ Using the concurrent tool class library, is thread safety safe
Flutter Widget : KeyedSubtree
Redis
2020-11_ Technical experience set
4000 word super detailed pointer
Symlink(): solution to protocol error in PHP artisan storage:link on win10
1-1 token
DEJA_VU3D - Cesium功能集 之 053-地下模式效果
Wechat applet - basic content
网络通讯之Socket-Tcp(一)
Flutter: self study system
TOGAF认证自学宝典V2.0
225. Implement stack with queue