微信企业号回调模式配置讲解 Java Servlet+Struts2版本 echostr校验失败解决

微信企业号回调模式配置讲解 Java Servlet+Struts2版本

echostr校验失败解决

echostr校验失败,请您检查是否正确解密并输出明文echostr

异常java.security.InvalidKeyException:illegal Key Size 也就是echostr校验失败,请您检查是否正确解密并输出明文echostr这个错误

企业微信登陆地址http://qy.weixin.qq.com/

配置成功以后

Servlet

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 微信加密签名
		String msg_signature = request.getParameter("msg_signature");
		// 时间戳
		String timestamp = request.getParameter("timestamp");
		// 随机数
		String nonce = request.getParameter("nonce");
		// 随机字符串
		String echostr = request.getParameter("echostr");
		// 打印请求地址
		System.out.println("request=" + request.getRequestURL());
		// 流
		PrintWriter out = response.getWriter();
		// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
		String result = null;
		try {
			WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(ParamesAPI.token, ParamesAPI.encodingAESKey, ParamesAPI.corpId);
			// 验证URL函数
			result = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr);
		} catch (AesException e) {
			e.printStackTrace();
		}
		if (result == null) {
			// result为空,赋予token
			result = ParamesAPI.token;
		}
		// 拼接请求参数
		String str = msg_signature + " " + timestamp + " " + nonce + " " + echostr;
		// 打印参数+地址+result
		System.out.println("Exception:" + result + " " + request.getRequestURL() + " " + "FourParames:" + str);
		String info = "Exception:" + result + " " + request.getRequestURL() + " " + "FourParames:" + str;
		log.info(info);
		out.print(result);
		out.close();
		out = null;
	}

官方回调页面的代码

?


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

import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.NodeList;

import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilderFactory;

import com.qq.weixin.mp.aes.WXBizMsgCrypt;

public class Sample {

    public static void main(String[] args) throws Exception {

        String sToken = "QDG6eK";

        String sCorpID = "wx5823bf96d3bd56c7";

        String sEncodingAESKey = "jWmYm7qr5nMoAUwZRjGtBxmz3KA1tkAj3ykkR6q2B2C";

        WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID);

        /*

        ------------使用示例一:验证回调URL---------------

        *企业开启回调模式时,企业号会向验证url发送一个get请求 

        假设点击验证时,企业收到类似请求:

        * GET /cgi-bin/wxpush?msg_signature=5c45ff5e21c57e6ad56bac8758b79b1d9ac89fd3&timestamp=1409659589&nonce=263014780&echostr=P9nAzCzyDtyTWESHep1vC5X9xho%2FqYX3Zpb4yKa9SKld1DsH3Iyt3tP3zNdtp%2B4RPcs8TgAE7OaBO%2BFZXvnaqQ%3D%3D 

        * HTTP/1.1 Host: qy.weixin.qq.com

        接收到该请求时,企业应        1.解析出Get请求的参数,包括消息体签名(msg_signature),时间戳(timestamp),随机数字串(nonce)以及公众平台推送过来的随机加密字符串(echostr),

        这一步注意作URL解码。

        2.验证消息体签名的正确性 

        3. 解密出echostr原文,将原文当作Get请求的response,返回给公众平台

        第2,3步可以用公众平台提供的库函数VerifyURL来实现。

        */

        // 解析出url上的参数值如下:

        // String sVerifyMsgSig = HttpUtils.ParseUrl("msg_signature");

        String sVerifyMsgSig = "5c45ff5e21c57e6ad56bac8758b79b1d9ac89fd3";

        // String sVerifyTimeStamp = HttpUtils.ParseUrl("timestamp");

        String sVerifyTimeStamp = "1409659589";

        // String sVerifyNonce = HttpUtils.ParseUrl("nonce");

        String sVerifyNonce = "263014780";

        // String sVerifyEchoStr = HttpUtils.ParseUrl("echostr");

        String sVerifyEchoStr = "P9nAzCzyDtyTWESHep1vC5X9xho/qYX3Zpb4yKa9SKld1DsH3Iyt3tP3zNdtp+4RPcs8TgAE7OaBO+FZXvnaqQ==";

        String sEchoStr; //需要返回的明文

        try {

            sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,

                    sVerifyNonce, sVerifyEchoStr);

            System.out.println("verifyurl echostr: " + sEchoStr);

            // 验证URL成功,将sEchoStr返回

            // HttpUtils.SetResponse(sEchoStr);

        catch (Exception e) {

            //验证URL失败,错误原因请查看异常

            e.printStackTrace();

        }

