BAT一直以來是許多程序猿的奮鬥目標,但若是有幸可以進入其中學習卻連自家的平臺API都沒辦法調用,那就有點說不過去了。所以,我這段時間一直在學習JAVA微信之間的對接開發,也從中看到了BAT的嚴謹之處。php
最好的參考工具(官方文檔):公衆平臺開發者文檔
參考博客:souvc的博客
測試接口:微信公衆號平臺接口測試
jdk:1.8
IDE:IDEA
服務器:騰訊雲(對學生有較大優惠)html
經過閱讀官方文檔,能夠得知若要接入微信公衆號平臺開發,開發者須要按照如下三步流程:
1. 填寫服務器配置
2. 驗證服務器地址的有效性
3. 依據接口文檔來實現業務邏輯java
咱們的應用服務器要接受微信服務器的get請求,其中包括四個參數(signature、timestamp、nonce、echostr),開發者經過檢驗signature對請求進行校驗(下面有校驗方式)。若確認這次GET請求來自微信服務器,請原樣返回echostr參數內容,則接入生效,成爲開發者成功,不然接入失敗。
注意:具體內容含義能夠經過閱讀官方文檔得知!
由官方文檔,咱們可知加密/校驗流程以下:
- 將token、timestamp、nonce三個參數進行字典序排序
- 將三個參數字符串拼接成一個字符串進行SHA1加密(SHA1加密在接下來的開發,有興趣的話能夠去了解一下)
- 開發者得到加密後的字符串可與signature對比,標識該請求來源於微信git
ps:微信提供了一份php示例代碼,有興趣的能夠了解一下spring
接下來,我將前兩個步驟合爲一個工具類去實現。廢話很少說,咱們直接上代碼。數組
/** * SignUtil * 驗證 signature 工具類 * Created by zggdczfr on 2016/10/21. */ public class SignUtil { //與接口配置信息中的ToKen一致 private static String token = ""; //該Token值爲本身定義 public static boolean checkSignature(String signature, 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 messageDigest = null; String tmpStr = null; try { // 將三個參數字符串拼接成一個字符串進行sha1加密 messageDigest = MessageDigest.getInstance("SHA-1"); byte[] digest = messageDigest.digest(content.toString().getBytes()); tmpStr = byteToStr(digest); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } content = null; // 3. 將sha1加密後的字符串可與signature對比,標識該請求來源於微信 return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; } /** * 將字節數組轉換爲十六進制字符串 * @param byteArray * @return */ private static String byteToStr(byte[] byteArray){ String strDigest = ""; for(int i=0; i < byteArray.length; i++){ strDigest += byteToHexStr(byteArray[i]); } return strDigest; } /** * 將字節轉換爲十六進制字符串 * @param mByte * @return */ private static String byteToHexStr(byte mByte){ 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[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; } }
接下來是實現第三步,這裏須要注意的一點是:微信提過get方法來驗證身份,經過post方法來實現信息的傳遞,也就是說之後的業務邏輯實現都將經過這裏配置的連接來對接。服務器
/** * Created by zggdczfr on 2016/10/21. */ @Controller @RequestMapping(value = "/wechat") public class SecurityController { private static final long serialVersionUID = 4323197796926899691L; private static final Logger LOGGER = Logger.getLogger(SecurityController.class); @RequestMapping("test") public String test(){ System.out.println("test"); return "/index.jsp"; } @RequestMapping(value = "security", method = RequestMethod.GET) public void WetChatGet(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "signature", required = true) String signature, @RequestParam(value = "timestamp", required = true) String timestamp, @RequestParam(value = "nonce", required = true) String nonce, @RequestParam(value = "echostr", required = true) String echostr) throws IOException { try { // 經過檢驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,不然接入失敗 if (SignUtil.checkSignature(signature, timestamp, nonce)) { PrintWriter out = response.getWriter(); out.print(echostr); out.close(); } } catch (Exception e){ LOGGER.log(Level.ERROR, "鏈接微信公衆號平臺測試失敗!"); } System.out.println("鏈接微信公衆號平臺測試成功!"); } @RequestMapping(value = "security", method = RequestMethod.POST) public void WetChatPost(HttpServletRequest request, HttpServletResponse response){ //業務邏輯處理 } }
接下來就是將咱們的代碼打包部署到服務器上來,經過測試接口來進行對接。
測試結果:
微信