在上一篇《微信公衆號開發(一)——環境搭建》中咱們已經準備好了微信公衆號開發環境,那麼接下來咱們要真正的開始進行公衆號的實際開發之旅。html
在真正的開發公衆號以前咱們必需要接入微信公衆平臺,那爲何要接入、如何接入本文就這些問題一一解答;java
首先咱們來了解一下接入平臺的原理,而後再貼出代碼上手實踐測試。web
微信服務器就至關於一個轉發服務器,終端(手機、Pad等)發起請求至微信服務器,微信服務器而後將請求轉發給咱們的應用服務器。應用服務器處理完畢後,將響應數據回發給微信服務器,微信服務器再將具體響應信息回覆到微信App終端。spring
通訊協議爲:HTTPjson
數據傳輸格式爲:XML數組
具體的流程以下圖所示:安全
來一張更加直觀的圖吧:springboot
咱們須要作的事情,就是對微信服務器轉發的HTTP請求作出響應。具體的請求內容,咱們按照特定的XML格式去解析,處理完畢後,也要按照特定的XML格式返回。服務器
在微信公衆平臺開發者文檔上,關於公衆號接入這一節內容在接入指南上寫的比較詳細的,文檔中說接入公衆號須要3個步驟,分別是:微信
一、填寫服務器配置
二、驗證服務器地址的有效性
三、依據接口文檔實現業務邏輯
其實,第3步已經不能算作公衆號接入的步驟,而是接入以後,開發人員能夠根據微信公衆號提供的接口所能作的一些開發。
第1步中服務器配置包含服務器地址(URL)、Token和EncodingAESKey。
服務器地址即公衆號後臺提供業務邏輯的入口地址,目前只支持80端口,以後包括接入驗證以及任何其它的操做的請求(例如消息的發送、菜單管理、素材管理等)都要從這個地址進入。接入驗證和其它請求的區別就是,接入驗證時是get請求,其它時候是post請求;
Token可由開發者能夠任意填寫,用做生成簽名(該Token會和接口URL中包含的Token進行比對,從而驗證安全性);
EncodingAESKey由開發者手動填寫或隨機生成,將用做消息體加解密密鑰。本例中所有以未加密的明文消息方式,不涉及此配置項。
以測試帳號爲例:
第1步 配置咱們的服務器參數
咱們點擊修改按鈕輸入url和token點擊提交;
第2步,驗證服務器地址的有效性,當點擊「提交」按鈕後,微信服務器將發送一個http的get請求到剛剛填寫的服務器地址,而且攜帶四個參數:
接到請求後,咱們須要作以下三步,若確認這次GET請求來自微信服務器,原樣返回echostr參數內容,則接入生效,不然接入失敗。
1. 將token、timestamp、nonce三個參數進行字典序排序
2. 將三個參數字符串拼接成一個字符串進行sha1加密
3. 開發者得到加密後的字符串可與signature對比,標識該請求來源於微信
第3步 依據接口文檔實現業務邏輯
驗證URL有效性成功後即接入生效,成爲開發者。你能夠在公衆平臺網站中申請微信認證,認證成功後,將得到更多接口權限,知足更多業務需求。
成爲開發者後,用戶每次向公衆號發送消息、或者產生自定義菜單、或產生微信支付訂單等狀況時,開發者填寫的服務器配置URL將獲得微信服務器推送過來的消息和事件,開
發者能夠依據自身業務邏輯進行響應,如回覆消息。
公衆號調用各接口時,通常會得到正確的結果,具體結果可見對應接口的說明。返回錯誤時,可根據返回碼來查詢錯誤緣由。全局返回碼說明
用戶向公衆號發送消息時,公衆號方收到的消息發送者是一個OpenID,是使用用戶微信號加密後的結果,每一個用戶對每一個公衆號有一個惟一的OpenID
一、首先咱們要建立一個java web 工程
二、建立一個controller 來進行服務器的驗證
package com.quanlian.controller; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import util.NetWorkHelper; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.quanlian.entity.AccessToken; import com.quanlian.entity.AccessTokenInfo; import com.quanlian.runner.MyApplicationRunner; @RestController public class WxController { private final String TOKEN = "super"; @RequestMapping(value="/hello") public String hello(){ return "hello"; } @RequestMapping(value = "wx") public String wxcheck(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException { String method = request.getMethod(); System.out.println(method); if(method.equals("POST")){ return wxMessage(request,response); }else{ String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); System.out.println(echostr); //排序 String sortString = sort(TOKEN, timestamp, nonce); //加密 String mySignature = sha1(sortString); if(signature!=null&&signature!=""&&signature.equals(mySignature)){ System.out.println("簽名校驗經過。"); return echostr; }else{ System.out.println("簽名校驗失敗."); return "xxxx"; } } } @RequestMapping(value="wxMessage",method=RequestMethod.POST) public String wxMessage(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException{ request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); System.out.println("請求進入"); String result = ""; try { Map<String,String> map = MessageHandlerUtil.parseXml(request); System.out.println("開始構造消息"); result = MessageHandlerUtil.buildXml(map); System.out.println(result); if(result.equals("")){ result = "未正確響應"; } } catch (Exception e) { e.printStackTrace(); System.out.println("發生異常:"+ e.getMessage()); } return result; } /** * 排序 */ public String sort(String token, String timestamp, String nonce){ String[] strArray = {token,timestamp,nonce}; Arrays.sort(strArray); StringBuilder sb = new StringBuilder(); for(String str : strArray){ sb.append(str); } return sb.toString(); } /** * 進行sha1加密 */ public String sha1(String str){ try { MessageDigest digest = MessageDigest.getInstance("SHA-1"); digest.update(str.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuffer hexString = new StringBuffer(); // 字節數組轉換爲 十六進制 數 for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } }
三、啓動咱們的服務,這裏直接運行SpringbootApplication.java就能夠了 我使用的是springboot 有關springboot 的知識請自行百度
四、運行咱們的natapp.exe 將咱們的服務映射到外網
五、將映射的http地址配置到測試帳號中
這裏的 URL必定要保證和natapp中映射的外網地址相匹配;
六、咱們的服務後臺是打印出以下信息表示咱們的本地服務器配置成功
Ok到這裏本文關於接入服務器的演示完畢!