Java微信公眾平台開發(一)–接入微信公眾平台 一、驗證服務器代碼編寫。二、服務器端驗證。

  • 2019 年 10 月 5 日
  • 筆記

今天正式開始微信公眾平台的二次開發。網上有很多的及射入微信公眾平台的教程。總的來說都差不多,當了解了接入流程解析,什麼都顯得理所當然。

所以我們還是先看微信給出的官網文檔吧:

地址:http://mp.weixin.qq.com/wiki/8/f9a0b8382e0b77d87b3bcc1ce6fbc104.html

通過文檔我們可以看出其中接入微信公眾平台開發,開發者需要按照如下步驟完成:

  • 填寫服務器配置
  • 驗證服務器地址的有效性
  • 依據接口文檔實現業務邏輯

一、驗證服務器代碼編寫。

按照開發文檔我們知道我們的應用服務器需要接受微信服務器的get請求,其中包含四個參數(signature、timestamp、nonce、echostr)然後通過校驗方式校驗服務器的可靠性,校驗方式如下:

  • 將token、timestamp、nonce三個參數進行字典序排序
  • 將三個參數字符串拼接成一個字符串進行sha1加密
  • 開發者獲得加密後的字符串可與signature對比,標識該請求來源於微信

①我在這裡寫了一個工具類去實現其中的前兩步,將三個參數排序並返回sha1加密後的字符串,代碼如下:

 1 package com.gede.wechat.util;   2   3 import java.security.MessageDigest;   4 import java.security.NoSuchAlgorithmException;   5 import java.util.Arrays;   6   7 /**   8 * @author gede   9 * @version date:2019年5月22日 下午2:50:43  10 * @description :  11 */  12 public class SignUtil {  13     // 與接口配置信息中的 Token 要一致  14     private static String token = "gede";  15     /**  16      * 驗證簽名  17      * @param signature  18      * @param timestamp  19      * @param nonce  20      * @return  21      */  22     public static boolean checkSignature(String signature, String timestamp, String nonce) {  23         String[] arr = new String[] { token, timestamp, nonce };  24         // 將 token、timestamp、nonce 三個參數進行字典序排序  25         Arrays.sort(arr);  26         StringBuilder content = new StringBuilder();  27         for (int i = 0; i < arr.length; i++) {  28             content.append(arr[i]);  29         }  30         MessageDigest md = null;  31         String tmpStr = null;  32  33         try {  34             md = MessageDigest.getInstance("SHA-1");  35             // 將三個參數字符串拼接成一個字符串進行 sha1 加密  36             byte[] digest = md.digest(content.toString().getBytes());  37             tmpStr = byteToStr(digest);  38         } catch (NoSuchAlgorithmException e) {  39             e.printStackTrace();  40         }  41  42         content = null;  43         // 將 sha1 加密後的字符串可與 signature 對比,標識該請求來源於微信  44         return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;  45     }  46  47     /**  48      * 將位元組數組轉換為十六進制字符串  49      * @param byteArray  50      * @return  51      */  52     private static String byteToStr(byte[] byteArray) {  53         String strDigest = "";  54         for (int i = 0; i < byteArray.length; i++) {  55             strDigest += byteToHexStr(byteArray[i]);  56         }  57         return strDigest;  58     }  59  60     /**  61      * 將位元組轉換為十六進制字符串  62      * @param mByte  63      * @return  64      */  65     private static String byteToHexStr(byte mByte) {  66         char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };  67         char[] tempArr = new char[2];  68         tempArr[0] = Digit[(mByte >>> 4) & 0X0F];  69         tempArr[1] = Digit[mByte & 0X0F];  70         String s = new String(tempArr);  71         return s;  72     }  73 }

②將我們的工具類應用到我們的服務器驗證過程中,這裡我新建一個controller為WechatSecurity,實現同一個get用於接收參數和返回驗證參數,簡單代碼如下:

 1 package com.gede.wechat.controller;   2   3 import java.io.PrintWriter;   4   5 import javax.servlet.http.HttpServletRequest;   6 import javax.servlet.http.HttpServletResponse;   7   8 import org.apache.log4j.Logger;   9 import org.springframework.stereotype.Controller;  10 import org.springframework.web.bind.annotation.RequestMapping;  11 import org.springframework.web.bind.annotation.RequestMethod;  12 import org.springframework.web.bind.annotation.RequestParam;  13  14 import com.gede.wechat.util.SignUtil;  15  16 /**  17 * @author gede  18 * @version date:2019年5月22日 下午2:53:46  19 * @description :  20 */  21 @Controller  22 @RequestMapping("/wechat")  23 public class WechatSecurity {  24     private static Logger logger = Logger.getLogger(WechatSecurity.class);  25  26     @RequestMapping(value = "security", method = RequestMethod.GET)  27     public void doGet(  28             HttpServletRequest request,  29             HttpServletResponse response,  30             @RequestParam(value = "signature", required = true) String signature,  31             @RequestParam(value = "timestamp", required = true) String timestamp,  32             @RequestParam(value = "nonce", required = true) String nonce,  33             @RequestParam(value = "echostr", required = true) String echostr) {  34         try {  35             if (SignUtil.checkSignature(signature, timestamp, nonce)) {  36                 PrintWriter out = response.getWriter();  37                 out.print(echostr);  38                 out.close();  39             } else {  40                 logger.info("這裡存在非法請求!");  41             }  42         } catch (Exception e) {  43             logger.error(e, e);  44         }  45     }  46  47     @RequestMapping(value = "security", method = RequestMethod.POST)  48     // post方法用於接收微信服務端消息  49     public void DoPost() {  50         System.out.println("這是post方法!");  51     }  52 }

那麼到這裡我們的服務器驗證的代碼就基本完成了,下面我們就進入驗證過程!

二、服務器端驗證。

 1、首先要將我們的內網穿透工具運行起來,然後再本地服務器上運行我們的項目。

 2.、在這裡我用的是測試號,其他的大家對號入座。測試號登錄網址 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

3、當我們點擊提交時,發現提交失敗。原因是之前忘記配置springMVC ,在準備工作中我們只是開啟了spring功能,現在我們開始配置springMVC

  在我們項目的src 下,新增appServlet.xml配置文件。開啟mvc,並指明mvc掃描包,代碼如下:

<?xml version="1.0" encoding="UTF-8"?>  <beans xmlns="http://www.springframework.org/schema/beans"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xmlns:p="http://www.springframework.org/schema/p"      xmlns:context="http://www.springframework.org/schema/context"      xmlns:mvc="http://www.springframework.org/schema/mvc"      xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">      <mvc:annotation-driven></mvc:annotation-driven>      <mvc:default-servlet-handler/>      <context:component-scan base-package="com.gede.wechat.controller"></context:component-scan>      <bean id="viewResolver"          class="org.springframework.web.servlet.view.InternalResourceViewResolver">          <property name="prefix" value="/WEB-INF/"></property>          <property name="suffix" value=".jsp"></property>      </bean>  </beans>

4、再打開我們的web.xml,添加appServlet.xml的掃描。

<?xml version="1.0" encoding="UTF-8"?>  <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">    <display-name>mychat</display-name>    <listener>      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>    </listener>    <context-param>      <param-name>contextConfigLocation</param-name>      <param-value>classpath:applicationContext.xml</param-value>    </context-param>      <servlet>        <servlet-name>appServlet</servlet-name>          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>          <init-param>              <param-name>contextConfigLocation</param-name>              <param-value>              classpath:appServlet.xml              </param-value>          </init-param>        <load-on-startup>1</load-on-startup>    </servlet>

5、這個時候我們再次重啟本地服務器,然後提交接口配置信息就大功告成了。