当前位置:网站首页>公纵号发送提示信息(用户微服务--消息微服务)
公纵号发送提示信息(用户微服务--消息微服务)
2022-07-03 11:53:00 【只因为你而温柔】
公纵号发送提示信息(用户微服务–消息微服务)
微信消息的集成(微信公众号)
场景:主要用于商城购买提示,金额提醒,活动广告等
申请微信测试号(和微信小程序有区别)
https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
拿到信息
查看具体文档
获取 access_token(这里区别其他的 token)
本质就是发送一个请求
发送消息模板文档
消息模板
拿到模板ID
总结需要的东西
appID,appsecret,模板 ID
流程:
1.根据 appid 和 appsecret 拿到 access_token 2.发一个请求(请求中包含模板内容,access_token)
用户微服务
pom.xml(需要用到消息微服务的api----因为AliSmsModel类在消息api中)
<dependency> <groupId>com.xiaoge</groupId> <artifactId>message-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
启动类
@SpringBootApplication @EnableEurekaClient public class MemberServiceApplication { public static void main(String[] args) { SpringApplication.run(MemberServiceApplication.class, args); } }
UserController
package com.xiaoge.controller; import com.alibaba.fastjson.JSON; import com.xiaoge.constant.QueueConstant; import com.xiaoge.domain.User; import com.xiaoge.domain.UserCollection; import com.xiaoge.model.WxMsgModel; 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.amqp.rabbit.core.RabbitTemplate; 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.time.LocalDateTime; import java.util.HashMap; 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; @Autowired private RabbitTemplate rabbitTemplate; @PostMapping("p/sms/wxSend") @ApiOperation("测试发送微信公众号消息") public ResponseEntity<String> wxSend(String openId, String name) { // 构建一个对象 WxMsgModel wxMsgModel = new WxMsgModel(); wxMsgModel.setToUser(openId); // 公纵号用户点击信息时去往地址 wxMsgModel.setUrl("https://www.baidu.com"); // 模版id wxMsgModel.setTemplateId("XIL5vtqbdBZbejJ2xfXv-cqXxLni9RzjG32Qjpg_OoY"); // 头颜色 wxMsgModel.setTopColor("#FF0000"); HashMap<String, Map<String, String>> data = new HashMap<>(); data.put("userName", WxMsgModel.buildMap(name, "#FF0000")); data.put("time", WxMsgModel.buildMap(LocalDateTime.now().toString(), "#FF0000")); data.put("product", WxMsgModel.buildMap("女朋友", "#FF0000")); data.put("money", WxMsgModel.buildMap("0.1", "#FF0000")); wxMsgModel.setData(data); // 用mq发消息 rabbitTemplate.convertAndSend(QueueConstant.WX_CHANGE_EX, QueueConstant.WX_CHANGE_KEY, JSON.toJSONString(wxMsgModel)); return ResponseEntity.ok("发送成功"); } }
消息微服务
message-api中模型类 用户微服务用到了该模型类
package com.xiaoge.model; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.HashMap; import java.util.Map; @Data @AllArgsConstructor @NoArgsConstructor public class WxMsgModel { @JsonProperty(value = "touser") private String toUser; @JsonProperty(value = "template_id") private String templateId; @JsonProperty(value = "url") private String url; @JsonProperty(value = "topcolor") private String topColor; @JsonProperty(value = "data") private Map<String, Map<String, String>> data; /** * 专门构建参数的 * * @param value * @param color * @return */ public static Map<String, String> buildMap(String value, String color) { HashMap<String, String> map = new HashMap<>(); map.put("value", value); map.put("color", color); return map; } }
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 wxChangeQueue() { return new Queue(QueueConstant.WX_CHANGE_QUEUE); } @Bean public DirectExchange wxChangeExchange() { return new DirectExchange(QueueConstant.WX_CHANGE_EX); } @Bean public Binding wxBind() { return BindingBuilder .bind(wxChangeQueue()) .to(wxChangeExchange()) .with(QueueConstant.WX_CHANGE_KEY); } }
application.yml
# 微信公纵号信息 wechat: app-id: wx010a59592d9c7234 app-secret: dd6508eb89c7509db542c4b8a0cb062e token-url: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s message-url: https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s
WechatProperties
package com.xiaoge.config; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @Classname WechatProperties * @Date 2022/6/25 下午5:31 * @Created by xiaoge * @Description TODO */ @Data @ConfigurationProperties(prefix = "wechat") public class WechatProperties { @ApiModelProperty("微信的应用的 id") private String appId; @ApiModelProperty("微信的密钥") private String appSecret; @ApiModelProperty("获取 Tokenurl 的地址") private String tokenUrl; @ApiModelProperty("发送微信模板消息的地址") private String messageUrl; }
WechatAutoConfiguration
package com.xiaoge.config; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; import javax.annotation.PostConstruct; /** * @Classname WechatAutoConfiguration * @Date 2022/6/25 下午5:32 * @Created by xiaoge * @Description TODO */ @Slf4j @Configuration @EnableConfigurationProperties(value = WechatProperties.class) public class WechatAutoConfiguration { @Autowired private RestTemplate restTemplate; @Autowired private WechatProperties wechatProperties; /** * volatile(jvm提供的轻量级的同步机制) 三大特性: * 1. 保证可见性 * 2. 不保证原子性 * 3. 禁止指令重排 * * 1. 验证volatile的可见性 * 1.1 假如int number = 0; number变量之前根本没有添加volatile关键字修饰, 没有可见性 * 1.2 添加了volatile, 可以解决可见性问题. * * 2. 验证volatile不保证原子性 * 2.1 原子性指的是什么意思? * 不可分割, 完整性, 也即某个线程正在做某个具体业务时, 中间不可以被加塞或者被分割, 需要整体完整 * 要么同时成功, 要么同时失败. * * 2.2 volatile不保证原子性 案例演示 * * number ++ 在多线程下是非线程安全的, 如何不加synchronized解决? * * 2.3 why? * 因为在线程自己工作内存写回主内存的时候, 太快了, 通知其他线程还没到, 其他线程也直接写回主内存了, 所以少于20000次, 所以出现写丢的情况. * * 2.4 如何解决原子性? * * 加synchronized * * 使用我们的juc 下 AtomicInteger * */ //因为我们需要定时刷新 token,为了让其他线程可以看到,我们使用 volatile 来修饰 private volatile String accessToken; /** * 这个spring实现了这个注解的规范 * 所有的bean对象创建完以后执行, 在项目启动完全之前执行 * 限制 不能有返回值, 也不能有参数 * * 因为消费者直接监听者生产者, * 当消费者挂了以后, * 在次启动时他会直接消费, * 但是这时候token是没有获取到的, * 这要会报尖token, 所以要在这里加这个注解 */ @PostConstruct public void tokenInit() { refushToken(); } /** * 刷新 token 的方法 两个小时以内获取一次 * initialDelay项目启动完后执行, 所以才会导致token失效, 因为消费者和他是同时执行的 */ @Scheduled(initialDelay = 7100 * 1000, fixedRate = 7100 * 1000) public void refushToken() { String tokenUrl = String.format(wechatProperties.getTokenUrl(), wechatProperties.getAppId(), wechatProperties.getAppSecret()); String jsonStr = restTemplate.getForObject(tokenUrl, String.class); JSONObject jsonObject = JSON.parseObject(jsonStr); String accessToken = jsonObject.getString("access_token"); if (!StringUtils.isEmpty(accessToken)) { log.info("token 获取成功"); this.accessToken = accessToken; return; } log.error("token 获取失败"); } public String getAccessToken() { return this.accessToken; } }
WechatListener(监听器, 并且发送提示信息)
package com.xiaoge.listener; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.rabbitmq.client.Channel; import com.xiaoge.config.WechatAutoConfiguration; import com.xiaoge.config.WechatProperties; import com.xiaoge.constant.QueueConstant; import com.xiaoge.model.WxMsgModel; 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.amqp.support.AmqpHeaders; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.handler.annotation.Header; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import java.io.IOException; /** * @Classname WechatListener * @Date 2022/6/25 下午5:46 * @Created by xiaoge * @Description TODO */ @Slf4j @Component public class WechatListener { @Autowired private WechatProperties wechatProperties; @Autowired private WechatAutoConfiguration wechatAutoConfiguration; @Autowired private SmsLogService smsLogService; @Autowired private RestTemplate restTemplate; @RabbitListener(queues = QueueConstant.WX_CHANGE_QUEUE, concurrency = "3-5") public void handlerWechatMessage(Channel channel, Message message) { String wxStr = new String(message.getBody()); // 拿到消息 WxMsgModel wxMsgModel = JSON.parseObject(wxStr, WxMsgModel.class); // 发型微信公纵号消息 realSendWxMsg(wxMsgModel); smsLogService.saveWxMsg(wxMsgModel); try { // 签收消息 channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); } catch (IOException e) { log.error("签收失败!"); } } /** * 真正发微信消息的方法 * 发送微信公纵号信息 * @param wxMsgModel */ private void realSendWxMsg(WxMsgModel wxMsgModel) { // 发送公纵号信息的url String messageUrl = String.format(wechatProperties.getMessageUrl(), wechatAutoConfiguration.getAccessToken()); // 发送消息 String result = restTemplate.postForObject(messageUrl, wxMsgModel, String.class); System.out.println(result); } }
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; import com.xiaoge.model.WxMsgModel; /** * @Classname SmsLogService * @Date 2022/6/25 下午3:19 * @Created by xiaoge * @Description TODO */ public interface SmsLogService extends IService<SmsLog>{ /** * 把wx信息保存进数据库 * @param wxMsgModel */ void saveWxMsg(WxMsgModel wxMsgModel); }
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.model.WxMsgModel; 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; /** * 把wx信息保存进数据库 * * @param wxMsgModel */ @Override public void saveWxMsg(WxMsgModel wxMsgModel) { SmsLog smsLog = new SmsLog(); smsLog.setContent("发微信消息成功"); smsLog.setUserId(wxMsgModel.getToUser()); smsLog.setResponseCode("200"); smsLog.setRecDate(new Date()); smsLog.setStatus(0); smsLog.setType(2); // 插入数据库 smsLogMapper.insert(smsLog); } }
Postman测试
打开微信小程序, 随便一个请求都带着token, 拿过来就行了
边栏推荐
猜你喜欢
Unicode encoding table download
If you can't learn, you have to learn. Jetpack compose writes an im app (II)
Why can't my MySQL container start
Cloud Computing future - native Cloud
剑指Offer06. 从尾到头打印链表
Qt+vtk+occt reading iges/step model
Wechat applet pages always report errors when sending values to the background. It turned out to be this pit!
Basic knowledge of OpenGL (sort it out according to your own understanding)
为什么我的mysql容器启动不了呢
laravel 时区问题timezone
随机推荐
Is it safe to open an account for online stock speculation? Who can answer
Develop plug-ins for idea
Flutter: about monitoring on flutter applications
Socket TCP for network communication (I)
【ManageEngine】IP地址扫描的作用
Redis notes 01: Introduction
347. Top k high frequency elements
DEJA_VU3D - Cesium功能集 之 053-地下模式效果
New features of ES6
[combinatorics] permutation and combination (summary of permutation and combination content | selection problem | set permutation | set combination)
Shutter: about inheritedwidget
Kubectl_ Command experience set
Unicode encoding table download
Talk about the state management mechanism in Flink framework
OpenGL index cache object EBO and lineweight mode
145. Post order traversal of binary tree
(construction notes) learn the specific technology of how to design reusable software entities from three levels: class, API and framework
Lambda expression
elastic_ L04_ introduction. md
Socket TCP for network communication (I)