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、这个时候我们再次重启本地服务器,然后提交接口配置信息就大功告成了。