閱讀本文前,請先認真閱讀微信官方文檔:微信公衆號技術文檔之接入指南
接入概述
接入微信公衆平臺開發,開發者需要按照如下步驟完成:
1、填寫服務器配置
2、驗證服務器地址的有效性
3、依據接口文檔實現業務邏輯
本文主要介紹第二個步驟的代碼實現。
第二步:驗證消息的確來自微信服務器
-
開發者提交信息後,微信服務器將發送GET請求到填寫的服務器地址URL上
(由於消息加解密方式選擇的爲明文模式,需加密模式時從官方文檔下載Java部分代碼,去除註釋部分代碼即可)/** * 消息加解密接入 */ public class EntryController extends Controller { public void accept() throws IOException { String method = getRequest().getMethod(); if ("GET".equals(method)) { doGet();//開發者模式驗證 }else { doPost();//接收消息 } } /* * 響應get請求,微信默認token校驗時使用get請求 */ private void doGet(){ //接收微信用來校驗信息的內置規定參數 String msgSignature =getPara("signature"); // 微信加密簽名 String timeStamp = getPara("timestamp"); // 時間戳 String nonce = getPara("nonce"); // 隨機數 String echoStr = getPara("echostr"); // 隨機字符串 //// 創建加密類 //WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(WechartConst.Token, WechartConst.EncodingAESKey,WechartConst.appId); // // 比對msgSignature 用token, timeStamp, nonce加密的參數是否一致,一致證明該接口來自微信,異常則不是來自微信 //String echostr = wxcpt.verifyUrl(msgSignature, timeStamp, nonce, echoStr); // 通過檢驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,否則接入失敗 //獲取微信服務器中配置的Token的值 String token = SystemConfig.WECHAT_TOKEN; if (WechatUtil.checkSignature(msgSignature,token, timeStamp, nonce)){ //原樣返回echostr參數內容 renderJson(echoStr); } } }
-
開發者通過檢驗signature對請求進行校驗(下面有校驗方式)。若確認此次GET請求來自微信服務器,請原樣返回echostr參數內容,則接入生效,成爲開發者成功,否則接入失敗。加密/校驗流程如下:
1)將token、timestamp、nonce三個參數進行字典序排序
2)將三個參數字符串拼接成一個字符串進行sha1加密
3)開發者獲得加密後的字符串可與signature對比,標識該請求來源於微信public class WechatUtil { /** * 驗證消息的確來自微信服務器 * @param msgSignature 微信加密簽名 * @param token 開發者填寫的token參數 * @param timeStamp 時間戳 * @param nonce 隨機數 * @return * @throws */ public static boolean checkSignature(String msgSignature, String token,String timeStamp, String nonce) { // 1.將token、timestamp、nonce三個參數進行字典序排序 String[] arr = new String[]{token, timeStamp, nonce}; Arrays.sort(arr); // 2. 將三個參數字符串拼接成一個字符串進行sha1加密 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"); // 將三個參數字符串拼接成一個字符串進行sha1加密 byte[] digest = md.digest(content.toString().getBytes()); tmpStr = BytesParserUtil.byteToStr(digest); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } // 3.將sha1加密後的字符串可與signature對比,標識該請求來源於微信 return tmpStr != null ? tmpStr.equals(msgSignature.toUpperCase()) : false; } }
注:代碼中使用到的工具類請參考: 字節轉換工具---- BytesParserUtil