玩一玩微信公眾號開發(二) 管理憑據和自定義菜單

管理access_token

access_token介紹

在前面我們成功的使用了Spring Boot Web程序和微信對接。但是這僅僅是一個開始,我們還需要獲取access_token,也就是憑據,才能進行之后的工作。微信開發文檔有如下介紹。

access_token是公眾號的全局唯一接口調用憑據,公眾號調用各接口時都需使用access_token。開發者需要進行妥善保存。access_token的存儲至少要保留512個字符空間。access_token的有效期目前為2個小時,需定時刷新,重復獲取將導致上次獲取的access_token失效。

微信開發文檔建議我們使用一個中控服務器,獲取和刷新token均由服務器進行,我們的程序只從中控服務器獲取access_token。由于每次獲取access_token都會刷新一個新token,因此如果在程序中直接獲取,可能造成token不一致和過期問題。

Spring Boot緩存配置

當然實際上并不是一定要另外整一個服務器。我們利用Spring的緩存功能,也可以比較好的完成任務。下面就來介紹一下。

首先,現在Spring Boot項目中添加下面的依賴,啟用Spring的緩存功能。

compile('org.springframework.boot:spring-boot-starter-cache')

上面的依賴僅僅啟用了Spring Boot的緩存抽象和自動配置功能。我們還需要選擇具體的緩存實現。Spring Boot支持多種Java 緩存實現。我隨便挑了個caffeine,它是由Guava庫獨立出來的緩存庫,使用Java 8編寫,我看著不錯。

compile 'com.github.ben-manes.caffeine:caffeine:2.4.0'

Spring Boot會自動配置caffeine,所以我們可以完全透明的使用它。當然,還需要進行一點配置。由于微信的access_token的過期時間為7200秒,所以我們的緩存需要在這之前獲取新的token。因此這里將caffeine的過期時間配置為7000秒,在application.properties中設置即可。

spring.cache.caffeine.spec=expireAfterWrite=7000s

緩存是配置好了,但是這就能直接使用了嗎?當然不是,我們還需要編寫獲取token的服務。獲取access_token需要微信公眾平臺開發者頁面上的appid和appsecret,我們先要獲取到它,然后配置到application.properties中。

yitian.study.weixin.appid=XXXXXXXXXXXXX
yitian.study.weixin.appsecret=XXXXXXXXXXXXX

獲取憑據

獲取access_token需要向https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET發送一個GET請求,并包含appid和appsecret兩個參數。如果成功獲取到token,微信服務器會返回下面這樣的json。

{"access_token":"ACCESS_TOKEN","expires_in":7200}

如果出現錯誤,則會返回錯誤信息json。

{"errcode":40013,"errmsg":"invalid appid"}

所以Kotlin代碼可以寫成這樣。在方法上使用了@Cacheable注解,Spring會將方法結果緩存起來,下次直接使用緩存結果。

@Service
class AccessTokenService(
        @Value("\${yitian.study.weixin.appid}") val appId: String,
        @Value("\${yitian.study.weixin.appsecret}") val appSecret: String,
        @Autowired val objectMapper: ObjectMapper
) {

    @Cacheable("access_token")
    fun refreshAccessToken(): String {
        val requestUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appId&secret=$appSecret"
        val json = URL(requestUrl).readText()
        try {
            val result = objectMapper.readValue(json, AccessTokenResult::class.java)
            return result.accessToken
        } catch (ex: JsonMappingException) {
            val error = objectMapper.readValue(json, ErrorResult::class.java)
            throw AccessTokenException(ex, error.toString())
        }
    }
}

在上面的代碼中注入了Spring Boot自動配置的ObjectMapper,用于將結果json轉換為Kotlin對象。上面用到的Bean和異常定義在下面。

data class ErrorResult(
        @JsonProperty("errcode") val errorCode: Int,
        @JsonProperty("errmsg") val errorMessage: String
) {
}

data class AccessTokenResult(
        @JsonProperty("access_token") val accessToken: String,
        @JsonProperty("expires_in") val expiresIn: Int) {
}

