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


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

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

今天我就給大家說下如何獲取用戶發送消息並實現回復,自己在弄這個過程走了許多坑。

要實現消息獲取和自動回復,需要了解微信是怎么實現這個過程:

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

接收普通消息

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

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

文本消息

<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結構,來對該消息進行響應(現支持回復文本、圖片、圖文、語音、視頻、音樂)。嚴格來說,發送被動響應消息其實並不是一種接口,而是對微信服務器發過來消息的一次回復。

 

回復文本消息

<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());
		}
	}

}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM