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

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

PHP:

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

JAVA:

  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. if(null!=keyword&&!keyword.equals(""))
  66. {
  67. String msgType = "text";
  68. String contentStr = "Welcome to wechat world!";
  69. String resultStr = textTpl.format(textTpl, fromUsername, toUsername, time, msgType, contentStr);
  70. this.print(resultStr);
  71. }else{
  72. this.print("Input something...");
  73. }
  74. }else {
  75. this.print("");
  76. }
  77. }
  78. //微信接口验证
  79. public boolean checkSignature(){
  80. String signature = final_request.getParameter("signature");
  81. String timestamp = final_request.getParameter("timestamp");
  82. String nonce = final_request.getParameter("nonce");
  83. String token=TOKEN;
  84. String[] tmpArr={token,timestamp,nonce};
  85. Arrays.sort(tmpArr);
  86. String tmpStr=this.ArrayToString(tmpArr);
  87. tmpStr=this.SHA1Encode(tmpStr);
  88. if(tmpStr.equalsIgnoreCase(signature)){
  89. return true;
  90. }else{
  91. return false;
  92. }
  93. }
  94. //向请求端发送返回数据
  95. public void print(String content){
  96. try{
  97. final_response.getWriter().print(content);
  98. final_response.getWriter().flush();
  99. final_response.getWriter().close();
  100. }catch(Exception e){
  101. }
  102. }
  103. //数组转字符串
  104. public String ArrayToString(String [] arr){
  105. StringBuffer bf = new StringBuffer();
  106. for(int i = 0; i < arr.length; i++){
  107. bf.append(arr[i]);
  108. }
  109. return bf.toString();
  110. }
  111. //sha1加密
  112. public String SHA1Encode(String sourceString) {
  113. String resultString = null;
  114. try {
  115. resultString = new String(sourceString);
  116. MessageDigest md = MessageDigest.getInstance("SHA-1");
  117. resultString = byte2hexString(md.digest(resultString.getBytes()));
  118. } catch (Exception ex) {
  119. }
  120. return resultString;
  121. }
  122. public final String byte2hexString(byte[] bytes) {
  123. StringBuffer buf = new StringBuffer(bytes.length * 2);
  124. for (int i = 0; i < bytes.length; i++) {
  125. if (((int) bytes[i] & 0xff) < 0x10) {
  126. buf.append("0");
  127. }
  128. buf.append(Long.toString((int) bytes[i] & 0xff, 16));
  129. }
  130. return buf.toString().toUpperCase();
  131. }
  132. //从输入流读取post参数
  133. public String readStreamParameter(ServletInputStream in){
  134. StringBuilder buffer = new StringBuilder();
  135. BufferedReader reader=null;
  136. try{
  137. reader = new BufferedReader(new InputStreamReader(in));
  138. String line=null;
  139. while((line = reader.readLine())!=null){
  140. buffer.append(line);
  141. }
  142. }catch(Exception e){
  143. e.printStackTrace();
  144. }finally{
  145. if(null!=reader){
  146. try {
  147. reader.close();
  148. } catch (IOException e) {
  149. e.printStackTrace();
  150. }
  151. }
  152. }
  153. return buffer.toString();
  154. }
  155. }
  156. %>
  157. <%
  158. WeiXinHandler handler=new WeiXinHandler();
  159. handler.valid();
  160. %>

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

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

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

  1. $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];

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

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

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

  1. String postStr=null;
  2. try{
  3. postStr=this.readStreamParameter(final_request.getInputStream());
  4. }catch(Exception e){
  5. e.printStackTrace();
  6. }
  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的代码写法

  1. echo "";
  2. exit;

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

  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. }

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

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

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

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

