java版微信公众平台消息接口应用示例
本文实例讲述了java版微信公众平台消息接口应用方法。分享给大家供大家参考,具体如下:
微信公众平台现在推出自动回复消息接口,但是由于是接口内容用的是php语言写的,很多地方操作起来让本人这个对java比较熟悉的小伙很别扭,所以仿照php的接口代码做了一套jsp语言编写的接口。
首先先把整个接口代码贴出来做下比较,然后我们再分析代码:
php:
<?php /** * wechat php test */ //define your token define("token", "weixin"); $wechatobj = new wechatcallbackapitest(); $wechatobj->valid(); class wechatcallbackapitest { public function valid() { $echostr = $_get["echostr"]; //valid signature , option if($this->checksignature()){ echo $echostr; exit; } } public function responsemsg() { //get post data, may be due to the different environments $poststr = $globals["http_raw_post_data"]; //extract post data if (!empty($poststr)){ $postobj = simplexml_load_string($poststr, 'simplexmlelement', libxml_nocdata); $fromusername = $postobj->fromusername; $tousername = $postobj->tousername; $keyword = trim($postobj->content); $time = time(); $texttpl = "<xml> <tousername><![cdata[%s]]></tousername> <fromusername><![cdata[%s]]></fromusername> <createtime>%s</createtime> <msgtype><![cdata[%s]]></msgtype> <content><![cdata[%s]]></content> <funcflag>0</funcflag> </xml>"; if(!empty( $keyword )) { $msgtype = "text"; $contentstr = "welcome to wechat world!"; $resultstr = sprintf($texttpl, $fromusername, $tousername, $time, $msgtype, $contentstr); echo $resultstr; }else{ echo "input something..."; } }else { echo ""; exit; } } private function checksignature() { $signature = $_get["signature"]; $timestamp = $_get["timestamp"]; $nonce = $_get["nonce"]; $token = token; $tmparr = array($token, $timestamp, $nonce); sort($tmparr); $tmpstr = implode( $tmparr ); $tmpstr = sha1( $tmpstr ); if( $tmpstr == $signature ){ return true; }else{ return false; } } } ?>
java:
<%@page import="java.util.date"%> <%@page import="org.dom4j.element"%> <%@page import="org.dom4j.documenthelper"%> <%@page import="org.dom4j.document"%> <%@page import="java.io.ioexception"%> <%@page import="java.io.inputstreamreader"%> <%@page import="java.io.bufferedreader"%> <%@page import="java.io.reader"%> <%@page import="java.security.messagedigest"%> <%@page import="java.util.arrays"%> <%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <% //weixinhandler为内部类不能使用非final类型的对象 final string token="weixin"; final httpservletrequest final_request=request; final httpservletresponse final_response=response; %> <% class weixinhandler{ public void valid(){ string echostr=final_request.getparameter("echostr"); if(null==echostr||echostr.isempty()){ responsemsg(); }else{ if(this.checksignature()){ this.print(echostr); }else{ this.print("error"); } } } //自动回复内容 public void responsemsg(){ string poststr=null; try{ poststr=this.readstreamparameter(final_request.getinputstream()); }catch(exception e){ e.printstacktrace(); } //system.out.println(poststr); if (null!=poststr&&!poststr.isempty()){ document document=null; try{ document = documenthelper.parsetext(poststr); }catch(exception e){ e.printstacktrace(); } if(null==document){ this.print(""); return; } element root=document.getrootelement(); string fromusername = root.elementtext("fromusername"); string tousername = root.elementtext("tousername"); string keyword = root.elementtexttrim("content"); string time = new date().gettime()+""; string texttpl = "<xml>"+ "<tousername><![cdata[%1$s]]></tousername>"+ "<fromusername><![cdata[%2$s]]></fromusername>"+ "<createtime>%3$s</createtime>"+ "<msgtype><![cdata[%4$s]]></msgtype>"+ "<content><![cdata[%5$s]]></content>"+ "<funcflag>0</funcflag>"+ "</xml>"; if(null!=keyword&&!keyword.equals("")) { string msgtype = "text"; string contentstr = "welcome to wechat world!"; string resultstr = texttpl.format(texttpl, fromusername, tousername, time, msgtype, contentstr); this.print(resultstr); }else{ this.print("input something..."); } }else { this.print(""); } } //微信接口验证 public boolean checksignature(){ string signature = final_request.getparameter("signature"); string timestamp = final_request.getparameter("timestamp"); string nonce = final_request.getparameter("nonce"); string token=token; string[] tmparr={token,timestamp,nonce}; arrays.sort(tmparr); string tmpstr=this.arraytostring(tmparr); tmpstr=this.sha1encode(tmpstr); if(tmpstr.equalsignorecase(signature)){ return true; }else{ return false; } } //向请求端发送返回数据 public void print(string content){ try{ final_response.getwriter().print(content); final_response.getwriter().flush(); final_response.getwriter().close(); }catch(exception e){ } } //数组转字符串 public string arraytostring(string [] arr){ stringbuffer bf = new stringbuffer(); for(int i = 0; i < arr.length; i++){ bf.append(arr[i]); } return bf.tostring(); } //sha1加密 public string sha1encode(string sourcestring) { string resultstring = null; try { resultstring = new string(sourcestring); messagedigest md = messagedigest.getinstance("sha-1"); resultstring = byte2hexstring(md.digest(resultstring.getbytes())); } catch (exception ex) { } return resultstring; } public final string byte2hexstring(byte[] bytes) { stringbuffer buf = new stringbuffer(bytes.length * 2); for (int i = 0; i < bytes.length; i++) { if (((int) bytes[i] & 0xff) < 0x10) { buf.append("0"); } buf.append(long.tostring((int) bytes[i] & 0xff, 16)); } return buf.tostring().touppercase(); } //从输入流读取post参数 public string readstreamparameter(servletinputstream in){ stringbuilder buffer = new stringbuilder(); bufferedreader reader=null; try{ reader = new bufferedreader(new inputstreamreader(in)); string line=null; while((line = reader.readline())!=null){ buffer.append(line); } }catch(exception e){ e.printstacktrace(); }finally{ if(null!=reader){ try { reader.close(); } catch (ioexception e) { e.printstacktrace(); } } } return buffer.tostring(); } } %> <% weixinhandler handler=new weixinhandler(); handler.valid(); %>
以上就是php接口和jsp接口的所有代码,现在我们来对一些需要注意的地方做下分析:
首先的从总体看的话,jsp要比php繁琐一些,因为很多函数需要自己写,像sha1加密,解析xml字符串等都需要自己找第三方的库。
第一点,我们要获取微信公众平台给jsp发送的post或get参数,正常情况下都是用request.getparameter就可以获取到,但是在写的过程中发现php是这样获取
$poststr = $globals["http_raw_post_data"];
这时通过查询一些资料知道这样获取的是无法通过$_get或$_post函数得到的”未识别 mime 类型的数据“,原始的 post 数据
(参考:)
所以这里使用获取原始数据流的方式来解析post的xml数据
string poststr=null; try{ poststr=this.readstreamparameter(final_request.getinputstream()); }catch(exception e){ e.printstacktrace(); }
//从输入流读取post参数 public string readstreamparameter(servletinputstream in){ stringbuilder buffer = new stringbuilder(); bufferedreader reader=null; try{ reader = new bufferedreader(new inputstreamreader(in)); string line=null; while((line = reader.readline())!=null){ buffer.append(line); } }catch(exception e){ e.printstacktrace(); }finally{ if(null!=reader){ try { reader.close(); } catch (ioexception e) { e.printstacktrace(); } } } return buffer.tostring(); }
第二个,是response消息返回给微信平台,我尝试的用最一般的out.print去做,但是发现没反应,观察php的代码写法
echo ""; exit;
猜想可能需要有个刷新的操作才能把消息response回去,于是找了下response内的一些函数做出以下尝试
//向请求端发送返回数据 public void print(string content){ try{ final_response.getwriter().print(content); final_response.getwriter().flush(); final_response.getwriter().close(); }catch(exception e){ } }
发现以上做法是可以在微信发送端得到消息的;
第三个,接口描述上说目前只支持80端口的服务端地址,所以我这里的做法是用apache服务器路由到tomcat的jsp上
关于微信公众平台的消息接口的详细介绍,可以参看微信公众平台的官方文档,里面介绍了消息的xml的格式和消息的发送方式等。
更多关于java算法相关内容感兴趣的读者可查看本站专题:《java字符与字符串操作技巧总结》、《java数组操作技巧总结》、《java数学运算技巧总结》、《java编码操作技巧总结》和《java数据结构与算法教程》
希望本文所述对大家java程序设计有所帮助。