Commit 7e86b4d6 by liangyuhang

普通消息和事件推送处理

parents
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.liang</groupId>
<artifactId>wechat-message-handle</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>wechat-message-handle</name>
<description>wechat-message-handle</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.12</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
package com.liang.wechat;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WechatMessageHandleApplication {
public static void main(String[] args) {
SpringApplication.run(WechatMessageHandleApplication.class, args);
}
}
package com.liang.wechat.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
import java.io.Serializable;
@Data
public class BaseMessage implements Serializable {
/**
* 开发者微信号
*/
@XStreamAlias("ToUserName")
private String toUserName;
/**
* 发送方openId
*/
@XStreamAlias("FromUserName")
private String fromUserName;
/**
* 消息创建时间
*/
@XStreamAlias("CreateTime")
private long createTime;
/**
* 消息类型
*/
@XStreamAlias("MsgType")
private String msgType;
}
package com.liang.wechat.bean.event;
import com.liang.wechat.bean.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
@Data
@XStreamAlias("xml")
public class EventMessage extends BaseMessage {
@XStreamAlias("Event")
private String event;
@XStreamAlias("EventKey")
private String eventKey;
}
package com.liang.wechat.bean.message;
import com.liang.wechat.bean.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 图片消息
*/
@Data
@XStreamAlias("xml")
public class ImageMessage extends BaseMessage {
/**
* 图片链接
*/
@XStreamAlias("PicUrl")
private String picUrl;
/**
* 图片素材ID
*/
@XStreamAlias("MediaId")
private String mediaId;
/**
* mediaId的包装,回复时用到
*/
@XStreamAlias("Image")
private Image image;
@Data
@AllArgsConstructor
public static class Image {
/**
* 通过素材管理中的接口上传多媒体文件,得到的id
*/
@XStreamAlias("MediaId")
private String mediaId;
}
}
package com.liang.wechat.bean.message;
import com.liang.wechat.bean.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
/**
* 链接消息
*/
@Data
@XStreamAlias("xml")
public class LinkMessage extends BaseMessage {
/**
* 消息标题
*/
@XStreamAlias("Title")
private String title;
/**
* 消息描述
*/
@XStreamAlias("Description")
private String description;
/**
* 消息链接
*/
@XStreamAlias("Url")
private String url;
}
package com.liang.wechat.bean.message;
import com.liang.wechat.bean.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
/**
* 地理位置消息
*/
@Data
@XStreamAlias("xml")
public class LocationMessage extends BaseMessage {
/**
* 地理位置维度
*/
@XStreamAlias("Location_X")
private String location_X;
/**
* 地理位置经度
*/
@XStreamAlias("Location_Y")
private String location_Y;
/**
* 地图缩放大小
*/
@XStreamAlias("Scale")
private String scale;
/**
* 地理位置信息
*/
@XStreamAlias("Label")
private String label;
}
package com.liang.wechat.bean.message;
import com.liang.wechat.bean.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 音乐消息,只有回复
*/
@Data
@XStreamAlias("xml")
public class MusicMessage extends BaseMessage {
@XStreamAlias("Music")
private Music music;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Music {
/**
* 音乐标题
*/
@XStreamAlias("Title")
private String title;
/**
* 音乐描述
*/
@XStreamAlias("Description")
private String description;
/**
* 音乐链接
*/
@XStreamAlias("MusicURL")
private String musicURL;
/**
* 高质量音乐链接,WIFI环境优先使用该链接播放音乐
*/
@XStreamAlias("HQMusicUrl")
private String hQMusicUrl;
/**
* 缩略图的媒体id,通过素材管理中的接口上传多媒体文件,得到的id
*/
@XStreamAlias("ThumbMediaId")
private String thumbMediaId;
}
}
package com.liang.wechat.bean.message;
import com.liang.wechat.bean.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 图文消息
*/
@Data
@XStreamAlias("xml")
public class NewsMessage extends BaseMessage {
/**
* 图文消息个数;当用户发送文本、图片、语音、视频、图文、地理位置这六种消息时,开发者只能回复1条图文消息;其余场景最多可回复8条图文消息
*/
@XStreamAlias("ArticleCount")
private int articleCount;
/**
* 图文消息信息,注意,如果图文数超过限制,则将只发限制内的条数
*/
@XStreamAlias("Articles")
private List<Article> articles;
@Data
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("item")
public static class Article {
/**
* 图文消息标题
*/
@XStreamAlias("Title")
private String title;
/**
* 图文消息描述
*/
@XStreamAlias("Description")
private String description;
/**
* 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
*/
@XStreamAlias("PicUrl")
private String picUrl;
/**
* 点击图文消息跳转链接
*/
@XStreamAlias("Url")
private String url;
}
}
package com.liang.wechat.bean.message;
import com.liang.wechat.bean.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
/**
* 小视频消息
*/
@Data
@XStreamAlias("xml")
public class ShortVideoMessage extends BaseMessage {
/**
* 视频消息媒体id,可以调用获取临时素材接口拉取数据
*/
@XStreamAlias("MediaId")
private String mediaId;
/**
* 视频消息缩略图的媒体id,可以调用获取临时素材接口拉取数据
*/
@XStreamAlias("ThumbMediaId")
private String thumbMediaId;
}
package com.liang.wechat.bean.message;
import com.liang.wechat.bean.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.Data;
/**
* 文本消息
*/
@Data
@XStreamAlias("xml")
public class TextMessage extends BaseMessage {
@XStreamAlias("Content")
private String content;
}
package com.liang.wechat.bean.message;
import com.liang.wechat.bean.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 视频消息
*/
@Data
@XStreamAlias("xml")
public class VideoMessage extends BaseMessage {
/**
* 视频消息媒体id,可以调用多媒体文件下载接口拉取数据
*/
@XStreamAlias("MediaId")
private String mediaId;
/**
* 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据
*/
@XStreamAlias("ThumbMediaId")
private String thumbMediaId;
/**
* 回复时用到
*/
@XStreamAlias("Video")
private Video video;
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Video {
/**
* 通过素材管理中的接口上传多媒体文件,得到的id
*/
@XStreamAlias("MediaId")
private String mediaId;
/**
* 视频消息的标题
*/
@XStreamAlias("Title")
private String title;
/**
* 视频消息的描述
*/
@XStreamAlias("Description")
private String description;
}
}
package com.liang.wechat.bean.message;
import com.liang.wechat.bean.BaseMessage;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* 语音消息
*/
@Data
@XStreamAlias("xml")
public class VoiceMessage extends BaseMessage {
/**
* 语音消息媒体id,可以调用获取临时素材接口拉取数据
*/
@XStreamAlias("MediaId")
private String mediaId;
/**
* 语音格式,如amr,speex等
*/
@XStreamAlias("Format")
private String format;
/**
* 语音识别结果,UTF8编码(注:由于客户端缓存,开发者开启或者关闭语音识别功能,对新关注者立刻生效,对已关注用户需要24小时生效。开发者可以重新关注此帐号进行测试)
*/
@XStreamAlias("Recognition")
private String recognition;
/**
* 回复时用到
*/
@XStreamAlias("Voice")
private Voice voice;
@Data
@AllArgsConstructor
public static class Voice {
/**
* 通过素材管理中的接口上传多媒体文件,得到的id
*/
@XStreamAlias("MediaId")
private String mediaId;
}
}
package com.liang.wechat.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "wx")
public class WechatConfig {
private String appId ;
private String secret;
private String token;
private String encodingAESKey;
}
package com.liang.wechat.constant;
public class WechatConstant {
/**
* 获取access_token的URL
*/
public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={1}&secret={2}";
/**
* 创建二维码URL
*/
public final static String CREATE_QRCODE_URL = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token={1}";
/**
* 展示二维码URL
*/
public static final String SHOW_QRCODE_URL = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket={1}";
/**
* 创建菜单URL
*/
public static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
/**
* 删除菜单URL
*/
public static final String DELETE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
/**
* 模版服务相关-设置所属行业
*/
public static final String SET_INDUSTRY = "https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=ACCESS_TOKEN";
/**
* 获取所属行业信息
*/
public static final String GET_INDUSTRY = "https://api.weixin.qq.com/cgi-bin/template/get_industry?access_token=ACCESS_TOKEN";
/**
* 获取所有模版信息
*/
public static final String GET_ALL_PRIVATE_TEMPLATE = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=ACCESS_TOKEN";
/**
* 发送模版消息
*/
public static final String TEMPLATE_SEND = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
/**
* 获取OAUTH认证的access_token
*/
public static final String OAUTH_GET_AT = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
/**
* 获取用户基本信息
*/
public static final String OAUTH_USER_INFO = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
/**
* 引导链接
*/
public static final String OAUTH2_AUTHORIZE = "";
}
package com.liang.wechat.controller;
import com.liang.wechat.constant.WechatConstant;
import com.liang.wechat.factory.MessageFactory;
import com.liang.wechat.strategy.MessageStrategy;
import com.liang.wechat.utils.WechatUtil;
import com.liang.wechat.utils.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.Objects;
@RestController
@Slf4j
@RequestMapping("/wechat")
public class WechatController {
@Autowired
private WechatUtil wechatUtil;
@Autowired
private MessageFactory messageFactory;
/**
* @param signature 微信加密签名,signature结合了开发者填写的 token 参数和请求中的 timestamp 参数、nonce参数。
* @param timestamp 时间戳
* @param nonce 随机数
* @param echostr 随机字符串
*/
@GetMapping
public String doGet(@RequestParam(value = "signature") String signature,
@RequestParam(value = "timestamp") String timestamp,
@RequestParam(value = "nonce") String nonce,
@RequestParam(value = "echostr") String echostr) {
if (!wechatUtil.checkSignature(signature, timestamp, nonce)) {
return null;
}
return echostr;
}
@PostMapping
public String doPost(@RequestBody String message) throws Exception {
log.info("接收微信的消息:{}", message);
//xml转map
Map<String, String> map = XmlUtil.xmlToMap(message);
String msgType = map.get("MsgType");
log.info("消息类型:{}", msgType);
String eventType = map.get("Event");
log.info("事件类型:{}", eventType);
MessageStrategy messageStrategy = messageFactory.getMessageStrategy(msgType, eventType);
if(Objects.isNull(messageStrategy)){
return null;
}
return messageStrategy.handleMessage(message);
}
}
package com.liang.wechat.enumeration;
public enum EventType {
/**
* 关注
*/
SUBSCRIBE("subscribe"),
/**
* 取消关注
*/
UNSUBSCRIBE("unsubscribe"),
/**
* 用户已关注时的事件推送
*/
SCAN("scan"),
/**
* 上报地理位置事件
*/
LOCATION("location"),
/**
* 自定义菜单事件(点击菜单拉取消息时的事件推送)
*/
CLICK("click"),
/**
* 点击菜单跳转链接时的事件推送
*/
VIEW("view");
private final String type;
EventType(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
package com.liang.wechat.enumeration;
import java.util.Arrays;
public enum MessageType {
/**
* 文本类型
*/
TEXT("text"),
/**
* 图片消息
*/
IMAGE("image"),
/**
* 语音消息
*/
VOICE("voice"),
/**
* 视频消息
*/
VIDEO("video"),
/**
* 小视频消息
*/
SHORTVIDEO("shortvideo"),
/**
* 位置消息
*/
LOCATION("location"),
/**
* 链接消息
*/
LINK("link"),
/**
* 事件消息
*/
EVENT("event"),
/**
* 图文列表
*/
NEWS("news");
private final String type;
MessageType(String type) {
this.type = type;
}
public String getType() {
return type;
}
public static String getType(String type) {
MessageType messageType = Arrays.stream(MessageType.values())
.filter(value -> value.getType().equalsIgnoreCase(type))
.findFirst().orElse(MessageType.TEXT);
return messageType.getType();
}
}
package com.liang.wechat.factory;
import com.liang.wechat.strategy.MessageStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
import java.util.Optional;
@Configuration
@Slf4j
public class MessageFactory {
//Spring会自动将实现类注入到这个Map中,key为bean id,value值则为对应的策略实现类
@Autowired
private Map<String, MessageStrategy> MESSAGE_STRATEGY_MAP;
public MessageStrategy getMessageStrategy(String msgType, String eventType) {
if (msgType.equals("event") && eventType != null) {
msgType = eventType;
}
return Optional.ofNullable(MESSAGE_STRATEGY_MAP.get(msgType)).orElse(null);
}
}
package com.liang.wechat.handler;
import com.liang.wechat.bean.message.ImageMessage;
import com.liang.wechat.strategy.MessageStrategy;
import com.liang.wechat.utils.WechatUtil;
import com.liang.wechat.utils.XmlUtil;
import org.springframework.stereotype.Service;
@Service("image")
public class ImageMessageHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
ImageMessage imageMessage = XmlUtil.xmlToBean(message, ImageMessage.class);
String mediaId = imageMessage.getMediaId();
return WechatUtil.sendImage(imageMessage,mediaId);
}
}
package com.liang.wechat.handler;
import com.liang.wechat.bean.message.LinkMessage;
import com.liang.wechat.strategy.MessageStrategy;
import com.liang.wechat.utils.WechatUtil;
import com.liang.wechat.utils.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service("link")
public class LinkMessageHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
LinkMessage linkMessage = XmlUtil.xmlToBean(message, LinkMessage.class);
log.info("发了链接消息");
//return WechatUtil.sendText(linkMessage,"发了链接消息");
return null;
}
}
package com.liang.wechat.handler;
import com.liang.wechat.bean.message.LocationMessage;
import com.liang.wechat.strategy.MessageStrategy;
import com.liang.wechat.utils.WechatUtil;
import com.liang.wechat.utils.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.text.MessageFormat;
@Slf4j
@Service("location")
public class LocationMessageHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
log.info("发了地理位置消息");
LocationMessage locationMessage = XmlUtil.xmlToBean(message, LocationMessage.class);
//return WechatUtil.sendText(locationMessage, "发了地理位置消息");
String pattern = "您发送的地理位置消息如下:{0},{1},{2},{3}";
String content = MessageFormat.format(pattern, locationMessage.getLocation_X(), locationMessage.getLocation_Y(), locationMessage.getScale(), locationMessage.getLabel());
return WechatUtil.sendText(locationMessage, content);
}
}
package com.liang.wechat.handler;
import com.liang.wechat.bean.message.ShortVideoMessage;
import com.liang.wechat.strategy.MessageStrategy;
import com.liang.wechat.utils.WechatUtil;
import com.liang.wechat.utils.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service("shortvideo")
public class ShortVideoMessageHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
log.info("发了小视频消息");
ShortVideoMessage shortVideoMessage = XmlUtil.xmlToBean(message, ShortVideoMessage.class);
//return WechatUtil.sendText(shortVideoMessage, "发了小视频消息");
return null;
}
}
package com.liang.wechat.handler;
import com.liang.wechat.bean.message.TextMessage;
import com.liang.wechat.strategy.MessageStrategy;
import com.liang.wechat.utils.WechatUtil;
import com.liang.wechat.utils.XmlUtil;
import org.springframework.stereotype.Service;
@Service("text")
public class TextMessageHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
TextMessage textMessage = XmlUtil.xmlToBean(message, TextMessage.class);
//return WechatUtil.sendText(textMessage, "你好");
return WechatUtil.sendText(textMessage);
}
}
package com.liang.wechat.handler;
import com.liang.wechat.bean.message.VideoMessage;
import com.liang.wechat.strategy.MessageStrategy;
import com.liang.wechat.utils.WechatUtil;
import com.liang.wechat.utils.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service("video")
public class VideoMessageHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
log.info("发了视频消息");
VideoMessage videoMessage = XmlUtil.xmlToBean(message, VideoMessage.class);
//return WechatUtil.sendText(videoMessage, "发了视频消息");
//TODO 格式都对不知道为什么不行
//VideoMessage.Video video = new VideoMessage.Video();
//video.setMediaId(videoMessage.getMediaId());
//video.setTitle("这是视频");
//video.setDescription("这是描述");
//return WechatUtil.sendVideo(videoMessage, video);
return null;
}
}
package com.liang.wechat.handler;
import com.liang.wechat.bean.message.VideoMessage;
import com.liang.wechat.bean.message.VoiceMessage;
import com.liang.wechat.strategy.MessageStrategy;
import com.liang.wechat.utils.WechatUtil;
import com.liang.wechat.utils.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service("voice")
public class VoiceMessageHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
log.info("发了语音消息");
VoiceMessage voiceMessage = XmlUtil.xmlToBean(message, VoiceMessage.class);
//return WechatUtil.sendText(voiceMessage, "发了语音消息");
String mediaId = voiceMessage.getMediaId();
return WechatUtil.sendVoice(voiceMessage, mediaId);
}
}
package com.liang.wechat.handler.event;
import com.liang.wechat.strategy.MessageStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 菜单点击事件处理
*/
@Slf4j
@Service("CLICK")
public class MenuClickEventHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
log.info("点击了");
return null;
}
}
package com.liang.wechat.handler.event;
import com.liang.wechat.strategy.MessageStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 菜单链接跳转事件处理
*/
@Slf4j
@Service("VIEW")
public class MenuViewEventHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
log.info("链接跳转了");
return null;
}
}
package com.liang.wechat.handler.event;
import com.liang.wechat.strategy.MessageStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 扫码事件处理
*/
@Slf4j
@Service("scan")
public class ScanEventHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
log.info("扫码了");
return null;
}
}
package com.liang.wechat.handler.event;
import com.liang.wechat.bean.event.EventMessage;
import com.liang.wechat.bean.message.LocationMessage;
import com.liang.wechat.bean.message.NewsMessage;
import com.liang.wechat.strategy.MessageStrategy;
import com.liang.wechat.utils.WechatUtil;
import com.liang.wechat.utils.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.Collections;
/**
* 关注事件处理
*/
@Slf4j
@Service("subscribe")
public class SubscribeEventHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
EventMessage eventMessage = XmlUtil.xmlToBean(message, EventMessage.class);
//return WechatUtil.sendText(locationMessage, "你好呀,欢迎关注我的公众号");
NewsMessage.Article article = new NewsMessage.Article();
article.setTitle("你好呀");
article.setDescription("欢迎关注我的公众号");
//article.setPicUrl("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png");
article.setUrl("https://www.baidu.com/");
return WechatUtil.sendNews(eventMessage, Collections.singletonList(article));
}
}
package com.liang.wechat.handler.event;
import com.liang.wechat.bean.event.EventMessage;
import com.liang.wechat.strategy.MessageStrategy;
import com.liang.wechat.utils.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 取关事件处理
*/
@Slf4j
@Service("unsubscribe")
public class UnsubscribeEventHandler implements MessageStrategy {
@Override
public String handleMessage(String message) {
EventMessage eventMessage = XmlUtil.xmlToBean(message, EventMessage.class);
String openId = eventMessage.getFromUserName();
log.info("openId:{} 取关了", openId);
return null;
}
}
package com.liang.wechat.service.material;
public interface MaterialService {
}
package com.liang.wechat.service.material;
import org.springframework.stereotype.Service;
@Service
public class MaterialServiceImpl implements MaterialService {
}
package com.liang.wechat.strategy;
/**
* 消息处理策略
*/
public interface MessageStrategy {
String handleMessage(String message);
}
package com.liang.wechat.utils;
import com.liang.wechat.bean.BaseMessage;
import com.liang.wechat.bean.message.*;
import com.liang.wechat.config.WechatConfig;
import com.liang.wechat.enumeration.MessageType;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class WechatUtil {
@Autowired
private WechatConfig wechatConfig;
public boolean checkSignature(String signature, String timestamp, String nonce) {
//1.将token、timestamp、nonce三个参数进行字典序排序
String[] arr = new String[]{wechatConfig.getToken(), timestamp, nonce};
Arrays.sort(arr);
//2.将三个参数字符串拼接成一个字符串进行sha1加密
String str = arr[0] + arr[1] + arr[2];
String sha1Hex = DigestUtils.sha1Hex(str);
return signature.equals(sha1Hex);
}
public static String sendText(TextMessage textMessage) {
return sendText(textMessage, textMessage.getContent());
}
public static String sendText(BaseMessage baseMessage, String content) {
TextMessage textMessage = new TextMessage();
textMessage.setCreateTime(System.currentTimeMillis());
textMessage.setFromUserName(baseMessage.getToUserName());
textMessage.setToUserName(baseMessage.getFromUserName());
textMessage.setMsgType(MessageType.TEXT.getType());
textMessage.setContent(content);
return XmlUtil.beanToXml(textMessage);
}
public static String sendImage(BaseMessage baseMessage, String mediaId) {
ImageMessage imageMessage = new ImageMessage();
imageMessage.setCreateTime(System.currentTimeMillis());
imageMessage.setFromUserName(baseMessage.getToUserName());
imageMessage.setToUserName(baseMessage.getFromUserName());
imageMessage.setMsgType(MessageType.IMAGE.getType());
imageMessage.setImage(new ImageMessage.Image(mediaId));
return XmlUtil.beanToXml(imageMessage);
}
public static String sendVoice(BaseMessage baseMessage, String mediaId) {
VoiceMessage voiceMessage = new VoiceMessage();
voiceMessage.setCreateTime(System.currentTimeMillis());
voiceMessage.setFromUserName(baseMessage.getToUserName());
voiceMessage.setToUserName(baseMessage.getFromUserName());
voiceMessage.setMsgType(MessageType.VOICE.getType());
voiceMessage.setVoice(new VoiceMessage.Voice(mediaId != null ? mediaId : ""));
return XmlUtil.beanToXml(voiceMessage);
}
public static String sendMusic(BaseMessage baseMessage, MusicMessage.Music music) {
MusicMessage musicMessage = new MusicMessage();
musicMessage.setCreateTime(System.currentTimeMillis());
musicMessage.setFromUserName(baseMessage.getToUserName());
musicMessage.setToUserName(baseMessage.getFromUserName());
musicMessage.setMsgType(MessageType.VOICE.getType());
musicMessage.setMusic(music);
return XmlUtil.beanToXml(musicMessage);
}
public static String sendVideo(BaseMessage baseMessage, VideoMessage.Video video) {
VideoMessage videoMessage = new VideoMessage();
videoMessage.setCreateTime(System.currentTimeMillis());
videoMessage.setFromUserName(baseMessage.getToUserName());
videoMessage.setToUserName(baseMessage.getFromUserName());
videoMessage.setMsgType(MessageType.VIDEO.getType());
videoMessage.setVideo(video);
String s = XmlUtil.beanToXml(videoMessage);
System.out.println("s = " + s);
return s;
}
public static String sendNews(BaseMessage baseMessage, List<NewsMessage.Article> articles) {
NewsMessage newsMessage = new NewsMessage();
newsMessage.setCreateTime(System.currentTimeMillis());
newsMessage.setFromUserName(baseMessage.getToUserName());
newsMessage.setToUserName(baseMessage.getFromUserName());
newsMessage.setMsgType(MessageType.NEWS.getType());
newsMessage.setArticleCount(articles.size());
newsMessage.setArticles(articles);
return XmlUtil.beanToXml(newsMessage);
}
}
package com.liang.wechat.utils;
import com.liang.wechat.bean.BaseMessage;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class XmlUtil {
public static Map<String, String> xmlToMap(String xmlStr) throws Exception {
Map<String, String> map = new HashMap<>(16);
//将xml格式的字符串转换成Document对象
Document doc = DocumentHelper.parseText(xmlStr);
//获取根节点
Element root = doc.getRootElement();
//获取根节点下的所有元素
List<Element> children = root.elements();
//循环所有子元素
if (children != null && children.size() > 0) {
for (Element o : children) {
map.put(o.getName(), o.getTextTrim());
}
}
return map;
}
public static <T extends BaseMessage> String beanToXml(T t) {
XStream xStream = new XStream();
xStream.processAnnotations(t.getClass());
return xStream.toXML(t);
}
public static <T> T xmlToBean(String xml, Class<T> clazz) {
XStream xstream = newXStreamInstance();
//先忽略未知的元素,防止从xml转换成对象时报错
xstream.ignoreUnknownElements();
xstream.processAnnotations(clazz);
return (T) xstream.fromXML(xml);
}
/**
* 扩展xstream,使其支持CDATA块
*/
private static XStream newXStreamInstance() {
return new XStream(new XppDriver() {
@Override
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
// 对所有xml节点的转换都增加CDATA标记
boolean cdata = true;
@Override
protected void writeText(QuickWriter writer, String text) {
if (this.cdata) {
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
} else {
writer.write(text);
}
}
};
}
});
}
}
server:
port: 8080
wx:
appId: wxdd95a0d4eb1c29f7
secret: d33cf03467a02d897bed1e1a1b7605f9
token: abc
spring:
redis:
host: 47.98.134.122
database: 2
port: 6379
timeout: 3000
{
"button":[
{
"name":"热门产品",
"sub_button":[
{
"type":"miniprogram",
"name":"知微舆论场",
"url":"https://trends.zhiweidata.com/",
"appid":"wx8f47f701f6a8e768",
"pagepath":"pages/index-v/index-v"
},
{
"type":"miniprogram",
"name":"危机案例库",
"url":"https://crisis.zhiweidata.com/",
"appid":"wx3287f77ae759a173",
"pagepath":"pages/index/index"
},
{
"type":"view",
"name":"知微事见",
"url":"https://ef.zhiweidata.com/"
}]
},
{
"name":"精选内容",
"sub_button":[
{
"type":"view",
"name":"新消费研究",
"url":"https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzU3MDMzMzIxMA==&action=getalbum&album_id=2522641317311709185&scene=173&from_msgid=2247485024&from_itemidx=1&count=3&nolastread=1#wechat_redirect"
},
{
"type":"view",
"name":"危机复盘",
"url":"https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzU3MDMzMzIxMA==&action=getalbum&album_id=2392137959220363267&scene=173&from_msgid=2247484665&from_itemidx=1&count=3&nolastread=1#wechat_redirect"
},
{
"type":"view",
"name":"年度报告",
"url":"https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzU3MDMzMzIxMA==&action=getalbum&album_id=2406680589417496577&scene=173&from_msgid=2247484643&from_itemidx=1&count=3&nolastread=1#wechat_redirect"
}]
},
{
"name":"限时福利",
"sub_button":[
{
"type":"click",
"name":"解锁案例",
"key":"UNLOCK_CASE"
},
{
"type":"click",
"name":"联系客服",
"key":"CONTACT_US"
}]
}]
}
\ No newline at end of file
package com.liang.wechat;
import com.liang.wechat.constant.WechatConstant;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class AccessTokenTest {
@Autowired
private TestRestTemplate testRestTemplate;
@Value("${wx.appid}")
private String appid;
@Value("${wx.secret}")
private String secret;
@Test
public void testGetAccessToken() {
ResponseEntity<String> forEntity = testRestTemplate.getForEntity(WechatConstant.ACCESS_TOKEN_URL, String.class, appid, secret);
System.out.println(forEntity);
}
}
package com.liang.wechat;
import com.liang.wechat.constant.WechatConstant;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.HashMap;
import java.util.Map;
@SpringBootTest
public class QrCodeTest {
@Test
public void testGetQrCodeUrl(){
}
//private String createTicket(String accessToken) {
// Map<String, String> intMap = new HashMap<>(8);
// intMap.put("scene_str", sceneStr);
// Map<String, Map<String, String>> mapMap = new HashMap<>(8);
// mapMap.put("scene", intMap);
// Map<String, Object> paramsMap = new HashMap<>(8);
// paramsMap.put("expire_seconds", expireSeconds);
// paramsMap.put("action_name", "QR_STR_SCENE");
// paramsMap.put("action_info", mapMap);
// ResponseEntity<JSONObject> entity = restTemplate.postForEntity(WechatConstant.CREATE_QRCODE_URL, paramsMap, JSONObject.class, accessToken);
// return entity.getBody().getString("ticket");
//}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment