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

以前介紹了自動回覆,下面介紹一些常見的消息處理樣式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方法測試便可


(持續更新)

相關文章
相關標籤/搜索