jsp 微信公众平台 token验证(php、jsp)(转载)的更多相关文章

  1. 微信公众平台Token验证失败的解决办法

    微信公众平台Token验证失败的解决办法 1.可查看url和token是否正确 2.查看服务器端口是否为80端口 3.你可以通过记录log日志来判断是否接受到微信提交过来的信息 1.$fp=fopen ...

  2. 微信公众平台——token验证php版

    这几天开始接触微信公众号的开发,注册这些就不说了,我是先弄了个测试号用着.进入正题 所谓token验证,其实就是微信服务器向自己要用到的服务器url发送一段数据,其中有一个参数$_GET['echho ...

  3. Senparc.Weixin.MP SDK 微信公众平台开发教程(三):微信公众平台开发验证

    要对接微信公众平台的"开发模式",即对接到自己的网站程序,必须在注册成功之后(见Senparc.Weixin.MP SDK 微信公众平台开发教程(一):微信公众平台注册),等待官方 ...

  4. 微信公众平台企业号验证接口、回调 PHP版

    微信公众平台企业号验证接口.回调 PHP版,本人为了解决这个企业号的验证和发送消息的问题,整整研究了几天时间,由于微信企业号刚推出来,网上资料太少了!后来在一些朋友的帮助下和本人重复调试完好下,最终整 ...

  5. Thinkphp5 微信公众号token验证不成功的原因

    最近要启动微信项目,上个月就开始了解微信的开发,这个月要启动项目,配置微信公众号信息一直失败.为此,我甚至手工写了微信提交过来的记录,如: &timestamp=1510210523& ...

  6. 服务器通过微信公众号Token验证测试的代码(Python版)

    我在阿里云租了一个云服务器,然后想把这个作为我的微信公众号的后台,启用微信公众号开发者需要正确的响应微信服务器的Token验证,为此把这个验证的Python代码贴出来,只要在服务器上运行这段代码,注意 ...

  7. C#开发微信公众平台-就这么简单(转载)

    写在前面 服务号和订阅号 URL配置 创建菜单 查询.删除菜单 接受消息 发送消息(图文.菜单事件响应) 示例Demo下载 后记 最近公司在做微信开发,其实就是接口开发,网上找了很多资料,当然园友也写 ...

  8. 分享:在微信公众平台做HTML5游戏经验谈(转载与http://software.intel.com/zh-cn/blogs/2013/04/03/html5)

    分享:在微信公众平台做HTML5游戏经验谈 Dawei Cheng 程大伟... 于 星期三, 03/04/2013 - 03:19 提交 最近微信公众游戏平台讨论得如火如荼,大有HTML5游戏即将引 ...

  9. 微信公众号token验证失败的一些总结

    这几天准备弄一个微信公众号,在进行服务器配置的时候出现总是出现token验证失败的报错. 实际上,这个问题很好解决.既然微信平台没有给我们很明确的报错提示,那么我们就可以通过跟踪获取到的请求参数进行分 ...

随机推荐

  1. CSS属性选择器温故-4

    1.属性选择器就是通过元素属性来找到元素 2.属性选择器语法 CSS3遵循了惯用的编码规则,通配符的使用提高了样式表的书写效率,也使CSS3的属性选择器更符合编码习惯 3.浏览器兼容性 CSS选择器总 ...

  2. gulp入坑系列(3)——创建多个gulp.task

    继续gulp的爬坑路,在准备get更多gulp的具体操作之前,先来明确一下在gulp中创建和使用多个task任务的情况. gulp所要做的操作都写在gulp.task()中,系统有一个默认的defau ...

  3. AJAX编程-封装ajax工具函数

    即 Asynchronous [e'sɪŋkrənəs] Javascript And XML,AJAX 不是一门的新的语言,而是对现有技术的综合利用.本质是在HTTP协议的基础上以异步的方式与服务器 ...

  4. jQuery高级技巧——性能优化篇

      通过CDN(Content Delivery Network)引入jQuery库 要提升网站中javascript的性能的最简单的一步就是引入最新版本的jQuery库,新发布的版本通常在性能上会有 ...

  5. 本地Git服务器的搭建及使用

    本地Git服务器的搭建及使用 Git本地服务器环境搭建 搭建好的本地git服务器的局域网ip是192.168.1.188,用户名是RSCSVN 教程链接:http://blog.csdn.net/cc ...

  6. 认识Runtime2

    我定义了一个Person类作为测试. 其中Person.h: // // Person.h // Test // // Created by zhanggui on 15/8/16. // Copyr ...

  7. JSONKit解析json数据

    先将第三方文件拖进工程 JSONKit.h和JSONKit.m 然后设置在ARC工程中添加MRC文件,如下图所示 #import "ViewController.h" #impor ...

  8. 解压缩框架--SSZipArchive

    下载地址:https://github.com/ZipArchive/ZipArchive 如果你直接将框架文件夹拖入项目,构建时会出现以下错误 解决方案: 点击+以后会弹出 如果使用cocoaPod ...

  9. MFC中添加用户自定义消息

    1.定义一个宏(用户自定义消息从WM_USER开始) #define WM_XXXXX WM_USER+数值 2.声明一个成员函数并实现 afx_msg LRESULT OnXXXXX( WPARAM ...

  10. Json常用的转换

    简单记录一下jquery里面的JSON.parse()和JSON.stringify()函数,和js中的eval()函数的用法 1,JSON.parse 函数(常用) 作用:将 JavaScript ...