版本說明:
V1:
2014-2-13更新,紅色字體代表最近一次更新的內容。
V2:
2014-3-30 更新,上一版本有很多讀者反應說最后還是無法通過微信 token 認證,此版本特意解決這個問題。紅色字體代表最近一次更新的內容。
至讀者:
對於版本 v1 不能成功的問題,我對此深表歉意,版本 v2 通過我再三測試,肯定能通過微信的 token,版本 v1 不能不能成功的問原因是 eclipse 新建的工程不對, 導致部署不成功,讀者可以留意一下這里。另外,要特意感謝一位朋友,他通過遠程協助給我演示了一遍,才能讓我把問題給解決了,同時還要感謝那些信任和支持我的朋友,感謝那些向我反映問題的讀者。
前言:
因為要進行微信開發,就必須要成為微信開發者,要想成為微信開發者,就必須要有服務器響應微信的 Token 驗證,如果沒有公網服務器環境,可以去了解下BAE、SAE或阿里雲,這里以 BAE 為例。
前提條件:
(1)擁有微信公眾平台帳號(申請地址:https://mp.weixin.qq.com/)
(2)擁有百度BAE開發者帳號(申請地址:http://developer.baidu.com/)
(3)搭建好 Java 開發環境,沒有搭建好的可參考
Java 開發環境搭建
准備工作:
下載一個集成好BAE開發環境的eclipse(也可以在線安裝插件),
在百度網頁(
http://developer.baidu.com/wiki/index.php?title=docs/cplat/ide/install
)最下面有一鍵安裝那里下載,這是已預裝了Baidu Eclipse插件以及 svn 版本管理工具的Eclipse安裝包,
下載到本地解壓即可用(有可能首次啟動會報錯 Eclipse is running in a JRE, but a JDK is required, 解決方法,點此進入)。非常簡單,不建議自己安裝插件,除非你很熟悉怎么去安裝。
如果你已經有了 MyEclipse 工具,那么,恭喜你,你不需要安裝 Baidu Eclipse 也可以搭建一個開發環境,具體操作,請看另外一篇博客。
步驟:
1、去BAE快速創建一個JAVA應用


圖 1
點擊 “創建應用” 填上應用名稱,點擊“保存”,如圖2


圖 2
你就會看到你創建好的應用:(圖 3)


圖 3
2、添加部署
點擊應用圖標,查看應用信息,點擊“應用引擎” 彈出“部署列表”頁面:圖 4


圖 4
點擊“添加部署”,按要求填寫, 類型選擇 Java-tomcat:圖5


圖 5
創建失敗並提示警告,由於 bae 升級到 3.0 版本,實行分批制度,看公告:圖 6


圖 6
很悲劇,如果你沒有搶到執行單元,那你就只能等搶到再說,否則你就無法部署你的代碼。
查看部署:BAE部署創建成功后,在部署列表中可看到剛創建的部署信息。
注意:代碼版本工具支持:svn和git,建議選擇 svn 因為這樣比較省事。
3、通過 SVN 檢入工程
在 bae 上的應用添加部署成功后,如圖 7

圖 7
點擊“點擊查看”按鈕,會打開一個新頁面,頁面上會打印 “hello world” ,這是因為我們的應用包含有示例代碼,也就是基礎工程,我們要將這個工程導出到本地,然后添加我們自己的代碼,我們點擊“點擊復制”復制 svn 的地址備用。
啟動我們安裝好的 Eclipse,
點擊 File -->new --> other,從彈出的窗口中選擇 svn,如圖 8


圖 8
點擊 “從 SVN檢出項目” --> Next --> 創建新的資源庫位置 --> Next --> 粘貼剛才復制的 SVN 的地址 --> 點擊顯示的地址 Next --> 驗證后會看到檢測出的項目,如圖 9


圖 9
點擊選中項目 --> Next --> 選中“做為新項目檢出,***”,如圖 10


圖 10
點擊 “Finish”,彈出頁面中選擇 “Yes” ,如圖 11


圖 11
注意:選擇 “Yes”后,如果要百度驗證,記得填寫有 user 時不能是中文,如果你的百度賬號是中文登錄,趕緊去賬號里關聯手機號或者Email,這樣你就可以通過手機號或者 Email 來登錄百度了。
(往下比更新前變動很大,各位多留意)
在彈出的新建項目向導對話框中選擇 Web --> Dynamic Web project (動態 web 工程),( 注意不要選擇 Baidu --> BAE Project ,版本 v1 叫大家選擇BAE Project 會發現很難打包) 如圖12:


圖 12
接着會彈出一個進程框,如圖13:

圖 13
然后在彈出的窗口中填上你的項目名稱,如圖 14:

圖 14
在彈出的窗口中選 Next,彈出如下窗口:

注意要選中復選框,生成 web.xml 文件, 點擊 “Finish”按鈕,如果彈出如圖15 所示對話框:

圖 15
點擊“OK”按鈕,接着就是等待檢出項目。
成功檢出來的項目是默認已經連接了 svn 的,並且不會報錯,有報錯的話,請留言聯系我。
4、在工程中添加代碼,讓其響應微信驗證
查看我們的工程,如圖 17


圖 17
新建一個 servlet 包,方法是:"src" --> 右鍵 --> new --> packages, 命名隨意,例如 org.ivy.course.servlet,如圖:

往包里添加一個能夠處理請求的Servlet 類,這次我采用向導的方式添加,如圖所示:

點擊圖中的 “Create a new Servlet ” ,在彈出窗口中填上類名 CoreServlet :

點擊 Next,注意彈出的窗口中的 URL mappings,訪問時要用到它:

點擊 Next 后點擊 “Finish”得到通過向導新建的類 CoreServlet:
- package org.ivy.course.servlet;
- import java.io.IOException;
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- /**
- * Servlet implementation class CoreServlet
- */
- @WebServlet("/CoreServlet")
- public class CoreServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- /**
- * Default constructor.
- */
- public CoreServlet() {
- // TODO Auto-generated constructor stub
- }
- /**
- * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
- */
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // TODO Auto-generated method stub
- }
- /**
- * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
- */
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // TODO Auto-generated method stub
- }
- }
新建的類 Servlet 可能會報錯,同時導入的頭文件也會報錯,如圖:

這是因為缺少 servlet-api.jar 這個包,網絡上下載這個包,添加到工程中就行了,做法是直接復制這個包,然后再工程的 WebContent/WEB-INF/Lib 中右鍵選擇 Paste 粘貼進去並右鍵刷新工程就行了,實在不行,請參考
我的博客 【The import javax.servlet cannot be resolved 解決方法
】。
我們在 doGet 方法中添加我們的代碼,完整如下:
- package org.ivy.course.servlet;
- import java.io.IOException;
- import java.io.PrintWriter;
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.ivy.course.util.SignUtil;
- /**
- * Servlet implementation class CoreServlet
- */
- @WebServlet("/CoreServlet")
- public class CoreServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- /**
- * Default constructor.
- */
- public CoreServlet() {
- // TODO Auto-generated constructor stub
- }
- /**
- * 確認請求來自微信服務器
- * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
- */
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // TODO Auto-generated method stub
- // my
- // 微信加密簽名
- String signature = request.getParameter("signature");
- // 時間戮
- String timestamp = request.getParameter("timestamp");
- // 隨機數
- String nonce = request.getParameter("nonce");
- // 隨機字符串
- String echostr = request.getParameter("echostr");
- PrintWriter out = response.getWriter();
- // 通過檢驗 signature 對請求進行校驗,若校驗成功則原樣返回 echostr,表示接入成功,否則接入失敗
- if(SignUtil.checkSignature(signature, timestamp, nonce)){
- out.print(echostr);
- }
- out.close();
- out = null;
- }
- /**
- * 處理微信服務器發來的消息
- * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
- */
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- // TODO Auto-generated method stub
- // 消息的接收、處理、響應
- }
- }
在doGet方法中調用了checkSignature方法,該方法還沒有實現,我們新建一個包 org.ivy.course.util 作為一個工具包,並往該包中添加新類 SignUtil,添加類的方法是:包名右鍵 -->new --> class,填上類名,其它默認,完整代碼如下:
- package org.ivy.course.util;
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
- import java.util.Arrays;
- public class SignUtil {
- /**
- * 與接口配置信息中的 token 要一致,這里賦予什么值,在接口配置信息中的Token就要填寫什么值,
- * 兩邊保持一致即可,建議用項目名稱、公司名稱縮寫等,我在這里用的是項目名稱weixinface
- */
- private static String token = "weixinface";
- /**
- * 驗證簽名
- * @param signature
- * @param timestamp
- * @param nonce
- * @return
- */
- public static boolean checkSignature(String signature, String timestamp, String nonce){
- String[] arr = new String[]{token, timestamp, nonce};
- // 將 token, timestamp, nonce 三個參數進行字典排序
- Arrays.sort(arr);
- StringBuilder content = new StringBuilder();
- for(int i = 0; i < arr.length; i++){
- content.append(arr[i]);
- }
- MessageDigest md = null;
- String tmpStr = null;
- try {
- md = MessageDigest.getInstance("SHA-1");
- // 將三個參數字符串拼接成一個字符串進行 shal 加密
- byte[] digest = md.digest(content.toString().getBytes());
- tmpStr = byteToStr(digest);
- } catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- content = null;
- // 將sha1加密后的字符串可與signature對比,標識該請求來源於微信
- return tmpStr != null ? tmpStr.equals(signature.toUpperCase()): false;
- }
- /**
- * 將字節數組轉換為十六進制字符串
- * @param digest
- * @return
- */
- private static String byteToStr(byte[] digest) {
- // TODO Auto-generated method stub
- String strDigest = "";
- for(int i = 0; i < digest.length; i++){
- strDigest += byteToHexStr(digest[i]);
- }
- return strDigest;
- }
- /**
- * 將字節轉換為十六進制字符串
- * @param b
- * @return
- */
- private static String byteToHexStr(byte b) {
- // TODO Auto-generated method stub
- char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
- char[] tempArr = new char[2];
- tempArr[0] = Digit[(b >>> 4) & 0X0F];
- tempArr[1] = Digit[b & 0X0F];
- String s = new String(tempArr);
- return s;
- }
- }
代碼添加完畢, 工程右鍵,刪除工程中的 ROOT.war 包, 然后工程右鍵 重新 打包一個 ROOT.war 包,名字必須和原來一樣,保存地址也和原來一樣,具體是,右鍵 --> Export --> WAR file:


