微信公眾平台開發好像已經火了很長一段時間,我好像有點后知后覺。但只從了解它后便有點不可收拾之勢,腦袋里總想着開發一個自己的公眾號,雖然不知道具體做什么。
下面就說說自己這段時間對公眾號的學習。
欲善其事,必先利其器。在開發之前先要申請一個公眾號,公眾號有三種,個人比較容易申請的是訂閱號,服務號還要審核,稍微麻煩一點,對於個人開發我建議申請服務號,
因為后面會做自定義菜單的功能。再就是我們需要有一個公網的服務器,這個可以申請sina的sae和百度的bae,個人比較喜歡sina的一點,比較容易上手。這里不講公眾號的申請
和sae服務器的申請和配置。
再做完這兩件事后我們就可以開始公眾號的開發了。首先我們需要了解微信公眾號的工作流程,對其有個整體的把握,要不今后就會換挺多簡單錯誤。在啟用開發者模式情況下
(下面內容都是在此模式下)當用戶通過微信客服端發送消息到微信服務后,微信服務器會將此消息轉發給我們的公網服務器,如上面所說sae和bae(以下內容也均是在sae下完成)
。具體的業務邏輯就在sae上完成,處理完后再將結果發回微信服務器,微信服務器再發給用戶。
申請到公眾號后,登陸公眾品台,可以看到微信已經幫我們准備好了許多功能,我們不需要編寫任何代碼就可以完成一個具有基本的公眾號,但這不是本文的目的,我們是要
用自己的代碼實現一些功能,因此我們要進入開發者中心去配置服務器接口。
下面就是本文核心內容:
試想一下讓兩個完全不沾邊的服務器(微信服務器和sae)對接的風險,因此必須有什么驗證機制的存在。具體的驗證過程是
1、微信服務器會以get方式調用我們部署在sae服務器上的servlet,並傳signature、timestamp、nonce、echostr四個參數。其中signature是微信加密簽名;timestamp
是時間戳,防止即使有別有用心之人獲得另外的參數而因時間戳的不一致無法完成驗證;nonce是隨機數;echostr是隨機字符串,用於返回給微信服務器作比較。
2、servlet接收到以上數據后,會將token(在servlet中寫好且要用公眾平台上開發者中心的token相同)timestamp、nonce按字典方式排序,再拼接成字符串進行sha1加密
將加密后的字符串與signature比較,如果相同就返回echostr。
3、微信服務器接收到返回的echostr,與發過去的echostr相比較,如果相同,就接入成功,否則失敗。

1 /** 2 * 核心請求處理類 3 * 4 */ 5 public class CrazyServlet extends HttpServlet { 6 7 private static final long serialVersionUID = 5021188348833856475L; 8 @Override 9 protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { 10 // 微信加密簽名 11 String signature = request.getParameter("signature"); 12 // 時間戳 13 String timestamp = request.getParameter("timestamp"); 14 // 隨機數 15 String nonce = request.getParameter("nonce"); 16 // 隨機字符串 17 String echostr = request.getParameter("echostr"); 18 PrintWriter out = response.getWriter(); 19 // 通過檢驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,否則接入失敗 20 if (SignUtil.checkSignature(signature, timestamp, nonce)) { 21 out.print(echostr); 22 } 23 out.close(); 24 out = null; 25 }

1 /** 2 * 請求校驗工具類 3 */ 4 public class SignUtil { 5 // 與接口配置信息中的Token要一致 6 private static String token = "845C2550903CE6FA54CACDB82EAD4350"; 7 8 9 public static boolean checkSignature(String signature, String timestamp, 10 String nonce) { 11 //從請求中(也就是微信服務器傳過來的)拿到的token, timestamp, nonce 12 String[] arr = new String[] { token, timestamp, nonce }; 13 // 將token、timestamp、nonce三個參數進行字典序排序 14 sort(arr); 15 StringBuilder content = new StringBuilder(); 16 for (int i = 0; i < arr.length; i++) { 17 content.append(arr[i]); 18 } 19 MessageDigest md = null; 20 String tmpStr = null; 21 22 try { 23 md = MessageDigest.getInstance("SHA-1"); 24 // 將三個參數字符串拼接成一個字符串進行sha1加密 25 byte[] digest = md.digest(content.toString().getBytes()); 26 //將字節數組轉成字符串 27 tmpStr = byteToStr(digest); 28 } catch (NoSuchAlgorithmException e) { 29 e.printStackTrace(); 30 } 31 32 content = null; 33 // 將sha1加密后的字符串可與signature對比,標識該請求來源於微信 34 return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; 35 } 36 37 //將加密后的字節數組變成字符串 38 private static String byteToStr(byte[] byteArray) { 39 String strDigest = ""; 40 for (int i = 0; i < byteArray.length; i++) { 41 strDigest += byteToHexStr(byteArray[i]); 42 } 43 return strDigest; 44 } 45 46 private static String byteToHexStr(byte mByte) { 47 char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 48 'B', 'C', 'D', 'E', 'F' }; 49 char[] tempArr = new char[2]; 50 tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; 51 tempArr[1] = Digit[mByte & 0X0F]; 52 53 String s = new String(tempArr); 54 return s; 55 } 56 //用於字典排序 57 public static void sort(String a[]) { 58 for (int i = 0; i < a.length - 1; i++) { 59 for (int j = i + 1; j < a.length; j++) { 60 if (a[j].compareTo(a[i]) < 0) { 61 String temp = a[i]; 62 a[i] = a[j]; 63 a[j] = temp; 64 } 65 } 66 } 67 } 68 }
再sae上配置好后,點擊開發者中心,首先啟用服務器配置。填寫url和token(和java代碼中的一樣)、EncodingAESKey是隨機生成,消息加解密方式選擇明文模式。
這里的url就是你在sae中創建應用的地址,我們已經將寫好的java代碼上傳到這個地址。token是微信服務器和sae服務器進行對接驗證是用到的(必須保持一致),消息
加密暫時選擇明文模式,如果選擇加密模式需要編寫加密代碼,以后會再轉到加密或兼容模式,這里先用明文模式。這樣我們就完成了,點擊提交(記得sae服務器要打開),
如果現實成功就說明接入完成,我們可以接着做下面的工作了。