        /*

        ------------使用示例二:对用户回复的消息解密---------------

        用户回复消息或者点击事件响应时,企业会收到回调消息,此消息是经过公众平台加密之后的密文以post形式发送给企业,密文格式请参考官方文档

        假设企业收到公众平台的回调消息如下:

        POST /cgi-bin/wxpush? msg_signature=477715d11cdb4164915debcba66cb864d751f3e6&timestamp=1409659813&nonce=1372623149 HTTP/1.1

        Host: qy.weixin.qq.com

        Content-Length: 613

        <xml>        <ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName><Encrypt><![CDATA[RypEvHKD8QQKFhvQ6QleEB4J58tiPdvo+rtK1I9qca6aM/wvqnLSV5zEPeusUiX5L5X/0lWfrf0QADHHhGd3QczcdCUpj911L3vg3W/sYYvuJTs3TUUkSUXxaccAS0qhxchrRYt66wiSpGLYL42aM6A8dTT+6k4aSknmPj48kzJs8qLjvd4Xgpue06DOdnLxAUHzM6+kDZ+HMZfJYuR+LtwGc2hgf5gsijff0ekUNXZiqATP7PF5mZxZ3Izoun1s4zG4LUMnvw2r+KqCKIw+3IQH03v+BCA9nMELNqbSf6tiWSrXJB3LAVGUcallcrw8V2t9EL4EhzJWrQUax5wLVMNS0+rUPA3k22Ncx4XXZS9o0MBH27Bo6BpNelZpS+/uh9KsNlY6bHCmJU9p8g7m3fVKn28H3KDYA5Pl/T8Z1ptDAVe0lXdQ2YoyyH2uyPIGHBZZIs2pDBS8R07+qN+E7Q==]]></Encrypt>

        <AgentID><![CDATA[218]]></AgentID>

        </xml>

        企业收到post请求之后应该        1.解析出url上的参数,包括消息体签名(msg_signature),时间戳(timestamp)以及随机数字串(nonce)

        2.验证消息体签名的正确性。

        3.将post请求的数据进行xml解析,并将<Encrypt>标签的内容进行解密,解密出来的明文即是用户回复消息的明文,明文格式请参考官方文档

        第2,3步可以用公众平台提供的库函数DecryptMsg来实现。

        */

        // String sReqMsgSig = HttpUtils.ParseUrl("msg_signature");

        String sReqMsgSig = "477715d11cdb4164915debcba66cb864d751f3e6";

        // String sReqTimeStamp = HttpUtils.ParseUrl("timestamp");

        String sReqTimeStamp = "1409659813";

        // String sReqNonce = HttpUtils.ParseUrl("nonce");

        String sReqNonce = "1372623149";

        // post请求的密文数据

        // sReqData = HttpUtils.PostData();

        String sReqData = "<xml><ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName><Encrypt><![CDATA[RypEvHKD8QQKFhvQ6QleEB4J58tiPdvo+rtK1I9qca6aM/wvqnLSV5zEPeusUiX5L5X/0lWfrf0QADHHhGd3QczcdCUpj911L3vg3W/sYYvuJTs3TUUkSUXxaccAS0qhxchrRYt66wiSpGLYL42aM6A8dTT+6k4aSknmPj48kzJs8qLjvd4Xgpue06DOdnLxAUHzM6+kDZ+HMZfJYuR+LtwGc2hgf5gsijff0ekUNXZiqATP7PF5mZxZ3Izoun1s4zG4LUMnvw2r+KqCKIw+3IQH03v+BCA9nMELNqbSf6tiWSrXJB3LAVGUcallcrw8V2t9EL4EhzJWrQUax5wLVMNS0+rUPA3k22Ncx4XXZS9o0MBH27Bo6BpNelZpS+/uh9KsNlY6bHCmJU9p8g7m3fVKn28H3KDYA5Pl/T8Z1ptDAVe0lXdQ2YoyyH2uyPIGHBZZIs2pDBS8R07+qN+E7Q==]]></Encrypt><AgentID><![CDATA[218]]></AgentID></xml>";

