首頁  >  文章  >  微信小程式  >  微信公眾平台開發系列

微信公眾平台開發系列

高洛峰
高洛峰原創
2018-05-14 15:28:581669瀏覽

開始微信大眾平台的開發,我們首先要了解微信平台可以幫助我們做哪些事?

使用您的公眾帳號登陸http://mp.weixin.qq.com/,選擇選單--高級功能-開發模式--查看文檔,即能看到微信公眾平台目前所能開發的功能。

一、通訊機制

微信公众平台开发系列

公眾平台的主要內容是

  • 接受用戶傳送給您公眾帳號的訊息

  • 給您的用戶回覆訊息

#需要特別說明的是,發送訊息和回覆消失是一個連貫的過程,只能在一個對話中完成。也就是說您的用戶不找您說話,您是不能主動發送訊息給你的客戶(群發是另一種情況,有次數限制。你也可以申請付費使用微信CRM平台)。所有的發送訊息和接受訊息,都需要微信平台進行中轉。

二、訊息類型

以下介紹使用者能傳送給您的訊息類型,也就是目前接受到的訊息類型。

1.接受訊息類型

1.1文字訊息:

這也是我們平常碰到最多的,可以根據文字中提到的一些關鍵字,進行判斷,判斷使用者的意義,並進行回覆。

1.2圖片訊息:

目前透過圖片理解使用者想表達的意思,還是有較大難度,因此多數的公眾帳號,會選擇忽略圖片資訊或選擇由人工來處理。只能說一句:圖片很美,但我看不懂。

1.3地理位置訊息:

用戶把他的位置寄給您,這對大多數公眾帳號來說,是一個重要的訊息。可以提供一些基於位置資訊的服務,例如飯店預訂公眾帳號,可以給你推薦你周邊的飯店。 另外一個補充是,可以在文字訊息中分析出位置訊息,並加以利用。例如用戶輸入“南京路步行街”,可以提供用戶南京路步行街的相關商家。

1.4連結訊息:

目前還沒有看到開發模式中特別有效的使用方法。使用比較多的可能會是購物時或是諮詢時,對所談論的對象進行明確。

1.5事件推播訊息:

當使用者進入和你對話的過程中,可以先和使用者打招呼等。這個消息目前只支援4.5版本,暫時還沒有開發。後續可想想的空間很大,例如使用者進入到會話之後,搖一搖會發生什麼事?

2.回覆訊息類型

  2.1文字訊息
   這是我們平時發送最多的一類訊息,當只需要簡單的文字即可回答用戶的訊息時,可用文本消息。文字訊息中可以帶有連結地址。

微信公众平台开发系列

 2.2圖文訊息
    圖文訊息,這是我們在推播訊息中經常看到的訊息格式。每項內容可以點擊查看更詳細資訊(當然你也可以把連結設為空,使其不能跳轉)

微信公众平台开发系列

   2.3音樂訊息
   在你的答覆中給用戶一個語音訊息或是音樂,可以獲得不少用戶的親青睞。
了解了公眾平台的通訊機制和訊息類型,接下來,我們開始準備開發環境了

#1.設定成為開發者模式

##登入微信工作平台,選擇進階功能-進入開發模式,成為開發者。需要做如下圖配置。 URL配置的資訊是指,微信的後台伺服器會將您的用戶訊息傳送到該URL處理。 Token是你和微信之間的密碼,用來驗證訊息是否是從微信的服務發送而來,而不是其他來攻擊你的系統。

現在你還不能設置,在設定時微信會GET請求你設定的URL,已偵測介面是否可以使用。只有等你準備好GET方法之後才可以進行設定。

微信公众平台开发系列

2.實作GET方法

#從文件中知道,我們需要實作POST和GET方法,GET方法用來驗證微信和你的通訊驗證,POST用於訊息處理。

新Servlet HelloWeChat,先實作其中的GET方法

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

1.WeChat geography Location message

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;amp;output=html&amp;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); 
    }

2. Road name, landmark building or shopping mall name

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!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn