歡迎光臨
每天分享高質量文章

使用 FastBootWeixin 框架快速開發微信公眾號

(點選上方公眾號,可快速關註)


來源:光閃 ,

my.oschina.net/u/2368090/blog/1539298

本框架基於SpringBoot實現,使用簡單快捷,可以快速的完成一個微信公眾號

在使用本框架前建議對微信公眾號開發檔案有所瞭解,不過在不瞭解公眾號檔案的情況下使用本框架也能完成一個簡單的微信公眾號。

一、簡單示例:

1. 申請測試公眾號

微信測試公眾號申請連結

https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

2. 準備完成,建立maven專案並加入maven依賴

    org.springframework.boot

    spring-boot-starter-parent

    1.5.6.RELEASE

 

   

   

        com.mxixm

        fastboot-weixin

        0.1.2.alpha

   

 

   

   

        org.springframework.boot

        spring-boot-starter-web

   

 

   

   

        org.apache.httpcomponents

        httpcore

   

   

        org.apache.httpcomponents

        httpclient

   

3. 編寫示例程式碼

在resource目錄下新建配置檔案application.properties或者其他spring boot支援的配置檔案型別,加入配置:

  • wx.token=隨機生成的一串字母與數字,推薦使用隨機生成32位的UUID

  • wx.appid=測試號的appid,測試號管理介面有

  • wx.appsecret=測試號的appsecret,測試號管理介面有

測試程式碼:

package com.mxixm.fastboot.weixin;

 

import com.mxixm.fastboot.weixin.annotation.WxApplication;

import com.mxixm.fastboot.weixin.annotation.WxAsyncMessage;

import com.mxixm.fastboot.weixin.annotation.WxButton;

import com.mxixm.fastboot.weixin.module.web.WxRequest;

import com.mxixm.fastboot.weixin.module.event.WxEvent;

import com.mxixm.fastboot.weixin.module.message.WxMessage;

import com.mxixm.fastboot.weixin.module.user.WxUser;

import com.mxixm.fastboot.weixin.mvc.annotation.WxController;

import com.mxixm.fastboot.weixin.mvc.annotation.WxEventMapping;

import com.mxixm.fastboot.weixin.mvc.annotation.WxMessageMapping;

import org.springframework.boot.SpringApplication;

 

@WxApplication

@WxController

public class WxApp {

 

    public static void main(String[] args) throws Exception {

        SpringApplication.run(WxApp.class, args);

    }

 

    /**

     * 定義微信選單

     */

    @WxButton(group = WxButton.Group.LEFT, main = true, name = “左”)

    public void left() {

    }

 

    /**

     * 定義微信選單

     */

    @WxButton(group = WxButton.Group.RIGHT, main = true, name = “右”)

    public void right() {

    }

 

    /**

     * 定義微信選單,並接受事件

     */

    @WxButton(type = WxButton.Type.CLICK,

            group = WxButton.Group.LEFT,

            order = WxButton.Order.FIRST,

            name = “文字訊息”)

    public String leftFirst(WxRequest wxRequest, WxUser wxUser) {

        return “測試文字訊息”;

    }

 

    /**

     * 定義微信選單,並接受事件

     */

    @WxButton(type = WxButton.Type.VIEW,

            group = WxButton.Group.LEFT,

            order = WxButton.Order.SECOND,

            url = “http://baidu.com”,

            name = “點選連結”)

    @WxAsyncMessage