        try {

            String sMsg = wxcpt.DecryptMsg(sReqMsgSig, sReqTimeStamp, sReqNonce, sReqData);

            System.out.println("after decrypt msg: " + sMsg);

            // TODO: 解析出明文xml标签的内容进行处理

            // For example:

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

            DocumentBuilder db = dbf.newDocumentBuilder();

            StringReader sr = new StringReader(sMsg);

            InputSource is = new InputSource(sr);

            Document document = db.parse(is);

            Element root = document.getDocumentElement();

            NodeList nodelist1 = root.getElementsByTagName("Content");

            String Content = nodelist1.item(0).getTextContent();

            System.out.println("Content:" + Content);

            

        catch (Exception e) {

            // TODO

            // 解密失败,失败原因请查看异常

            e.printStackTrace();

        }

    /*

        ------------使用示例三:企业回复用户消息的加密---------------

        企业被动回复用户的消息也需要进行加密,并且拼接成密文格式的xml串。

        假设企业需要回复用户的明文如下:

        <xml>

        <ToUserName><![CDATA[mycreate]]></ToUserName>

        <FromUserName><![CDATA[wx5823bf96d3bd56c7]]></FromUserName>

        <CreateTime>1348831860</CreateTime>

        <MsgType><![CDATA[text]]></MsgType>

        <Content><![CDATA[this is a test]]></Content>

        <MsgId>1234567890123456</MsgId>

        <AgentID>128</AgentID>

        </xml>

        为了将此段明文回复给用户,企业应:            1.自己生成时间时间戳(timestamp),随机数字串(nonce)以便生成消息体签名,也可以直接用从公众平台的post url上解析出的对应值。

        2.将明文加密得到密文。    3.用密文,步骤1生成的timestamp,nonce和企业在公众平台设定的token生成消息体签名。            4.将密文,消息体签名,时间戳,随机数字串拼接成xml格式的字符串,发送给企业。

        以上2,3,4步可以用公众平台提供的库函数EncryptMsg来实现。

        */

        String sRespData = "<xml><ToUserName><![CDATA[mycreate]]></ToUserName><FromUserName><![CDATA[wx5823bf96d3bd56c7]]></FromUserName><CreateTime>1348831860</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[this is a test]]></Content><MsgId>1234567890123456</MsgId><AgentID>128</AgentID></xml>";

        try{

            String sEncryptMsg = wxcpt.EncryptMsg(sRespData, sReqTimeStamp, sReqNonce);

            System.out.println("after encrypt sEncrytMsg: " + sEncryptMsg);

            // 加密成功

            // TODO:

            // HttpUtils.SetResponse(sEncryptMsg);

        }

        catch(Exception e)

        {

            e.printStackTrace();

            // 加密失败

        }

    }

}

来重点了:echostr校验失败,请您检查是否正确解密并输出明文echostr

有可能会遇到这样的错误。大家就百度搜索也找不到。因为官方提供了解决方案。所以,仔细

看官方提供的验证加密的源代码是有作用的。

说明:异常java.security.InvalidKeyException:illegal Key Size的解决方案

* 在官方网站下载JCE无限制权限策略文件(JDK7的下载地址:

*   http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html

* 下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt

* 如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件

* 如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件

Struts2

?


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

    public String execute() throws Exception {

        // 将请求、响应的编码均设置为UTF-8(防止中文乱码)

        HttpServletRequest request = ServletActionContext.getRequest();

        HttpServletResponse response = ServletActionContext.getResponse();

        request.setCharacterEncoding("UTF-8");

        response.setCharacterEncoding("UTF-8");

        //微信加密签名

        String msg_signature = request.getParameter("msg_signature");

        // 时间戳

        String timestamp = request.getParameter("timestamp");

        // 随机数

        String nonce = request.getParameter("nonce");

        // 随机字符串

        String echostr = request.getParameter("echostr");

        PrintWriter out = response.getWriter();

        String result = null;

        // 请求校验

        try{

            WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(ParamesAPI.token, ParamesAPI.encodingAESKey, ParamesAPI.corpId);

            //验证URL函数

            result = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr);

        

            if(result==null){

                result = ParamesAPI.token;

            }else{

                out.print(result);

            }

        }catch (Exception e) {

            e.printStackTrace();

            log.error("请求错误,稍后再试",e);

        }

        out.close();

        out = null;

        return null;

      }

个人微博 http://weibo.com/zxshuai319 

个人博客http://my.oschina.net/xshuai/blog

有问题请回复本博客

个人联盟http://www.bengbeng.com/?sid=687095  

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-29 01:12:32

微信企业号回调模式配置讲解 Java Servlet+Struts2版本 echostr校验失败解决的相关文章

微信企业号回调模式验证与发送消息

最近放假闲着无聊,研究了一下微信企业号, 打算通过企业号做一个运维报警信息发送的功能,记录自己的操作 第一步 注册企业号,网上一搜一大把的教程,这里略过  微信企业号登录地址  https://qy.weixin.qq.com/ 第二步  登录后 点左侧 应用中心 -新建应用 第三步  在第二步第一图中的自建应用下面找到刚刚新建的应用 拉到最下面有一个模式选择,点击回调模式 会看到下图界面 Token 和EncodingAESKey 点击随机获取即可,上面的url需要你有自己的服务地址  你的服

