【JavaWeb】(9)初识微信公众号开发

1. 申请公众号

首先我们必须先申请号所需要开发的微信公众号,这里传送门:https://mp.weixin.qq.com/,申请的流程我就不介绍了。


2. 创建工程

创建web工程,首先创建WeChatServlet类,重写它的doGet方法:

	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();
		if (CheckUtil.checkSignature(signature, timestamp, nonce)) {
			out.print(echostr);
		}
	}
这是CheckUtil工具类:

public class CheckUtil {

	private static final String token = "doomthr";

	public static boolean checkSignature(String signature, String timestamp,
			String nonce) {
		String[] arr = new String[] { token, timestamp, nonce };

		// 排序
		Arrays.sort(arr);

		// 生成字符串
		StringBuffer content = new StringBuffer();
		for (int i = 0; i < arr.length; i++) {
			content.append(arr[i]);
		}
		// sha1加密
		String temp = getSha1(content.toString());

		return temp.equals(signature);
	}

	/**
	 * sha1加密
	 * 
	 * @param str
	 * @return
	 */
	public static String getSha1(String str) {
		if (null == str || 0 == str.length())
			return null;
		char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
				'a', 'b', 'c', 'd', 'e', 'f' };
		try {
			MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
			mdTemp.update(str.getBytes("UTF-8"));
			byte[] md = mdTemp.digest();
			int j = md.length;
			char[] buf = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte byte0 = md[i];
				buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
				buf[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(buf);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return null;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return null;
		}
	}
}
这个工具类主要验证了我们开发环境和微信后台环境的对接。


3. 内网映射到外网

完成上述操作后在浏览器通过本地打开我们的WeChatServlet,看是否成功。成功后,就需要将我们内网映射到外网了。

这里我们使用的是ngrok工具,它的使用方法也很简单。先从命令提示行里切换到我们ngrok的安装路径,然后执行以下语句:

ngrok -config ngrok.cfg -subdomain wechat 8080
其中wechat是我们起的名字,8080是我们使用的端口。

执行完毕后,它会生成一个外网的http地址,我们用这个地址替换我们本地的地址,看是否映射成功,成功后就可以提交我们的开发者服务器配置了。

URL(服务器地址)就填写我们外网的地址,Token填写我们工具类中定义的token,点击生成EncodingAESKey,然后提交就可以了。

这里有可能会出现token验证失败、或者验证超时,检查下我们的代码,多提交几次就成功了

提交成功后,点击启用开发模式。

这里注意:开发模式和编辑模式是互相排斥的,二者只能使用一个。


4. 实现消息的接收和响应

返回我们的工程,创建MessageText实体类:

public class TextMessage {
	private String ToUserName;
	private String FromUserName;
	private long CreateTime;
	private String MsgType;
	private String Content;
	private String MsgId;
}
生成每一个属性的set和get方法。

这里注意,每一个属性的大小写和全名都要和帮助文档上的一致。

然后编写MessageUtil工具类,用来执行Stirng和Map还有xml之间的转换:

/**
	 * xml转换为map集合
	 * 
	 * @param request
	 * @return
	 * @throws IOException
	 * @throws DocumentException
	 */
	public static Map xmlToMap(HttpServletRequest request)
			throws IOException, DocumentException {
		Map map = new HashMap();
		SAXReader reader = new SAXReader();
		InputStream in = request.getInputStream();
		Document doc = reader.read(in);

		Element root = doc.getRootElement();

		List list = root.elements();

		for (Element e : list) {
			map.put(e.getName(), e.getText());
		}
		in.close();

		return map;
	}

	/**
	 * 将文本消息转换为xml
	 * 
	 * @param textMeesage
	 * @return
	 */
	public static String texMessageToXml(TextMessage textMeesage) {
		XStream xStream = new XStream();
		xStream.alias("xml", textMeesage.getClass());
		return xStream.toXML(textMeesage);
	}
这里还需要两个jar包,没有的需要下载一下,一个是解析xml的dom4j的jar包,一个是转换xml的xstream的jar包。

