文章来源:爱听音乐的狗博客
开发环境的搭建
1、进入Ngrok官网,下载客户端
2、选择需要下载的版本并解压
3、注册ngrok账号并登陆,在隧道管理页进行隧道的开通
4、 填写隧道信息
5、隧道连接
在开通隧道之后会产生一个隧道id,可以在终端中根据隧道id进行连接,当终端出现在线时,代表连接成功,这时其他人就可以通过域名来连接到本地端口
开发接入
1、接口测试号申请
在微信公众号平台技术文档中选择 --> "开始开发" --> "接口测试号申请" --> "进入微信公众账号测试号申请系统"
使用自己的微信账号进行扫描,进入测试号管理页面
2、扫描二维码关注公众号
在测试号管理页面下方有测试号二维码扫面,使用微信扫码即可关注测试公众号
3、接入
在微信公众平台技术文档中有很详细的接入指南
接入第一步:填写服务器配置
在测试号管理页可以进行接口信息的配置,填写服务器地址(URL)、Token,其中URL是开发者用来接收微信消息和事件的接口URL。Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性),这时候点提交,肯定是配置失败
第二步:验证消息的确来自微信服务器
开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数包括"signature"、"timestamp"、"nonce"、"echostr",通过对signature进行校验,确认此次GET请求来自微信服务器就返回"echostr"参数内容,接入就生效。
校验方式为:将token、timestamp、nonce三个参数进行字典序排序 ,然后三个参数字符串拼接成一个字符串进行sha1加密 ,最后开发者获得加密后的字符串可与signature对比,相同则标识该请求来源于微信
校验signature的Java示例代码:
创建WxServlet 继承自 HttpServlet,重写doGet方法,在方法中调用WxService的check方法校验signature,根据提供的校验方法校验成功,就返回"echostr"参数内容
@WebServlet("/wx")
public class WxServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/**
* signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
* timestamp 时间戳
* nonce 随机数
* echostr 随机字符串
*/
String signature = req.getParameter("signature");
String timestamp = req.getParameter("timestamp");
String nonce = req.getParameter("nonce");
String echostr = req.getParameter("echostr");
// 检验signature
if (WxService.check(timestamp, nonce, signature)) {
// 校验成功,原样返回echostr参数内容
System.out.println("校验成功");
PrintWriter writer = resp.getWriter();
writer.print(echostr);
writer.flush();
writer.close();
} else {
System.out.println("校验失败");
}
}
}
创建 WxService,提供校验的方法以及加密方式,常量TOKEN为微信接口配置信息页填写的Token
public class WxService {
// 微信公众号配置的TOKEN
private static final String TOKEN = "hjwx";
/**
* 微信接入验证
* @param timestamp 时间戳
* @param nonce 随机数
* @param signature 微信加密签名
* @return
*/
public static boolean check(String timestamp, String nonce, String signature) {
/**
* 1)将token、timestamp、nonce三个参数进行字典序排序
* 2)将三个参数字符串拼接成一个字符串进行sha1加密
* 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
*/
String[] strs = new String[]{TOKEN, timestamp, nonce};
Arrays.sort(strs);
String str = strs[0] + strs[1] + strs[2];
String mySignature = sha1(str);
return mySignature.equalsIgnoreCase(signature);
}
/**
* 进行sha1加密
* @param str
* @return
*/
private static String sha1(String str) {
try {
//获取加密对象
MessageDigest messageD = MessageDigest.getInstance("sha1");
//加密
byte[] digest = messageD.digest(str.getBytes());
//处理加密结果
char[] chars = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
StringBuilder stringBuilder = new StringBuilder();
for (byte b:digest) {
stringBuilder.append(chars[(b>>4) & 15]);
stringBuilder.append(chars[b & 15]);
}
return stringBuilder.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
在Tomcat上运行Java示例代码,此时需要将Tomcat端口改为8080,因为在做内网穿透时,配置的本地端口是localhost:8080,所以外部访问的域名相当于访问localhost:8080,再次点击微信测试号管理页的接口配置信息提交按钮,配置就会成功了。
提示
Ngrok提供的免费域名不太稳定,如果测试号管理业显示"配置失败",但是Java代码中验证成功并在控制台打印了"校验成功",此时代码是没有任何问题的,原因出在Ngrok的域名所导致的不稳定;多提交几次就不会存在问题