1. 程式人生 > >微信企業號回調模式配置解說 Java Servlet+Struts2版本號 echostr校驗失敗解決

微信企業號回調模式配置解說 Java Servlet+Struts2版本號 echostr校驗失敗解決

del com crypt atp org use ase http err

微信企業號回調模式配置解說 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

有問題請回復本博客

sid=687095" rel="nofollow">

個人聯盟http://www.bengbeng.com/?

sid=687095

微信企業號回調模式配置解說 Java Servlet+Struts2版本號 echostr校驗失敗解決