class AccessTokenException(val ex: Throwable, val msg: String) : Throwable(msg, ex) {
}

這樣,access_token的管理工作就算完成了。以后我們需要獲取access_token,直接從AccessTokenService調用就行了。

自定義菜單

對于個人性質的訂閱號,沒有自定義菜單等高級功能。所以下面我改用微信測試號來驗證這些功能。另外,我們可以使用微信公眾平臺的在線調試工具來幫助我們開發。

微信開發文檔的截圖來看,我猜它很久沒更新過了。怪不得寫的并不咋地,我看了半天也沒明白怎么創建自定義菜單。從網上找了一篇微信公眾平臺開發(八) 自定義菜單功能開發,雖然用的是PHP語言,但是講的還可以。

新建菜單

首先先看看微信文檔的注意事項。

1、自定義菜單最多包括3個一級菜單,每個一級菜單最多包含5個二級菜單。
2、一級菜單最多4個漢字,二級菜單最多7個漢字,多出來的部分將會以“...”代替。
3、創建自定義菜單后,菜單的刷新策略是,在用戶進入公眾號會話頁或公眾號profile頁時,如果發現上一次拉取菜單的請求在5分鐘以前,就會拉取一下菜單,如果菜單有更新,就會刷新客戶端的菜單。測試時可以嘗試取消關注公眾賬號后再次關注,則可以看到創建后的效果。

需要創建菜單的時候,我們需要向微信發送一個[https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN](https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN)的POST請求,

請求體是類似這樣的JSON。這些按鈕的type屬性可以指定為多種按鈕類型,有不同的作用。這些按鈕類型和JSON屬性的詳細信息直接參考官方文檔吧。

{
  "button": [
    {
      "name": "實用功能",
      "sub_button": [
        {
          "type": "click",
          "name": "天氣預報",
          "key": "weather_forecast"
        },
        {
          "type": "click",
          "name": "說個笑話",
          "key": "speak_jokes"
        }
      ]
    },
    {
      "type": "media_id",
      "name": "捐贈作者",
      "media_id": "g78zk9TnnoFBaGJV4jpEDqR2y-fDNgOOFQkiCfrZIbA"
    }
  ]
}

如果添加菜單成功,就會返回這樣的JSON字符串。

{"errcode":0,"errmsg":"ok"}

如果出現錯誤,就會返回錯誤碼和錯誤信息。

{"errcode":40018,"errmsg":"invalid button name size"}

本來我想著找一個比較好用的Java/Kotlin的HTTP傳輸庫來進行這些接口的操作。但是找了半天居然沒發現比較好用的,只有一個比較舊的Apache HttpClient,最近更新時間還是2011年。怪不得我看網上關于Java開發微信的資源比較少,原來真的挺麻煩的。

所以呢,這個功能就這樣作罷吧。如果需要更新菜單可以使用在線調試工具,這個倒是比較方便。

查詢自定義菜單

這個倒是比較簡單。我們只要向下面的URL發送GET請求即可,微信服務器就會將對應的自定義菜單的JSON格式返回給我們。

https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN

刪除自定義菜單

刪除自定義菜單也很簡單,同樣的,向下面的URL發送GET請求即可。

https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN

結語

本來微信開發還有很多內容。但是到了這里我就完全不想寫了。一來與微信交互需要發送多種類型的HTTP請求給微信服務器。但是我找了一下沒找到好用的Java或Kotlin類庫。二來微信的官方開發文檔寫的實在是捉急,例子殘缺不全,很多地方也沒講明白。我強行硬啃Spring英文文檔都能看個八九不離十。但是我看微信的官方中文文檔居然有地方看不懂。所以這系列就到此為止了。謝謝大家的支持!

代碼放在csdn代碼庫上了,雖然不是一個完整的項目,但是包含了與微信對接和管理憑據的一點代碼。對于想用Java或Kotlin開發微信公眾號的同學可能有一點參考價值。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容