微信公众平台现在推出自动回复消息接口,但是由于是接口内容用的是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. Ansible用于网络设备管理 part 3 使用NAPALM成品库

    闲话 经过了这俩月的闲暇时间的瞎逛和瞎琢磨,我发现NAPALM是一条路,NAPALM是由帅哥David Barroso和美女Elisa Jasinska创建的一个项目,都是颜值高的技术牛人啊,真是不给 ...

  2. Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结

    Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结 1. office word  excel pdf 的web预览要求 ...

  3. IOS 杂笔-18 (let 与 var)

    var 是 variable的缩写形式,是变量的意思 ,是可改变的,并不是数据类型. let 是常量的意思,不可改变的.

  4. C++中的常量折叠

    先看例子: #include <iostream> using namespace std; int main() { ; int * p = (int *)(&a); *p = ...

  5. APP国际化

    1.app本地内容国际化 ①在项目中新建一个New File ---> iOS Resource -> String File ---> 命名为Localizable(之所以命名为L ...

  6. MySQL 存储过程实例 与 ibatis/mybatis/hibernate/jdbc 如何调用存储过程

    虽然MySQL的存储过程,一般情况下,是不会使用到的,但是在一些特殊场景中,还是有需求的.最近遇到一个sql server向mysql迁移的项目,有一些sql server的存储过程需要向mysql迁 ...

  7. jquery.qrcode.js 插件生成二维码

    下载地址:https://github.com/jeromeetienne/jquery-qrcode 例子: <!doctype html> <html> <head& ...

  8. 命令行方式使用abator.jar生成ibatis相关代码和sql语句xml文件

    最近接手一个老项目,使用的是数据库是sql server 2008,框架是springmvc + spring + ibatis,老项目是使用abator插件生成的相关代码,现在需要增加新功能,要添加 ...

  9. 第一篇 UEditor入门部署和体验

    UEditor 是由百度「FEX前端研发团队」开发的所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码. UEditor富文本编辑器,轻量, ...

  10. Python Backup Files

    近来书写 Python 脚本进行替换以前的 shell 脚本,发现 Python 优于 shell 的最直观的一点Python 结构明了,可读性高(本人认为)在此做一些记录 本次记录利用 Python ...