微信公众平台开发实战(01) 开启开发模式

目录结构

  • 项目结构图
  • 在本地创建项目并在Jetty成功部署运行
  • 源代码
    1. 注册工具类
    2. 核心Servlet

    3. Web工程配置文件
    4. Maven工程文件
  • 在GitHub上创建项目,上传本地代码
  • 上传工程WAR档至SAE
  • 配置微信的Token相关信息
  • 参考文档
  • 完整项目源代码

项目结构图

微信公众平台开发实战(01) 开启开发模式

源代码文件说明

序号文件名说明
1readme.txt项目说明文件
2pom.xmlMaven工程文件
3web.xmlWeb项目配置文件(这里主要配置Servlet的信息)
4index.jsp首页文件,显示时间信息,主要用来判断工程是否部署成功
5SignUtil.java工具类
6Coreservlet.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 [email protected]:8080

 在浏览器中测试工程: 

微信公众平台开发实战(01) 开启开发模式
 

源代码

注册工具类

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上创建项目

微信公众平台开发实战(01) 开启开发模式

先将代码添加到本地的Git库

选择工程,右键,Team -> Share Project...

微信公众平台开发实战(01) 开启开发模式
 

选“Git”:
微信公众平台开发实战(01) 开启开发模式

勾选“Use or create repository in parent folder of project”,这个选项的意思是在本地(父文件夹中)创建git库:

微信公众平台开发实战(01) 开启开发模式
 

出现警告,不用理会,点“Create Repository”按钮:
微信公众平台开发实战(01) 开启开发模式
 

本地Git库创建成功,点“Finish”按钮,完成创建。
微信公众平台开发实战(01) 开启开发模式
 

由于Build以后会生成Target目录,而我们不希望上传这个目录到Git的托管库GitHub中,所以我们需要过滤这个文件夹

运行“Git Bash”工具(这个工具安装Git后就有了),转到工程文件夹下,这里是 D:\E422\workspace2\wxquan

微信公众平台开发实战(01) 开启开发模式
 

修改前(target文件上有问号):
微信公众平台开发实战(01) 开启开发模式
 

修改后(target文件上没有问号了):
微信公众平台开发实战(01) 开启开发模式

准备提交代码到GitHub: 

选择项目,右键,Team -> Commit...
微信公众平台开发实战(01) 开启开发模式
 

输入注释,选择所有的文件(这里为了以后导入工程方便,我们把所有的工程文件也加进去,一个20个文件)

在此之前要先配置好 eclipse 的 Git:
微信公众平台开发实战(01) 开启开发模式
 

输入项目的git地址:
微信公众平台开发实战(01) 开启开发模式
 

如果没有问题,“Source ref:”的下拉框会有值,选择“refs/heads/master”,然后点击右边的“Add Spec”:
微信公众平台开发实战(01) 开启开发模式
 

这样,下面的“Specifications for push”就有内容了,然后点击“Finish”按钮,开始提交:
微信公众平台开发实战(01) 开启开发模式
 

开始提交:
微信公众平台开发实战(01) 开启开发模式
 

正在提交:
微信公众平台开发实战(01) 开启开发模式
 

提交完成:
微信公众平台开发实战(01) 开启开发模式
 

刷新浏览器,查询GitHub中的项目信息:
微信公众平台开发实战(01) 开启开发模式
 

上传工程WAR档至SAE

将eclipse中的工程导出为wxquan.war档,上传到SAE中,成功部署后测试工程:

微信公众平台开发实战(01) 开启开发模式
 

配置微信的Token相关信息

登录微信公众平台后,选左边的【开发者中心】:
微信公众平台开发实战(01) 开启开发模式
 

输入正确的URL和Token(这些在由服务器中的项目名称和相关设置确定),同时自动生成“EncodingAESKey“
微信公众平台开发实战(01) 开启开发模式

 

成功后会得到“提交成功”的信息。
微信公众平台开发实战(01) 开启开发模式

 

最后的结果:
微信公众平台开发实战(01) 开启开发模式
 

成功订阅后可以收到消息:
微信公众平台开发实战(01) 开启开发模式
 

参考文档

  1. 微信公众帐号开发教程第3篇-开发模式启用及接口配置
  2. 《微信公众平台应用开发:方法、技巧与案例》试读

完整源代码

相关推荐