微信公众号快速开发(三)多种消息类型处理

以前介绍了自动回复,下面介绍一些常见的消息处理样式java

开始开发——关键字回复

功能描述

当咱们公众号发送一些关键词的时候,公众号会回复自动回复有关关键词的信息。git

实现思路

  1. 消息类型为文本样式
  2. 接收的客服端消息中要包含该关键字

代码开发

为便于扩展,将消息处理的方法写到服务层,新建收发信息的dtogithub

1、便于扩展为不一样类型的消息,修改收发消息的封装,改用dto模式spring

  • 基础消息实体类
@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 {

}
复制代码

2、抽取消息处理的服务类与消息处理的方法到服务层json

@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;
    }
}
复制代码

3、封装的常量类api

public class WeChatConstants {

    /** * 公众号appid */
    public static String APP_ID = "wxa02348cd5ec17d28"; 

    /** * AppSecret */
    public static String APPSECRET = "2ffbf0ff3516af025942ec8ca67f27d8"; 

    /** * 公众号配置相关 */
    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";
}
复制代码

测试样例

在手机微信或电脑微信直接发送带【关键字】的信息便可springboot

开始开发——接收事件推送

功能描述

微信公众号有多种不一样事件信息,包括其触发事件的类型,响应处理。最多见的,当咱们点击关注某公众号以后,公众号将自动推送给咱们介绍信息后者活动宣传等。微信

实现思路

1、参考微信公众平台技术文档->消息管理->接收事件推送app

2、查看对应消息事件格式,扩展消息实体的dto微信公众平台

3、在原消息基础上,添加事件的逻辑判断

下面以关注/取消事件和自定义菜单事件作演示

代码开发

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;
    }
}

复制代码

测试样例

1、先取消对测试公众的关注(断点调试依然能够看到消息类型为event)

2、在测试号管理中再次扫描二维码关注

代码开发

开始开发——自定义菜单及其事件

功能描述

当咱们点开一个订阅的公共号时,点击聊天输入框最左侧的按钮,能够切换到公众号的菜单栏,有的菜单选项中多个子菜单,有的菜单选择会自动跳转到其余页面。这为咱们的公众号提供更为便捷的窗口和功能的扩展。

实现思路——自定义菜单

1、参考微信公众平台技术文档->自定义菜单->【自定义菜单...接口】和消息管理->接收事件推送->[4-6菜单事件]

2、按照文档,咱们应先建立自定义的菜单。简单的说:

  • 菜单分为一级菜单和二级菜单,一级最多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天内获取次数有限,开发者需自行存储

3、根据请求示例,封装好咱们自定义的json数据

4、根据文档->获取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);
}

复制代码

测试样例

1、直接运行上述的main方法,查看运行日志,生成成功

2、查看微信客户端的聊天页面,点开二级菜单

3、若日志显示成功,客户端没反应,尝试从新关注订阅号,或重启natapp

实现思路——自定义菜单事件

1、封装菜单事件的参数,扩展dto

2、增长消息处理的业务逻辑

代码开发

1、消息发送实体类

public class MsgSendDto extends MsgSendEntity {
    ...
    
    // 菜单的key值
    @XmlElement(name = "EventKey")
    private String eventKey;
}


复制代码

2、消息处理方法,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;
    }
}

复制代码

测试样例

1、运行springboot

2、点开微信菜单栏,点击菜单按钮

开始开发——发送模板信息

功能描述

这个也很常见,好比当咱们在公众号平台购买商品后,平台会发送下单结果的通知信息,这个相似与邮寄同样,也是模板信息。文档也说,模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中,如信用卡刷卡通知,商品购买成功通知等。

实现思路

1、参考微信公众平台技术文档->消息管理->模板消息接口

2、在测试公众号中配置新增模板

3、编写工具类方法,支持https的post请求,url为:

api.weixin.qq.com/cgi-bin/tem…

代码开发

1、测试公众号->模板消息接口->新增配置模板

我这里依然使用官方文档的例子

如图

)

2、封装发送模板信息的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"
        }
    }
}
复制代码

3、建立发送模板信息的方法

// 发送模板消息的接口
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方法测试便可


(持续更新)

相关文章
相关标签/搜索