java微信开发第二步 获取消息和回复消息

网友投稿 300 2023-07-17


java微信开发第二步 获取消息和回复消息

接着上一篇java微信开发API第一步 服务器接入进行学习,下面介绍java微信开发第二步:获取消息和回复消息,具体内容如下

* 本示例根据微信开发文档:http://mp.weixin.qq.com/wiki/home/index.html最新版(4/3/2016 5:34:36 PM )进行开发演示。

* 编辑平台:myeclipse10.7+win32+jdk1.7+tomcat7.0 

* 服务器:阿里云 windows server 2008 64bits

* 平台要求:servlet使用注解方式,平台要求:j2ee6.0+、jdk6.0+、tomcat7.0+

* 演示更加注重于api解析。

* 为了便于测试说明,每个测试用例为独立,不依赖于其它方法。对于封装,不多加考虑。

* 演示尽可能按照API要求进行,目的:了解文档使用方式,达到举一反三的效果。

* 知识要求:牢固的java基础、了解http网络通信知识、对于javaweb有足够了解、json解析

* 在每篇文章结束会给出该部分演示源码。在分析完API之后,会以源码包的形式给出所有演示源码。

* 当前时间:4/3/2016 5:32:57 PM ,以该时间为准。

文档地址:http://mp.weixin.qq.com/wiki/17/f298879f8fb29ab98b2f2971d42552fd.html

消息管理

接收消息-接收普通消息

接收消息-接收事件推送

发送消息-被动回复消息

发送消息-被动回复时的加解密

发送消息-客服消息

发送消息-群发接口

发送消息-模板消息接口

发送消息-模板消息运营规范

二、文档理解

1、接收消息

文档这样解释:​当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。

理解:微信服务器将用户发送的消息通过Post流的形式返回给req。当我们想要获取用户发送的消息时,可以通过req.getInputStream()获取。当然,我们可以根据文档上关于消息的返回的xml格式,进行必要的解析。

实现:

/*

* 该部分我们获取用户发送的信息,并且解析成的形式进行显示

*/

// 解析用户发送过来的信息

InputStream is = req.getInputStream();// 拿取请求流

// 将解析结果存储在HashMap中

Map map = new HashMap();

// 解析xml,将获取到的返回结果xml进行解析成我们习惯的文字信息

SAXReader reader = new SAXReader();// 第三方jar:dom4j【百度:saxreader解析xml】

Document document = null;

try {

document = reader.read(is);

} catch (DocumentException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

// 得到xml根元素

Element root = document.getRootElement();

// 得到根元素的所有子节点

Listhttp:// elementList = root.elements();

// 遍历所有子节点

for (Element e : elementList)

map.put(e.getName(), e.getText());

// 测试输出

Set keySet = map.keySet();

// 测试输出解析后用户发过来的信息

System.out.println(TAG + ":解析用户发送过来的信息开始");

for (String key : keySet) {

System.out.println(key + ":" + map.get(key));

}

System.out.println(TAG + ":解析用户发送过来的信息结束");

2、发送消息

理解:用户发送请求,会产生一个POST请求,我们可以通过Respone进行回复消息。但是,回复的内容有严格的格式要求,只有满足格式要求,微信服务器才会进行处理返回给用户。通过查看文档“消息管理”模块,我们可以看到微信中有各种各样的消息,每类消息都有自己特定的格式要求,我们必须按照要求才可以正常的给用户返回特定的信息。我们尝试按照文档的要求格式给用户回复文本信息、图文消息。重点:按照文档要求构造需要的参数。特别注意:参数区分大小写。

1)、实现1-回复普通文本消息:

//实例1:发送普通文本消息,请查看文档关于“回复文本消息”的xml格式

// 第一步:按照回复文本信息构造需要的参数

TextMsg textMsg = new TextMsg();

textMsg.setToUserName(map.get("FromUserName"));// 发送和接收信息“User”刚好相反

textMsg.setFromUserName(map.get("ToUserName"));

textMsg.setCreateTime(new Date().getTime());// 消息创建时间 (整型)

textMsg.setMsgType("text");// 文本类型消息

textMsg.setContent("我是服务器回复给用户的信息");

// // 第二步,将构造的信息转化为微信识别的xml格式【百度:xstream bean转xml】

XStream xStream = new XStream();

xStream.alias("xml", textMsg.getClass());

String textMsg2Xml = xStream.toXML(textMsg);

System.out.println(textMsg2Xml);

// // 第三步,发送xml的格式信息给微信服务器,服务器转发给用户

PrintWriter printWriter = resp.getWriter();

printWriter.print(textMsg2Xml);

2)、实现2-回复图文消息:

//实例2,发送图文消息。请查看文档关于“回复图文消息”的xml格式

// 第一步:按照回复图文信息构造需要的参数

List

