我们在上一章节新建了一个web项目,名称为weChat,接下来的章节我们都在此项目基础上添加功能,包括以后的微信硬件jsapi的实现。
既然我们上一章节已经成功和微信公众平台对接成功,本章节着重介绍公众号回复用户的文本消息,也就是说用户向公众号发送消息,公众号响应用户发送的消息,类似于咱们和朋友之间的对话。那么该如何实现呢?其实用户发送文本消息,然后公众平台响应用户发送的消息分为两部分功能,1、公众号接收用户发送的文本消息 2、公众号响应用户的文本消息,也就是把响应消息再推送给用户。那么接下来我们该如何开发呢,请接着继续往下看。
一、公众号接收用户发送的文本消息
如上图所示,我们在公众号里面发送"123",公众号接收到"123"文本消息,并做出“你好,已接收到内容”的响应消息,在这个收发过程中,发送方和接收方进行了调换(ToUserName和FromUserName值互换),收发都是以xml格式在后台进行传输的,接下来我们就开始做公众号是怎么接收到"123"这个文本消息的呢?
所以掌握各种消息类型的接收回复就是进行微信公众平台开发的基础!
下面是微信自己的文档我在这里再展示一番:
当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。(上一节填写的http://100.200.300.400/weChat/weChatServlet),实际上推送到了weChatServlet的doPost方法上,上一节doGet方法已经讲过,现在终于可以用到doPost啦!
请注意:
1、关于重试的消息排重,推荐使用msgid排重。
2、微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。假如服务器无法保证在五秒内处理并回复,
可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。详情请见“发送消息-被动回复消息”。
3、如果开发者需要对用户消息在5秒内立即做出回应,即使用“发送消息-被动回复消息”接口向用户被动回复消息时,可以在
公众平台官网的开发者中心处设置消息加密。开启加密后,用户发来的消息和开发者回复的消息都会被加密(但开发者通过客服
接口等API调用形式向用户发送消息,则不受影响)。关于消息加解密的详细说明,请见“发送消息-被动回复消息加解密说明”。
各消息类型的推送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位整型
上面是理论部分,初学者会比较难以理解,不用太过追究,下面直接上java代码
我们继续编写上一章节新建项目weChat项目的WeChatServlet类,其中微信和用户之间的所有交互都在post方法中实现
import java.io.IOException; import java.io.PrintWriter; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.test.util.MessageUtil; /** * 核心请求处理类 */ public class WeChatServlet extends HttpServlet { private static final long serialVersionUID = 1508798736675904038L; /** * 确认请求来自微信服务器 */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 微信加密签名 String signature = request.getParameter("signature"); System.out.println("微信加密签名signature:-----------------------"+signature); // 时间戳 String timestamp = request.getParameter("timestamp"); System.out.println("时间戳timestamp:-----------------------"+timestamp); // 随机数 String nonce = request.getParameter("nonce"); System.out.println("随机数nonce:-----------------------"+nonce); // 随机字符串 String echostr = request.getParameter("echostr"); System.out.println("随机字符串echostr:-----------------------"+echostr); //System.out.println("token-----------------------:"+token); PrintWriter out = response.getWriter(); // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 if (SignUtil.checkSignature("weixinTest", signature, timestamp, nonce)) { out.print(echostr); //System.out.println("这是:"+echostr); } out.close(); out = null; } /** * 处理微信服务器发来的消息 */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("微信服务器发来消息------------"); // 将请求、响应的编码均设置为UTF-8(防止中文乱码) request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); try{ //xml请求解析 Map<String, String> requestMap = MessageUtil.parseXml(request); //发送方帐号(open_id) String fromUserName = requestMap.get("FromUserName"); //公众帐号 String toUserName = requestMap.get("ToUserName"); //消息类型 String msgType = requestMap.get("MsgType"); //消息创建时间 String createTime = requestMap.get("CreateTime"); //地理位置纬度 String location_X = requestMap.get("Location_X"); //地理位置经度 String location_Y = requestMap.get("Location_Y"); //微信服务器post过来的内容 String weixinContent = requestMap.get("Content"); System.out.println("公众号用户发送过来的文本消息内容:"+weixinContent); String respMessage = "<xml>" +"<ToUserName><![CDATA["+fromUserName+"]]></ToUserName>" +"<FromUserName><![CDATA["+toUserName+"]]></FromUserName>" +"<CreateTime>12345678</CreateTime>" +"<MsgType><![CDATA[text]]></MsgType>" +"<Content><![CDATA[你妹的]]></Content>" +"</xml>"; // 响应回复消息 PrintWriter out = response.getWriter(); out.print(respMessage); out.close(); }catch(Exception e){ e.printStackTrace(); } } }
上述代码变量weixinContent就是接收到用户发送的文本消息,在这里呢 你可以用微信发送任意文本消息,接收到消息后,这个案例会回复“你妹的”,上面用到了个工具类MessageUtil解析xml,其中dom.jar自行下载,在这里不在提供。
MessageUtil类代码:
import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; /*** * * @author V型知识库 www.vxzsk.com * linfanhehe@163.com * */ public class MessageUtil { /** * 解析微信发来的请求(XML) * * @param request * @return * @throws Exception */ @SuppressWarnings("unchecked") public static Map<String, String> parseXml(HttpServletRequest request) throws Exception { // 将解析结果存储在HashMap中 Map<String, String> map = new HashMap<String, String>(); // 从request中取得输入流 InputStream inputStream = request.getInputStream(); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List<Element> elementList = root.elements(); // 遍历所有子节点 for (Element e : elementList) { map.put(e.getName(), e.getText()); } // 释放资源 inputStream.close(); inputStream = null; return map; } }
把编译后的代码重新部署到服务器上,重启tomcat,输入任意文本消息,例如"啊",运行效果图如下:
如果程序有错误微信会提示“无法提供服务”。
服务器端日志:
感觉本站内容不错,读后有收获?小额赞助,鼓励网站分享出更好的教程