Home  >  Article  >  WeChat Applet  >  Message interface developed by WeChat

Message interface developed by WeChat

高洛峰
高洛峰Original
2017-03-09 15:55:341716browse

In this article, let’s take a look at the message interface developed by WeChat

I feel that WeChat development is about calling the WeChat interface, so I will read and try to call the WeChat interface when I have no work arrangements. , calling the WeChat interface requires sending http get and post requests, so it is best to write an httputil class first to specifically send get and post requests. However, my Java network programming is not good, so I Baidu some code and then encapsulate some myself. , it can be used normally. The code is as follows

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.Map;
import javax.activation.MimetypesFileTypeMap;
/**
 * 
 * @author luolei
 *
 */
public class HttpUtil {
    
    public static String httpGet(String httpUrl){
        StringBuffer buffer = null; 
        try{
            URL url = new URL(httpUrl);
            HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  
            httpUrlConn.setDoInput(true);  
            httpUrlConn.setRequestMethod("GET"); 
         // 获取输入流  
            InputStream inputStream = httpUrlConn.getInputStream();  
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
            // 读取返回结果  
            buffer = new StringBuffer();  
            String str = null;  
            while ((str = bufferedReader.readLine()) != null) {  
                buffer.append(str);  
            }  
            // 释放资源  
            bufferedReader.close();  
            inputStreamReader.close();  
            inputStream.close();  
            httpUrlConn.disconnect(); 
        }catch(Exception e){
            e.printStackTrace();
        }
        return buffer.toString();
        
    }
    
    /**
     * 
     * 发 post 请求,
     */
    public static String httpPost(String httpUrl,String data){
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(httpUrl);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(data);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常!"+e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    }
    
    /**
     * 上传图片
     * 
     * @param urlStr
     * @param textMap
     * @param fileMap
     * @return
     */
    public static String formUpload(String urlStr, Map<String, String> textMap,
            Map<String, String> fileMap) {
        String res = "";
        HttpURLConnection conn = null;
        String BOUNDARY = "---------------------------123821742118716"; //boundary就是request头和上传文件内容的分隔符
        try {
            URL url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
//            System.out.println(conn);
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(30000);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn
                    .setRequestProperty("User-Agent",
                            "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
            conn.setRequestProperty("Content-Type",
                    "multipart/form-data; boundary=" + BOUNDARY);
            OutputStream out = new DataOutputStream(conn.getOutputStream());
            // text
            if (textMap != null) {
                StringBuffer strBuf = new StringBuffer();
                Iterator iter = textMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry) iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    strBuf.append("\r\n").append("--").append(BOUNDARY).append(
                            "\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\""
                            + inputName + "\"\r\n\r\n");
                    strBuf.append(inputValue);
                }
                out.write(strBuf.toString().getBytes());
            }
            // file
            if (fileMap != null) {
                Iterator iter = fileMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry) iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    File file = new File(inputValue);
                    String filename = file.getName();
                    String contentType = new MimetypesFileTypeMap()
                            .getContentType(file);
                    if (filename.endsWith(".png")) {
                        contentType = "image/png";
                    }
                    if (contentType == null || contentType.equals("")) {
                        contentType = "application/octet-stream";
                    }
                    StringBuffer strBuf = new StringBuffer();
                    strBuf.append("\r\n").append("--").append(BOUNDARY).append(
                            "\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\""
                            + inputName + "\"; filename=\"" + filename
                            + "\"\r\n");
                    strBuf.append("Content-Type:" + contentType + "\r\n\r\n");
                    out.write(strBuf.toString().getBytes());
                    DataInputStream in = new DataInputStream(
                            new FileInputStream(file));
                    int bytes = 0;
                    byte[] bufferOut = new byte[1024];
                    while ((bytes = in.read(bufferOut)) != -1) {
                        out.write(bufferOut, 0, bytes);
                    }
                    in.close();
                }
            }
            byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
            out.write(endData);
            out.flush();
            out.close();
            // 读取返回数据
            StringBuffer strBuf = new StringBuffer();
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                strBuf.append(line).append("\n");
            }
            res = strBuf.toString();
            reader.close();
            reader = null;
        } catch (Exception e) {
            System.out.println("发送POST请求出错。" + urlStr);
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.disconnect();
                conn = null;
            }
        }
        return res;
    }
    
}

where httpGet and httpPost are used to send get and post requests. In WeChat development, the message interface is generally in xml format, and the others The data uploaded and returned by the interface is generally json, so a package for parsing json is needed. I use fastjson. Of course, you can also use gson

Now let’s start testing the message interface. First, we need to Understand the request process:

The WeChat server will send a get request based on the filled in URL for verification. When the verification is successful, it will still send a post request based on the URL. The message format is xml format

Message type development document Yes, there are mainly messages such as text, pictures, and voices, as well as some events such as attention, clicks, and jumps.

These messages and events are in xml format, so the messages in xml format need to be parsed. I use dom4j to parse,

The doPost method of the connected servlet is verified before parsing the message,

I followed the method written in Liu Feng's blog and wrote a MessageUtil, which encapsulates the method of parsing xml and puts the parsed results in map3b196469fdc8cfa403b3383d58a116c6. The specific code is as follows:

public static Map18fed3eaa375b9cabd6da695ec776cac parseXml(HttpServletRequest request) throws Exception {  
        // 将解析结果存储在HashMap中  
        Map18fed3eaa375b9cabd6da695ec776cac map = new HashMap18fed3eaa375b9cabd6da695ec776cac();  
  
        // 从request中取得输入流  
        InputStream inputStream = request.getInputStream();  
        // 读取输入流  
        SAXReader reader = new SAXReader();  
        Document document = reader.read(inputStream);  
        // 得到xml根元素  
        Element root = document.getRootElement();  
        // 得到根元素的所有子节点  
        List558dc77cf99fee6757323747f07fa144 elementList = root.elements();  
  
        // 遍历所有子节点  
        for (Element e : elementList)  
            map.put(e.getName(), e.getText());  
  
        // 释放资源  
        inputStream.close();  
        inputStream = null;  
  
        return map;  
    }

Then the parsed xml will be saved in the map according to the tag name-content

Then the message type msgType## can be taken out from it

#String msgType = requestMap.get("MsgType");

Then determine the type of message, different message types, let different servlets handle it,

// 文本消息
            if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
                request.getRequestDispatcher("TextMessage").forward(request, response);
            }
            // 图片消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
                request.getRequestDispatcher("ImageServlet").forward(request, response);
            }
            // 地理位置消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
                request.getRequestDispatcher("LocationServlet").forward(request, response);
            }
            // 链接消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
                request.getRequestDispatcher("LinkServlet").forward(request, response);
            }
            // 音频消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
                request.getRequestDispatcher("VedioServlet").forward(request, response);
            }
            // 事件推送
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
                // 事件类型
                String eventType = requestMap.get("Event");
                // 订阅
                if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
                    request.getRequestDispatcher("SubServlet").forward(request, response);
                }
                // 取消订阅
                else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
                    // TODO 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息
                    
                }
                // 自定义菜单点击事件
                else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
                    // TODO 自定义菜单权没有开放,暂不处理该类消息
                    request.getRequestDispatcher("ClickServlet").forward(request, response);
                }
            }

Different servlets process different messages and can return different messages as needed. The format of the returned message is also in xml format. The return message type is the same as the acceptance The message types are basically similar. These returned messages can be encapsulated. Each xml tag corresponds to the field name, and the content is the content of the field.

Example:

public class BaseMessageResp {
    // 接收方帐号(收到的OpenID)  
    private String ToUserName;  
    // 开发者微信号  
    private String FromUserName;  
    // 消息创建时间 (整型)  
    private long CreateTime;  
    // 消息类型(text/music/news)  
    private String MsgType;  
    // 位0x0001被标志时,星标刚收到的消息  
    private int FuncFlag;

The set and get methods are omitted

public class TextMessage extends BaseMessageResp {
    // 回复的消息内容  
    private String Content;  
  
    public String getContent() {  
        return Content;  
    }  
  
    public void setContent(String content) {  
        Content = content;  
    }
}

Because different messages have the same fields, a common base class is written.

Now we are one step away from returning the message to the user. The technology converts these pojo classes into xml strings

Using xstream

/** 
     * 文本消息对象转换成xml 
     *  
     * @param textMessage 文本消息对象 
     * @return xml 
     */  
    public static String textMessageToXml(TextMessage textMessage) {  
        xstream.alias("xml", textMessage.getClass());  
        return xstream.toXML(textMessage);  
    }

This is just a simple description. For details, you can see Liu Feng’s blog. I forgot the link. You should be able to go to Baidu.

Finally, return the obtained string to the WeChat server to reply to the user. .

You can write a simple subscription account using only these message interfaces. It should be that the public account of a general company seems to jump to its own website through a view type button.

Now you can use the above interface to accept various messages sent by users, and then process the messages in advance, or call some APIs, such as weather, jokes, articles, etc. APIs to get the results. After analysis, follow You can return the format you want to the user, and you can practice a subscription account such as a life assistant. However, the subscription account you apply for has limited permissions, and I don't know if I can do it.

The above is the detailed content of Message interface developed by WeChat. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn