微信公衆號開發:獲取用戶發送消息並實現回覆(Java)

在上一篇文章寫了如何配置服務器:html

https://blog.csdn.net/qq_36313726/article/details/81027366java

今天我就給你們說下如何獲取用戶發送消息並實現回覆,本身在弄這個過程走了許多坑。服務器

要實現消息獲取和自動回覆,須要瞭解微信是怎麼實現這個過程:微信

我從微信官方文檔摘取了下面比較重要的信息微信開發

接收普通消息

當普通微信用戶向公衆帳號發消息時,微信服務器將POST消息的XML數據包到開發者填寫的URL上。app

文本消息在請求的輸出流中,而不是參數位置,參數是對xml中標籤的解釋。dom

文本消息post

<xml>  
<ToUserName>< ![CDATA[toUser] ]></ToUserName>  
<FromUserName>< ![CDATA[fromUser] ]></FromUserName>  <CreateTime>1348831860</CreateTime>  
<MsgType>< ![CDATA[text] ]></MsgType>  
<Content>< ![CDATA[this is a test] ]></Content>  
<MsgId>1234567890123456</MsgId>  
</xml>
 

  

參數 描述
ToUserName 開發者微信號
FromUserName 發送方賬號(一個OpenID)
CreateTime 消息建立時間 (整型)
MsgType text
Content 文本消息內容
MsgId 消息id,64位整型

被動回覆用戶消息

當用戶發送消息給公衆號時(或某些特定的用戶操做引起的事件推送時),會產生一個POST請求,開發者能夠在響應包(Get)中返回特定XML結構,來對該消息進行響應(現支持回覆文本、圖片、圖文、語音、視頻、音樂)。嚴格來講,發送被動響應消息其實並非一種接口,而是對微信服務器發過來消息的一次回覆。測試

 

回覆文本消息ui

<xml> <ToUserName>< ![CDATA[toUser] ]></ToUserName> 
<FromUserName>< ![CDATA[fromUser] ]></FromUserName> <CreateTime>12345678</CreateTime> 
<MsgType>< ![CDATA[text] ]></MsgType> 
<Content>< ![CDATA[你好] ]></Content> 
</xml>

  

參數 是否必須 描述
ToUserName 接收方賬號(收到的OpenID)
FromUserName 開發者微信號
CreateTime 消息建立時間 (整型)
MsgType text
Content 回覆的消息內容(換行:在content中可以換行,微信客戶端就支持換行顯示)

 

在網上看到這張圖片很好理解

 

微信公衆號開發文檔說了,只有對服務器進行驗證的時候纔會使用到get請求到服務器的url中,其它一概使用post請求。

所以用戶發送消息時,微信服務器是經過post請求到咱們的服務器上。

能夠看下我寫的代碼來理解這個過程,這個代碼有部分利用上一篇文章說過的步驟:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.qq.weixin.mp.aes.AesException;
import com.qq.weixin.mp.aes.SHA1;

/**
 * Servlet implementation class test
 */