    public WxMessage link() {

        return WxMessage.News.builder().addItem(“測試圖文訊息”, “測試”, “https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/logo_white.png”, “http://baidu.com”).build();

    }

 

    /**

     * 接受微信事件

     * @param wxRequest

     * @param wxUser

     */

    @WxEventMapping(type = WxEvent.Type.UNSUBSCRIBE)

    public void unsubscribe(WxRequest wxRequest, WxUser wxUser) {

        System.out.println(wxUser.getNickName() + “退訂了公眾號”);

    }

 

    /**

     * 接受使用者文字訊息,非同步傳迴文字訊息

     * @param content

     * @return dummy

     */

    @WxMessageMapping(type = WxMessage.Type.TEXT)

    @WxAsyncMessage

    public String text(WxRequest wxRequest, String content) {

        WxSession wxSession = wxRequest.getWxSession();

        if (wxSession != null && wxSession.getAttribute(“last”) != null) {

            return “上次收到訊息內容為” + wxSession.getAttribute(“last”);

        }

        return “收到訊息內容為” + content;

    }

 

    /**

     * 接受使用者文字訊息,同步傳回圖文訊息

     * @param content

     * @return dummy

     */

    @WxMessageMapping(type = WxMessage.Type.TEXT, wildcard = “1*”)

    public WxMessage message(WxSession wxSession, String content) {

        wxSession.setAttribute(“last”, content);

        return WxMessage.News.builder()

                .addItem(WxMessage.News.Item.builder().title(content).description(“隨便一點”)

                        .picUrl(“http://k2.jsqq.net/uploads/allimg/1702/7_170225142233_1.png”)

                        .url(“http://baidu.com”).build())

                .addItem(WxMessage.News.Item.builder().title(“第二條”).description(“隨便二點”)

                        .picUrl(“http://k2.jsqq.net/uploads/allimg/1702/7_170225142233_1.png”)

                        .url(“http://baidu.com”).build())

                .build();

    }

 

    /**

     * 接受使用者文字訊息,非同步傳迴文字訊息

     * @param content

     * @return dummy

     */

    @WxMessageMapping(type = WxMessage.Type.TEXT, wildcard = “2*”)

    @WxAsyncMessage

    public String text2(WxRequestBody.Text text, String content) {

        boolean match = text.getContent().equals(content);

        return “收到訊息內容為” + content + “!結果匹配!” + match;

    }

}

4. 配置內網穿透

因為微信公眾號需要配置自己的伺服器介面,測試時可直接使用本地進行測試,使用內網穿透可以令微信公眾平臺訪問到你自己本地的伺服器。

軟體可使用ngrok或者natapp,使用方式請參考兩者官方檔案。

5. 配置測試公眾號

在測試公眾號的介面配置資訊中填寫在第三步中生成的域名,token使用配置檔案中的token,儲存後,如果不出意外應該會驗證成功。如有問題請及時反饋。

二、示例說明

上面的示例在啟動後,請關註自己的公眾號,此時公眾號的選單應該是有兩個主選單:左、右,同時左有兩個子選單:文字訊息、點選連結。

在點選文字訊息選單時,會收到文字訊息,內容為:測試文字訊息。

在點選第二個點選連結時,會跳轉至百度,並收到一條圖文訊息,標題是測試圖文訊息。

給公眾號傳送文字訊息,訊息內容不是1開頭時,會收到公眾號回覆內容:”收到訊息內容為” + 傳送的內容。

給公眾號傳送文字訊息,訊息內容是1開頭時,會收到圖文訊息的回覆。

當有使用者退訂公眾號時,會在System.out中列印使用者暱稱 + “退訂了公眾號”

三、示例講解

註解@WxApplication用於宣告該應用為微信application,並使用SpringApplication啟動。若已有SpringBoot環境,請在你的@SpringApplication類上加入註解@EnableWxMvc,效果一樣。可以看原始碼。

註解@WxController用於宣告該類為微信Controller,只有宣告了這個註解,才會系結在微信伺服器的請求對映中,否則該類會被忽略。

註解@WxButton(group = WxButton.Group.LEFT, main = true, name = “左”)用於宣告一個按鈕箱,group代表分組,有左中右三個分組,分別對應微信的三個一級選單。main為boolean值,代表該選單項是否為一級選單。name就是選單名。

註解@WxButton(type = WxButton.Type.CLICK, group = WxButton.Group.LEFT, order = WxButton.Order.FIRST, name = “文字訊息”) 用於宣告左邊分組的子選單,order代表順序,這裡是第一個。

public String leftFirst(WxRequest wxRequest, WxUser wxUser) { return “測試文字訊息”; } 這裡有三個點:

  • WxRequest是自動系結的引數,當使用者在公眾號上進行某些操作後,微信伺服器會給配置中填寫的域名的根路徑傳送一個Post請求,請求內容是xml格式的訊息,這條訊息內容中標記了具體的資訊,可參考公眾號檔案。這裡wxRequest為封裝過的微信請求內容,可以透過這個wxRequest獲得一些資訊。

  • wxUser是透過微信api介面獲取的使用者相關資訊,這個還涉及到另外一個內容,後面講解。

  • 傳回String,此時會直接使用微信定義的文字訊息,同步傳回給使用者,即直接對微信伺服器的這個請求進行響應,參考:被動回覆訊息

https://mp.weixin.qq.com/wiki?t=resource/res_main&id;=mp1421140543

@WxButton(type = WxButton.Type.VIEW, group = WxButton.Group.LEFT, order = WxButton.Order.SECOND, url = “http://baidu.com“, name = “點選連結”) 該註解同上面,型別變為View,具體內容可參考該列舉註釋,或者公眾號檔案。註意每種選單型別都有自己的限制,請參考檔案,如不滿足條件啟動時就會發生異常。

註解@WxAsyncMessage表明非同步回覆訊息,參考客服訊息,暫時未對多客服進行支援。

https://mp.weixin.qq.com/wiki?t=resource/res_main&id;=mp1421140547

WxMessage.News.builder(),在WxMessage類中,有不同的靜態內部類,以及他們的builder,透過builder可以方便的構造微信不同型別的訊息,請參考被動回覆訊息和客服訊息。

註解@WxEventMapping(type = WxEvent.Type.UNSUBSCRIBE)系結取消訂閱事件,當有使用者取消關註時,會進入這個註解下麵的邏輯。還有一點要註解,WxEventMapping所有的回覆內容都會被非同步傳送給使用者。

註解@WxMessageMapping(type = WxMessage.Type.TEXT)表示系結使用者傳送的文字訊息到下麵的方法邏輯,public String text(String content) { return “收到訊息內容為” + content; }。content會自動被賦值為使用者傳送的文字內容。

註解@WxMessageMapping(type = WxMessage.Type.TEXT, wildcard = “1*”)與上面相同,不同的是wildcard萬用字元,該萬用字元支援對訊息內容做通配,改寫該通配邏輯的會進入下麵的執行邏輯。

四、功能支援

1. Spring Boot風格的啟動方式

與Spring Boot完美整合,如果自己沒有SpringBoot專案,想直接使用該框架搭建公眾號,可直接使用@WxApplication標記啟動類,該註解支援引數:menuAutoCreate,預設為true。表示自動建立微信選單,可以設定為false關閉自動建立選單的行為。若已有Spring Boot專案,想引入此框架,只需在你的任意配置類上標記註解@EnableWxMvc即可,引數同上。

2. Spring Mvc風格的Mapping

共支援三種Mapping:

  • @WxButton,微信按鈕系結與生成。引數說明:group表示左中右三個分組,name為按鈕名,type選單型別,main是否為一級選單。order顯示順序。key為事件key,若交給框架管理,則key會自動生成,無需配置。url為view型別的訪問地址。mediaId為媒體ID。

  • @WxMessageMapping,微信訊息系結。引數說明:type訊息型別、wildcard萬用字元支援多個、pattern正則運算式,暫時不支援哈哈、name系結名,不必要。

  • @WxEventMapping,微信事件系結。引數說明:type事件型別、name系結名,不必要。

註意:系結所在類需宣告為@WxController

3. Spring Mvc風格的引數系結

支援以下型別引數:

  • WxRequest:微信伺服器的請求封裝

  • WxRequest.Body:微信伺服器的請求體內容封裝

  • WxRequest.Body.field:WxRequest裡的任意屬性名,都可以直接系結到引數,但是要註意訊息型別與引數值,有些訊息不會有某些內容。暫時還不支援不同訊息區分系結的不同的Request型別,後續可加入支援。

  • WxSession:類比於HttpSession,預設實現使用fromUserName作為sessionId

  • WxUser:這個是較為特殊的型別,其實是透過WxUserProvider介面提供的,本框架提供一個預設的實現DefaultWxUserProvider implements WxUserProvider,該實現透過微信api獲取使用者資訊,以WxUser型別傳回,當然你也可以使用自己的實現類,只用宣告為SpringBean即可自動註入,泛型型別也可以由你自己確定,引數中有該泛型型別的引數,都會被自動使用WxUserProvider.getUser獲取並系結到引數中。

引數系結目前支援這幾種,如果有更好的方案需要支援,也可以直接提出意見與建議,我會及時進行處理的。

4. Spring Mvc風格的傳回值

傳回值支援以下型別:

  • String 該傳回值會以文字訊息形式傳回給使用者

  • WxMessage及其子類 該傳回值可以很方便的使用對應訊息型別的Builder去構造,此時會以對應型別的訊息傳回給使用者。

  • @WxAsyncMessage 標記非同步傳回訊息,透過這個註解,可以令訊息的傳回值以非同步訊息的形式呼叫客服介面傳送給使用者。@WxEventMapping的傳回值只能以這種形式傳送。

  • String或者WxMessage的Iterable或者Array。該型別會分為多條非同步訊息傳送給使用者。

上面非同步傳送訊息都是使用的WxMessageTemplate傳送的,下麵講解。

5. Spring風格的訊息傳送

本框架提供WxMessageTemplate傳送訊息,同時在template中提供了WxMessageProcesser支援,作用是在訊息傳送前對訊息做處理。

如同步傳回訊息時,需要寫入fromUserName欄位,而該欄位是訊息傳送時的toUserName欄位,沒有必要讓框架的使用者去處理這個欄位,在WxCommonMessageProcesser處理器中就對該欄位進行了處理,有興趣的可以參考原始碼。

同時還支援以下轉換:對於media型別的訊息,可以直接使用mediaUrl或者mediaPath寫入素材路徑,訊息轉換器透過WxMediaManager自動管理素材獲得必要的素材id。(關於WxMediaManager下麵寫)

註意:所有的訊息處理文字訊息,建議都使用WxMessage裡的對應訊息內容的builder來生成!

6. 素材自動管理

本框架提供WxMediaManager來管理素材,同時使用嵌入式資料庫儲存素材與本地檔案的對應關係,目前這部分功能我雖然完成了,但是總感覺有很大的不妥,希望有人能幫我看看順便提點意見。

上面訊息傳送中的媒體其實也是透過素材管理器來實現的。

7. 內建AccessToken管理

本框架提供WxTokenStore介面來儲存token,並提供一個預設的基於記憶體的實現MemoryWxTokenStore,若有分散式需要可以自行實現該介面,並把實現類作為Bean註入Spring即可。

8. 微信介面呼叫與傳回值自動處理

使用WxApiInvokeSpi介面與WxInvokerProxyFactory工廠類自動生成微信介面呼叫代理,只需要宣告方法和註解即可,預設使用HttpComponent呼叫介面。有興趣的小夥伴可以看看原始碼,我寫的也不太好,有更好的建議歡迎提出。

同時對傳回值做初步分析,如果介面傳回內容的errorCode不為0,則會作為異常丟擲。異常體係為WxException及其子類。

PS:你也可以使用這種方式任意生成自己的代理呼叫介面,後續我會加入檔案,暫時懶。。。

9. 選單自動生成與自動更新

可以透過開關開啟與關閉,透過@WxButton註解生成選單結構,並自動呼叫介面判斷選單是否改變,自動生成與更新選單。

10. 內建微信介面認證

可以正確響應微信傳送的Token驗證,方便快捷。

11. 完全無侵入的MVC樣式

使用本框架,不會對SpringMvc自己原生的Mapping產生任何影響,也不會佔用任何獨有的Mapping關係(除了認證請求)。在此框架存在的情況下,你可以使用任何SpringMvc的原生功能,包括根目錄的請求,也不會被微信伺服器獨自佔用。

12. 微信Web認證攔截器與URL自動轉換

提供微信OAUTH2認證攔截,透過配置wx.mvc.interceptor.includePatterns和wx.mvc.interceptor.excludePatterns來配置攔截的標的地址,你可以提供一個WxOAuth2Callback介面的實現類作為Bean,在WxOAuth2Interceptor中會自動註入這個bean,併在微信Web認證透過後呼叫after(WxOAuth2Context context)方法把相關的context傳遞給該Bean的方法,你可以在該方法中獲取到context了的WxWebUser,並透過WxUserManager把WxWebUser轉換為WxUser。關係詳細資訊請參考:微信網頁授權

https://mp.weixin.qq.com/wiki?t=resource/res_main&id;=mp1421140842

附加功能:自動判斷訊息中的url是否需要新增OAuth重定向,請參考WxRedirectUtils。

五、相關連結

  1. JavaDocs

  2. 微信公眾號開發檔案

  3. OSChina倉庫

  4. Github

六、暫時不支援的功能

1. 自定義客服回覆訊息

之後可以加入支援,使用註解定義訊息客服,類似於@RabbitListener的方式

2. 訊息加解密

沒有想到好的方式把訊息加解密融合到SpringMvc中

3. 個性化選單

稍微有點麻煩,使用者分類

4. 高階使用者管理

使用者分組什麼的是否有好的實現?暫時沒有需求

5. 公眾號其他高階功能

如支付等

6. 待最佳化:WxMediaStore

七、更新日誌

0.0.1-SNAPSHOT

初始版本

0.1.0-SNAPSHOT:

  1. 加入WxSession,類似HttpSession,預設實現中sessionId是fromUserName。如果自行提供WxSessionManager的實現類bean,則會使用你的Bean作為manager,預設實現是基於記憶體的,請自行擴充套件。

  2. 最佳化WxRequest,原始版本為直接把微信請求內容作為Request,更新為WxRequest為微信伺服器請求的包裝,內部的body屬性為微信伺服器請求體。

  3. 拆分不同的訊息請求體

0.1.1-SNAPSHOT:

最佳化訊息引數系結,新增指定訊息體系結,參考WxRequestBody

0.1.2.SNAPSHOT & 0.1.2.alpha

上傳maven中央倉庫,生成javadoc,以及一系列規範化

看完本文有收穫?請轉發分享給更多人

關註「ImportNew」,提升Java技能

贊(0)

分享創造快樂