上一章给大家分享的是开发微信公众号(三) , 今天继续更新第四篇 搭建本地测试环境。
- 推荐一款软件: Ngrok(内网穿透工具)
Ngrok可以实现内网穿透,也就是说我们可以将内网的服务器映射到外网给别人访问,这对于我们在本地开发环境中调试微信代码是以及给用户演示一些东西非常快速和有帮助的,因为可以直接使用我们自己的内网的电脑作为服务器。不过需要翻墙访问。
国内提供Ngrok服务的网站:https://natapp.cn/
因为微信公众号开发要进行调试,每次实现功能后都需要部署到公网服务器进行测试,所以我们需要把内网的部署服务器映射到外网,让微信服务器可以正常访问到。
一.注册natapp账号
- 实名认证
- 购买隧道
二. 下载natapp客户端
2. 安装natapp
win/Mac/Linux安装步骤详细参考博客:http://blog.csdn.net/xunxianren007/article/details/54954520
1.双击natapp
2.输入natapp命令
3. 复制之前natapp账号购买的authtoken, 执行 natapp -authtoken + your authtoken
微信公众平台接入
接入概述
在微信公众平台开发者文档上,接入指南上写的比较详细的,文档中说接入公众号需要3个步骤,分别是:
1、填写服务器配置
2、验证服务器地址的有效性
3、依据接口文档实现业务逻辑
第一步:填写服务器配置
第1步中服务器配置包含服务器地址(URL)、令牌(Token) 和 消息加解密密钥(EncodingAESKey)
在登录微信公众平台官网开发–>基本设置页面–>服务器配置中配置
1. 服务器地址(URL)即公众号后台提供业务逻辑的入口地址,目前只支持80端口,之后包括接入验证以及任何其它的操作的请求(例如消息的发送、菜单管理、素材管理等)都要从这个地址进入。接入验证和其它请求的区别就是,接入验证时是get请求,其它时候是post请求;
2. Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性);
3. EncodingAESKey由开发者手动填写或随机生成,将用作消息体加解密密钥。本例中全部以未加密的明文消息方式,不涉及此配置项。
第二步:验证消息的确来自微信服务器
第2步,验证服务器地址的有效性,当点击“提交”按钮后,微信服务器将发送一个http的get请求到刚刚填写的服务器地址,并且携带四个参数:
接到请求后,我们需要做如下三步,若确认此次GET请求来自微信服务器,原样返回echostr参数内容,则接入生效,否则接入失败。
1. 将token、timestamp、nonce三个参数进行字典序排序
2. 将三个参数字符串拼接成一个字符串进行sha1加密 (可逆加密解密函数)
3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
下面我们用Java代码来演示一下这个验证过程
使用IntelliJ IDEA创建一个JavaWeb项目,代码如下:
- 新建Servlet项目
package com.qj.servlet;
import com.qj.util.CheckUtil;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/*
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\ = /O
____/`---'\____
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||- \
| | \\\ - /// | |
| \_| ''\---/'' | |
\ .-\__ `-` ___/-. /
___`. .' /--.--\ `. . __
."" '< `.___\_<|>_/___.' >'"".
| | : `- \`.;`\ _ /`;.`/ - ` : | |
\ \ `-. \_ __\ /__ _/ .-` / /
======`-.____`-.___\_____/___.-`____.-'======
`=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
佛祖保佑 永无BUG
*/
@WebServlet(name = "WeixinServlet")
public class WeixinServlet extends HttpServlet {
/*
* 自定义token, 用作生成签名,从而验证安全性
* */
private final String TOKEN = "qingjian";
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("-----开始校验签名-----");
/**
* 接收微信服务器发送请求时传递过来的参数
*/
String signature = request.getParameter("signature");//
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce"); //随机数
String echostr = request.getParameter("echostr");//随机字符串
/**
* 将token、timestamp、nonce三个参数进行字典序排序
* 并拼接为一个字符串
*/
String sortStr = sort(TOKEN,timestamp,nonce);
/**
* 字符串进行shal加密
*/
String mySignature = shal(sortStr);
/**
* 校验微信服务器传递过来的签名 和 加密后的字符串是否一致, 若一致则签名通过
*/
if(!"".equals(signature) && !"".equals(mySignature) && signature.equals(mySignature)){
System.out.println("-----签名校验通过-----");
response.getWriter().write(echostr);
}else {
System.out.println("-----校验签名失败-----");
}
}
/**
* 参数排序
* @param token
* @param timestamp
* @param nonce
* @return
*/
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();
}
/**
* 字符串进行shal加密
* @param str
* @return
*/
public String shal(String str){
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update(str.getBytes());
byte messageDigest[] = digest.digest();
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 "";
}
}
- 在web.xml中配置 servlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>WeixinServlet</servlet-name>
<servlet-class>com.qj.servlet.WeixinServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WeixinServlet</servlet-name>
<url-pattern>/WeixinServlet</url-pattern>
</servlet-mapping>
</web-app>
- 在index.jsp中编写hello world 测试
<%--
Created by IntelliJ IDEA.
User: qingjian
Date: 2019/9/12
Time: 12:17
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>微信公众号测试</title>
</head>
<body>
Hello World !
</body>
</html>
- 启动natapp,进行内网穿透
cmd输入命令:natapp -authtoken your token
进入微信测试公众号管理界面,在接口配置信息中填入映射的外网地址和代码中声明的token(注意: URL是 外网的ip地址加上 web.xml中配置的servlet名称)如下图所示:
点击提交,会显示配置成功, 控制台就会打印信息, 显示签名校验通过
到此,我们的微信公众号应用已经能够和微信服务器正常通信