目录结构
- 项目结构图
- 在本地创建项目并在Jetty成功部署运行
- 源代码
- 注册工具类
-
核心Servlet
- Web工程配置文件
- Maven工程文件
- 在GitHub上创建项目,上传本地代码
- 上传工程WAR档至SAE
- 配置微信的Token相关信息
- 参考文档
- 完整项目源代码
项目结构图
源代码文件说明
序号 | 文件名 | 说明 |
1 | readme.txt | 项目说明文件 |
2 | pom.xml | Maven工程文件 |
3 | web.xml | Web项目配置文件(这里主要配置Servlet的信息) |
4 | index.jsp | 首页文件,显示时间信息,主要用来判断工程是否部署成功 |
5 | SignUtil.java | 工具类 |
6 | Coreservlet.java | 获取Token的Servlet |
在本地创建项目并在Jetty成功部署运行
确保工程在eclipse的Jetty容器中成功运行(SAE是基于Jetty的,不是Tomcat)
Running Jetty 6.1.26
2014-10-20 14:01:27.605:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
ParentLoaderPriority enabled
Context path:/wxquan
ProjectClassLoader: entry=D:\E422\workspace2\wxquan\target\classes
ProjectClassLoader: entry=D:\Java\apache-maven-3.1.0\repo\javax\servlet\servlet-api\2.4\servlet-api-2.4.jar
ProjectClassLoader: entry=D:\Java\apache-maven-3.1.0\repo\javax\servlet\jsp\jsp-api\2.1\jsp-api-2.1.jar
Excluded entry=D:\E422\workspace2\wxquan\target\test-classes
2014-10-20 14:01:27.649:INFO::jetty-6.1.26
2014-10-20 14:01:27.853:INFO::Started SelectChannelConnector@0.0.0.0:8080
在浏览器中测试工程:
源代码
注册工具类
SignUtil.java
package com.coderdream.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import org.apache.log4j.Logger;
/**
* 请求校验工具类
*
*/
public class SignUtil {
public static String TAG = "SignUtil";
/**
* 与开发模式接口配置信息中的Token保持一致
*/
private static String token = "weixinToken";
/**
* 校验签名
*
* @param signature
* 微信加密签名
* @param timestamp
* 时间戳
* @param nonce
* 随机数
* @return
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
Logger logger = Logger.getLogger(SignUtil.class);
Date utilDate = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String str = sdf.format(utilDate);
logger.debug(TAG + " checkSignature " + str);
// 对token、timestamp和nonce按字典排序
String[] paramArr = new String[] { token, timestamp, nonce };
Arrays.sort(paramArr);
// 将排序后的结果拼接成一个字符串
String content = paramArr[0].concat(paramArr[1]).concat(paramArr[2]);
String ciphertext = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
// 对接后的字符串进行sha1加密
byte[] digest = md.digest(content.toString().getBytes());
ciphertext = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 将sha1加密后的字符串与signature进行对比
boolean flag = ciphertext != null ? ciphertext.equals(signature.toUpperCase()) : false;
logger.debug(TAG + " checkSignature result: " + flag);
return flag;
}
/**
* 将字节数组转换为十六进制字符串
*
* @param byteArray
* @return
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* 将字节转换为十六进制字符串
*
* @param mByte
* @return
*/
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;
}
}
核心Servlet
CoreServlet.java
package com.coderdream.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.coderdream.util.SignUtil;
/**
* 请求处理的核心类
*
*/
public class CoreServlet extends HttpServlet {
private static final long serialVersionUID = 4440739483644821986L;
/**
* 请求校验(确认请求来自微信服务器)
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 微信加密签名
String signature = request.getParameter("signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串
String echostr = request.getParameter("echostr");
PrintWriter out = response.getWriter();
// 请求校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
out.print(echostr);
}
out.close();
out = null;
}
/**
* 处理微信服务器发来的消息
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO 消息的接收、处理、响应
}
}
Web工程配置文件
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>weixin</display-name> <servlet> <servlet-name>coreServlet</servlet-name> <servlet-class>com.coderdream.servlet.CoreServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>coreServlet</servlet-name> <url-pattern>/coreServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
Maven工程文件
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.coderdream</groupId> <artifactId>wxquan</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>wxquan Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <!-- --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> <scope>provided</scope> </dependency> </dependencies> <build> <finalName>wxquan</finalName> </build> </project>
在GitHub上创建项目并上传本地代码
先在GitHub上创建项目
先将代码添加到本地的Git库
选择工程,右键,Team -> Share Project...
选“Git”:
勾选“Use or create repository in parent folder of project”,这个选项的意思是在本地(父文件夹中)创建git库:
出现警告,不用理会,点“Create Repository”按钮:
本地Git库创建成功,点“Finish”按钮,完成创建。
由于Build以后会生成Target目录,而我们不希望上传这个目录到Git的托管库GitHub中,所以我们需要过滤这个文件夹
运行“Git Bash”工具(这个工具安装Git后就有了),转到工程文件夹下,这里是 D:\E422\workspace2\wxquan
修改前(target文件上有问号):
修改后(target文件上没有问号了):
准备提交代码到GitHub:
选择项目,右键,Team -> Commit...
输入注释,选择所有的文件(这里为了以后导入工程方便,我们把所有的工程文件也加进去,一个20个文件)
在此之前要先配置好 eclipse 的 Git:
输入项目的git地址:
如果没有问题,“Source ref:”的下拉框会有值,选择“refs/heads/master”,然后点击右边的“Add Spec”:
这样,下面的“Specifications for push”就有内容了,然后点击“Finish”按钮,开始提交:
开始提交:
正在提交:
提交完成:
刷新浏览器,查询GitHub中的项目信息:
上传工程WAR档至SAE
将eclipse中的工程导出为wxquan.war档,上传到SAE中,成功部署后测试工程:
配置微信的Token相关信息
登录微信公众平台后,选左边的【开发者中心】:
输入正确的URL和Token(这些在由服务器中的项目名称和相关设置确定),同时自动生成“EncodingAESKey“
成功后会得到“提交成功”的信息。
最后的结果:
成功订阅后可以收到消息:
参考文档
完整源代码