articles = new ArrayList
();

Article a = new Article();

a.setTitle("我是图片标题");

a.setUrl("baidu.com");// 该地址是点击图片跳转后

a.setPicUrl("http://b.hiphotos.baidu.com/image/pic/item/08f790529822720ea5d058ba7ccb0a46f21fab50.jpg");// 该地址是一个有效的图片地址

a.setDescription("我是图片的描述");

articles.add(a);

PicAndTextMsg picAndTextMsg = new PicAndTextMsg();

picAndTextMsg.setToUserName(map.get("FromUserName"));// 发送和接收信息“User”刚好相反

picAndTextMsg.setFromUserName(map.get("ToUserName"));

picAndTextMsg.setCreateTime(new Date().getTime());// 消息创建时间 (整型)

picAndTextMsg.setMsgType("news");// 图文类型消息

picAndTextMsg.setArticleCount(1);

picAndTextMsg.setArticles(articles);

// 第二步,将构造的信息转化为微信识别的xml格式【百度:xstream bean转xml】

XStream xStream = new XStream();

xStream.alias("xml", picAndTextMsg.getClass());

xStream.alias("item", a.getClass());

String picAndTextMsg2Xml = xStream.toXML(picAndTextMsg);

System.out.println(picAndTextMsg2Xml);

// 第三步,发送xml的格式信息给微信服务器,服务器转发给用户

PrintWriter printWriter = resp.getWriter();

printWriter.print(picAndTextMsg2Xml);

该部分所有操作源码,可以直接使用

CoreServlet.java(包括服务器接入、接收用户发送消息、回复普通文字消息、回复图文消息。需要第三方jar:dom4j、xstream)

package com.gist.servlet;

import java.io.IOException;

import java.io.InputStream;

import java.io.PrintWriter;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Date;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.Set;

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 org.dom4j.Document;

import org.dom4j.DocumentException;

import org.dom4j.Element;

import org.dom4j.io.SAXReader;

import com.gist.bean.Article;

import com.gist.bean.PicAndTextMsg;

import com.thoughtworks.xstream.XStream;

/**

* @author 高远 邮箱:wgyscsf@163.com 博客 http://blog.csdn.net/wgyscsf

* 编写时期 2016-4-3 下午4:34:05

*/

@WebServlet("/CoreServlet")

public class CoreServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

String TAG = "CoreServlet";

/*

* 第二步:验证服务器地址的有效性 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,

* GET请求携带四个参数:signature、timestamp、nonce、echostr

* 开发者通过检验signature对请求进行校验(下面有校验方式)。 若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,

* 则接入生效, 成为开发者成功,否则接入失败。

*

* 加密/校验流程如下: 1. 将token、timestamp、nonce三个参数进行字典序排序 2.

* 将三个参数字符串拼接成一个字符串进行sha1加密 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

*/

/*

* 字典排序(lexicographical

* order)是一种对于随机变量形成序列的排序方法。其方法是,按照字母顺序,或者数字小大顺序,由小到大的形成序列。

*/

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp)

throws ServletException, IOException {

// 设置编码

req.setCharacterEncoding("utf-8");

resp.setContentType("html/text;charset=utf-8");

resp.setCharacterEncoding("utf-8");

// 获取输出流

PrintWriter printWriter = resp.getWriter();

// 设置一个全局的token,开发者自己设置。api这样解释:Token可由开发者可以任意填写,

// 用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)

String token = "wgyscsf";

// 根据api说明,获取上述四个参数

String signature = req.getParameter("signature");

String timestamp = req.getParameter("timestamp");

String nonce = req.getParameter("nonce");

String echostr = req.getParameter("echostr");

// // temp:临时打印,观看返回参数情况

// System.out.println(TAG + ":signature:" + signature + ",timestamp:"

// + timestamp + ",nonce:" + nonce + ",echostr:" + echostr);

// 根据api所说的“加密/校验流程”进行接入。共计三步

// 第一步:将token、timestamp、nonce三个参数进行字典序排序

String[] parms = new String[] { token, timestamp, nonce };// 将需要字典序排列的字符串放到数组中

Arrays.sort(parms);// 按照api要求进行字典序排序

// 第二步:将三个参数字符串拼接成一个字符串进行sha1加密

// 拼接字符串

String parmsString = "";// 注意,此处不能=null。

for (int i = 0; i < parms.length; i++) {

parmsString += parms[i];

}

// sha1加密

String mParms = null;// 加密后的结果

MessageDigest digest = null;

try {

digest = java.security.MessageDigest.getInstance("SHA");

} catch (NoSuchAlgorithmException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

digest.update(parmsString.getBytes());

byte messageDigest[] = digest.digest();

// Create Hex String

StringBuffer hexString = new StringBuffer();

// 字节数组转换为 十六进制 数

for (int i = 0; i < messageDigest.length; i++) {

String shaHex = Integer.toHexString(messageKCHOgPNyYBDigest[i] & 0xFF);

if (shaHex.length() < 2) {

hexString.append(0);

}

hexString.append(shaHex);

}

mParms = hexString.toString();// 加密结果

/*

* api要求: 若确认此次GET请求来自微信服务器,请原样返回echostr参数内容, 则接入生效, 成为开发者成功,否则接入失败。

*/

// 第三步: 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信接入成功。

// System.out.println(TAG + ":" + mParms + "---->" + signature);

if (mParms.equals(signature)) {

// System.out.println(TAG + ":" + mParms + "---->" + signature);

printWriter.write(echostr);

} else {

// 接入失败,不用回写

// System.out.println(TAG + "接入失败");

}

}

/*

* 查看api文档关于收发消息推送的消息格式基本一致。 如以下格式:

* <![CDATA[toUser]]>

* <![CDATA[fromUser]]>

* 1348831860 <![CDATA[text]]>

* <![CDATA[this is a test]]>

* 1234567890123456 那么,我们就可以进行统一处理。

*/

/*

* 我们先获取输入流,看输入流里面的信息。通过测试打印输出流,我们可以看到每次用户请求,都会收到req请求,请求格式是xml格式,该信息在文档中有说明。

*/

/*

* 特别注意,req.getInputStream()只能获取一次,并且只能读取一次。如果想要多次读取,需要另外想办法。为了简单起见,

* 我们只获取一次req.getInputStream(),不再打印输出流信息。直接打印解析后的信息。

*/

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp)

