今天正式开始微信公众平台的二次开发。网上有很多的及射入微信公众平台的教程。总的来说都差不多,当了解了接入流程解析,什么都显得理所当然。
所以我们还是先看微信给出的官网文档吧:
地址:http://mp.weixin.qq.com/wiki/8/f9a0b8382e0b77d87b3bcc1ce6fbc104.html
通过文档我们可以看出其中接入微信公众平台开发,开发者需要按照如下步骤完成:
按照开发文档我们知道我们的应用服务器需要接受微信服务器的get请求,其中包含四个参数(signature、timestamp、nonce、echostr)然后通过校验方式校验服务器的可靠性,校验方式如下:
①我在这里写了一个工具类去实现其中的前两步,将三个参数排序并返回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、这个时候我们再次重启本地服务器,然后提交接口配置信息就大功告成了。