微信公眾號快速開發(fā)(三)多種消息類型處理

之前介紹了自動回復(fù),下面介紹一些常見的消息處理樣式

開始開發(fā)——關(guān)鍵字回復(fù)

功能描述

當(dāng)我們公眾號發(fā)送一些關(guān)鍵詞的時候,公眾號會回復(fù)自動回復(fù)有關(guān)關(guān)鍵詞的信息。

實現(xiàn)思路

  1. 消息類型為文本樣式
  2. 接收的客服端消息中要包含該關(guān)鍵字

代碼開發(fā)

為便于擴展,將消息處理的方法寫到服務(wù)層,新建收發(fā)信息的dto

一、便于擴展為不同類型的消息,修改收發(fā)消息的封裝,改用dto模式

  • 基礎(chǔ)消息實體類
@Data
@XmlAccessorType(XmlAccessType.FIELD) // 映射類中的所有字段到XML
public class MsgSendEntity {
    /**
     * 公有部分
     */
    //  開發(fā)者微信號
    @XmlElement(name = "ToUserName") // 指定名稱映射
    private String toUserName;

    // 發(fā)送方帳號(一個OpenID)
    @XmlElement(name = "FromUserName")
    private String fromUserName;

    // 消息創(chuàng)建時間 (整型)
    @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;

    // 消息創(chuàng)建時間 (整型)
    @XmlElement(name = "CreateTime")
    private Long createTime;

    // 消息類型
    @XmlElement(name = "MsgType")
    private String msgType;

    // 文本消息內(nèi)容
    @XmlElement(name = "Content")
    private String content;
}
  • 新建消息實體類的dto
@Data
@XmlRootElement(name = "xml") // 根節(jié)點
@XmlAccessorType(XmlAccessType.FIELD) // 映射類中的所有字段到XML
public class MsgSendDto extends MsgSendEntity {

    // 文本消息內(nèi)容
    @XmlElement(name = "Content")
    private String content;
}
@Data
@XmlRootElement(name="xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class MsgReplyDto extends MsgReplyEntity {

}

二、抽取消息處理的服務(wù)類與消息處理的方法到服務(wù)層

@Service
public class MsgHandleServiceImpl implements IMsgHandleService {
    
    @Override
    public MsgReplyEntity handle(MsgSendEntity msgSend) {
        WeChatUtil.getLogger().info("客戶端接收的內(nèi)容為:{}"+msgSend);

        // 服務(wù)端消息回復(fù)的實體類
        MsgReplyEntity msgReply = new MsgReplyEntity();
        // 根據(jù)接收的信息回復(fù),接收和發(fā)送方相反
        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)) {
            // 默認(rèn)回復(fù)相同的類型消息
            msgReply.setMsgType(msgType);
            String contentSend = msgSend.getContent();

            // 關(guān)鍵詞處理
            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);
                //設(shè)置圖文個數(shù)
                msgReply.setArticleCount(1);
                //設(shè)置圖文明細列表
                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 {
                // 非關(guān)鍵字,原樣返回
                contentReply = msgSend.getContent();
            }
            msgReply.setContent(contentReply);
        }
        
        WeChatUtil.getLogger().info("服務(wù)端回復(fù)的內(nèi)容為:{}"+msgReply);
        return msgReply;
    }
}

三、封裝的常量類

public class WeChatConstants {

    /**
     * 公眾號appid
     */
    public static String APP_ID = "wxa02348cd5ec17d28"; 

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

    /**
     * 公眾號配置相關(guān)
     */
    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";
}

測試樣例

在手機微信或電腦微信直接發(fā)送帶【關(guān)鍵字】的信息即可

image

開始開發(fā)——接收事件推送

功能描述

微信公眾號有多種不同事件信息,包括其觸發(fā)事件的類型,響應(yīng)處理。最常見的,當(dāng)我們點擊關(guān)注某公眾號之后,公眾號將自動推送給我們介紹信息后者活動宣傳等。

實現(xiàn)思路

一、參考微信公眾平臺技術(shù)文檔->消息管理->接收事件推送

image

二、查看對應(yīng)消息事件格式,擴展消息實體的dto

image

三、在原消息基礎(chǔ)上,添加事件的邏輯判斷

下面以關(guān)注/取消事件和自定義菜單事件做演示

代碼開發(fā)

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("感謝關(guān)注chetwhy![親親]\r\n現(xiàn)在回復(fù)【chet】\r\n馬上查閱java博客![大兵]");
            }
        }

        WeChatUtil.getLogger().info("服務(wù)端回復(fù)的內(nèi)容為:{}"+msgReply);
        return msgReply;
    }
}

測試樣例

一、先取消對測試公眾的關(guān)注(斷點調(diào)試依然可以看到消息類型為event)

二、在測試號管理中再次掃描二維碼關(guān)注

image

代碼開發(fā)

開始開發(fā)——自定義菜單及其事件

功能描述

當(dāng)我們點開一個訂閱的公共號時,點擊聊天輸入框最左側(cè)的按鈕,可以切換到公眾號的菜單欄,有的菜單選項中多個子菜單,有的菜單選擇會自動跳轉(zhuǎn)到其他頁面。這為我們的公眾號提供更為便捷的窗口和功能的擴展。

實現(xiàn)思路——自定義菜單

一、參考微信公眾平臺技術(shù)文檔->自定義菜單->【自定義菜單...接口】和消息管理->接收事件推送->[4-6菜單事件]

image