throws ServletException, IOException {

// 设置编码

req.setCharacterEncoding("utf-8");

resp.setContentType("html/text;charset=utf-8");

resp.setCharacterEncoding("utf-8");

/*

* 该部分我们获取用户发送的信息,并且解析成的形式进行显示

*/

// 解析用户发送过来的信息

InputStream is = req.getInputStream();// 拿取请求流

// 将解析结果存储在HashMap中

Map map = new HashMap();

// 解析xml,将获取到的返回结果xml进行解析成我们习惯的文字信息

SAXReader reader = new SAXReader();// 第三方jar:dom4j【百度:saxreader解析xml】

Document document = null;

try {

document = reader.read(is);

} catch (DocumentException e1) {

// TODO Auto-generated catch block

e1.printStackTrace();

}

// 得到xml根元素

Element root = document.getRootElement();

// 得到根元素的所有子节点

List elementList = root.elements();

// 遍历所有子节点

for (Element e : elementList)

map.put(e.getName(), e.getText());

// 测试输出

Set keySet = map.keySet();

// 测试输出解析后用户发过来的信息

System.out.println(TAG + ":解析用户发送过来的信息开始");

for (String key : keySet) {

System.out.println(key + ":" + map.get(key));

}

System.out.println(TAG + ":解析用户发送过来的信息结束");

/*

* 该部分我们尝试按照文档的要求格式给用户回复文本信息、图文消息。重点:按照文档要求构造需要的参数。特别注意:参数区分大小写。

*/

// //实例1:发送普通文本消息,请查看文档关于“回复文本消息”的xml格式

//

// // 第一步:按照回复文本信息构造需要的参数

// TextMsg textMsg = new TextMsg();

// textMsg.setToUserName(map.get("FromUserName"));// 发送和接收信息“User”刚好相反

// textMsg.setFromUserName(map.get("ToUserName"));

// textMsg.setCreateTime(new Date().getTime());// 消息创建时间 (整型)

// textMsg.setMsgType("text");// 文本类型消息

// textMsg.setContent("我是服务器回复给用户的信息");

//

// // // 第二步,将构造的信息转化为微信识别的xml格式【百度:xstream bean转xml】

// XStream xStream = new XStream();

// xStream.alias("xml", textMsg.getClass());

// String textMsg2Xml = xStream.toXML(textMsg);

// System.out.println(textMsg2Xml);

//

// // // 第三步,发送xml的格式信息给微信服务器,服务器转发给用户

// PrintWriter printWriter = resp.getWriter();

// printWriter.print(textMsg2Xml);

// //实例2,发送图文消息。请查看文档关于“回复图文消息”的xml格式

// 第一步:按照回复图文信息构造需要的参数

List

articles = new ArrayList
();

Article a = new Article();

a.setTitle("我是图片标题");

a.setUrl("baidu.com");// 该地址是点击图片跳转后

a.setPicUrl("http://b.hiphotos.baidu.com/image/pic/item/08f790529822720ea5d058ba7ccb0a46f21fab50.jpg");// 该地址是一个有效的图片地址

a.setDescription("我是图片的描述");

articles.add(a);

PicAndTextMsg picAndTextMsg = new PicAndTextMsg();

picAndTextMsg.setToUserName(map.get("FromUserName"));// 发送和接收信息“User”刚好相反

picAndTextMsg.setFromUserName(map.get("ToUserName"));

picAndTextMsg.setCreateTime(new Date().getTime());// 消息创建时间 (整型)

picAndTextMsg.setMsgType("news");// 图文类型消息

picAndTextMsg.setArticleCount(1);

picAndTextMsg.setArticles(articles);

// 第二步,将构造的信息转化为微信识别的xml格式【百度:xstream bean转xml】

XStream xStream = new XStream();

xStream.alias("xml", picAndTextMsg.getClass());

xStream.alias("item", a.getClass());

String picAndTextMsg2Xml = xStream.toXML(picAndTextMsg);

System.out.println(picAndTextMsg2Xml);

// 第三步,发送xml的格式信息给微信服务器,服务器转发给用户

PrintWriter printWriter = resp.getWriter();

printWriter.print(picAndTextMsg2Xml);

}

}