完成后,再重写我们的WeChatServlet里面的doPost方法:

public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();
		try {
			Map map = MessageUtil.xmlToMap(request);
			String fromUserName = map.get("FromUserName");
			String toUserName = map.get("ToUserName");
			String msgType = map.get("MsgType");
			String content = map.get("Content");

			String message = null;

			if ("text".equals(msgType)) {
				TextMessage text = new TextMessage();
				text.setFromUserName(toUserName);
				text.setToUserName(fromUserName);
				text.setMsgType("text");
				text.setCreateTime(new Date().getTime());
				text.setContent("您发送的消息是:" + content);
				message = MessageUtil.texMessageToXml(text);
			}
			System.out.println(message);
			out.print(message);
		} catch (DocumentException e) {
			e.printStackTrace();
		} finally {
			out.close();
		}
	}
然后测试向公众号发送消息,它已经可以根据你发的消息做自动回复了!

5. 添加其他的自动回复等操作

继续完善我们的工程,使它和我们用编辑器编辑的效果一致。

添加几种消息类型的常量:

	public static final String MESSAGE_TEXT = "text";
	public static final String MESSAGE_IMAGE = "image";
	public static final String MESSAGE_VOICE = "voice";
	public static final String MESSAGE_VIDEO = "video";
	public static final String MESSAGE_LINK = "link";
	public static final String MESSAGE_LOCATION = "location";
	public static final String MESSAGE_EVENT = "event";
	public static final String MESSAGE_SUBSCRIBE = "subscribe";
	public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe";
	public static final String MESSAGE_CLICK = "CLICK";
	public static final String MESSAGE_VIEW = "VIEW";
添加生成消息的方法:

/**
	 * 主菜单
	 * 
	 * @return
	 */
	public static String menuText() {
		StringBuffer sb = new StringBuffer();
		sb.append("欢迎你的关注,请按照菜单提示操作:\n\n");
		sb.append("1、近期好看的电影\n");
		sb.append("2、87届奥斯卡获奖电影\n");
		sb.append("回复?调出帮助菜单");
		return sb.toString();
	}

	/**
	 * 回复1的菜单
	 * @return
	 */
	public static String firstMenu() {
		StringBuffer sb = new StringBuffer();
		sb.append("近期口碑不错的电影推荐——《大圣归来》,很不错,建议体验一下哦~");
		return sb.toString();
	}

	/**
	 * 回复2的菜单
	 * @return
	 */
	public static String secondMenu() {
		StringBuffer sb = new StringBuffer();
		sb.append("《消失的爱人》——87届奥斯卡最佳女主角获奖电影,爱情悬疑类型电影迷的最爱。");
		return sb.toString();
	}
修改WeChatServlet类,根据不同消息做出不同的回复:

if (MessageUtil.MESSAGE_TEXT.equals(msgType)) {
				if ("1".equals(content)) {
					message = MessageUtil.initText(toUserName, fromUserName,
							MessageUtil.firstMenu());
				} else if ("2".equals(content)) {
					message = MessageUtil.initText(toUserName, fromUserName,
							MessageUtil.secondMenu());
				} else if ("?".equals(content) || "?".equals(content)) {
					message = MessageUtil.initText(toUserName, fromUserName,
							MessageUtil.menuText());
				}
				// TextMessage text = new TextMessage();
				// text.setFromUserName(toUserName);
				// text.setToUserName(fromUserName);
				// text.setMsgType("text");
				// text.setCreateTime(new Date().getTime());
				// text.setContent("您发送的消息是:" + content);
				// message = MessageUtil.texMessageToXml(text);
			} else if (MessageUtil.MESSAGE_EVENT.equals(msgType)) {
				String eventType = map.get("Event");
				if (MessageUtil.MESSAGE_SUBSCRIBE.equals(eventType)) {
					message = MessageUtil.initText(toUserName, fromUserName,
							MessageUtil.menuText());
				}
			}

OK~


源码下载


你可能感兴趣的:(JavaWeb)