今天打算開發一個微信公衆平臺的一個閱讀功能,使用開發者模式,第一個件就是要經過驗證,就是token的驗證. php
我寫的東西比較直接沒有過多的解釋性語言,若是有疑問能夠經過評論來討論一下. java
接口開發必定要先看好接口說明,這個是很重要的,你對接口文檔的理解直接影響到你的接口開發速度與質量. web
開發工具:eclipse 3.5 算法
使用技術:struts2 , spring 3.0 , hibernate 3.3 ,dom4j 等等 spring
測試網址(僞): http://www.xyz.com/weixin_msg.action 服務器
測試token: token(您在使用的時候別忘了換成你本身的.) 微信
===========接===口===說===明============================= app
公衆平臺用戶提交信息後,微信服務器將發送GET請求到填寫的URL上,而且帶上四個參數: 微信公衆平臺
參數 | 描述 |
---|---|
signature | 微信加密簽名 |
timestamp | 時間戳 |
nonce | 隨機數 |
echostr | 隨機字符串 |
開發者經過檢驗signature對請求進行校驗(下面有校驗方式)。若確認這次GET請求來自微信服務器,請原樣返回echostr參數內容,則接入生效,不然接入失敗。
signature結合了開發者填寫的token參數和請求中的timestamp參數、nonce參數。
加密/校驗流程: 1. 將token、timestamp、nonce三個參數進行字典序排序 2. 將三個參數字符串拼接成一個字符串進行sha1加密 3. 開發者得到加密後的字符串可與signature對比,標識該請求來源於微信
=====================================================
action代碼.我使用的是struts2因此是action.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.StringBufferInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; import com.xyz.bbs.weixin.utils.WeixinMessageDigestUtil; import com.xyz.framework.utils.MessageDigestUtil; import com.xyz.framework.web.BaseAction; @SuppressWarnings("serial") @Controller("WeixinActionId") @Scope("prototype") public class WeixinAction extends BaseAction { private static final String TOKEN = "token"; private static final String GET = "GET"; private String signature; private String timestamp; private String nonce; private String echostr; /** * 微信回調方法、包括doGet & doPost * @return */ public String msg(){ if (GET.equals(getRequest().getMethod())) { //get doget(); }else { //post } //爲何返回null? return null; } /** * get方式驗證token */ public void doget(){ logger.debug("signature" + signature); logger.debug("timestamp" + timestamp); logger.debug("nonce" + nonce); logger.debug("echostr" + echostr); Arrays.sort(ArrTmp); StringBuffer sb = new StringBuffer(); for (int i = 0; i < ArrTmp.length; i++) { sb.append(ArrTmp[i]); } String pwd = WeixinMessageDigestUtil.getInstance().encipher(sb.toString()); if(pwd.equals(signature)){ if(!"".equals(echostr) && echostr != null){ try { System.out.println("response"); this.getResponse().getWriter().write(echostr); } catch (IOException e) { e.printStackTrace(); } } } } //一下代碼不用看的. //getter && setter public String getSignature() { return signature; } public void setSignature(String signature) { this.signature = signature; } public String getTimestamp() { return timestamp; } public void setTimestamp(String timestamp) { this.timestamp = timestamp; } public String getNonce() { return nonce; } public void setNonce(String nonce) { this.nonce = nonce; } public String getEchostr() { return echostr; } public void setEchostr(String echostr) { this.echostr = echostr; } }
加密工具類
import java.security.*; import java.util.Arrays; /* * SHA1 水印算法工具類 * AJ 2013-04-12 */ public final class WeixinMessageDigestUtil { private static final WeixinMessageDigestUtil _instance = new WeixinMessageDigestUtil(); private MessageDigest alga; private WeixinMessageDigestUtil() { try { alga = MessageDigest.getInstance("SHA-1"); } catch(Exception e) { throw new InternalError("init MessageDigest error:" + e.getMessage()); } } public static WeixinMessageDigestUtil getInstance() { return _instance; } public static String byte2hex(byte[] b) { String des = ""; String tmp = null; for (int i = 0; i < b.length; i++) { tmp = (Integer.toHexString(b[i] & 0xFF)); if (tmp.length() == 1) { des += "0"; } des += tmp; } return des; } public String encipher(String strSrc) { String strDes = null; byte[] bt = strSrc.getBytes(); alga.update(bt); strDes = byte2hex(alga.digest()); //to HexString return strDes; } public static void main(String[] args) { String signature="b7982f21e7f18f640149be5784df8d377877ebf9"; String timestamp="1365760417"; String nonce="1365691777"; String[] ArrTmp = { "token", timestamp, nonce }; Arrays.sort(ArrTmp); StringBuffer sb = new StringBuffer(); for (int i = 0; i < ArrTmp.length; i++) { sb.append(ArrTmp[i]); } String pwd =WeixinMessageDigestUtil.getInstance().encipher(sb.toString()); if (signature.equals(pwd)) { System.out.println("token 驗證成功~!"); }else { System.out.println("token 驗證失敗~!"); } } }
服務搭建完成以後就能夠進行測試了,這個測試方法就不用我寫了吧..
看到他說明你成功了.
最後簡單說一下爲何action返回的是null而不是一個String.
你們都以後默認寫struts2的時候須要指定返回路徑,一般使用String來作.struts會根據你所返回的值去查找對應的頁面.返回null就是由於微信接口協議,協議中說了echostr參數要遠洋返回,若是是使用瀏覽器來看的話頁面只有echostr的值,沒有其餘的字符.直接返回response,到頁面就輸出print了.