`

[029] 微信公众帐号开发教程第5篇-各种消息的接收与响应

 
阅读更多

前一篇文章里我们已经把微信公众平台接口中消息及相关操作都进行了封装,本章节将主要介绍如何接收微信服务器发送的消息并做出响应。


明确在哪接收消息

从微信公众平台接口消息指南中可以了解到,当用户向公众帐号发消息时,微信服务器会将消息通过POST方式提交给我们在接口配置信息中填写的URL,而我们就需要在URL所指向的请求处理类CoreServlet的doPost方法中接收消息、处理消息和响应消息。


接收、处理、响应消息

下面先来看我已经写好的CoreServlet的完整代码:

package org.liufeng.course.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.liufeng.course.service.CoreService;
import org.liufeng.course.util.SignUtil;

/**
 * 核心请求处理类
 * 
 * @author liufeng
 * @date 2013-05-18
 */
public class CoreServlet extends HttpServlet {
	private static final long serialVersionUID = 4440739483644821986L;

	/**
	 * 确认请求来自微信服务器
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 微信加密签名
		String signature = request.getParameter("signature");
		// 时间戳
		String timestamp = request.getParameter("timestamp");
		// 随机数
		String nonce = request.getParameter("nonce");
		// 随机字符串
		String echostr = request.getParameter("echostr");

		PrintWriter out = response.getWriter();
		// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
		if (SignUtil.checkSignature(signature, timestamp, nonce)) {
			out.print(echostr);
		}
		out.close();
		out = null;
	}

	/**
	 * 处理微信服务器发来的消息
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 将请求、响应的编码均设置为UTF-8(防止中文乱码)
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");

		// 调用核心业务类接收消息、处理消息
		String respMessage = CoreService.processRequest(request);
		
		// 响应消息
		PrintWriter out = response.getWriter();
		out.print(respMessage);
		out.close();
	}

}
代码说明:

1)第51行代码:微信服务器POST消息时用的是UTF-8编码,在接收时也要用同样的编码,否则中文会乱码;

2)第52行代码:在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上;

3)第54行代码:调用CoreService类的processRequest方法接收、处理消息,并得到处理结果;

4)第57~59行:调用response.getWriter().write()方法将消息的处理结果返回给用户

从doPost方法的实现可以看到,它是通过调用CoreService类的processRequest方法接收、处理消息的,这样做的目的是为了解耦,即业务相关的操作都不在Servlet里处理,而是完全交由业务核心类CoreService去做。下面来看CoreService类的代码实现:

package org.liufeng.course.service;

import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.liufeng.course.message.resp.TextMessage;
import org.liufeng.course.util.MessageUtil;

/**
 * 核心服务类
 * 
 * @author liufeng
 * @date 2013-05-20
 */
public class CoreService {
	/**
	 * 处理微信发来的请求
	 * 
	 * @param request
	 * @return
	 */
	public static String processRequest(HttpServletRequest request) {
		String respMessage = null;
		try {
			// 默认返回的文本消息内容
			String respContent = "请求处理异常,请稍候尝试!";

			// 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");

			// 回复文本消息
			TextMessage textMessage = new TextMessage();
			textMessage.setToUserName(fromUserName);
			textMessage.setFromUserName(toUserName);
			textMessage.setCreateTime(new Date().getTime());
			textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
			textMessage.setFuncFlag(0);

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

			textMessage.setContent(respContent);
			respMessage = MessageUtil.textMessageToXml(textMessage);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return respMessage;
	}
}

代码说明:

1)第29行:调用消息工具类MessageUtil解析微信发来的xml格式的消息,解析的结果放在HashMap里;

2)32~36行:从HashMap中取出消息中的字段;

3)39-44、84行:组装要返回的文本消息对象;

4)47~82行:演示了如何接收微信发送的各类型的消息,根据MsgType判断属于哪种类型的消息;

5)85行:调用消息工具类MessageUtil将要返回的文本消息对象TextMessage转化成xml格式的字符串;


关于事件推送(关注、取消关注、菜单点击)

对于消息类型的判断,像文本消息、图片消息、地理位置消息、链接消息和语音消息都比较好理解,有很多刚接触的朋友搞不懂事件推送消息有什么用,或者不清楚该如何判断用户关注的消息。那我们就专门来看下事件推送,下图是官方消息接口文档中关于事件推送的说明:

这里我们只要关心两个参数:MsgType和Event。当MsgType=event时,就表示这是一条事件推送消息;而Event表示事件类型,包括订阅、取消订阅和自定义菜单点击事件。也就是说,无论用户是关注了公众帐号、取消对公众帐号的关注,还是在使用公众帐号的菜单,微信服务器都会发送一条MsgType=event的消息给我们,而至于具体这条消息表示关注、取消关注,还是菜单的点击事件,就需要通过Event的值来判断了。(注意区分Event和event)


连载五篇教程总结

经过5篇的讲解,已经把开发模式启用,接口配置,消息相关工具类的封装,消息的接收与响应全部讲解完了,而且贴上了完整的源代码,相信有一定Java基础的朋友可以看的明白,能够通过系列文章基本掌握微信公众平台开发的相关技术知识。下面我把目前项目的完整结构贴出,方便大家对照:



如果觉得文章对你有所帮助,请留言支持或关注微信公众帐号xiaoqrobot支持柳峰哦!


分享到:
评论
1 楼 csu_hqj 2013-12-17  
谢谢  思路很清楚  学些了

相关推荐

    JAVA微信开发资料

    微信公众帐号开发教程第 5 篇-各种消息的接收与响应 39 微信公众帐号开发教程第 6 篇-文本消息的内容长度限制揭秘 45 微信公众帐号开发教程第 7 篇-文本消息中换行符的使用.. 49 微信公众帐号开发教程第 8 篇-文本...

    微信公众帐号开发教程

    [037] 微信公众帐号开发教程第13篇-图文消息全攻略 - 柳峰的专栏 - 博客频道 - CSDN.NET [038] 微信公众帐号开发教程第14篇-自定义菜单的创建及菜单事件响应 - 柳峰的专栏 - 博客频道 - CSDN.NET [040] 微信公众帐号...

    微信公众帐号开发教程第3篇-开发模式启用及接口配置

    微信公众帐号开发教程第3篇-开发模式启用及接口配置

    微信公共账号开发教程

    2. 微信公众帐号开发教程第2篇-微信公众帐号的类型(普通和会议) 3. 微信公众帐号开发教程第3篇-开发... 微信公众帐号开发教程第5篇-各种消息的接收与响应 6. 微信公众帐号开发教程第6篇-文本消息的内容长度限制揭秘

    java开发微信公众平台

    微信公众帐号开发教程第1 篇-引言 微信公众帐号开发教程第2 篇-微信公众帐号的类型(普通和会议) 微信公众帐号开发教程第3 篇-开发模式启用及接口配置 ...微信公众帐号开发教程第5 篇-各种消息的接收与响应

    微信小程序开发图解案例教程-源代码

    微信小程序开发图解案例教程-源代码微信小程序开发图解案例教程-源代码微信小程序开发图解案例教程-源代码微信小程序开发图解案例教程-源代码微信小程序开发图解案例教程-源代码微信小程序开发图解案例教程-源代码...

    微信小程序开发合同协议书范本-最新通用.pdf

    微信小程序开发合同协议书范本-最新通用.pdf微信小程序开发合同协议书范本-最新通用.pdf微信小程序开发合同协议书范本-最新通用.pdf微信小程序开发合同协议书范本-最新通用.pdf微信小程序开发合同协议书范本-最新...

    微信开发实例 微信公众平台开发 之微信接口前期准备

    微信开发实例 微信公众平台开发教程-深入浅出微信公众平台实战开发(微网站、LBS云、Api接口调用、服务号高级接口)1.微信接口前期准备。由北风网提供,微信开发实例微信公众平台基础篇: 1)微信公众平台简介:开发...

    微信公众平台开发入门教程

    微信公众平台开发入门教程

    微信公众平台最佳实践-源代码-方倍工作室

    自从方倍工作室在博客园推出微信公众平台开发系列教程后,受到广大微信开发人员及爱好者的热情关注,相头文章的日访问量高达上万人次,而《微信公众平台开发入门教程》一门阅读量早已超出20万,很多博文被很多有影响...

    微信公众账号开发教程

    经过这3个公众帐号的开发,对目前微信公众平台开放的api算是比较熟悉了,像文本消息、图文消息、音乐消息、语音消息、位置消息等全部用到过,菜单也使用过。所以,就有了写微信公众帐号开发教程的想法,将学习到的...

    微信公众平台应用开发实战-完整扫描版 pdf 文档

    第三部分(第5~7章)以迭代的方式讲解了3个实战案例的完整开发过程,这3个实战案例涉及的应用分别是娱乐型、应用型和游戏型的,其中应用型实战案例用到了人脸识别等技术;第四部分(第8~9章)详细探讨了应对海量...

    微信小程序开发合同协议书范本-最新通用.docx

    微信小程序开发合同协议书范本-最新通用.docx微信小程序开发合同协议书范本-最新通用.docx微信小程序开发合同协议书范本-最新通用.docx微信小程序开发合同协议书范本-最新通用.docx微信小程序开发合同协议书范本-...

    微信公众平台开发教程,Java

    微信公众平台的开发教程,用Java写的,挺有借鉴的意义

    微信公众平台开发教程Java版

    微信公众平台开发教程Java版 微信公众平台开发教程Java版

    《微信公众平台入门到精通》--ZTalk

    共16期微信公众平台开发教程,微信平台的界面操作--&gt;微信消息借口API--&gt;新浪云平台SAE+PHP作为公众平台的服务端--&gt;订阅事件响应--&gt;SAE STORAGE--&gt;收发文字、图文、音频、地理位置,处理退订事件--&gt;SAE数据库、缓存、...

    微信公众平台从入门到精通1-17

    番外篇 微信会议公众账号详解 第七章 公众平台开发模式介绍 第八章 新浪云计算平台注册和使用 第九章 用微信开发模式做欢迎词 第十章 公众账号发送欢迎图文消息 第十一章 公众账号自定义回复功能 第十二章 公众账号...

    微信公众账号开发教程(java)

    微信公众账号开发教程(java) 程主要是面向有一定Java编程基础的朋友 1)前沿知识:微信公众帐号的分类、两种模式各自的特点和区别、开发模式的配置使用等; 2)API中各类消息的使用(我已经对api进行封装并打成了jar...

    微信公众平台开发教程4

    微信公众平台开发教程,适合初学者了解入门,用的是php语言,简单易懂,欢迎下载

Global site tag (gtag.js) - Google Analytics