TestMsg.java(普通文字消息bean)

package com.gist.bean;

/**

* @author 高远 邮箱:wgyscsf@163.com 博客 http://blog.csdn.net/wgyscsf

* 编写时期 2016-4-4 下午2:09:27

*/

public class TextMsg {

private String ToUserName;

private String FromUserName;

private long CreateTime;

private String MsgType;

@Override

public String toString() {

return "TextMsg [ToUserName=" + ToUserName + ", FromUserName="

+ FromUserName + ", CreateTime=" + CreateTime + ", MsgType="

+ MsgType + ", Content=" + Content + "]";

}

private String Content;

public TextMsg(String toUserName, String fromUserName, long createTime,

String msgType, String content) {

super();

ToUserName = toUserName;

FromUserName = fromUserName;

CreateTime = createTime;

MsgType = msgType;

Content = content;

}

public TextMsg() {

super();

}

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 long getCreateTime() {

return CreateTime;

}

public void setCreateTime(long createTime) {

CreateTime = createTime;

}

public String getMsgType() {

return MsgType;

}

public void setMsgType(String msgType) {

MsgType = msgType;

}

public String getContent() {

return Content;

}

public void setContent(String content) {

Content = content;

}

}

Article.java(图文消息内部Article bean)

package com.gist.bean;

/**

* @author 高远 邮箱:wgyscsf@163.com 博客 http://blog.csdn.net/wgyscsf

* 编写时期 2016-4-4 下午2:47:08

*/

public class Article {

private String Title;

@Override

public String toString() {

return "item [Title=" + Title + ", Description=" + Description

+ ", PicUrl=" + PicUrl + ", Url=" + Url + "]";

}

public String getTitle() {

return Title;

}

public void setTitle(String title) {

Title = title;

}

public String getDescription() {

return Description;

}

public void setDescription(String description) {

Description = description;

}

public String getPicUrl() {

return PicUrl;

}

public void setPicUrl(String picUrl) {

PicUrl = picUrl;

}

public String getUrl() {

return Url;

}

public void setUrl(String url) {

Url = url;

}

private String Description;

private String PicUrl;

private String Url;

}

PicAndTextMsg.java(图文消息 bean)

package com.gist.bean;

import java.util.List;

/**

* @author 高远 邮箱:wgyscsf@163.com 博客 http://blog.csdn.net/wgyscsf

* 编写时期 2016-4-4 下午2:47:08

*/

public class PicAndTextMsg {

private String ToUserName;

private String FromUserName;

private long CreateTime;

private String MsgType;

private int ArticleCount;

private List

Articles;

@Override

public String toString() {

return "PicAndTextMsg [ToUserName=" + ToUserName + ", FromUserName="

+ FromUserName + ", CreateTime=" + CKCHOgPNyYBreateTime + ", MsgType="

+ MsgType + ", ArticleCount=" + ArticleCount + ", Articles="

+ Articles + "]";

}

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 long getCreateTime() {

return CreateTime;

}

public void setCreateTime(long createTime) {

CreateTime = createTime;

}

public String getMsgType() {

return MsgType;

}

public void setMsgType(String msgType) {

MsgType = msgType;

}

public int getArticleCount() {

return ArticleCount;

}

public void setArticleCount(int articleCount) {

ArticleCount = articleCount;

}

public List

getArticles() {

return Articles;

}

public void setArticles(List

articles) {

Articles = articles;

}

}

更多精彩内容请点击《android微信开发教程汇总》,《java微信开发教程汇总》欢迎大家学习阅读。

以上就是本文的全部内容,希望对大家学习开java微信API有所帮助,也希望大家继续关注新内容的更新,不要错过哦!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java Web开发项目中中文乱码解决方法汇总
下一篇:Java struts2 validate用户登录校验功能实现
相关文章

 发表评论

暂时没有评论,来抢沙发吧~