本文實例講述了java版微信公眾平臺消息接口應用方法。分享給大家供大家參考,具體如下:
微信公眾平臺現在推出自動回復消息接口,但是由于是接口內容用的是PHP語言寫的,很多地方操作起來讓本人這個對Java比較熟悉的小伙很別扭,所以仿照PHP的接口代碼做了一套jsp語言編寫的接口。
首先先把整個接口代碼貼出來做下比較,然后我們再分析代碼:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
<?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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
<% @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是這樣獲取
1
|
$postStr = $GLOBALS [ "HTTP_RAW_POST_DATA" ]; |
這時通過查詢一些資料知道這樣獲取的是無法通過$_GET或$_POST函數得到的”未識別 MIME 類型的數據“,原始的 POST 數據
所以這里使用獲取原始數據流的方式來解析post的xml數據
1
2
3
4
5
6
|
String postStr=null; try { postStr=this.readStreamParameter(final_request.getInputStream()); } catch (Exception e){ e.printStackTrace(); } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
//從輸入流讀取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的代碼寫法
1
2
|
echo "" ; exit ; |
猜想可能需要有個刷新的操作才能把消息response回去,于是找了下response內的一些函數做出以下嘗試
1
2
3
4
5
6
7
8
9
|
//向請求端發送返回數據 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程序設計有所幫助。