python 微信企业号-回调模式接收微信端客户端发送消息并被动返回消息

说明:此代码用于接收手机微信端发送的消息 #-*- coding:utf-8 -*- from flask import Flask,request from WXBizMsgCrypt import WXBizMsgCrypt import xml.etree.cElementTree as ET import sys app = Flask(__name__) @app.route('/index',methods=['GET','POST']) def index():         s

微信公众账号开发接口实现 - java servlet

原文:微信公众账号开发接口实现 - java servlet 源代码下载地址:http://www.zuidaima.com/share/1550463697898496.htm 微信公众平台开发接口验证token.收取.回复消息实现 其实只需要两个类:DeiponseMessage.java.Wechat.java 项目截图 缺少的jar包下载列表: http://mirrors.ibiblio.org/pub/mirrors/maven2/commons-beanutils/commons-

通过生产者消费者模式例子讲解Java基类方法wait、notify、notifyAll

wait(),notify()和notifyAll()都是Java基类java.lang.Object的方法. 通俗解释wait():在当前线程等待其它线程唤醒.notify(): 唤醒一个线程正在等待这个对象的监视器.notifyAll(): 唤醒在这个对象监视器上等待的所有线程.这三个方法,都是Java语言提供的实现线程间阻塞(Blocking)和控制进程内调度(inter-process communication)的底层机制.下面通过一个生产者/消费者的例子来讲解这三个方法的使用 /**

Java运行环境变量配置中java与javac版本不一致的解决方法

原帖:http://www.cnblogs.com/shined/p/4492615.html 问题描述: 在Windows命令行窗口中通过运行java与javac语句发现java配置没有问题 图1: 图2: 但是设置了环境变量JAVA_HOME为jdk1.5.0_14的安装目录,并且在PATH变量中加入了%JAVA_HOME%\bin,但在Windows命令行下, 执行java -version却显示: java version "1.6.0_13"     而执行javac -ve

微信企业号验证

微信企业号回调模式验证机制官方文档有说明,也是解密字符串后返回解密内容,下面是一个调试通过的接口验证: <?php //添加腾讯提供的接口文件 include_once "WXBizMsgCrypt.php"; //设置自己企业号的相关参数 $encodingAesKey=""; $corpId=""; $token=""; //获取待验证的参数 $sVerifyMsgSig = $_GET["msg_sign

微信企业号开发:启用回调模式

微信企业号开发如何启用回调模式?就是简单的登陆PC版微信,点击应用中心,选择需要应用,再点击回调模式启用? 似乎不是这么简单!! 可以看到核心的只有三个URL,Token,EncodingAESKey这三个参数可以随便填写吗?1URL可以随便填写吗? 可以肯定的是,不能随便填写.不信你可以试试.因为点击确定后微信会给这个URL发送信息.因此这个URL必须是外网可以访问的地址.而且后台还必须处理微信发送过来的信息.例如URL 是http://www.hao123.com/可以在外网方法,但点击保存

C#开发微信门户及应用(21)-微信企业号的消息和事件的接收处理及解密

原文:C#开发微信门户及应用(21)-微信企业号的消息和事件的接收处理及解密 在上篇随笔<C#开发微信门户及应用(19)-微信企业号的消息发送(文本.图片.文件.语音.视频.图文消息等)>介绍了有关企业号的消息发送,官方特别声明消息是不用加密发送的.但是在回调的服务器上,也就是我们网站的服务器上,微信传过来的消息是加密的,需要我们调用类库对消息和事件进行解密操作,由于官方的例子不全,因此摸索了不少时间,最终顺利解密收到的各种消息和事件.本文主要介绍 微信企业号的消息和事件的接收处理及解密操作.

引领移动协同需求Cnskype结合微信企业号推出企业办公、通讯整合方案

微信企业号的推出,堪比屠龙宝刀重出江湖,一时间企业级市场风云再起,或许还将引发一轮腥风血雨.为了抢占市场先机,诸多第三方开发商和企业级软件厂商闻风而动,以冲刺的步伐,争先推出企业号的集成应用服务和解决方案,为移动办公市场"添柴加火". 有着"连接一切"野心的企业号,通过统一工作入口,将企业需要的各种移动办公应用整合在一起,从而实现企业员工内部.上下游供应链间的协作.从目前市场上推出的企业号的应用和服务来看,微信企业号承载的基础应用便是协同办公,部分业内人士认为,这绝