小弟應運營要求要更改公衆號菜單,本覺得是在公衆號官網上進行配置便可,,誰知道 居然是開發者模式編輯的。無奈,從未接觸過公衆號開發的我。有開始啃開了微信開發的api,原來的作這個得小夥伴,跑路了。但沒有交接。哎~~~html
廢話很少說。開啓流程。java
一、小弟這個僅僅是【訂閱號】的開發。進入公衆號後左邊菜單找到web
這是該公衆號開發時用到的關鍵參數列表,以下:spring
這裏介紹下幾個開發中用到的重要參數:數據庫
一、開發者ID(AppId):就是開發人員在開發該訂閱號 的帳號apache
二、開發者密碼(AppSecret) : 就是開發人員在開發該訂閱號 的密碼json
三、IP白名單:該參數是微信服務器的一個ip白名單的驗證,若是沒有該白名單,微信服務器就不會認可你的地址是安全的。不能獲取access_token參數api
四、服務器地址(URL):他是微信回調 你的服務器的地址。記住這個服務器地址是你的。不是微信的。並且這個地址有些硬性條件安全
(1)該url必須開通外網映射,無論你是在公司 仍是在家。這個地址必須外網可以訪問到。服務器
(2)該url端口號必須是80,至於映射到本地應用端口是XXXX都無所謂。配置外網映射 我使用的是Sunny-Ngrok(https://www.ngrok.cc/)內網穿透服務,這個是一個網站提供,裏面有免費的http外網映射。其餘的映射服務均失敗(多是本身太菜)。。格式,外網映射地址+應用驗證接口
五、令牌(Token):驗證使用的一個自定義字符串
六、消息加解密密鑰:這個參數是發送/接收消時加密用的。但若是設置是明文方式,那麼這個參數沒用到。我就沒用到
七、消息加密/解密方式:明文、兼容、安全
以上參數,構成了微信開發的基礎參數。但想要真正開發,還有一些準備要作。
1、驗證:
不能可直接在生產環境開發,大牛這麼作的都不多。因此須要一個測試環境。那麼就是開發者工具中的【公衆號測試帳號】中,就能夠建立,目前其餘幾項我就是看看沒有仔細研究,後期補發。點擊進入:
用手機微信直接受權登陸便可:
簡單說明一下,測試帳號信息表中的內容是根據登陸的微信生成的。。我試了好幾回都不會變。應該是帳號綁定的。注意,,這時測試帳號的帳號和密碼,,前者的帳號 密碼是生產環境。還有 這個登陸的微信必須是該公衆號管理員受權綁定的微信帳號才行。
在公衆號左側菜單 人員設置中添加人員(建立者忽略),而後開發者工具中的Web開發者工具綁定一個開發者的微信號便可。
* 而後說說接口配置信息,第一次測試帳號配置是空的。url 也就是你的服務器地址,必須是80端口或443(也就是http和https默認端口)外網可以訪問到的地址+你的驗證應用接口地址 和第4 配置套路如出一轍好比 http://xxxx.cn/wx/yanzhengApi,驗證的java demo爲:
@ResponseBody @RequestMapping(value = "/WechatCallbackApi", method = RequestMethod.GET) public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 微信加密簽名 String signature = request.getParameter("signature"); System.out.println("微信加密簽名=====" + signature); // 隨機字符串 String echostr = request.getParameter("echostr"); System.out.println("隨機字符串=====" + echostr); // 時間戳 String timestamp = request.getParameter("timestamp"); System.out.println("時間戳=====" + echostr); // 隨機數 String nonce = request.getParameter("nonce"); System.out.println("隨機數=====" + echostr); String[] str = { TOKEN, timestamp, nonce }; Arrays.sort(str); // 字典序排序 String bigStr = str[0] + str[1] + str[2]; System.out.println("=====================" + bigStr); MessageDigestUtils digestutil = new MessageDigestUtils(); String sha1 = MessageDigestUtils.sha1(bigStr); // 確認請求來至微信 if (sha1.equals(signature)) { System.out.println("=====驗證成功============"); response.getWriter().print(echostr); } }
這個demo 方法上面確定還有一個controller 的mapping,本身寫吧。
* 下面的token 就是上述第5點的token
單機提交,若是沒有問題,會提示配置成功(這裏須要肯定你的藉口在接收到請求後的響應時間,太長微信都不認, 多試幾回就能夠了),不然就是配置失敗。失敗的緣由,其實很簡單。就是你的url配置的問題。通常token不會有問題。上述圖片中是我配置好久才成功的截圖。能夠修改。提交驗證是,會請求上述demo。大哥斷點就知道怎麼回事了。並且微信的api文檔對這塊說的仍是比較清楚的。就是沒有明說url配置須要80或443 端口(PS:其實api文檔也說明了。可是,是在另外一個頁面說明的。。【開始開發】-【接入指南】最下方纔說明,這裏配置url啥都沒說。)
完成以上工做久具有了 訂閱號開發的最基本的配置。
* JS接口安全域名 我沒有用到。這裏不作介紹
使用你的登陸測試帳號的微信掃描一下 【測試號二維碼】就會使當前微信關注這個訂閱號了。點擊關注。進入後,發現啥玩意都沒有。咋辦。新建菜單,這個自定義菜單可使用微信提供的web頁面建立 也可使用java寫,java 的demo以下
工具類:
package com.tiancaibao.service.weixin; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.log4j.Logger; import org.springframework.util.StringUtils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.tiancaibao.weixin.pojo.token.WeixinToken; /** * 獲取微信access_token工具類 */ public class WeiXinAccessTokenUtil { private static final Logger DEBUG_LOGGER = Logger.getLogger(WeiXinAccessTokenUtil.class); /** * 從微信上 * 獲取微信access_token * */ public static WeixinToken getWeiXinAccessToken(String appid,String secret) { if(StringUtils.isEmpty(appid)|| StringUtils.isEmpty(secret)) { DEBUG_LOGGER.error("appid or secret is null"); return null; } WeixinToken token = new WeixinToken(); try { String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+secret; HttpClient httpClient = new HttpClient(); GetMethod getMethod = new GetMethod(url); int execute = httpClient.executeMethod(getMethod); System.out.println("execute:"+execute); String getResponse = getMethod.getResponseBodyAsString(); System.out.println("========return的json========"+getResponse); JSONObject json = (JSONObject) JSON.parseObject(getResponse); token.setAccessToken(json.getString("access_token")); token.setExpiresIn(new Integer(json.getString("expires_in"))); Date createtime=new Date();; token.setCreatetime(createtime); } catch (IOException e) { DEBUG_LOGGER.error("getAccessToken failed,desc:::"+e); e.printStackTrace(); } return token; } }
access_token實體:
package com.tiancaibao.weixin.pojo.token; import java.io.Serializable; import java.util.Date; public class WeixinToken implements Serializable { private Integer id; private String accessToken; private Integer expiresIn; private Date createtime; protected String fields; private static final long serialVersionUID = 1L; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getAccessToken() { return accessToken; } public void setAccessToken(String accessToken) { this.accessToken = accessToken == null ? null : accessToken.trim(); } public Integer getExpiresIn() { return expiresIn; } public void setExpiresIn(Integer expiresIn) { this.expiresIn = expiresIn; } public Date getCreatetime() { return createtime; } public void setCreatetime(Date createtime) { this.createtime = createtime; } public void setFields(String fields) { this.fields = fields; } public String getFields() { return fields; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(getClass().getSimpleName()); sb.append(" ["); sb.append("Hash = ").append(hashCode()); sb.append(", id=").append(id); sb.append(", accessToken=").append(accessToken); sb.append(", expiresIn=").append(expiresIn); sb.append(", createtime=").append(createtime); sb.append(", fields=").append(fields); sb.append(", serialVersionUID=").append(serialVersionUID); sb.append("]"); return sb.toString(); } }
請求建立工具:
package com.tiancaibao.weixin.menu; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ConnectException; import java.net.URL; import java.net.URLEncoder; import java.util.Date; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.tiancaibao.service.weixin.MyX509TrustManager; /** * * 開發人員: liming </br> */ public class WeixinUtil { private static Logger log = LoggerFactory.getLogger(WeixinUtil.class); // 菜單建立(POST) 限100(次/天) public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN"; /*** * 自定義菜單建立接口: http請求方式:POST(請使用https協議) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN 自定義菜單查詢接口: http請求方式:GET https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN 自定義菜單刪除接口: http請求方式:GET https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN * */ /** * 建立菜單 * * @param menu 菜單實例 * @param accessToken 有效的access_token * @return 0表示成功,其餘值表示失敗 */ public static int createMenu(Menu menu, String accessToken) { int result = 0; // 拼裝建立菜單的url String url = menu_create_url.replace("ACCESS_TOKEN", accessToken); // 將菜單對象轉換成json字符串 String jsonMenu = JSONObject.toJSONString(menu); // 調用接口建立菜單 JSONObject jsonObject = httpRequest(url, "POST", jsonMenu); if (null != jsonObject) { if (0 != jsonObject.getInteger("errcode")) { result = jsonObject.getInteger("errcode"); log.error("建立菜單失敗 errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg")); } } return result; } /** * 描述: 發起https請求並獲取結果 * @param requestUrl 請求地址 * @param requestMethod 請求方式(GET、POST) * @param outputStr 提交的數據 * @return JSONObject(經過JSONObject.get(key)的方式獲取json對象的屬性值) */ public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) { JSONObject jsonObject = null; StringBuffer buffer = new StringBuffer(); try { // 建立SSLContext對象,並使用咱們指定的信任管理器初始化 TrustManager[] tm = { new MyX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); // 從上述SSLContext對象中獲得SSLSocketFactory對象 SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(requestUrl); HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection(); httpUrlConn.setSSLSocketFactory(ssf); httpUrlConn.setDoOutput(true); httpUrlConn.setDoInput(true); httpUrlConn.setUseCaches(false); // 設置請求方式(GET/POST) httpUrlConn.setRequestMethod(requestMethod); if ("GET".equalsIgnoreCase(requestMethod)) httpUrlConn.connect(); // 當有數據須要提交時 if (null != outputStr) { OutputStream outputStream = httpUrlConn.getOutputStream(); // 注意編碼格式,防止中文亂碼 outputStream.write(outputStr.getBytes("UTF-8")); outputStream.close(); } // 將返回的輸入流轉換成字符串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 釋放資源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); jsonObject = JSONObject.parseObject(buffer.toString()); } catch (ConnectException ce) { log.error("Weixin server connection timed out."); } catch (Exception e) { log.error("https request error:{}", e); } return jsonObject; } /** * 發送圖片消息 * @param accesstoken * { "touser":"OPENID", "msgtype":"image", "image": { "media_id":"MEDIA_ID" } } * @param openid */ public static int SendCustomerMessage(String accesstoken ){ String url="https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="+accesstoken; ImageMsg image =new ImageMsg(); Image ima= new Image(); ima.setMedia_id("FsM7Uo7Nk1YDdSZr8zYu7p079vyXhsvdbW3ArYpwqcM"); image.setImage(ima); image.setTouser("ovlNE1A7Zlufu0wfMYiweE6igo-c"); image.setMsgtype("image");// 圖片類型消息 String jsonMenu = JSONObject.toJSONString(image); System.out.println(jsonMenu); // 調用接口建立菜單 JSONObject jsonObject = httpRequest(url, "POST", jsonMenu); int result = 0; if (null != jsonObject) { if (0 != jsonObject.getInteger("errcode")) { result = jsonObject.getInteger("errcode"); log.error("建立菜單失敗 errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg")); } } return result; } public static void main(String[] args) { } }
自定義菜單建立main:
package com.tiancaibao.weixin.menu; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.tiancaibao.service.weixin.WeiXinAccessTokenUtil; import com.tiancaibao.weixin.pojo.token.WeixinToken; /** * 類名: MenuManager </br> * * 描述:菜單管理器類 </br> */ public class MenuManager { private static Logger log = LoggerFactory.getLogger(MenuManager.class); public static void main(String[] args) { // 第三方用戶惟一憑證 測試 String appId = "wxxxxxxx"; // 第三方用戶惟一憑證密鑰 String appSecret = "xxxxxxxxxxxx"; WeixinToken weiXinAccessToken = WeiXinAccessTokenUtil.getWeiXinAccessToken(appId, appSecret); if (null != weiXinAccessToken) { String asstoken=weiXinAccessToken.getAccessToken(); // 調用接口建立菜單 int result = WeixinUtil.createMenu(getMenu(), asstoken); // 判斷菜單建立結果 if (0 == result) log.info("菜單建立成功!"); else log.info("菜單建立失敗,錯誤碼:" + result); } } /** * 組裝菜單數據 * * @return */ private static Menu getMenu() { //新菜單自定義 CommonButton mainBtn1New = new CommonButton(); mainBtn1New.setName("呀!活動"); mainBtn1New.setType("view"); mainBtn1New.setKey("http://weixin.xxxx"); CommonButton btn2_1 = new CommonButton(); btn2_1.setName("歷史文章"); btn2_1.setType("view"); btn2_1.setUrl("xxxx"); CommonButton btn2_2 = new CommonButton(); btn2_2.setName("積分商城"); btn2_2.setType("view"); btn2_2.setUrl("http://xxxx"); CommonButton btn2_3 = new CommonButton(); btn2_3.setName("客服熱線"); btn2_3.setType("click"); btn2_3.setKey("咱們的服務熱線xx,工做時間 9:00-20:00,歡迎有問題撥打熱線哦~"); CommonButton btn3_1 = new CommonButton(); btn3_1.setName("個人資產"); btn3_1.setType("view"); btn3_1.setKey("http://xxxx"); CommonButton btn3_2 = new CommonButton(); btn3_2.setName("登陸註冊"); btn3_2.setType("view"); btn3_2.setKey("http://xxx"); CommonButton btn3_3 = new CommonButton(); btn3_3.setName("我要出借"); btn3_3.setType("view"); btn3_3.setKey("http://xxx"); CommonButton btn3_4 = new CommonButton(); btn3_4.setName("下載APP"); btn3_4.setType("view"); btn3_4.setKey("https://xxx"); /** * 微信: mainBtn1,mainBtn2,mainBtn3底部的三個一級菜單。 執行前觀察appSecret參數是否須要重置。記得的話就不須要。。不急的。估計懸了。。要重置, * 但重置後會不會對全有的菜單有影響呢?~~ */ // ComplexButton mainBtn1 = new ComplexButton(); // mainBtn1.setName("呀!活動"); // //一級下有4個子菜單 // mainBtn1.setSub_button(new CommonButton[] {btn8,btn9}); ComplexButton mainBtn2 = new ComplexButton(); mainBtn2.setName("呀!姿式"); mainBtn2.setSub_button(new CommonButton[] { btn2_1,btn2_2, btn2_3 }); ComplexButton mainBtn3 = new ComplexButton(); mainBtn3.setName("呀!個人"); mainBtn3.setSub_button(new CommonButton[] { btn3_1,btn3_2,btn3_3, btn3_4 }); /** * 封裝整個菜單 */ Menu menu = new Menu(); menu.setButton(new Button[] { mainBtn1New, mainBtn2, mainBtn3 }); return menu; } }
CommonButton:
package com.tiancaibao.weixin.menu; /** * 類名: CommonButton </br> * 包名: com.souvc.weixin.menu * 描述: 子菜單項 :沒有子菜單的菜單項,有多是二級菜單項,也有多是不含二級菜單的一級菜單。 </br> */ public class CommonButton extends Button { private String type; private String key; private String url; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } }
complexButton:
package com.tiancaibao.weixin.menu; public class ComplexButton extends Button { private Button[] sub_button; public Button[] getSub_button() { return sub_button; } public void setSub_button(Button[] sub_button) { this.sub_button = sub_button; } }
Button:
package com.tiancaibao.weixin.menu; /** * 類名: Button </br> * 包名: com.souvc.weixin.menu * 描述: 菜單項的基類 </br> */ public class Button { private String name;//全部一級菜單、二級菜單都共有一個相同的屬性,那就是name public String getName() { return name; } public void setName(String name) { this.name = name; } }
Menu:
package com.tiancaibao.weixin.menu; /** * 類名: Menu </br> * 包名: com.souvc.weixin.menu * 描述: 整個菜單對象的封裝 </br> */ public class Menu { private Button[] button; public Button[] getButton() { return button; } public void setButton(Button[] button) { this.button = button; } }
以上就是 自定菜單的建立源碼及過程。一級菜單和二級菜單的編輯 使用了java 的多態特性。api文檔中也給出了具體的demo 能夠參考。至於相關的事件和特性也請參看api文檔,寫的很詳細了,不作贅述。
附加,接收微信回調處理方法:
/* * 特別注意,req.getInputStream()只能獲取一次,而且只能讀取一次。若是想要屢次讀取,須要另外想辦法。爲了簡單起見, */ @ResponseBody @RequestMapping(value = "/WechatCallbackApi", method = RequestMethod.POST) public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 設置編碼 req.setCharacterEncoding("utf-8"); resp.setContentType("html/text;charset=utf-8"); resp.setCharacterEncoding("utf-8"); /* * 該部分咱們獲取用戶發送的信息,而且解析成<K,V>的形式進行顯示 */ // 解析用戶發送過來的信息 InputStream is = req.getInputStream();// 拿取請求流 // 將解析結果存儲在HashMap中 Map<String, String> map = new HashMap<String, String>(); // 解析xml,將獲取到的返回結果xml進行解析成咱們習慣的文字信息 SAXReader reader = new SAXReader();// Document document = null; try { document = reader.read(is);// 讀取流中的內容 } catch (DocumentException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // 獲得xml根元素 Element root = document.getRootElement(); // 獲得根元素的全部子節點 List<Element> elementList = root.elements(); // 遍歷全部子節點,將全部的節點存放到map中,讀取的時候方便 for (Element e : elementList) map.put(e.getName(), e.getText()); Set<String> keySet = map.keySet(); // 輸出解析後用戶發過來的信息 System.out.println("===解析用戶發送過來的信息開始"); String FromUserName = "";// 用戶的openid String event = "";// 事件類型 boolean ismessage = false; String messsgeContent = ""; String shopid = ""; String EventKey = ""; for (String key : keySet) { System.out.println(key + ":" + map.get(key)); if ("FromUserName".equals(key)) { FromUserName = map.get(key); } if ("Event".equals(key)) { event = map.get(key); } // 關鍵詞報文開頭 if ("MsgId".equals(key)) { ismessage = true; } if ("Content".equals(key)) { messsgeContent = map.get(key); } if ("EventKey".equals(key)) { EventKey = map.get(key); } } System.out.println("==========是否發送message==============" + ismessage); System.out.println(":解析用戶發送過來的信息結束"); /* * 該部分咱們嘗試按照文檔的要求格式給用戶回覆文本信息、圖文消息。重點:按照文檔要求構造須要的參數。特別注意:參數區分大小寫。 */ // 發送普通文本消息,請查看文檔關於「回覆文本消息」的xml格式 // 第一步:按照回覆文本信息構造須要的參數 TextMsg textMsg = new TextMsg(); textMsg.setToUserName(map.get("FromUserName"));// 發送和接收信息「User」恰好相反 textMsg.setFromUserName(map.get("ToUserName")); textMsg.setCreateTime(new Date().getTime());// 消息建立時間 (整型) textMsg.setMsgType("text");// 文本類型消息 Date subscribedate = new Date(); // 自定義菜單爲 CLICK,關注爲subscribe if (event.equals("CLICK")) { textMsg.setContent("咱們的服務熱線xxxx,工做時間 9:00-20:00,歡迎有問題撥打熱線哦~\ue415"); } else if (event.equals("subscribe")) { // 查詢是否有關注記錄 Weixinshopsubscriberecord selectInfoByOpenId = wexinSubscibeservice.selectInfoByOpenId(FromUserName); System.out.println("=============查詢是否有關注記錄==========" + selectInfoByOpenId); if (EventKey != "" || EventKey != null || !"".equals(EventKey)) { System.out.println("===========================EventKey===============" + EventKey.toString()); String[] Str = EventKey.split("_"); // 此判斷是爲了防止二維碼參數爲空的狀況 if (Str.length > 1) { shopid = Str[1]; } } // 未關注 if (selectInfoByOpenId == null) { // 初次關注 String FirstSubscribe = "終於等到你還好我沒放棄,右下角快去開啓你的財富之旅吧!" ; if(!"".equals(shopid)){ FirstSubscribe+=" 來源編號:"+ shopid; } textMsg.setContent(FirstSubscribe); Weixinshopsubscriberecord weixinshop = new Weixinshopsubscriberecord(); weixinshop.setOpenid(FromUserName); weixinshop.setShopid(shopid); weixinshop.setState("1"); weixinshop.setSubscribedate(subscribedate); weixinshop.setSubscribetime(subscribedate); // 保存openid wexinSubscibeservice.SubscribeSave(weixinshop); } else { // 取消後再次關注 selectInfoByOpenId.setState("2"); selectInfoByOpenId.setSubscribedate(subscribedate); selectInfoByOpenId.setSubscribetime(subscribedate); selectInfoByOpenId.setOpenid(FromUserName); selectInfoByOpenId.setShopid(shopid); wexinSubscibeservice.UpdateSubscribe(selectInfoByOpenId);// 更改記錄 String SecondSubscribe = "歡迎回到財富之路,等你啓程!" ; if(!"".equals(shopid)){ SecondSubscribe+=" 來源編號:"+ shopid; } textMsg.setContent(SecondSubscribe); } } else if (event.equals("unsubscribe")) { Weixinshopsubscriberecord weixinshop = new Weixinshopsubscriberecord(); weixinshop.setState("0");// 取消關注爲0 weixinshop.setSubscribedate(subscribedate); weixinshop.setSubscribetime(subscribedate); weixinshop.setOpenid(FromUserName); weixinshop.setShopid(shopid); wexinSubscibeservice.UpdateSubscribe(weixinshop); } // 是否發送客服消息 Boolean issend = false; /** * 回覆圖片消息 */ ImageMsg imagemsg = new ImageMsg(); imagemsg.setToUserName(map.get("FromUserName"));// 發送和接收信息「User」恰好相反 imagemsg.setFromUserName(map.get("ToUserName")); imagemsg.setCreateTime(new Date().getTime());// 消息建立時間 (整型) imagemsg.setMsgType("image");// 文本類型消息 Image Image = new Image(); // Image.setMediaId("FsM7Uo7Nk1YDdSZr8zYu7p079vyXhsvdbW3ArYpwqcM");//圖片ID,不固定 Image.setMediaId("6GTGDx7tGKMgnHv2Qzd9-orxsSaNBr4TdLN_n2zdw14");// 圖片ID,不固定 imagemsg.setImage(Image); // 消息內容 if (ismessage) { if (messsgeContent.indexOf("建軍節快樂") != -1) { textMsg.setContent("活動已結束,歡迎下次來參加哦\ue409"); }else if(messsgeContent.indexOf("中秋") != -1){ textMsg.setContent("http://4xxx/index.jsp?aid=fe66eb90a5ea40e3a956ecaf2926f1c9&activityid=110312&wuid=457767&keyversion=0&isFromApiFilter=1"); }else if (messsgeContent.indexOf("客服 聯繫 電話") != -1) { textMsg.setContent("咱們的客服熱線:xxx,快去撥打吧,美麗的客服妹子在等你~"); } else if (messsgeContent.indexOf("你好") != -1 || messsgeContent.indexOf("在麼") != -1 || messsgeContent.indexOf("在") != -1 || messsgeContent.indexOf("在?") != -1 || messsgeContent.indexOf("你好?") != -1 || messsgeContent.indexOf("您好?") != -1 || messsgeContent.indexOf("你好?") != -1 || messsgeContent.indexOf("你好啊?") != -1 || messsgeContent.indexOf("hi") != -1 || messsgeContent.indexOf("hello") != -1) { textMsg.setContent("Hi~~~想我了嗎?有任何問題,請電話騷擾咱們的客服哦,客服電話:xxx \ue032"); } else if (messsgeContent.indexOf("好買酒") != -1 || messsgeContent.indexOf("好賣酒") != -1 || messsgeContent.indexOf("酒") != -1) { // textMsg.setContent("呀呀,你是「好買酒」過來的吧?路途遙遠,辛苦啦\ue056 // \n即日起,掃描上方二維碼實名註冊xxx,便可享受5000元體驗金\ue106+80元現金紅包\ue106+20%加息券\ue106「三重好禮」大禮包,機不可失,失再也不來,快去完成註冊吧\ue056"); XStream xStream = new XStream(); xStream.alias("xml", imagemsg.getClass()); String imagemsgXml = xStream.toXML(imagemsg); System.out.println("回覆圖片的xml====" + imagemsgXml); PrintWriter printWriter = resp.getWriter(); printWriter.print(imagemsgXml); issend = true; } else { textMsg.setContent( "憋~着~急~哈~\ue415你的消息,小編我已收到,容我慢慢回覆哈~\ue056有問題最好仍是找咱們的客服妹子哈,xxx,人家可比我這個成天只知道碼字送積分的小編專業滴多哈~~~\ue409"); } } XStream xStream = new XStream(); xStream.alias("xml", textMsg.getClass()); String textMsg2Xml = xStream.toXML(textMsg); System.out.println("返回給微信服務器,讓其發送用戶消息的報文====" + textMsg2Xml); // 第三步,發送xml的格式信息給微信服務器,服務器轉發給用戶 // 除了這個,已關注再掃描的事件 if (!event.equals("SCAN")) { PrintWriter printWriter = resp.getWriter(); printWriter.print(textMsg2Xml); System.out.println("======文本發送了============"); } if (issend) { /** * 發送客服文本消息 */ // 第一步 獲取accesstoken String accesstoken = ""; Date date1 = new Date(); Date date2 = new Date(); Weixincommoninfo selectaccesstoken = weixincommoInfoservice.selectInfo(); // 查看是否有accesstoken if (selectaccesstoken == null) { selectaccesstoken = new Weixincommoninfo(); WeixinToken weiXinAccessToken = WeiXinAccessTokenUtil.getWeiXinAccessToken(); accesstoken = weiXinAccessToken.getAccessToken(); selectaccesstoken.setSavefiled("accesstoken"); selectaccesstoken.setSaveinfo(accesstoken); selectaccesstoken.setExpiresIn(weiXinAccessToken.getExpiresIn()); selectaccesstoken.setCreatetime(date1); date2.setHours(date1.getHours() + 1);// 此處將accesstoken的有效期,設置爲1小時 selectaccesstoken.setEffectivetime(date2); weixincommoInfoservice.Saveinfo(selectaccesstoken); } else { Date date = new Date(); // 判斷當前時間是否在accesstoken 的有效期內, Date effectivetime = selectaccesstoken.getEffectivetime(); if (effectivetime.getTime() > date.getTime()) { accesstoken = selectaccesstoken.getSaveinfo(); System.out.println("數據庫中的accesstoken能用"); } else { WeixinToken weiXinAccessToken = WeiXinAccessTokenUtil.getWeiXinAccessToken(); selectaccesstoken = new Weixincommoninfo(); accesstoken = weiXinAccessToken.getAccessToken(); selectaccesstoken.setSavefiled("accesstoken"); selectaccesstoken.setSaveinfo(accesstoken); selectaccesstoken.setExpiresIn(weiXinAccessToken.getExpiresIn()); selectaccesstoken.setCreatetime(date1); date2.setHours(date1.getHours() + 1); selectaccesstoken.setEffectivetime(date2); weixincommoInfoservice.upadateInfo(selectaccesstoken); System.out.println("數據庫中的accesstoken不呢能用,從新獲取更新"); } } // 第二步發送消息 System.out.println("發送客服消息======================="); String mescont = "呀呀,你是「好買酒」過來的吧?路途遙遠,辛苦啦\ue056 \n即日起,掃描下方二維碼實名註冊xxx,便可享受5000元體驗金\ue106+80元現金紅包\ue106+20%加息券\ue106「三重好禮」大禮包,機不可失,失再也不來,快去完成註冊吧\ue056"; WeixinUtil.SendCustomerTextMessage(accesstoken, FromUserName, mescont); } }