@WebServlet("/test")
public class test extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

		String signature = request.getParameter("signature");
		String timestamp = request.getParameter("timestamp");
		String nonce = request.getParameter("nonce");
		String echostr = request.getParameter("echostr");
		String token = "jylife";
		String jiami = "";
		String openid=request.getParameter("openid");
		String body=request.getParameter("body");
		System.out.println(body);
		Date date=new Date();
        try {
            jiami=SHA1.getSHA1(token, timestamp, nonce,"");//這裏是對三個參數進行加密
       } catch (AesException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }
        System.out.println("加密"+jiami);
        System.out.println("自己"+signature);
           PrintWriter out=response.getWriter();
           if(jiami.equals(signature))
           out.print(echostr);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        //獲取服務器發送過來的信息,由於不是參數,得用輸入流讀取
		BufferedReader reader = null;
        StringBuilder sb = new StringBuilder();
        try{
            reader = new BufferedReader(new InputStreamReader(request.getInputStream(), "utf-8"));
            String line = null;
            while ((line = reader.readLine()) != null){
                sb.append(line);
            }
        } catch (IOException e){
            e.printStackTrace();
        } finally {
            try{
                if (null != reader){ reader.close();}
            } catch (IOException e){
            	e.printStackTrace();
            }
        }
        System.out.println("用戶發送過來信息:"+sb);//將用戶發送得消息打印出來
        /*	能夠request看出全部的參數信息
         * 	Enumeration enu=request.getParameterNames();  
			while(enu.hasMoreElements()){  
			String paraName=(String)enu.nextElement();  
			System.out.println(paraName+": "+request.getParameter(paraName));  
			}
         */
		String openid=request.getParameter("openid");//獲取參數中的openid
		PrintWriter out=response.getWriter();
			String replyMsg = "<xml>"
					+ "<ToUserName><![CDATA["+openid+"]]></ToUserName>"//回覆用戶時,這裏是用戶的openid;但用戶發送過來消息這裏是微信公衆號的原始id
					+ "<FromUserName><![CDATA["+"這裏微信公衆號的原始id"+"]]></FromUserName>"//這裏填寫微信公衆號 的原始id;用戶發送過來時這裏是用戶的openid
					+ "<CreateTime>1531553112194</CreateTime>"//這裏能夠填建立信息的時間,目前測試隨便填也能夠
					+ "<MsgType><![CDATA[text]]></MsgType>"//文本類型,text,能夠不改
					+ "<Content><![CDATA[我喜歡你]]></Content>"//文本內容,我喜歡你
					+ "<MsgId>1234567890123456</MsgId> "//消息id,隨便填,但位數要夠
					+ " </xml>";
			System.out.println(replyMsg);//打印出來
			out.println(replyMsg);//回覆

	}

}

  

這裏仍是強調一下,文本消息在輸出流中,獲取參數是看不到的;若是仍是有點犯暈,能夠將裏面註釋掉的輸出所有request參數代碼部分運行一下。

 最後我參考微信官方給的實例,對代碼作了一點適配,能夠不須要手動配置微信開發者的初始id

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.qq.weixin.mp.aes.AesException;
import com.qq.weixin.mp.aes.SHA1;

/**
 * Servlet implementation class test
 */
@WebServlet("/test")
public class test extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

		String signature = request.getParameter("signature");
		String timestamp = request.getParameter("timestamp");
		String nonce = request.getParameter("nonce");
		String echostr = request.getParameter("echostr");
		String token = "jylife";
		String jiami = "";
		String openid=request.getParameter("openid");
		String body=request.getParameter("body");
		System.out.println(body);
		Date date=new Date();
        try {
            jiami=SHA1.getSHA1(token, timestamp, nonce,"");//這裏是對三個參數進行加密
       } catch (AesException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }
           PrintWriter out=response.getWriter();
           if(jiami.equals(signature))
           out.print(echostr);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
		PrintWriter out=response.getWriter();
		try
		{
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document document = db.parse(request.getInputStream());
			Element root = document.getDocumentElement();
			String  wechatId = root.getElementsByTagName("ToUserName").item(0).getTextContent();
			String 	openid = root.getElementsByTagName("FromUserName").item(0).getTextContent();
			String 	msg = root.getElementsByTagName("Content").item(0).getTextContent();//用戶發送的內容
			System.out.println(msg);//打印用戶發送的消息
			String content="";
			//對用戶發送過來的內容選擇要回復的內容
			if(msg.matches("喜歡"))
			{
				content="我也喜歡你";
			}
			else
			{
				content="我也不喜歡你";
			}
			String replyMsg = "<xml>"
					+ "<ToUserName><![CDATA["+openid+"]]></ToUserName>"//回覆用戶時,這裏是用戶的openid;但用戶發送過來消息這裏是微信公衆號的原始id
					+ "<FromUserName><![CDATA["+wechatId+"]]></FromUserName>"//這裏填寫微信公衆號 的原始id;用戶發送過來時這裏是用戶的openid
					+ "<CreateTime>1531553112194</CreateTime>"//這裏能夠填建立信息的時間,目前測試隨便填也能夠
					+ "<MsgType><![CDATA[text]]></MsgType>"//文本類型,text,能夠不改
					+ "<Content><![CDATA["+content+"]]></Content>"//文本內容,我喜歡你
					+ "<MsgId>1234567890123456</MsgId> "//消息id,隨便填,但位數要夠
					+ " </xml>";
			System.out.println(replyMsg);//打印出來
			out.println(replyMsg);//回覆
		}
		catch(Exception e)
		{
			System.out.println(e.toString());
		}
	}

}
相關文章
相關標籤/搜索