公众号自定义URL配置及验证
接口配置信息
登录微信公众平台,点击左侧导航栏上的基本配置按钮,会出现如下图信息:
在这个界面,我们可以设置微信服务号的自定义服务器地址URL、Token、消息加解密秘钥,并且可以获取到该服务号的AppID、AppSecret信息。点击修改配置按钮(第一次开启时该按钮名称叫启用),可以修改和配置URL信息,如下图:
这样,当配置了服务器信息之后,通过微信服务号发送的消息就能够发送到我们自定义的服务器URL上进行处理。当然,开启了自定义服务配置之后,通过微信公众平台设置的菜单等信息就会失效,需要通过接口的方式进行设置,这块后面会讲到。
接口配置验证
验证需要用到的参数:
上面说的很清楚,当点击提交自定义的服务器配置之后,微信服务器会访问该服务器配置URL,并携带这四个参数,而我们配置的服务器端就需要进行验证,验证通过方可使用。
服务器端验证代码
CoreServlet:
/**
* 核心请求处理类
* @author TanJin
* @date 2015-8-6
*/
public class CoreServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected Logger logger = LoggerFactory.getLogger(getClass());
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
String signature = request.getParameter("signature"); // 微信加密签名
String timestamp = request.getParameter("timestamp"); // 时间戳
String nonce = request.getParameter("nonce"); // 随机数
String echostr = request.getParameter("echostr"); // 随机字符串
PrintWriter out = response.getWriter();
// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
out.print(echostr);
}
out.close();
out = null;
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response){
//将请求、响应的编码均设置为UTF-8(防止中文乱码)
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
//调用核心业务类接收消息、处理消息
String respMessage = CoreService.getInstance().processRequest(request);
//响应消息
PrintWriter out = response.getWriter();
out.print(respMessage);
out.close();
}
}
请求校验工具SighUtil:
/**
* 请求校验工具类
* @date 2015-7-21
*/
public class SignUtil {
protected static Logger logger = LoggerFactory.getLogger(SignUtil.class);
/**
* 验证签名
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
String[] arr = new String[] {WechatConstant.token, timestamp, nonce};
// 将token、timestamp、nonce三个参数进行字典序排序
Arrays.sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
String tmpStr = sha1(content.toString()); //进行sha1数字签名
logger.info("[SignUtil] [sha1 after tmpStr:{}]", tmpStr);
// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
return tmpStr != null ? tmpStr.equals(signature.toLowerCase()) : false;
}
/**
* 对给定字符串内容进行sha1数字签名
* @date 2015-8-28
*/
public static String sha1(String content) {
MessageDigest md = null;
String tmpStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
// 将三个参数字符串拼接成一个字符串进行sha1加密
byte[] digest = md.digest(content.getBytes());
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return tmpStr.toLowerCase();
}
/**
* 将字节数组转换为十六进制字符串
* @date 2015-7-21
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* 将字节转换为十六进制字符串
* @date 2015-7-21
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
}
- 这里唯一需要注意的就是SignUtil类中的成员变量token,这里赋予什么值,在接口配置信息中的Token就要填写什么值,两边保持一致即可,没有其他要求,建议用项目名称、公司名称缩写等。
web.xml配置:
<servlet>
<servlet-name>wechatServiceAccount</servlet-name>
<servlet-class>com.common.component.wechat.controller.CoreServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>wechatServiceAccount</servlet-name>
<url-pattern>/wechat/service/core</url-pattern>
</servlet-mapping>
到这里为止,微信服务号的服务器配置及校验相关的操作就完成了,根据这个流程,就能够使用服务号做一些自定义的操作了。