二、按照文檔,我們應(yīng)先創(chuàng)建自定義的菜單。簡單的說:

  • 菜單分為一級菜單和二級菜單,一級最多3個,二級最多5個;
  • 菜單借口大致有10種類型,分為按鈕(click,view),掃碼(scancode_push,scancode_waitmsg),拍照相冊(pic_sysphoto,pic_photo_or_album,pic_weixin),位置(location_select),文件(media_id)等
  • post請求,https協(xié)議,請求參數(shù)需攜帶access_token

公眾平臺以access_token為接口調(diào)用憑據(jù),來調(diào)用接口,所有接口的調(diào)用需要先獲取access_token,access_token在2小時內(nèi)有效,過期需要重新獲取,但1天內(nèi)獲取次數(shù)有限,開發(fā)者需自行存儲

三、根據(jù)請求示例,封裝好我們自定義的json數(shù)據(jù)

四、根據(jù)文檔->獲取access_token,編寫工具類獲取返回的token

image

代碼開發(fā)

1封裝自定義菜單的json數(shù)據(jù)

 {
     "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創(chuàng)建獲取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){
            // 替換示例種參數(shù),發(fā)送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");
            // 設(shè)置憑據(jù)的失效時間,默認(rèn)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";
    
    /**
     * 創(chuàng)建自定義菜單
     * @param menuJson
     */
    public static void createMenu(String menuJson){
        //發(fā)起請求到指定的接口,并且?guī)喜藛蝚son數(shù)據(jù)
        String result = HttpUtil.post(CREATE_MENU_URL.replace("ACCESS_TOKEN",getAccessToken()), menuJson);
        WeChatUtil.getLogger().info("創(chuàng)建自定義菜單結(jié)果:{}", result);
    }
}    

4.寫一個主方法,將之前封裝的json傳入createMenu方法。運行即可

public static void main(String[] args) {
    String menu = "...";
    createMenu(menu);
}

測試樣例

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

image

二、查看微信客戶端的聊天頁面,點開二級菜單

image

三、若日志顯示成功,客戶端沒反應(yīng),嘗試重新關(guān)注訂閱號,或重啟natapp

實現(xiàn)思路——自定義菜單事件

一、封裝菜單事件的參數(shù),擴展dto

二、增加消息處理的業(yè)務(wù)邏輯

代碼開發(fā)

一、消息發(fā)送實體類

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 = "謝謝您的點贊關(guān)注[拇指]";
                }
                msgReply.setMsgType("text");
                msgReply.setContent(contentReply);
            }
        }

        WeChatUtil.getLogger().info("服務(wù)端回復(fù)的內(nèi)容為:{}"+msgReply);
        return msgReply;
    }
}

測試樣例

一、運行springboot

二、點開微信菜單欄,點擊菜單按鈕

image

開始開發(fā)——發(fā)送模板信息

功能描述

這個也很常見,比如當(dāng)我們在公眾號平臺購買商品后,平臺會發(fā)送下單結(jié)果的通知信息,這個類似與郵寄一樣,也是模板信息。文檔也說,模板消息僅用于公眾號向用戶發(fā)送重要的服務(wù)通知,只能用于符合其要求的服務(wù)場景中,如信用卡刷卡通知,商品購買成功通知等。

實現(xiàn)思路

一、參考微信公眾平臺技術(shù)文檔->消息管理->模板消息接口

image

二、在測試公眾號中配置新增模板

image

三、編寫工具類方法,支持https的post請求,url為:

https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=ACCESS_TOKEN

代碼開發(fā)

一、測試公眾號->模板消息接口->新增配置模板

我這里依然使用官方文檔的例子

image

如圖

image

)

二、封裝發(fā)送模板信息的json數(shù)據(jù),相關(guān)信息都改成自己的,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"
        }
    }
}

三、創(chuàng)建發(fā)送模板信息的方法

// 發(fā)送模板消息的接口
public static final String SEND_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";

/**
  * 發(fā)送模板信息
  * @param data 模板json數(shù)據(jù)
  */
public static void sendTemplate(String data){
    String result = HttpUtil.post(SEND_TEMPLATE_URL.replace("ACCESS_TOKEN", getAccessToken()),data);
    WeChatUtil.getLogger().info("發(fā)送模板消息結(jié)果:{}",result);
}

測試樣例

使用第二步的json數(shù)據(jù),直接在main方法測試即可

image

詳細過程,可參考源代碼(持續(xù)更新):https://github.com/chetwhy/cloud-flow

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 微信服務(wù)號開發(fā) 整體流程 域名報備,服務(wù)器搭建 Python開發(fā)環(huán)境和項目的初始化搭建; 微信公眾號注冊及開發(fā)模式...
    飛行員suke閱讀 4,690評論 0 14
  • 開發(fā)前首先我們要知道一些概念 各公眾號區(qū)別:1、訂閱號:為媒體和個人提供一種信息傳播方式,主要偏于為用戶傳達資訊(...
    CoderZS閱讀 3,525評論 1 19
  • 一、公眾號介紹 微信公眾號分類 訂閱號:主要偏于為用戶傳達資訊(類似報紙雜志),認(rèn)證前后都是每天只可以群發(fā)一條消息...
    小花的胖次閱讀 6,824評論 3 37
  • 一、前言 微信公眾號開發(fā) (1) 微信接入認(rèn)證成為開發(fā)者 微信公眾號開發(fā) (2) 消息處理 本文將實現(xiàn) 根據(jù)App...
    zhengqingya閱讀 457評論 0 2
  • 大家好,我是IT修真院深圳分院第6期學(xué)員,一枚正直善良的JAVA程序員。 今天給大家分享一下,修真院官網(wǎng)復(fù)盤項目中...
    blue_gogogo閱讀 633評論 1 3

友情鏈接更多精彩內(nèi)容