之前介绍了自动回复,下面介绍一些常见的消息处理样式
开始开发——关键字回复
功能描述
当我们公众号发送一些关键词的时候,公众号会回复自动回复有关关键词的信息。
实现思路
- 消息类型为文本样式
- 接收的客服端消息中要包含该关键字
代码开发
为便于扩展,将消息处理的方法写到服务层,新建收发信息的dto
一、便于扩展为不同类型的消息,修改收发消息的封装,改用dto模式
- 基础消息实体类
@Data
@XmlAccessorType(XmlAccessType.FIELD) // 映射类中的所有字段到XML
public class MsgSendEntity {
/**
* 公有部分
*/
// 开发者微信号
@XmlElement(name = "ToUserName") // 指定名称映射
private String toUserName;
// 发送方帐号(一个OpenID)
@XmlElement(name = "FromUserName")
private String fromUserName;
// 消息创建时间 (整型)
@XmlElement(name = "CreateTime")
private Long createTime;
// 消息类型
@XmlElement(name = "MsgType")
private String msgType;
// 消息id,64位整型
@XmlElement(name = "MsgId")
private Long msgId;
}
@Data
@XmlAccessorType(XmlAccessType.FIELD)
public class MsgReplyEntity {
// 用户的OpenID
@XmlElement(name = "ToUserName")
private String toUserName;
// 测试号的微信号
@XmlElement(name = "FromUserName")
private String fromUserName;
// 消息创建时间 (整型)
@XmlElement(name = "CreateTime")
private Long createTime;
// 消息类型
@XmlElement(name = "MsgType")
private String msgType;
// 文本消息内容
@XmlElement(name = "Content")
private String content;
}
- 新建消息实体类的dto
@Data
@XmlRootElement(name = "xml") // 根节点
@XmlAccessorType(XmlAccessType.FIELD) // 映射类中的所有字段到XML
public class MsgSendDto extends MsgSendEntity {
// 文本消息内容
@XmlElement(name = "Content")
private String content;
}
@Data
@XmlRootElement(name="xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class MsgReplyDto extends MsgReplyEntity {
}
二、抽取消息处理的服务类与消息处理的方法到服务层
@Service
public class MsgHandleServiceImpl implements IMsgHandleService {
@Override
public MsgReplyEntity handle(MsgSendEntity msgSend) {
WeChatUtil.getLogger().info("客户端接收的内容为:{}"+msgSend);
// 服务端消息回复的实体类
MsgReplyEntity msgReply = new MsgReplyEntity();
// 根据接收的信息回复,接收和发送方相反
msgReply.setFromUserName(msgSend.getToUserName());
msgReply.setToUserName(msgSend.getFromUserName());
msgReply.setCreateTime(new Date().getTime());
String msgType = msgSend.getMsgType();
String contentReply = null;
// 处理不同类型的消息
if (msgType.equals(WeChatConstants.MSG_TYPE_TEXT)) {
// 默认回复相同的类型消息
msgReply.setMsgType(msgType);
String contentSend = msgSend.getContent();
// 关键词处理
if (contentSend.contains("你好")) {
contentReply = "你好吗\r\nhow are you";
} else if (contentSend.contains("哈哈")||contentSend.contains("haha")) {
contentReply = "我也喜欢哈哈大笑";
} else if (contentSend.contains("chet")){
msgReply.setMsgType(WeChatConstants.MSG_TYPE_NEWS);
//设置图文个数
msgReply.setArticleCount(1);
//设置图文明细列表
ArticleItem item = new ArticleItem();
item.setTitle("chet的github博客");
item.setPicUrl("https://chetwhy.github.io/");
item.setDescription("chet的掘金博客");
item.setUrl("https://juejin.im/timeline");
msgReply.setItem(new ArticleItem[]{item});
}else {
// 非关键字,原样返回
contentReply = msgSend.getContent();
}
msgReply.setContent(contentReply);
}
WeChatUtil.getLogger().info("服务端回复的内容为:{}"+msgReply);
return msgReply;
}
}
三、封装的常量类
public class WeChatConstants {
/**
* 公众号appid
*/
public static String APP_ID = "wxa02348cd5ec17d28";
/**
* AppSecret
*/
public static String APPSECRET = "***";
/**
* 公众号配置相关
*/
public static final String URL = "ups.tiaodu.cn";
public static final String TOKEN = "123qwe";
/**
* 消息类型
*/
public static final String MSG_TYPE_TEXT = "text";
public static final String MSG_TYPE_NEWS = "news";
}
测试样例
在手机微信或电脑微信直接发送带【关键字】的信息即可
开始开发——接收事件推送
功能描述
微信公众号有多种不同事件信息,包括其触发事件的类型,响应处理。最常见的,当我们点击关注某公众号之后,公众号将自动推送给我们介绍信息后者活动宣传等。
实现思路
一、参考微信公众平台技术文档->消息管理->接收事件推送
二、查看对应消息事件格式,扩展消息实体的dto
三、在原消息基础上,添加事件的逻辑判断
下面以关注/取消事件和自定义菜单事件做演示
代码开发
1为MsgSendDto添加事件属性
...
public class MsgSendDto {
...
// 事件类型 subscribe(订阅)、unsubscribe(取消订阅)、CLICK(点击菜单)
@XmlElement(name = "Event")
private String event;
}
2增加常量类
public class WeChatConstants {
...
public static final String MSG_TYPE_EVENT = "event";
public static final String MSG_TYPE_EVENT_SUBSCRIBE = "subscribe";
}
3消息处理方法,增加判断逻辑
@Service
public class MsgHandleServiceImpl {
public MsgReplyEntity handle(MsgSendEntity msgSend) {
...
// 处理不同类型的消息
if (msgType.equals(WeChatConstants.MSG_TYPE_TEXT)) {
...
}else if(msgType.equals(WeChatConstants.MSG_TYPE_EVENT)){
// 订阅事件
if(msgSend.getEvent().equals(WeChatConstants.MSG_TYPE_EVENT_SUBSCRIBE)){
msgReply.setMsgType(WeChatConstants.MSG_TYPE_TEXT);
msgReply.setContent("感谢关注chetwhy![亲亲]\r\n现在回复【chet】\r\n马上查阅java博客![大兵]");
}
}
WeChatUtil.getLogger().info("服务端回复的内容为:{}"+msgReply);
return msgReply;
}
}
测试样例
一、先取消对测试公众的关注(断点调试依然可以看到消息类型为event)
二、在测试号管理中再次扫描二维码关注
代码开发
开始开发——自定义菜单及其事件
功能描述
当我们点开一个订阅的公共号时,点击聊天输入框最左侧的按钮,可以切换到公众号的菜单栏,有的菜单选项中多个子菜单,有的菜单选择会自动跳转到其他页面。这为我们的公众号提供更为便捷的窗口和功能的扩展。
实现思路——自定义菜单
一、参考微信公众平台技术文档->自定义菜单->【自定义菜单...接口】和消息管理->接收事件推送->[4-6菜单事件]
二、按照文档,我们应先创建自定义的菜单。简单的说:
- 菜单分为一级菜单和二级菜单,一级最多3个,二级最多5个;
- 菜单借口大致有10种类型,分为按钮(click,view),扫码(scancode_push,scancode_waitmsg),拍照相册(pic_sysphoto,pic_photo_or_album,pic_weixin),位置(location_select),文件(media_id)等
- post请求,https协议,请求参数需携带access_token
公众平台以access_token为接口调用凭据,来调用接口,所有接口的调用需要先获取access_token,access_token在2小时内有效,过期需要重新获取,但1天内获取次数有限,开发者需自行存储
三、根据请求示例,封装好我们自定义的json数据
四、根据文档->获取access_token,编写工具类获取返回的token
代码开发
1封装自定义菜单的json数据
{
"button":[
{
"type":"click",
"name":"今日歌曲",
"key":"V1001_TODAY_MUSIC"
},
{
"name":"菜单",
"sub_button":[
{
"type":"view",
"name":"搜索",
"url":"http://www.soso.com/"
},
{
"type":"miniprogram",
"name":"wxa",
"url":"http://mp.weixin.qq.com",
"appid":"wx286b93c14bbf93aa",
"pagepath":"pages/lunar/index"
},
{
"type":"click",
"name":"赞一下我们",
"key":"V1001_GOOD"
}]
}]
}
起名字费劲,我这里照搬的微信的菜单名,两个按钮型一级菜单,其中有两个子菜单
2创建获取access token的工具类方法
public class WeChatUtil {
// 获取access_token的路径模板
public static final String GET_ACCESSTOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
public static String accessToken;
public static long expiresTime;
/**
* 获取access_token
* @return access_token
*/
public static String getAccessToken(){
// 第一次获取或access token已过期
if(accessToken==null||new Date().getTime()>expiresTime){
// 替换示例种参数,发送https的get请求
String result = HttpUtil.get(GET_ACCESSTOKEN_URL.replace("APPID", WeChatConstants.APP_ID).replace("APPSECRET", WeChatConstants.APPSECRET));
JSONObject json = JSONObject.parseObject(result);
accessToken = json.getString("access_token");
// 有效事件,单位秒
Long expires_in = json.getLong("expires_in");
// 设置凭据的失效时间,默认7200s,提前五分钟过期
expiresTime = new Date().getTime()+((expires_in-60*5)*1000);
WeChatUtil.getLogger().info("access_token={},expires_time={}",accessToken,expiresTime);
}
return accessToken;
}
}
3船舰自定菜单的工具类方法
public class WeChatUtil {
// 自定义菜单接口
public static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
/**
* 创建自定义菜单
* @param menuJson
*/
public static void createMenu(String menuJson){
//发起请求到指定的接口,并且带上菜单json数据
String result = HttpUtil.post(CREATE_MENU_URL.replace("ACCESS_TOKEN",getAccessToken()), menuJson);
WeChatUtil.getLogger().info("创建自定义菜单结果:{}", result);
}
}
4.写一个主方法,将之前封装的json传入createMenu方法。运行即可
public static void main(String[] args) {
String menu = "...";
createMenu(menu);
}
测试样例
一、直接运行上述的main方法,查看运行日志,生成成功
二、查看微信客户端的聊天页面,点开二级菜单
三、若日志显示成功,客户端没反应,尝试重新关注订阅号,或重启natapp
实现思路——自定义菜单事件
一、封装菜单事件的参数,扩展dto
二、增加消息处理的业务逻辑
代码开发
一、消息发送实体类
public class MsgSendDto extends MsgSendEntity {
...
// 菜单的key值
@XmlElement(name = "EventKey")
private String eventKey;
}
二、消息处理方法,key即为json中的"key"键
@Service
public class MsgHandleServiceImpl implements IMsgHandleService {
@Override
public MsgReplyEntity handle(MsgSendDto msgSend) {
...
// 处理不同类型的消息
if (msgType.equals(WeChatConstants.MSG_TYPE_TEXT)) {
...
}else if(msgType.equals(WeChatConstants.MSG_TYPE_EVENT)){
// 订阅事件
if(msgSend.getEvent().equals(WeChatConstants.MSG_TYPE_EVENT_SUBSCRIBE)){
...
}else if(msgSend.getEvent().equals(WeChatConstants.MSG_TYPE_EVENT_CLICK)){
String eventKey = msgSend.getEventKey();
//判断按钮的key值
if ("V1001_TODAY_MUSIC".equals(eventKey)){
contentReply = "《年少有为》- 李荣浩\n" +
"《The Spectre》- Alan Walker";
}else if("V1001_GOOD".equals(eventKey)){
contentReply = "谢谢您的点赞关注[拇指]";
}
msgReply.setMsgType("text");
msgReply.setContent(contentReply);
}
}
WeChatUtil.getLogger().info("服务端回复的内容为:{}"+msgReply);
return msgReply;
}
}
测试样例
一、运行springboot
二、点开微信菜单栏,点击菜单按钮
开始开发——发送模板信息
功能描述
这个也很常见,比如当我们在公众号平台购买商品后,平台会发送下单结果的通知信息,这个类似与邮寄一样,也是模板信息。文档也说,模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中,如信用卡刷卡通知,商品购买成功通知等。
实现思路
一、参考微信公众平台技术文档->消息管理->模板消息接口
二、在测试公众号中配置新增模板
三、编写工具类方法,支持https的post请求,url为:
https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=ACCESS_TOKEN
代码开发
一、测试公众号->模板消息接口->新增配置模板
我这里依然使用官方文档的例子
如图
)
二、封装发送模板信息的json数据,相关信息都改成自己的,template_id即上面的【模板ID】
{
"touser":"o50E15lhQXW0SlsYg3bKFrywtKC8",
"template_id":"RXl8FLezLbHaBrPWTwK295CNgkNpR69Et40K3oOoK0",
"url":"http://weixin.qq.com/download",
"miniprogram":{
"appid":"xiaochengxuappid12345",
"pagepath":"index?foo=bar"
},
"data":{
"first": {
"value":"恭喜你购买成功!",
"color":"#173177"
},
"keyword1":{
"value":"巧克力",
"color":"#173177"
},
"keyword2": {
"value":"39.8元",
"color":"#173177"
},
"keyword3": {
"value":"2014年9月22日",
"color":"#173177"
},
"remark":{
"value":"欢迎再次购买!",
"color":"#173177"
}
}
}
三、创建发送模板信息的方法
// 发送模板消息的接口
public static final String SEND_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
/**
* 发送模板信息
* @param data 模板json数据
*/
public static void sendTemplate(String data){
String result = HttpUtil.post(SEND_TEMPLATE_URL.replace("ACCESS_TOKEN", getAccessToken()),data);
WeChatUtil.getLogger().info("发送模板消息结果:{}",result);
}
测试样例
使用第二步的json数据,直接在main方法测试即可
详细过程,可参考源代码(持续更新):https://github.com/chetwhy/cloud-flow
网友评论