zoukankan      html  css  js  c++  java
  • jsp 微信公众平台 token验证(php、jsp)(转载)

    微信公众平台现在推出自动回复消息接口,但是由于是接口内容用的是PHP语言写的,很多地方操作起来让本人这个对java比较熟悉的小伙很别扭,所以仿照PHP的接口代码做了一套jsp语言编写的接口。

    首先先把整个接口代码贴出来做下比较,然后我们再分析代码:

    PHP:

    [php] view plain copy
     
    1. <?php  
    2. /** 
    3.   * wechat php test 
    4.   */  
    5.   
    6. //define your token  
    7. define("TOKEN", "weixin");  
    8. $wechatObj = new wechatCallbackapiTest();  
    9. $wechatObj->valid();  
    10.   
    11. class wechatCallbackapiTest  
    12. {  
    13.     public function valid()  
    14.     {  
    15.         $echoStr = $_GET["echostr"];  
    16.   
    17.         //valid signature , option  
    18.         if($this->checkSignature()){  
    19.             echo $echoStr;  
    20.             exit;  
    21.         }  
    22.     }  
    23.   
    24.     public function responseMsg()  
    25.     {  
    26.         //get post data, May be due to the different environments  
    27.         $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];  
    28.   
    29.         //extract post data  
    30.         if (!empty($postStr)){  
    31.                   
    32.                 $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);  
    33.                 $fromUsername = $postObj->FromUserName;  
    34.                 $toUsername = $postObj->ToUserName;  
    35.                 $keyword = trim($postObj->Content);  
    36.                 $time = time();  
    37.                 $textTpl = "<xml>  
    38.                             <ToUserName><![CDATA[%s]]></ToUserName>  
    39.                             <FromUserName><![CDATA[%s]]></FromUserName>  
    40.                             <CreateTime>%s</CreateTime>  
    41.                             <MsgType><![CDATA[%s]]></MsgType>  
    42.                             <Content><![CDATA[%s]]></Content>  
    43.                             <FuncFlag>0</FuncFlag>  
    44.                             </xml>";               
    45.                 if(!empty( $keyword ))  
    46.                 {  
    47.                     $msgType = "text";  
    48.                     $contentStr = "Welcome to wechat world!";  
    49.                     $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);  
    50.                     echo $resultStr;  
    51.                 }else{  
    52.                     echo "Input something...";  
    53.                 }  
    54.   
    55.         }else {  
    56.             echo "";  
    57.             exit;  
    58.         }  
    59.     }  
    60.           
    61.     private function checkSignature()  
    62.     {  
    63.         $signature = $_GET["signature"];  
    64.         $timestamp = $_GET["timestamp"];  
    65.         $nonce = $_GET["nonce"];      
    66.                   
    67.         $token = TOKEN;  
    68.         $tmpArr = array($token, $timestamp, $nonce);  
    69.         sort($tmpArr);  
    70.         $tmpStr = implode( $tmpArr );  
    71.         $tmpStr = sha1( $tmpStr );  
    72.           
    73.         if( $tmpStr == $signature ){  
    74.             return true;  
    75.         }else{  
    76.             return false;  
    77.         }  
    78.     }  
    79. }  
    80.   
    81. ?>  

    JAVA:

    [java] view plain copy
     
    1. <%@page import="java.util.Date"%>  
    2. <%@page import="org.dom4j.Element"%>  
    3. <%@page import="org.dom4j.DocumentHelper"%>  
    4. <%@page import="org.dom4j.Document"%>  
    5. <%@page import="java.io.IOException"%>  
    6. <%@page import="java.io.InputStreamReader"%>  
    7. <%@page import="java.io.BufferedReader"%>  
    8. <%@page import="java.io.Reader"%>  
    9. <%@page import="java.security.MessageDigest"%>  
    10. <%@page import="java.util.Arrays"%>  
    11. <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>  
    12. <%  
    13.     //WeiXinHandler为内部类不能使用非final类型的对象  
    14.     final String TOKEN="weixin";  
    15.     final HttpServletRequest final_request=request;   
    16.     final HttpServletResponse final_response=response;  
    17. %>  
    18. <%   
    19. class WeiXinHandler{  
    20.     public void valid(){  
    21.         String echostr=final_request.getParameter("echostr");  
    22.         if(null==echostr||echostr.isEmpty()){  
    23.             responseMsg();  
    24.         }else{  
    25.             if(this.checkSignature()){  
    26.                 this.print(echostr);  
    27.             }else{  
    28.                 this.print("error");                                                                                                                                                                                                                                                                                                                                           
    29.             }  
    30.         }  
    31.     }  
    32.     //自动回复内容  
    33.     public void responseMsg(){  
    34.         String postStr=null;  
    35.         try{  
    36.             postStr=this.readStreamParameter(final_request.getInputStream());  
    37.         }catch(Exception e){  
    38.             e.printStackTrace();  
    39.         }  
    40.         //System.out.println(postStr);  
    41.         if (null!=postStr&&!postStr.isEmpty()){  
    42.             Document document=null;  
    43.             try{  
    44.                 document = DocumentHelper.parseText(postStr);  
    45.             }catch(Exception e){  
    46.                 e.printStackTrace();  
    47.             }  
    48.             if(null==document){  
    49.                 this.print("");  
    50.                 return;  
    51.             }  
    52.             Element root=document.getRootElement();  
    53.             String fromUsername = root.elementText("FromUserName");  
    54.             String toUsername = root.elementText("ToUserName");  
    55.             String keyword = root.elementTextTrim("Content");  
    56.             String time = new Date().getTime()+"";  
    57.             String textTpl = "<xml>"+  
    58.                         "<ToUserName><![CDATA[%1$s]]></ToUserName>"+  
    59.                         "<FromUserName><![CDATA[%2$s]]></FromUserName>"+  
    60.                         "<CreateTime>%3$s</CreateTime>"+  
    61.                         "<MsgType><![CDATA[%4$s]]></MsgType>"+  
    62.                         "<Content><![CDATA[%5$s]]></Content>"+  
    63.                         "<FuncFlag>0</FuncFlag>"+  
    64.                         "</xml>";               
    65.               
    66.             if(null!=keyword&&!keyword.equals(""))  
    67.             {  
    68.                 String msgType = "text";  
    69.                 String contentStr = "Welcome to wechat world!";  
    70.                 String resultStr = textTpl.format(textTpl, fromUsername, toUsername, time, msgType, contentStr);  
    71.                 this.print(resultStr);  
    72.             }else{  
    73.                 this.print("Input something...");  
    74.             }  
    75.   
    76.         }else {  
    77.             this.print("");  
    78.         }  
    79.     }  
    80.     //微信接口验证  
    81.     public boolean checkSignature(){  
    82.         String signature = final_request.getParameter("signature");  
    83.         String timestamp = final_request.getParameter("timestamp");  
    84.         String nonce = final_request.getParameter("nonce");  
    85.         String token=TOKEN;  
    86.         String[] tmpArr={token,timestamp,nonce};  
    87.         Arrays.sort(tmpArr);  
    88.         String tmpStr=this.ArrayToString(tmpArr);  
    89.         tmpStr=this.SHA1Encode(tmpStr);  
    90.         if(tmpStr.equalsIgnoreCase(signature)){  
    91.             return true;  
    92.         }else{  
    93.             return false;  
    94.         }  
    95.     }  
    96.     //向请求端发送返回数据  
    97.     public void print(String content){  
    98.         try{  
    99.             final_response.getWriter().print(content);  
    100.             final_response.getWriter().flush();  
    101.             final_response.getWriter().close();  
    102.         }catch(Exception e){  
    103.               
    104.         }  
    105.     }  
    106.     //数组转字符串  
    107.     public String ArrayToString(String [] arr){  
    108.         StringBuffer bf = new StringBuffer();  
    109.         for(int i = 0; i < arr.length; i++){  
    110.          bf.append(arr[i]);  
    111.         }  
    112.         return bf.toString();  
    113.     }  
    114.     //sha1加密  
    115.     public String SHA1Encode(String sourceString) {  
    116.         String resultString = null;  
    117.         try {  
    118.            resultString = new String(sourceString);  
    119.            MessageDigest md = MessageDigest.getInstance("SHA-1");  
    120.            resultString = byte2hexString(md.digest(resultString.getBytes()));  
    121.         } catch (Exception ex) {  
    122.         }  
    123.         return resultString;  
    124.     }  
    125.     public final String byte2hexString(byte[] bytes) {  
    126.         StringBuffer buf = new StringBuffer(bytes.length * 2);  
    127.         for (int i = 0; i < bytes.length; i++) {  
    128.             if (((int) bytes[i] & 0xff) < 0x10) {  
    129.                 buf.append("0");  
    130.             }  
    131.             buf.append(Long.toString((int) bytes[i] & 0xff, 16));  
    132.         }  
    133.         return buf.toString().toUpperCase();  
    134.     }  
    135.     //从输入流读取post参数  
    136.     public String readStreamParameter(ServletInputStream in){  
    137.         StringBuilder buffer = new StringBuilder();  
    138.         BufferedReader reader=null;  
    139.         try{  
    140.             reader = new BufferedReader(new InputStreamReader(in));  
    141.             String line=null;  
    142.             while((line = reader.readLine())!=null){  
    143.                 buffer.append(line);  
    144.             }  
    145.         }catch(Exception e){  
    146.             e.printStackTrace();  
    147.         }finally{  
    148.             if(null!=reader){  
    149.                 try {  
    150.                     reader.close();  
    151.                 } catch (IOException e) {  
    152.                     e.printStackTrace();  
    153.                 }  
    154.             }  
    155.         }  
    156.         return buffer.toString();  
    157.     }  
    158. }  
    159. %>  
    160. <%  
    161.     WeiXinHandler handler=new WeiXinHandler();  
    162.     handler.valid();  
    163. %>  

    以上就是PHP接口和JSP接口的所有代码,现在我们来对一些需要注意的地方做下分析:

    首先的从总体看的话,jsp要比PHP繁琐一些,因为很多函数需要自己写,像sha1加密,解析xml字符串等都需要自己找第三方的库。

    第一点,我们要获取微信公众平台给jsp发送的post或get参数,正常情况下都是用request.getParameter就可以获取到,但是在写的过程中发现PHP是这样获取

    [php] view plain copy
     
    1. $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];  

    这时通过查询一些资料知道这样获取的是无法通过$_GET或$_POST函数得到的”未识别 MIME 类型的数据“,原始的 POST 数据

    (参考:http://blog.csdn.net/china_skag/article/details/7284227

    所以这里使用获取原始数据流的方式来解析post的xml数据

    [java] view plain copy
     
    1. String postStr=null;  
    2.         try{  
    3.             postStr=this.readStreamParameter(final_request.getInputStream());  
    4.         }catch(Exception e){  
    5.             e.printStackTrace();  
    6.         }  
    [java] view plain copy
     
    1. //从输入流读取post参数  
    2.     public String readStreamParameter(ServletInputStream in){  
    3.         StringBuilder buffer = new StringBuilder();  
    4.         BufferedReader reader=null;  
    5.         try{  
    6.             reader = new BufferedReader(new InputStreamReader(in));  
    7.             String line=null;  
    8.             while((line = reader.readLine())!=null){  
    9.                 buffer.append(line);  
    10.             }  
    11.         }catch(Exception e){  
    12.             e.printStackTrace();  
    13.         }finally{  
    14.             if(null!=reader){  
    15.                 try {  
    16.                     reader.close();  
    17.                 } catch (IOException e) {  
    18.                     e.printStackTrace();  
    19.                 }  
    20.             }  
    21.         }  
    22.         return buffer.toString();  
    23.     }  


    第二个,是response消息返回给微信平台,我尝试的用最一般的out.print去做,但是发现没反应,观察PHP的代码写法

    [php] view plain copy
     
    1. echo "";  
    2. exit;  

    猜想可能需要有个刷新的操作才能把消息response回去,于是找了下response内的一些函数做出以下尝试

    [java] view plain copy
     
    1. //向请求端发送返回数据  
    2.     public void print(String content){  
    3.         try{  
    4.             final_response.getWriter().print(content);  
    5.             final_response.getWriter().flush();  
    6.             final_response.getWriter().close();  
    7.         }catch(Exception e){  
    8.               
    9.         }  
    10.     }  

    发现以上做法是可以在微信发送端得到消息的;

    第三个,接口描述上说目前只支持80端口的服务端地址,所以我这里的做法是用apache服务器路由到tomcat的jsp上

    关于微信公众平台的消息接口的详细介绍,可以参看微信公众平台的官方文档,里面介绍了消息的xml的格式和消息的发送方式等。

    转载地址:http://blog.csdn.net/wangqianjiao/article/details/8469780/

  • 相关阅读:
    【转】Winform窗体显示在父窗体的中间位置几种代码
    【转】图片上传
    【转】Web文件的ContentType类型大全
    【原】FileUpload控件上传文件
    【转】winform编程实现程序最小化到系统托盘代码
    【原】页面跳转以及表单提交中有中文的解决办法
    【转】asp.net弹出窗体大全
    .NET的发展及组成结构
    如何成为一个优秀的程序员?
    设计模式详细系列教程 (二) 创建型模式
  • 原文地址:https://www.cnblogs.com/xyyt/p/5872807.html
Copyright © 2011-2022 走看看