(1)去 基于ngrok的国内高速内网穿透设备 就是NATAPP,不使用ngrok 的原因就是下载的有点慢,natapp 下载得很快。
下面的是我的隧道和相关的信息:
需要修改配置的话 点击上图的配置按钮 可以进行端口号的修改。
这个需要下载natapp.exe文件。点击后输入这个命令:natapp -authtoken=34db9a0153570800
该命令中的参数authtoken 可以在 已拥有的隧道中,点击显示或者点击复制,进行拿取。
启动后出现下面这个界面:
在这个启动后,接着就是需要我们将自己的项目部署在Tomcat上。 记住需要修改Tomcat的端口号。要和自己的隧道中的端口号保持一致才可以进行正常的访问。
我使用的是Tomcat8.5 和Tomcat9 ,这两个服务器虽然版本提高了但是和7的目录一样的。
在Eclipse 中 编写好简单的测试应用,右键到处war包,部署到Tomcat 的WebApp下,会自动解包。
部署后的项目如上图。
这之后我们需要登录我们自己的微信公众号,由于在做这个部分的时候我的公众号认证工作还在进行中所以我使用了企业微信进行了链接的调用,
当然我们也可以直接在地址栏键入我们的域名外加请求的应用。也可以访问到我们自己的应用。
下图是在企业微信中配置自己的链接,这个我们首先要建立一个测试应用才可以。
校验代码可以百度查找,我的主要是测试使用的。下面的四个类。
抽象的BaseServlet类:
package com.yang.wechat.natapp.test;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class StringServletBase
*/
@WebServlet("/StringServletBase")
public abstract class StringServletBase extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* Constructor of the object.
*/
public StringServletBase() {
super();
}
/**
* Destruction of the servlet.
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* The doGet method of the servlet.
*
* This method is called when a form has its tag value method equals to get.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
response.setContentType("text/plain");
String str = parseString(request);
if (str != null) {
out.print(str);
}
out.flush();
out.close();
}
/**
* The doPost method of the servlet.
*
* This method is called when a form has its tag value method equals to post.
*
* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
/**
* Initialization of the servlet.
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
}
/**
* @param request
* @return
* @Author:lulei
* @Description: 接口需要输出的字符串
*/
protected abstract String parseString(HttpServletRequest request);
}
WeiXinServlet:
package com.yang.wechat.natapp.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import com.yang.wechat.natapp.util.SignUtil;
/**
* 这其中用到了写文件的操作,写 文件的目的是将收到的参数存储下来 期初的目的是用来判断参数是否接收到。 接收到参数后,将其存储在硬盘的F盘下,命名为log。
* Servlet implementation class WeiXinServlet
*/
@WebServlet("/WeiXinServlet")
public class WeiXinServlet extends StringServletBase {
// 生成文件路径
private static String path = "F:\\";
// 文件路径+名称
private static String filenameTemp;
private static final long serialVersionUID = 1L;
/**
* @param request
* @return
* @throws ServletException
* @throws IOException
* @Author:lulei
* @Description: 这里是微信服务器验证
*/
protected String check(HttpServletRequest request) {
// 接收微信加密签名 如:6b7f03cf1577058a0ea15aef95a72e4c5a20d669
String signature = request.getParameter("signature");
// 获取时间戳 如:1507884908
String timestamp = request.getParameter("timestamp");
// 获取随机数 如: 3469273860
String nonce = request.getParameter("nonce");
// 获取随机字符串 如:5440238404538859375
String echostr = request.getParameter("echostr");
String str = signature + " _ " + timestamp + " _ " + nonce + " " + echostr + " ";
createFile("log", str);
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
//如果校验成功 在此处将前端传过来 的 随机字符串 返回到微信服务器。
return echostr;
}
//如果是自己的测试数据一定会返回null,
//如果不匹配的话返回一个null 给微信服务器。
return null;
}
@Override
protected String parseString(HttpServletRequest request) {
// 微信首次验证
return check(request);
}
public static boolean createFile(String fileName, String filecontent) {
Boolean bool = false;
filenameTemp = path + fileName + ".txt";// 文件路径+名称+文件类型
File file = new File(filenameTemp);
try {
// 如果文件不存在,则创建新的文件
if (!file.exists()) {
file.createNewFile();
bool = true;
System.out.println("success create file,the file is " + filenameTemp);
// 创建文件成功后,写入内容到文件里
writeFileContent(filenameTemp, filecontent);
}
} catch (Exception e) {
e.printStackTrace();
}
return bool;
}
/**
* 向文件中写入内容
*
* @param filepath
* 文件路径与名称
* @param newstr
* 写入的内容
* @return
* @throws IOException
*/
public static boolean writeFileContent(String filepath, String newstr) throws IOException {
Boolean bool = false;
String filein = newstr + "\r\n";// 新写入的行,换行
String temp = "";
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
FileOutputStream fos = null;
PrintWriter pw = null;
try {
File file = new File(filepath);// 文件路径(包括文件名称)
// 将文件读入输入流
fis = new FileInputStream(file);
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);
StringBuffer buffer = new StringBuffer();
// 文件原有内容
for (int i = 0; (temp = br.readLine()) != null; i++) {
buffer.append(temp);
// 行与行之间的分隔符 相当于“\n”
buffer = buffer.append(System.getProperty("line.separator"));
}
buffer.append(filein);
fos = new FileOutputStream(file);
pw = new PrintWriter(fos);
pw.write(buffer.toString().toCharArray());
pw.flush();
bool = true;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
// 不要忘记关闭
if (pw != null) {
pw.close();
}
if (fos != null) {
fos.close();
}
if (br != null) {
br.close();
}
if (isr != null) {
isr.close();
}
if (fis != null) {
fis.close();
}
}
return bool;
}
}
Encrypt:
package com.yang.wechat.natapp.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Encrypt {
/**
* @param str
* 需要加密的字符串
* @param encName
* 加密种类 MD5 SHA-1
* @return
* @Author:zy
* @Description: 实现对字符串的加密
*/
public static String encrypt(String str, String encName) {
String reStr = null;
try {
MessageDigest md5 = MessageDigest.getInstance(encName);
byte[] bytes = md5.digest(str.getBytes());
StringBuffer stringBuffer = new StringBuffer();
for (byte b : bytes) {
int bt = b & 0xff;
if (bt < 16) {
stringBuffer.append(0);
}
stringBuffer.append(Integer.toHexString(bt));
}
reStr = stringBuffer.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return reStr;
}
}
SignUtil:
package com.yang.wechat.natapp.util;
import java.util.Arrays;
public class SignUtil {
/**
* @param signature
* @param timestamp
* @param nonce
* @return
* @Author:zy
* @Description: 微信权限验证
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
String token = "zuoshouYang";
String[] arr = new String[] { token, timestamp, nonce };
//按字典排序
Arrays.sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
//加密并返回验证结果
return signature == null ? false : signature.equals(Encrypt.encrypt(content.toString(), "SHA-1"));
}
}
以上代码参考了网上的相关的博客,如有不妥之处,请通知我
经过以上准备便开始配置我们的服务器了,上面的代码是用于服务器的配置,也可以先测试下域名是否可用都可以的,
测试域名可用与否,最简单直接建一个html文件就可以。