这篇文章一起看看微信开发的消息接口
感觉微信开发就是要调用微信的接口,所以在没安排工作的时候看和试着调用微信接口,调用微信接口需要发送http的get和post请求,所以最好先写个httputil类,专门发送get和post请求,然而我的java网络编程学的并不好,于是百度一些代码,然后自己封装一些,可以正常使用就行了,代码如下
import java.io.bufferedreader;
import java.io.datainputstream;
import java.io.dataoutputstream;
import java.io.file;
import java.io.fileinputstream;
import java.io.ioexception;
import java.io.inputstream;
import java.io.inputstreamreader;
import java.io.outputstream;
import java.io.printwriter;
import java.net.httpurlconnection;
import java.net.url;
import java.net.urlconnection;
import java.util.iterator;
import java.util.map;
import javax.activation.mimetypesfiletypemap;
/**
*
* @author luolei
*
*/
public class httputil {
public static string httpget(string httpurl){
stringbuffer buffer = null;
try{
url url = new url(httpurl);
httpurlconnection httpurlconn = (httpurlconnection) url.openconnection();
httpurlconn.setdoinput(true);
httpurlconn.setrequestmethod("get");
// 获取输入流
inputstream inputstream = httpurlconn.getinputstream();
inputstreamreader inputstreamreader = new inputstreamreader(inputstream, "utf-8");
bufferedreader bufferedreader = new bufferedreader(inputstreamreader);
// 读取返回结果
buffer = new stringbuffer();
string str = null;
while ((str = bufferedreader.readline()) != null) {
buffer.append(str);
}
// 释放资源
bufferedreader.close();
inputstreamreader.close();
inputstream.close();
httpurlconn.disconnect();
}catch(exception e){
e.printstacktrace();
}
return buffer.tostring();
}
/**
*
* 发 post 请求,
*/
public static string httppost(string httpurl,string data){
printwriter out = null;
bufferedreader in = null;
string result = "";
try {
url realurl = new url(httpurl);
// 打开和url之间的连接
urlconnection conn = realurl.openconnection();
// 设置通用的请求属性
conn.setrequestproperty("accept", "*/*");
conn.setrequestproperty("connection", "keep-alive");
conn.setrequestproperty("user-agent",
"mozilla/4.0 (compatible; msie 6.0; windows nt 5.1;sv1)");
// 发送post请求必须设置如下两行
conn.setdooutput(true);
conn.setdoinput(true);
// 获取urlconnection对象对应的输出流
out = new printwriter(conn.getoutputstream());
// 发送请求参数
out.print(data);
// flush输出流的缓冲
out.flush();
// 定义bufferedreader输入流来读取url的响应
in = new bufferedreader(
new inputstreamreader(conn.getinputstream()));
string line;
while ((line = in.readline()) != null) {
result += line;
}
} catch (exception e) {
system.out.println("发送 post 请求出现异常!"+e);
e.printstacktrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(ioexception ex){
ex.printstacktrace();
}
}
return result;
}
/**
* 上传图片
*
* @param urlstr
* @param textmap
* @param filemap
* @return
*/
public static string formupload(string urlstr, map<string, string> textmap,
map<string, string> filemap) {
string res = "";
httpurlconnection conn = null;
string boundary = "---------------------------123821742118716"; //boundary就是request头和上传文件内容的分隔符
try {
url url = new url(urlstr);
conn = (httpurlconnection) url.openconnection();
// system.out.println(conn);
conn.setconnecttimeout(5000);
conn.setreadtimeout(30000);
conn.setdooutput(true);
conn.setdoinput(true);
conn.setusecaches(false);
conn.setrequestmethod("post");
conn.setrequestproperty("connection", "keep-alive");
conn
.setrequestproperty("user-agent",
"mozilla/5.0 (windows; u; windows nt 6.1; zh-cn; rv:1.9.2.6)");
conn.setrequestproperty("content-type",
"multipart/form-data; boundary=" + boundary);
outputstream out = new dataoutputstream(conn.getoutputstream());
// text
if (textmap != null) {
stringbuffer strbuf = new stringbuffer();
iterator iter = textmap.entryset().iterator();
while (iter.hasnext()) {
map.entry entry = (map.entry) iter.next();
string inputname = (string) entry.getkey();
string inputvalue = (string) entry.getvalue();
if (inputvalue == null) {
continue;
}
strbuf.append("\r\n").append("--").append(boundary).append(
"\r\n");
strbuf.append("content-disposition: form-data; name=\""
+ inputname + "\"\r\n\r\n");
strbuf.append(inputvalue);
}
out.write(strbuf.tostring().getbytes());
}
// file
if (filemap != null) {
iterator iter = filemap.entryset().iterator();
while (iter.hasnext()) {
map.entry entry = (map.entry) iter.next();
string inputname = (string) entry.getkey();
string inputvalue = (string) entry.getvalue();
if (inputvalue == null) {
continue;
}
file file = new file(inputvalue);
string filename = file.getname();
string contenttype = new mimetypesfiletypemap()
.getcontenttype(file);
if (filename.endswith(".png")) {
contenttype = "image/png";
}
if (contenttype == null || contenttype.equals("")) {
contenttype = "application/octet-stream";
}
stringbuffer strbuf = new stringbuffer();
strbuf.append("\r\n").append("--").append(boundary).append(
"\r\n");
strbuf.append("content-disposition: form-data; name=\""
+ inputname + "\"; filename=\"" + filename
+ "\"\r\n");
strbuf.append("content-type:" + contenttype + "\r\n\r\n");
out.write(strbuf.tostring().getbytes());
datainputstream in = new datainputstream(
new fileinputstream(file));
int bytes = 0;
byte[] bufferout = new byte[1024];
while ((bytes = in.read(bufferout)) != -1) {
out.write(bufferout, 0, bytes);
}
in.close();
}
}
byte[] enddata = ("\r\n--" + boundary + "--\r\n").getbytes();
out.write(enddata);
out.flush();
out.close();
// 读取返回数据
stringbuffer strbuf = new stringbuffer();
bufferedreader reader = new bufferedreader(new inputstreamreader(
conn.getinputstream()));
string line = null;
while ((line = reader.readline()) != null) {
strbuf.append(line).append("\n");
}
res = strbuf.tostring();
reader.close();
reader = null;
} catch (exception e) {
system.out.println("发送post请求出错。" + urlstr);
e.printstacktrace();
} finally {
if (conn != null) {
conn.disconnect();
conn = null;
}
}
return res;
}
}
其中的httpget 和httppost 用来发送get,和post请求,微信开发里面,消息接口一般是xml格式的,其他的接口上传和返回的数据一般是json,所以需要一个解析json的包,我用的是fastjson,当然也可以用gson
现在开始消息接口的测试,首先要了解请求过程:
微信服务器会根据填写的url发送get请求进行验证,当验证成功,还是根据url发送post请求,消息格式为xml格式
消息类型开发文档上有,主要有文本,图片,语音等消息,还有一些事件,如关注,点击,和跳转。
这些消息和事件是xml格式,所以要对xml格式的消息进行解析,我用的dom4j解析,
在之前验证接入的servlet的dopost方法解析消息,
我是按照柳峰的博客里面写的方法,写了个messageutil,里面封装了解析xml的方法,并把解析出来的结果放在map<string,string>中,具体代码如下:
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;
}
那么经过解析后的xml会按照 标签名 - 内容 保存在map中
然后可以从中取出消息类型msgtype
string msgtype = requestmap.get("msgtype");
然后判断消息的类型,不同的消息类型,让不同的servlet去处理,
// 文本消息
if (msgtype.equals(messageutil.req_message_type_text)) {
request.getrequestdispatcher("textmessage").forward(request, response);
}
// 图片消息
else if (msgtype.equals(messageutil.req_message_type_image)) {
request.getrequestdispatcher("imageservlet").forward(request, response);
}
// 地理位置消息
else if (msgtype.equals(messageutil.req_message_type_location)) {
request.getrequestdispatcher("locationservlet").forward(request, response);
}
// 链接消息
else if (msgtype.equals(messageutil.req_message_type_link)) {
request.getrequestdispatcher("linkservlet").forward(request, response);
}
// 音频消息
else if (msgtype.equals(messageutil.req_message_type_voice)) {
request.getrequestdispatcher("vedioservlet").forward(request, response);
}
// 事件推送
else if (msgtype.equals(messageutil.req_message_type_event)) {
// 事件类型
string eventtype = requestmap.get("event");
// 订阅
if (eventtype.equals(messageutil.event_type_subscribe)) {
request.getrequestdispatcher("subservlet").forward(request, response);
}
// 取消订阅
else if (eventtype.equals(messageutil.event_type_unsubscribe)) {
// todo 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息
}
// 自定义菜单点击事件
else if (eventtype.equals(messageutil.event_type_click)) {
// todo 自定义菜单权没有开放,暂不处理该类消息
request.getrequestdispatcher("clickservlet").forward(request, response);
}
}
不同的servlet里面处理不同的消息,可以根据需要返回不同的消息,返回消息的格式也是xml格式的,返回消息类型跟接受的消息类型基本类似,可以对这些返回的消息进行封装,每个xml标签对应字段名,内容就是字段的内容
例子:
public class basemessageresp {
// 接收方帐号(收到的openid)
private string tousername;
// 开发者微信号
private string fromusername;
// 消息创建时间 (整型)
private long createtime;
// 消息类型(text/music/news)
private string msgtype;
// 位0x0001被标志时,星标刚收到的消息
private int funcflag;
省略了set,get方法
public class textmessage extends basemessageresp {
// 回复的消息内容
private string content;
public string getcontent() {
return content;
}
public void setcontent(string content) {
content = content;
}
}
因为不同的消息有相同的字段,因此写了通用的基类。
现在离返回消息给用户还差一步,技术将这些pojo类转化为xml字符串
用的是xstream
/**
* 文本消息对象转换成xml
*
* @param textmessage 文本消息对象
* @return xml
*/
public static string textmessagetoxml(textmessage textmessage) {
xstream.alias("xml", textmessage.getclass());
return xstream.toxml(textmessage);
}
这里只是简单的描述,具体的可以以看柳峰的博客,链接我忘记了,应该可以百度的到
最后将得到的string 返回给微信服务器就可以回复用户了。
只用这些消息接口就可以写一个简单的订阅号了,应该,一般公司的公众号好像是通过view类型的button跳到自己的网站里面去。
现在用上面的接口可以接受用户发送的各种消息,然后提前消息,可以自己进行处理,或者调用一些api,如天气,笑话,文章等api,得到结果,解析后,按照自己希望的格式返回给用户,可以实习一个生活助手之类的订阅号,但是个人申请的订阅号的权限有限,不知道能不能够胜任。
以上就是微信开发的消息接口的详细内容。