導出后,項目右鍵刷新工程,包 ROOT.war 就會重新出現在工程中,然后我們提交我們的工程到百度 BAE 上就行了,具體做法看下面。
5、提交修改后的代碼
工程右鍵 --> Team --> 提交 --> ok, 如圖 18


圖 18
如果要驗證,就輸入你的百度賬號密碼,提交成功后,部署列表狀態欄會顯示“有新版”,此時點擊“快捷發布”也等同上線。如圖 19 所示:


圖 19
發布后,點擊查看,在彈出頁面的地址中添加上面叫你記住的那個
URL mappings
,如果你沒有改過,默認是“
/CoreServlet
”,如果你 實在忘了,可以到
你的類
CoreServlet 中找到這個語句:
@WebServlet(
"/CoreServlet"
),就是這個后綴,舉
個例子,例如你點擊查看的網站是
< http://weitest.duapp.com > ,添加后綴后的地址是 < http://weitest.duapp.com
/CoreServlet > 填完網址后回車,就能看到如下頁面:

看到此畫面就說明你離成功只差一步了,記住復制此網頁的地址備用。
6、成為微信開發者
打開微信公眾平台 -> 高級功能 -> 開發者模式,見圖 20:


將我們剛才復制的地址黏貼到 URL ;
在填寫 Token 之前,也回到我們的項目,在類 SignUtil 中有這么一句代碼:
- private static String token = "weixinface";
代碼中的 token 的值我們可以隨意寫,但是,這里是什么值,在微信平台上就要填寫對應的內容,所有,在 Token 那里填上 weixinface,點擊“提交”,如果代碼沒有問題,瞬間你就可以看到“你已成為開發者” 的提示:如圖 22


圖 22
到此,所有的工作都已經完成,你可以不斷豐富你的代碼,實現不同的功能。你也可以在自己的微信中關注自己的訂閱號,只需掃描公眾平台的二維碼就行了。
擴展說明:
其實,上述提交代碼到百度 BAE 中的這么一個操作,我覺得更多的是將 BAE 作為一個谷倉,就是一個存放代碼的服務器來用,以方便我們在任何地方都可以通過 SVN 工具檢出我們的代碼,從而隨時開始我們的項目,特別是多人一起做的項目,而微信 Token 認證訪問的其實只有 ROOT.war 這個包,不信,你可以另外安裝一個 SVN 工具,重新打包 ROOT.war,並通過 SVN 將 ROOT.war 這個包提交到 BAE 上,一樣可以通過微信 Token 驗證,我的另外一篇博客就是僅僅提交 ROOT.war 這個包的,有興趣的可以去看看,但是,這是為什么?其實也很簡單,我們打包的 ROOT.war 中其實已經有我們的所以源代碼了,你可以解壓 ROOT.war 文件,看看里面到底有些什么東西,你就會懂的。