微信公众号开发(一)
微信公众号开发前准备
一、提供外网地址
因为微信那边需要我们提供一个外网能访问的地址给它使用,而为了方便开发,我这里使用了ngrok
配置外网地址直接指向我本机的地址
1.到http://natapp.cn//#download下载ngrok。
2.打开cmd,切换到解压的目录,运行ngrok -config ngrok.cfg -subdomain fengzp 8080命令,其中'fengzp'是我自己定义的域名,8080是指向的端口。
3.运行结果。
二、接入微信公众号
注册公众号
访问微信公众号注册地址,注册一个测试公众号,登陆。
微信公众号接入
在微信公众平台开发者文档上,关于公众号接入这一节内容在接入指南上写的比较详细的,文档中说接入公众号需要3个步骤,分别是:
1、填写服务器配置
2、验证服务器地址的有效性
3、依据接口文档实现业务逻辑
其实,第3步已经不能算做公众号接入的步骤,而是接入之后,开发人员可以根据微信公众号提供的接口所能做的一些开发。
第1步中服务器配置包含服务器地址(URL)、Token和EncodingAESKey。
服务器地址即公众号后台提供业务逻辑的入口地址,目前只支持80端口,之后包括接入验证以及任何其它的操作的请求(例如消息的发送、菜单管理、素材管理等)都要从这个地址进入。接入验证和其它请求的区别就是,接入验证时是get请求,其它时候是post请求;
Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性);
EncodingAESKey由开发者手动填写或随机生成,将用作消息体加解密密钥。本例中全部以未加密的明文消息方式,不涉及此配置项。
第2步,验证服务器地址的有效性,当点击“提交”按钮后,微信服务器将发送一个http的get请求到刚刚填写的服务器地址,并且携带四个参数:
接到请求后,我们需要做如下三步,若确认此次GET请求来自微信服务器,原样返回echostr参数内容,则接入生效,否则接入失败。
1. 将token、timestamp、nonce三个参数进行字典序排序
2. 将三个参数字符串拼接成一个字符串进行sha1加密
3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
实际代码:编写一个servlevt,在其中的doGet方法中定义校验方法,具体代码如下:
package com.feng.web.service.servlet;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;
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 com.feng.web.model.WxMessage;
import com.feng.web.service.util.BeanUtil;
import com.feng.web.service.util.WxMsgUtil;
/**
*
* @author fengzp
*
*/
@WebServlet(urlPatterns = "/WxServlet")
public class WxServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = -6008816817887502362L;
/**
* Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
*/
private final String TOKEN = "fengzp";
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("开始校验签名");
/**
* 接收微信服务器发送请求时传递过来的4个参数
*/
String signature = request.getParameter("signature");// 微信加密签名signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
String timestamp = request.getParameter("timestamp");// 时间戳
String nonce = request.getParameter("nonce");// 随机数
String echostr = request.getParameter("echostr");// 随机字符串
System.out.println(signature);
System.out.println(timestamp);
System.out.println(nonce);
System.out.println(echostr);
// response.getWriter().print(echostr);
// 加密
String mySignature = sha1(sort(TOKEN, timestamp, nonce));
// 校验签名
if (mySignature != null && mySignature != "" && mySignature.equals(signature)) {
System.out.println("签名校验通过。");
response.getWriter().write(echostr);
// response.getWriter().print(echostr);
} else {
System.out.println("签名校验失败.");
}
}
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();
}
private String sha1(String str) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.update(str.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
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 "";
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
然后进入微信测试公众号管理界面,在接口配置信息中的URL填写这个servlet的外网地址和我们自定义的token,如下图所示:
到此我们的微信公众号已接入完毕。