To start the development of the WeChat public platform, we must first understand what the WeChat platform can help us do?
Use your public account to log in to http://mp.weixin.qq.com/, select the menu--Advanced functions-Development mode--View documents, and you can see the current status of the WeChat public platform functions that can be developed.
The main content of the public platform is
Accept the public account sent by users to you Message
Reply a message to your user
It should be noted that sending a message and disappearing the reply are a continuous process. Can be done in one conversation. In other words, if your users don't talk to you, you can't actively send messages to your customers (mass messaging is another situation, with a limit on the number of times. You can also apply to pay to use the WeChat CRM platform). All messages sent and received need to be transferred by the WeChat platform.
The following introduces the types of messages that users can send you, which are the types of messages currently received.
1.1 Text message:
This is what we usually encounter the most. We can judge based on some keywords mentioned in the text. Determine the user's meaning and respond.
1.2 Picture messages:
Currently, it is still difficult to understand what users want to express through pictures. Therefore, most public accounts will choose to ignore picture information or choose to process it manually. All I can say is: the pictures are beautiful, but I can’t understand them.
1.3 Geolocation message:
The user sends you his location, which is important information for most public accounts. It can provide some services based on location information, such as hotel reservation public account, which can recommend hotels around you. Another addition is that location information can be analyzed and used in text messages. For example, if the user inputs "Nanjing Road Pedestrian Street", the user can be provided with relevant merchants of Nanjing Road Pedestrian Street.
1.4 Link message:
Currently, we have not seen a particularly effective method of use in development mode. It may be used more often when shopping or consulting, to clarify the person you are talking about.
1.5 Event push message:
When the user enters the conversation with you, you can greet the user first, etc. This message currently only supports version 4.5 and has not yet been developed. There is a lot of room to think about in the future. For example, after the user enters the session, what will happen if he shakes it?
2.1 Text message
This is the type of message we usually send the most. When only simple text is needed to answer the user's message, text can be used information. Text messages can contain link addresses.
2.2 Graphic Message
Graphic message, this is the message format we often see in push messages. Each item of content can be clicked to view more detailed information (of course you can also set the link to empty so that it cannot jump)
2.3 Music News
In your Giving users a voice message or music in the reply will be favored by many users.
Understanding the communication mechanism and message types of the public platform, next, we begin to prepare the development environment
1. Set to developer mode
Log in to WeChat Work platform, select advanced features-enter development mode and become a developer. You need to configure it as shown below. The URL configuration information means that WeChat's backend server sends your user messages to the URL for processing. Token is a password between you and WeChat. It is used to verify whether the message is sent from WeChat's service and not from others attacking your system.
You can't set it up yet. During setup, WeChat will make a GET request for the URL you set, and it will check whether the interface can be used. You can only set this up after you have the GET method ready.
2. Implement the GET method
As we know from the documentation, we need to implement the POST and GET methods, and the GET method is used for verification WeChat and your communication verification, POST is used for message processing.
Create a new Servlet HelloWeChat, first implement the GET method
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO 为了简单起见,先不对消息来源进行校验 response.setContentType("text/html;charset=UTF-8"); PrintWriter pw = response.getWriter(); String echo = request.getParameter("echostr"); echo = new String(echo.getBytes("ISO-8859-1"),"UTF-8"); pw.println(echo); }
can be used locally at http://localhost:8080/QiyadengWeb/HelloWeChat?echostr=hello Chinese. Test it first. If there are no problems, you can deploy it to the server and then set it up on the WeChat public platform.
3. Implement the POST method
The POST method first receives the XML sent from the WeChat public platform and extracts the message sender and message content. For more message sending content, you can add your own processing logic, and finally assemble it into a reply message XML and return it to the WeChat public platform.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter pw = response.getWriter(); String wxMsgXml = IOUtils.toString(request.getInputStream(),"utf-8"); WeChatTextMessage textMsg = null; try { textMsg = getWeChatTextMessage(wxMsgXml); } catch (Exception e) { e.printStackTrace(); } StringBuffer replyMsg = new StringBuffer(); if(textMsg != null){ //增加你所需要的处理逻辑,这里只是简单重复消息 replyMsg.append("您给我的消息是:"); replyMsg.append(textMsg.getContent()); } else{ replyMsg.append(":)不是文本的消息,我暂时看不懂"); } String returnXml = getReplyTextMessage(replyMsg.toString(), textMsg.getFromUserName()); pw.println(returnXml); }
Regarding debugging, here is a tool Fiddler recommended. You can simulate WeChat POST messages to your local area without having to deploy to the server for debugging every time. Regarding how to use Fiddler's POST data, you can refer to the content marked in the figure below.
4. Deploy and test
Complete the first step and have a conversation with your public account. There is no reply to the message. If you have any questions, congratulations.
5. Dependency library
For students who use maven, just add the following dependencies. Non-maven users can find these libraries and add them to the builder path.
<dependency> <groupId>joda-time</groupId> <artifactId>joda-time</artifactId> <version>2.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.3</version> </dependency>
6. Complete code
package com.qiyadeng.wechat; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; /** * Servlet implementation class HelloWeChat */ public class HelloWeChat extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public HelloWeChat() { super(); } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO 为了简单起见,先不对消息来源进行校验 response.setContentType("text/html;charset=UTF-8"); PrintWriter pw = response.getWriter(); String echo = request.getParameter("echostr"); echo = new String(echo.getBytes("ISO-8859-1"),"UTF-8"); pw.println(echo); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter pw = response.getWriter(); String wxMsgXml = IOUtils.toString(request.getInputStream(),"utf-8"); WeChatTextMessage textMsg = null; try { textMsg = getWeChatTextMessage(wxMsgXml); } catch (Exception e) { e.printStackTrace(); } StringBuffer replyMsg = new StringBuffer(); if(textMsg != null){ //增加你所需要的处理逻辑,这里只是简单重复消息 replyMsg.append("您给我的消息是:"); replyMsg.append(textMsg.getContent()); } else{ replyMsg.append(":)不是文本的消息,我暂时看不懂"); } String returnXml = getReplyTextMessage(replyMsg.toString(), textMsg.getFromUserName()); pw.println(returnXml); } private WeChatTextMessage getWeChatTextMessage(String xml){ XStream xstream = new XStream(new DomDriver()); xstream.alias("xml", WeChatTextMessage.class); xstream.aliasField("ToUserName", WeChatTextMessage.class, "toUserName"); xstream.aliasField("FromUserName", WeChatTextMessage.class, "fromUserName"); xstream.aliasField("CreateTime", WeChatTextMessage.class, "createTime"); xstream.aliasField("MsgType", WeChatTextMessage.class, "messageType"); xstream.aliasField("Content", WeChatTextMessage.class, "content"); xstream.aliasField("MsgId", WeChatTextMessage.class, "msgId"); WeChatTextMessage wechatTextMessage = (WeChatTextMessage)xstream.fromXML(xml); return wechatTextMessage; } private String getReplyTextMessage(String content, String weChatUser){ WeChatReplyTextMessage we = new WeChatReplyTextMessage(); we.setMessageType("text"); we.setFuncFlag("0"); we.setCreateTime(new Long(new Date().getTime()).toString()); we.setContent(content); we.setToUserName(weChatUser); we.setFromUserName("shanghaiweather");//TODO 你的公众帐号微信号 XStream xstream = new XStream(new DomDriver()); xstream.alias("xml", WeChatReplyTextMessage.class); xstream.aliasField("ToUserName", WeChatReplyTextMessage.class, "toUserName"); xstream.aliasField("FromUserName", WeChatReplyTextMessage.class, "fromUserName"); xstream.aliasField("CreateTime", WeChatReplyTextMessage.class, "createTime"); xstream.aliasField("MsgType", WeChatReplyTextMessage.class, "messageType"); xstream.aliasField("Content", WeChatReplyTextMessage.class, "content"); xstream.aliasField("FuncFlag", WeChatReplyTextMessage.class, "funcFlag"); String xml =xstream.toXML(we); return xml; } }
Location identification is a message that is often used in practical applications, especially many merchants, which provide users with special information by understanding their location. products or recommendations from shopping malls. Users may send two types of messages:
1. WeChat geographical location information
2. Road names, landmark buildings or shopping mall names
Get to know what information WeChat location message contains
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1351776360</CreateTime> <MsgType><![CDATA[location]]></MsgType> <Location_X>23.134521</Location_X> <Location_Y>113.358803</Location_Y> <Scale>20</Scale> <Label><![CDATA[位置信息]]></Label> <MsgId>1234567890123456</MsgId> </xml>
The main information included is longitude, latitude and the location of the Label. Corresponding services can be provided to users based on the location information described in the label. You can also provide your latest products or regional products based on the user's longitude and latitude information.
First define the WeChatLocationMessage class based on WeChat’s geographical location information, and convert Xml into a WeChatLocationMessage object
public class WeChatLocationMessage { private String toUserName; private String fromUserName; private String createTime; private String msgType; private String locationx; private String localtiony; private String scale; private String label; private String msgId; public static WeChatLocationMessage getWeChatLocationMessage(String xml){ XStream xstream = new XStream(new DomDriver()); WeChatLocationMessage message = null; xstream.alias("xml", WeChatLocationMessage.class); xstream.aliasField("ToUserName", WeChatLocationMessage.class, "toUserName"); xstream.aliasField("FromUserName", WeChatLocationMessage.class, "fromUserName"); xstream.aliasField("CreateTime", WeChatLocationMessage.class, "createTime"); xstream.aliasField("MsgType", WeChatLocationMessage.class, "msgType"); xstream.aliasField("Location_X", WeChatLocationMessage.class, "locationx"); xstream.aliasField("Location_Y", WeChatLocationMessage.class, "localtiony"); xstream.aliasField("Scale", WeChatLocationMessage.class, "scale"); xstream.aliasField("Label", WeChatLocationMessage.class, "label"); xstream.aliasField("MsgId", WeChatLocationMessage.class, "msgId"); message = (WeChatLocationMessage)xstream.fromXML(xml); return message; } //getter and setter }
This article uses Baidu’s map API to find Take the nearest bank as an example.
public String getPalace(String query,String lat,String lng) throws ClientProtocolException, IOException{ HttpClient httpClient = new DefaultHttpClient(); String url = palceRequestUrl(query,lat,lng); logger.log(Level.INFO, url); HttpGet httpget = new HttpGet(url); ResponseHandler<String> responseHandler = new BasicResponseHandler(); String responseBody = httpClient.execute(httpget, responseHandler); logger.log(Level.INFO,"baidu response:"+responseBody); return responseBody; } public String palceRequestUrl(String query,String lat,String lng) throws UnsupportedEncodingException { String url = WeChatConstant.BASEURL + "place/search?query=" + URLEncoder.encode(query,"UTF-8") + "&key=" + WeChatConstant.MAPKEY +"&location="+lat+","+lng +"&radius=2000"+"&output=" + WeChatConstant.OUTPUTFORMAT; return url; }
Output results
<PlaceSearchResponse> <status>OK</status> <results> <result> <name>中国工商银行东长安街支行</name> <location> <lat>39.915891</lat> <lng>116.41867</lng> </location> <address>东城区东长安街1号东方广场西三办公楼1楼</address> <uid>a025683c73033c35a21de987</uid> <detail_url>http://api.map.baidu.com/place/detail?uid=a025683c73033c35a21de987&amp;output=html&amp;source=placeapi </detail_url> <tag>银行,王府井/东单</tag> </result> </results> </PlaceSearchResponse>
Next, the recent location information reflected by Baidu Map is displayed to WeChat users in the format of graphic messages
public static String getWeChatReplyNewsMessageByBaiduPlace(List<BaiduPlaceResponse> placeList, double lat, double lng,String userName, int size){ WeChatReplyNewsMessage newsMessage = new WeChatReplyNewsMessage(); List<Item> items = new ArrayList<Item>(); StringBuffer strBuf = new StringBuffer(); logger.log(Level.INFO,"placeList count="+placeList.size()); newsMessage.setItems(items); if(placeList.size()>size){ newsMessage.setArticleCount(size); } else{ newsMessage.setArticleCount(placeList.size()); } logger.log(Level.INFO,"article count="+newsMessage.getArticleCount()); newsMessage.setCreateTime(new Date().getTime()+""); newsMessage.setMsgType("news"); newsMessage.setFuncFlag("0"); newsMessage.setToUserName(userName); newsMessage.setFromUserName(WeChatConstant.FROMUSERNAME); for(int i = 0;i <newsMessage.getArticleCount();i++){ BaiduPlaceResponse place = placeList.get(i); Double distance = GeoUtil.DistanceOfTwoPoints(Double.valueOf(place.getLng()), Double.valueOf(place.getLat()), lng, lat, GaussSphere.Beijing54); Item item = new Item(); item.setTitle(place.getName()+"["+distance+"米]"+"\n"+place.getAddress()+"\n"+place.getTelephone()); item.setPicUrl(""); item.setUrl(place.getDetailUrl()); item.setDescription(""); items.add(item); } logger.log(Level.INFO,"newMessage="+newsMessage.toString()); strBuf = strBuf.append(getWeChatNewsMessage(newsMessage)); return strBuf.toString(); } public static String getWeChatNewsMessage(WeChatReplyNewsMessage newsMessage){ XStream xstream = new XStream(new DomDriver()); xstream.alias("xml", WeChatReplyNewsMessage.class); xstream.aliasField("ToUserName", WeChatReplyNewsMessage.class, "toUserName"); xstream.aliasField("FromUserName", WeChatReplyNewsMessage.class, "fromUserName"); xstream.aliasField("CreateTime", WeChatReplyNewsMessage.class, "createTime"); xstream.aliasField("MsgType", WeChatReplyNewsMessage.class, "msgType"); xstream.aliasField("ArticleCount", WeChatReplyNewsMessage.class, "articleCount"); xstream.aliasField("Content", WeChatReplyNewsMessage.class, "content"); xstream.aliasField("FuncFlag", WeChatReplyNewsMessage.class, "funcFlag"); xstream.aliasField("Articles", WeChatReplyNewsMessage.class, "items"); xstream.alias("item", Item.class); xstream.aliasField("Title", Item.class, "title"); xstream.aliasField("Description", Item.class, "description"); xstream.aliasField("PicUrl", Item.class, "picUrl"); xstream.aliasField("Url", Item.class, "url"); return xstream.toXML(newsMessage); }
For information such as road names, landmark buildings, etc., the method is to determine the longitude and latitude of the input location information through third-party map information.
This article uses Baidu Map API to determine the longitude and latitude of the location being searched.
After determining the longitude and latitude, the problem becomes the same as the first message type, and the corresponding processing is done according to the longitude and latitude.
public String getGeoCode(String query) throws ClientProtocolException, IOException{ HttpClient httpClient = new DefaultHttpClient(); String url = geoCodeRequestUrl(query); logger.log(Level.INFO, url); HttpGet httpget = new HttpGet(url); ResponseHandler<String> responseHandler = new BasicResponseHandler(); String responseBody = httpClient.execute(httpget, responseHandler); logger.log(Level.INFO,"baidu response:"+responseBody); return responseBody; } public String geoCodeRequestUrl(String query) throws UnsupportedEncodingException{ String url = WeChatConstant.BASEURL + "geocoder?address=" + URLEncoder.encode(query,"UTF-8") + "&key=" + WeChatConstant.MAPKEY + "&output=" + WeChatConstant.OUTPUTFORMAT; return url; }
For more related articles in the WeChat public platform development series, please pay attention to the PHP Chinese website!