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

1 /** 2 * 核心請(qǐng)求處理類 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 // 時(shí)間戳 13 String timestamp = request.getParameter("timestamp"); 14 // 隨機(jī)數(shù) 15 String nonce = request.getParameter("nonce"); 16 // 隨機(jī)字符串 17 String echostr = request.getParameter("echostr"); 18 PrintWriter out = response.getWriter(); 19 // 通過(guò)檢驗(yàn)signature對(duì)請(qǐng)求進(jìn)行校驗(yàn),若校驗(yàn)成功則原樣返回echostr,表示接入成功,否則接入失敗 20 if (SignUtil.checkSignature(signature, timestamp, nonce)) { 21 out.print(echostr); 22 } 23 out.close();24 out = null;25 }servlet中的doGet()

1 /** 2 * 請(qǐng)求校驗(yàn)工具類 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 //從請(qǐng)求中(也就是微信服務(wù)器傳過(guò)來(lái)的)拿到的token, timestamp, nonce12 String[] arr = new String[] { token, timestamp, nonce };13 // 將token、timestamp、nonce三個(gè)參數(shù)進(jìn)行字典序排序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 // 將三個(gè)參數(shù)字符串拼接成一個(gè)字符串進(jìn)行sha1加密25 byte[] digest = md.digest(content.toString().getBytes());26 //將字節(jié)數(shù)組轉(zhuǎn)成字符串27 tmpStr = byteToStr(digest);28 } catch (NoSuchAlgorithmException e) {29 e.printStackTrace();30 }31 32 content = null;33 // 將sha1加密后的字符串可與signature對(duì)比,標(biāo)識(shí)該請(qǐng)求來(lái)源于微信34 return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;35 }36 37 //將加密后的字節(jié)數(shù)組變成字符串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 }驗(yàn)證核心代碼再sae上配置好后,點(diǎn)擊開(kāi)發(fā)者中心,首先啟用服務(wù)器配置。填寫(xiě)url和token(和java代碼中的一樣)、EncodingAESKey是隨機(jī)生成,消息加解密方式選擇明文模式。
這里的url就是你在sae中創(chuàng)建應(yīng)用的地址,我們已經(jīng)將寫(xiě)好的java代碼上傳到這個(gè)地址。token是微信服務(wù)器和sae服務(wù)器進(jìn)行對(duì)接驗(yàn)證是用到的(必須保持一致),消息
加密暫時(shí)選擇明文模式,如果選擇加密模式需要編寫(xiě)加密代碼,以后會(huì)再轉(zhuǎn)到加密或兼容模式,這里先用明文模式。這樣我們就完成了,點(diǎn)擊提交(記得sae服務(wù)器要打開(kāi)),
如果現(xiàn)實(shí)成功就說(shuō)明接入完成,我們可以接著做下面的工作了。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注