在上一篇微信开发的博文中微信开发(01)之如何成为开发者,我们开启了微信开发者模式,本篇博文我们简单的处理微信关注者发给我们公众号的消息。
在开启微信开发者模式时,我们配置了一个url地址,当我们提交开启微信开发者模式,腾讯的微信服务器会向该url地址发送一个get请求,并且携带一些参数,让我们来验证。说到get请求,就必须说到post请求,关注我们公众号的微信粉丝发来的消息,触发的事件,腾讯的微信服务器则会像该url地址发送一个post请求,请求的内容就是以xml文档形式的字符串。
所以该url地址的get请求的处理方法,专门用于开启微信开发者模式;而post请求则用于处理微信粉丝发给我们的消息,或者触发的事件,所以我们后面的微信开发工作的起点就是该url地址的post处理方法。
下面我们处理一个最简单的例子:粉丝发送任意一个文本信息给我们,我们给他回复一个消息:“你好,+ 他微信的openid”
下面直接贴代码:
url对应的处理servlet:
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();
// 请求校验,若校验成功则原样返回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 signature = request.getparameter("signature");
string timestamp = request.getparameter("timestamp");
string nonce = request.getparameter("nonce");
printwriter out = response.getwriter();
// 请求校验
if (signutil.checksignature(signature, timestamp, nonce)) {
message msgobj = xmlutil.getmessageobject(request); // 读取微信客户端发来的消息(xml字符串),并将其转换为消息对象
if(msgobj != null){
string xml = "<xml>" +
"<tousername><![cdata[" + msgobj.getfromusername() + "]]></tousername>" + // 接收方帐号(收到的openid)
"<fromusername><![cdata[" + msgobj.gettousername() + "]]></fromusername>" + // 开发者微信号
"<createtime>12345678</createtime>" +
"<msgtype><![cdata[text]]></msgtype>" +
"<content><![cdata[你好,"+ msgobj.getfromusername() +"]]></content>" +
"</xml>";
out.write(xml); // 回复微信客户端的消息(xml字符串)
out.close();
return;
}
}
out.write("");
out.close();
}
}
xml字符串的处理工具类,实现xml消息到消息对象的转换:
public class xmlutil
{
/**
* 从request中读取用户发给公众号的消息内容
* @param request
* @return 用户发给公众号的消息内容
* @throws ioexception
*/
public static string readrequestcontent(httpservletrequest request) throws ioexception
{
// 从输入流读取返回内容
inputstream inputstream = request.getinputstream();
inputstreamreader inputstreamreader = new inputstreamreader(inputstream, "utf-8");
bufferedreader bufferedreader = new bufferedreader(inputstreamreader);
string str = null;
stringbuilder buffer = new stringbuilder();
while ((str = bufferedreader.readline()) != null) {
buffer.append(str);
}
// 释放资源
bufferedreader.close();
inputstreamreader.close();
inputstream.close();
return buffer.tostring();
}
/**
* 将xml文档的内容转换成map
* @param xmldoc
* @return map
*/
public static map<string, string> xmltomap(string xmldoc)
{
//创建一个新的字符串
stringreader read = new stringreader(xmldoc);
//创建新的输入源sax 解析器将使用 inputsource 对象来确定如何读取 xml 输入
inputsource source = new inputsource(read);
//创建一个新的saxbuilder
saxbuilder sb = new saxbuilder();
map<string, string> xmlmap = new hashmap<string, string>();
try {
document doc = sb.build(source); //通过输入源构造一个document
element root = doc.getrootelement(); //取的根元素
list<element> cnodes = root.getchildren(); //得到根元素所有子元素的集合(根元素的子节点,不包括孙子节点)
element et = null;
for(int i=0;i<cnodes.size();i++){
et = (element) cnodes.get(i); //循环依次得到子元素
xmlmap.put(et.getname(), et.gettext());
}
} catch (jdomexception e) {
e.printstacktrace();
} catch (ioexception e) {
e.printstacktrace();
}
return xmlmap;
}
/**
* 将保存xml内容的map转换成对象
* @param map
* @return
*/
public static message getmessageobject(map<string, string> map)
{
if(map != null){
string msgtype = map.get("msgtype");
// 消息类型(文本消息:text, 图片消息:image, 语音消息:voice, 视频消息:video,
// 地理位置消息:location, 链接消息:link)
if("text".equals(msgtype)){
textmessage msg = new textmessage();
xmlutil.initcommonmsg(msg, map);
msg.setcontent(map.get("content"));
return msg;
}
if("imagemessage".equals(msgtype)){
imagemessage msg = new imagemessage();
xmlutil.initcommonmsg(msg, map);
msg.setpicurl(map.get("picurl"));
msg.setmediaid(map.get("mediaid"));
return msg;
}
if("video".equals(msgtype)){
videomessage msg = new videomessage();
xmlutil.initcommonmsg(msg, map);
msg.setmediaid(map.get("mediaid"));
msg.setthumbmediaid(map.get("thumbmediaid"));
return msg;
}
if("voice".equals(msgtype)){
voicemessage msg = new voicemessage();
xmlutil.initcommonmsg(msg, map);
msg.setmediaid(map.get("mediaid"));
msg.setformat(map.get("format"));
return msg;
}
if("location".equals(msgtype)){
locationmessage msg = new locationmessage();
msg.setlocation_x(map.get("location_x"));
msg.setlocation_y(map.get("location_y"));
msg.setscale(map.get("scale"));
msg.setlabel(map.get("label"));
return msg;
}
if("link".equals(msgtype)){
linkmessage msg = new linkmessage();
xmlutil.initcommonmsg(msg, map);
msg.settitle(map.get("title"));
msg.setdescription(map.get("description"));
msg.seturl(map.get("url"));
return msg;
}
}
return null;
}
/**
* 将保存xml内容的map转换成对象
* @param map
* @return
* @throws ioexception
*/
public static message getmessageobject(httpservletrequest request) throws ioexception
{
string xmldoc = xmlutil.readrequestcontent(request); // 读取微信客户端发了的消息(xml)
map<string, string> map = xmlutil.xmltomap(xmldoc); // 将客户端发来的xml转换成map
if(map != null){
string msgtype = map.get("msgtype");
// 消息类型(文本消息:text, 图片消息:image, 语音消息:voice, 视频消息:video,
// 地理位置消息:location, 链接消息:link)
if("text".equals(msgtype)){
textmessage msg = new textmessage();
xmlutil.initcommonmsg(msg, map);
msg.setcontent(map.get("content"));
return msg;
}
/*if("imagemessage".equals(msgtype)){
imagemessage msg = new imagemessage();
xmlutil.initcommonmsg(msg, map);
msg.setpicurl(map.get("picurl"));
msg.setmediaid(map.get("mediaid"));
return msg;
}
if("video".equals(msgtype)){
videomessage msg = new videomessage();
xmlutil.initcommonmsg(msg, map);
msg.setmediaid(map.get("mediaid"));
msg.setthumbmediaid(map.get("thumbmediaid"));
return msg;
}
if("voice".equals(msgtype)){
voicemessage msg = new voicemessage();
xmlutil.initcommonmsg(msg, map);
msg.setmediaid(map.get("mediaid"));
msg.setformat(map.get("format"));
return msg;
}
if("location".equals(msgtype)){
locationmessage msg = new locationmessage();
msg.setlocation_x(map.get("location_x"));
msg.setlocation_y(map.get("location_y"));
msg.setscale(map.get("scale"));
msg.setlabel(map.get("label"));
return msg;
}
if("link".equals(msgtype)){
linkmessage msg = new linkmessage();
xmlutil.initcommonmsg(msg, map);
msg.settitle(map.get("title"));
msg.setdescription(map.get("description"));
msg.seturl(map.get("url"));
return msg;
}*/
}
return null;
}
public static void initcommonmsg(message msg, map<string, string> map)
{
msg.setmsgid(map.get("msgid"));
msg.setmsgtype(map.get("msgtype"));
msg.settousername(map.get("tousername"));
msg.setfromusername(map.get("fromusername"));
msg.setcreatetime(map.get("createtime"));
}
}
粉丝发来的消息分为了6中类型(文本消息, 图片消息, 语音消息, 视频消息, 地理位置消息, 链接消息):
/**
* 微信消息基类
* @author yuanfang
* @date 2015-03-23
*/
public class message
{
private string msgid; // 消息id,64位整型
private string msgtype; // 消息类型(文本消息:text, 图片消息:image, 语音消息:voice, 视频消息:video, 地理位置消息:location, 链接消息:link)
private string tousername; //开发者微信号
private string fromusername; // 发送方帐号(一个openid)
private string createtime; // 消息创建时间 (整型)
public string gettousername() {
return tousername;
}
public void settousername(string tousername) {
tousername = tousername;
}
public string getfromusername() {
return fromusername;
}
public void setfromusername(string fromusername) {
fromusername = fromusername;
}
public string getcreatetime() {
return createtime;
}
public void setcreatetime(string createtime) {
createtime = createtime;
}
public string getmsgtype() {
return msgtype;
}
public void setmsgtype(string msgtype) {
msgtype = msgtype;
}
public string getmsgid() {
return msgid;
}
public void setmsgid(string msgid) {
msgid = msgid;
}
}
文本消息类:
package com.sinaapp.wx.msg;
public class textmessage extends message
{
private string content; // 文本消息内容
public string getcontent() {
return content;
}
public void setcontent(string content) {
content = content;
}
}
ok,对粉丝发送给我们公众号的任意的文本消息的最简单处理就完成,我们简单的回复他:你好,然后加上他微信的openid,类似于:你好,orjydljfkg3-r0_dj3rkdfvjl
更多微信开发之处理微信客户端发来的消息。