在微信接口開發中,許多服務的使用都離不開Access Token,Access Token相當於打開這些服務的鑰匙,正常情況下會在7200秒內失效,重復獲取將導致上次獲取的Token失效,本文將首先介紹如何獲取Access Token,再介紹如何通過Access Token來在微信內添加自定義菜單(注意,開發者需要申請測試賬號來測試自定義菜單,如何申請請參照前文)。
申請Access Token
獲取Access Token接口的網址如下:
方括號內的參數可以在測試賬號首頁找到,被塗抹處即是:
真實請求的實例如下:
執行上述請求后,接口返回的內容如下:
這里我們就拿到了接下來需要使用的access_token:
ZiBTYeRMEMeCEM-Ol9ny_NE-XkgRbsP4snOqTRLh_nfp_UzFsYXVDtguf7jbZt70IQRkmEwU1n0cbxdWmJTdNg
,該Token將在7200秒,也就是2個小時內失效,之后需要重新請求前面的URL獲取新的Token。
創建自定義菜單目前服務號和通過認證的訂閱號均可申請自定義菜單,成功創建自定義菜單后,微信公眾賬號界面如下圖所示:
目前自定義菜單最多包括三個一級菜單,每個一級菜單最多包含五個二級菜單。一級菜單最多4個漢字,二級菜單最多7個漢字,多出來的部分會以“…”代替。請注意,創建自定義菜單后,由於微信客戶端緩存,需要一定時間才在微信客戶端展現出來,最快捷的方式是重新關注微信公眾賬號,這樣馬上就能看到自定義菜單。
目前自定義菜單接口可實現兩種類型的按鈕:
click:用戶點擊click類型按鈕后,微信服務器會通過消息接口推送類型為event的結構給開發者,並且帶上按鈕中開發者填寫的key值,開發者可以通過自定義的key值與用戶進行交互。
view:用戶點擊view類型按鈕后,微信客戶端將會打開開發者在按鈕中填寫的url值(網頁鏈接),達到打開網頁的目的。建議與網頁授權獲取用戶基本信息接口結合,獲得用戶的登入個人信息。
創建菜單的接口如下:
https://api.weixin.qq.com/cgi-bin/menu/create?access_token=[ACCESS_TOKEN]
其中中括號內的變量ACCESS_TOKEN即為我們前面獲得的Token值。接下來我們開發一個簡單的Apex網頁,我們將通過這個網頁來創建自定義菜單。
WeChatUtilityPage:網頁,負責提交創建自定義菜單的申請,並顯示創建成功與否的結果;
WechatUtilityController: 控制器類,負責網頁背后的具體業務邏輯處理。
WeChatUtilityPage的源代碼如下:
1 <apex:page standardstylesheets="false" showHeader="false" sidebar="false" controller="WechatUtilityController"> 2 <apex:form > 3 <font face="微軟雅黑"><strong>菜單服務系列:</strong><br /><br /> 4 <apex:commandButton value="注冊微信菜單" action="{!register}" id="register" /> 5 </apex:form> 6 {!msg} 7 <apex:pageMessages /> 8 </apex:page>
畫面非常簡單,只有一段文字顯示以及一個“注冊微信菜單”按鈕,點擊按鈕將處罰WechatUtilityController里的register方法,返回消息通過msg對象來顯示,該對象的定義也在WechatUtilityController里,如果有系統異常,則將通過<apex: pageMessage/>來顯示異常堆棧信息。下面我們看來看代碼:
1 public class WechatUtilityController { 2 public static String msg{get;set;} 3 4 public String accessToken{get;set;} 5 public WechatUtilityController (){ 6 accessToken = ‘ZiBTYeRMEMeCEM-Ol9ny_NE-XkgRbsP4snOqTRLh_nfp_UzFsYXVDtguf7jbZt70IQRkmEwU1n0cbxdWmJTdNg’; 7 } 8 9 public void register(){ 10 Http h = new Http(); 11 HttpRequest req = new HttpRequest(); 12 req.setMethod('POST'); 13 req.setHeader('Accept-Encoding','gzip,deflate'); 14 req.setHeader('Content-Type','text/xml;charset=UTF-8'); 15 req.setHeader('User-Agent','Jakarta Commons-HttpClient/3.1'); 16 17 String xml = '{"button":[{"name":"關於我們","sub_button":[{"type":"click","name":"公司簡介","key":"公司簡介"},{"type":"click","name":"社會責任","key":"社會責任"},{"type":"click","name":"聯系我們","key":"聯系我們"}]},{"name":"產品服務","sub_button":[{"type":"click","name":"微信平台","key":"微信平台"},{"type":"click","name":"微博應用","key":"微博應用"},{"type":"click","name":"手機網站","key":"手機網站"}]},{"name":"技術支持","sub_button":[{"type":"click","name":"文檔下載","key":"文檔下載"},{"type":"click","name":"技術社區","key":"技術社區"},{"type":"click","name":"服務熱線","key":"服務熱線"}]}]}'; 18 19 req.setBody(xml); 20 req.setEndpoint('https://api.weixin.qq.com/cgi-bin/menu/create?access_token=‘ + accessToken); 21 String bodyRes = ‘’; 22 23 try{ 24 HttpResponse res = h.send(req); 25 bodyRes = res.getBody(); 26 } 27 catch(System.CalloutException e) { 28 System.debug('Callout error: '+ e); 29 ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, e.getMessage())); 30 } 31 msg = bodyRes; 32 } 33 34 }
上面的代碼構造了一段XML文,並將此XML問Post到req.setEnpoint方法里制定的URL。XML里即包含了對自定義菜單內容的具體定義,該XML的接口要求如下:
完成后保存代碼即可看到前面微信截圖所顯示的效果。
創建菜單點擊事件處理方法
前面的菜單中我們定義的都是click類型的菜單,但該類型菜單被點擊的時候,微信將經由騰訊服務器向開發者指定的URL發送一段XML文,該XML的結構說明如下:
這和我們前面處理用戶發送消息的方式其實是一致的,我們可以在前文准備的方法架構基礎上添加處理代碼,找到前文的如下代碼段:
1 if(msgType.equals('text')){ 2 rtnMsg = handleText(inMsg); 3 }
在該代碼段的基礎上點擊else處理分支:
1 if(msgType.equals('text')){ 2 3 rtnMsg = handleText(inMsg); 4 5 } 6 else if(msgType.equals('event')){ 7 rtnMsg = handleEvent(inMsg); 8 }
上面的代碼else分支判斷如果用戶發送來的消息類型是event類型則調用handleEvent方法來處理,此時用戶可能是關注了微信賬號,可能是取消了關注,也可能是點擊了菜單…,在handleEvent方法里要進一步判斷,留意方法里的eventKey是前面XML里用戶自定義的:
1 private static String handleEvent(IncomingMsg msg){ 2 String event = msg.event; 3 String strTmp = ''; 4 if(event.equals('subscribe')){ 5 strTmp = '歡迎關注本賬號!'; 6 } 7 else if(event.equals('unsubscribe')){ 8 strTmp = ''; 9 } 10 else if(event.equals('CLICK')){ 11 strTmp = '您點擊了' + msg.eventKey; 12 } 13 String result = composeTextReply(msg, strTmp); 14 return result; 15 }
其中composeTextReply方法的定義如下:
1 private static String composeTextReply(IncomingMsg msg, String content){ 2 String strTmp = '<xml><ToUserName><![CDATA[{0}]]></ToUserName><FromUserName><![CDATA[{1}]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[{2}]]></Content></xml>'; 3 String[] arguments = new String[]{msg.fromUserName, msg.toUserName, content}; 4 String strReply = String.format(strTmp, arguments); 5 return strReply; 6 }
方法運行效果如下,當用戶點擊了微信菜單后,系統會自動將eventKey里包含的信息發送給用戶,這里是為了演示效果進行的簡化,真實場景里可以根據需求進行具體功能訂制:





