java_微信公众号开发笔记

服务器配置Url:用于接收微信服务器回调http://www.*****.com/wxProcess.servlet  在web.xml中配置

<servlet>
		<servlet-name>wxProcessServlet</servlet-name>
		<servlet-class>com.operation.action.params.WxProcessServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>wxProcessServlet</servlet-name>
		<url-pattern>/wxProcess.servlet</url-pattern>
	</servlet-mapping>


类1

package com.operation.action.params;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.main.comm.util.MsgParser;
import com.main.comm.util.SignUtil;
import com.main.comm.util.WxConstant;
import com.operation.service.params.WxHandler;
import com.operation.vo.params.BaseSdMsg;

public class WxProcessServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	/**
	 * 确认请求来自微信服务器
	 */
	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 (signature != null && timestamp != null && nonce != null
				&& echostr != null) {
			if (SignUtil.checkSignature(WxConstant.TOKEN, signature, timestamp,
					nonce)) {
				System.out.println("check pass " + echostr);
				out.print(echostr);
			}
		}
		out.close();
		out = null;
	}

	/**
	 * 处理微信服务器发来的消息
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		if (request.getParameter("mss") != null) {
			System.out.println("-----receive mss");
			InputStream inputStream = request.getInputStream();
			try {
				int formlength = request.getContentLength();
				if (formlength > 0) {
					byte[] formcontent = new byte[formlength];
					int totalread = 0;
					int nowread = 0;
					while (totalread < formlength) {
						nowread = inputStream.read(formcontent, totalread,
								formlength);
						totalread += nowread;
					}
					inputStream.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				inputStream.close();
			}
		} else {
			System.out.println("-----receive mp msg-----");
			request.setCharacterEncoding("UTF-8");
			response.setCharacterEncoding("UTF-8");
			InputStream stream = request.getInputStream();
			PrintWriter out = response.getWriter();
			try {
				ApplicationContext context = WebApplicationContextUtils
						.getWebApplicationContext(getServletContext());
				WxHandler handler = (WxHandler) context.getBean("wxHandler");
				BaseSdMsg sdMsg = handler.getHandleRecvMsg(MsgParser
						.inputStreamToString(stream, "UTF-8"));
				if(null != sdMsg && !"".equals(sdMsg)){
					System.out.println("之后返回"+sdMsg.toXml());
					out.print(sdMsg.toXml());
				}else{
					System.out.println("sdMsg为空");
				}
			} catch (Exception e) {
				e.printStackTrace();
				out.print("");
			} finally {
				stream.close();
				out.close();
			}
		}
	}

}
 
类2
package com.operation.service.params;

import com.operation.vo.params.ArticleSdMsg;
import com.operation.vo.params.BaseSdMsg;
import com.operation.vo.params.ImgSdMsg;
import com.operation.vo.params.UserInfoMsg;

/**
 * 微信逻辑封装
 * 
 * @author myh
 * 
 */
public interface WxHandler {

	/**
	 * 处理信息
	 * 
	 * @param xml
	 * @return
	 */
	public BaseSdMsg getHandleRecvMsg(String xml);

	/**
	 * 根据openId获取userInfo
	 * 
	 * @param openId
	 * @return
	 */
	public UserInfoMsg getUserInfoMsg(String openId) throws Exception;

	public String sendImgSdMsg(String openId, String imgUrl) throws Exception;

	public ImgSdMsg replyImgSdMsg(String openId, String imgUrl)
			throws Exception;

	public ImgSdMsg replyImgSdMsgByMaterial(String openId, String imgUrl)
			throws Exception;

	ArticleSdMsg replyArticleSdMsg(String openId);
}

类3

package com.operation.vo.params;

import com.main.comm.util.MsgParser;
import com.main.comm.util.WxConstant;

/**
 * 基础发送消息
 * 
 * @author myh
 * 
 */

public abstract class BaseSdMsg {

	private String toUserName;
	// 开发者微信号
	private String fromUserName;
	// 消息创建时间 (整型)
	private long createTime;
	// 消息类型(text/music/news)
	private String msgType;

	// 位0x0001被标志时,星标刚收到的消息
	// private int funcFlag;

	public String getToUserName() {
		return toUserName;
	}

	public void setToUserName(String toUserName) {
		this.toUserName = toUserName;
	}

	public String getFromUserName() {
		return fromUserName;
	}

	public void setFromUserName(String fromUserName) {
		this.fromUserName = fromUserName;
	}

	public long getCreateTime() {
		return createTime;
	}

	public void setCreateTime(long createTime) {
		this.createTime = createTime;
	}

	public String getMsgType() {
		return msgType;
	}

	public void setMsgType(String msgType) {
		this.msgType = msgType;
	}

	public String toXml() {
		String xml = MsgParser.toXml(this);
		String temp = xml;
		if (this.msgType == WxConstant.MSGTYPE_IMG) {
			temp = xml.substring(0, xml.indexOf("<MediaId>") - 1);
			temp += "<Image>"
					+ xml.substring(xml.indexOf("<MediaId>"), xml
							.indexOf("</xml>") - 1);
			temp += "</Image></xml>";
		} else if (this.msgType == WxConstant.MSGTYPE_VOICE) {
			temp = xml.substring(0, xml.indexOf("<MediaId>") - 1);
			temp += "<Voice>"
					+ xml.substring(xml.indexOf("<MediaId>"), xml
							.indexOf("</xml>") - 1);
			temp += "</Voice></xml>";
		} else if (this.msgType == WxConstant.MSGTYPE_ARTICLE) {
			ArticleSdMsg msg = (ArticleSdMsg) this;
			StringBuffer sb = new StringBuffer();
			sb.append("<xml>");
			sb.append("<ToUserName><![CDATA[" + msg.getToUserName()
					+ "]]></ToUserName>");
			sb.append("<FromUserName><![CDATA[" + msg.getFromUserName()
					+ "]]></FromUserName>");
			sb.append("<CreateTime>" + msg.getCreateTime() + "</CreateTime>");
			sb
					.append("<MsgType><![CDATA[" + msg.getMsgType()
							+ "]]></MsgType>");
			sb.append("<ArticleCount>" + msg.getArticleCount()
					+ "</ArticleCount>");
			sb.append("<Articles>");
			for (ArticleSdMsgPart part : msg.getParts()) {
				sb.append("<item>");
				sb
						.append("<Title><![CDATA[" + part.getTitle()
								+ "]]></Title> ");
				sb.append("<Description><![CDATA[" + part.getDescription()
						+ "]]></Description>");
				sb.append("<PicUrl><![CDATA[" + part.getPicUrl()
						+ "]]></PicUrl>");
				sb.append("<Url><![CDATA[" + part.getUrl() + "]]></Url>");
				sb.append("</item>");
			}
			sb.append("</Articles>");
			sb.append("</xml>");
			temp = sb.toString();
		}
		return temp;
	}

}
类4
package com.main.comm.util;

import java.beans.PropertyDescriptor;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.operation.vo.params.BaseRecvMsg;
import com.operation.vo.params.BaseSdMsg;
import com.operation.vo.params.EventRecvMsg;
import com.operation.vo.params.ImgSdMsg;
import com.sun.org.apache.commons.beanutils.ConvertUtils;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

/**
 * 微信消息解析
 * 
 * @author myh
 * 
 */
public class MsgParser {
	private static final int BUFFER_SIZE = 256;

	public static BaseRecvMsg parseXml(String xml) throws Exception {
		// 将解析结果存储在HashMap中
		Map<String, String> map = new HashMap<String, String>();

		Document document = DocumentHelper.parseText(xml);
		// 得到xml根元素
		Element root = document.getRootElement();
		// 得到根元素的所有子节点
		@SuppressWarnings("unchecked")
		List<Element> elementList = root.elements();

		// 遍历所有子节点
		for (Element e : elementList)
			map.put(e.getName(), e.getText());

		return tradeMsg(map);
	}

	public static BaseRecvMsg parseXml(InputStream inputStream)
			throws Exception {
		// 将解析结果存储在HashMap中
		Map<String, String> map = new HashMap<String, String>();

		// 读取输入流
		SAXReader reader = new SAXReader();
		Document document = reader.read(inputStream);
		// 得到xml根元素
		Element root = document.getRootElement();
		// 得到根元素的所有子节点
		@SuppressWarnings("unchecked")
		List<Element> elementList = root.elements();

		// 遍历所有子节点
		for (Element e : elementList)
			map.put(e.getName(), e.getText());

		return tradeMsg(map);
	}

	public static BaseRecvMsg tradeMsg(Map<String, String> data)
			throws Exception {
		BaseRecvMsg msg = null;
		if (StringUtils.isNotBlank(data.get("MsgType"))) {
			String msgType = data.get("MsgType");
			if (msgType.equals(WxConstant.MSGTYPE_EVENT))
				msg = new EventRecvMsg();
			if (msg != null) {
				PropertyDescriptor pe = null;
				for (String key : data.keySet()) {
					pe = PropertyUtils.getPropertyDescriptor(msg, StringUtils
							.uncapitalize(key));
					if (pe != null) {
						PropertyUtils.setProperty(msg, StringUtils
								.uncapitalize(key), ConvertUtils.convert(data
								.get(key), pe.getPropertyType()));
					}
				}
			}
		} else {
			// throw new Exception("not found msgtype");
		}
		return msg;
	}

	public static String inputStreamToString(InputStream in, String encoding)
			throws Exception {
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		try {
			byte[] data = new byte[BUFFER_SIZE];
			int count = -1;
			while ((count = in.read(data, 0, BUFFER_SIZE)) != -1)
				outStream.write(data, 0, count);
			data = null;
			if (encoding != null)
				return new String(outStream.toByteArray(), encoding);
			else
				return new String(outStream.toByteArray());
		} finally {
			outStream.close();
		}
	}

	public static String sendMsgToJson(Object msg) {
		String json = null;
		if (msg instanceof ImgSdMsg) {
			ImgSdMsg imgSdMsg = (ImgSdMsg) msg;
			json = "{\"touser\" :\"" + imgSdMsg.getToUserName() + "\",";
			json += "\"msgtype\":\"" + imgSdMsg.getMsgType() + "\",";
			json += "\"" + imgSdMsg.getMsgType() + "\":{";
			json += "\"media_id\":\"" + imgSdMsg.getMediaId() + "\"";
			json += "}}";
		} else {

		}
		return json;
	}

	public static String toXml(BaseSdMsg msg) {
		xstream.alias("xml", msg.getClass());
		return xstream.toXML(msg);
	}

	private static XStream xstream = new XStream(new XppDriver() {
		public HierarchicalStreamWriter createWriter(Writer out) {
			return new PrettyPrintWriter(out) {
				// 对所有xml节点的转换都增加CDATA标记
				boolean cdata = true;

				public void startNode(String name, Class clazz) {
					if (!name.equals("xml")) {
						if (name.equals("createTime")) {
							cdata = false;
						} else {
							cdata = true;
						}
						super.startNode(StringUtils.capitalize(name), clazz);
					} else {
						super.startNode(name, clazz);
					}
				}

				protected void writeText(QuickWriter writer, String text) {
					if (cdata) {
						writer.write("<![CDATA[");
						writer.write(text);
						writer.write("]]>");
					} else {
						writer.write(text);
					}
				}
			};
		}
	});
}
类5

package com.operation.service.impl.params;

import java.io.File;
import java.util.HashSet;
import java.util.Set;

import weibo4j.org.json.JSONObject;

import com.main.comm.util.MsgParser;
import com.main.comm.util.WxConnector;
import com.main.comm.util.WxConstant;
import com.operation.service.params.ParamsService;
import com.operation.service.params.TokenManager;
import com.operation.service.params.WxHandler;
import com.operation.vo.params.ArticleSdMsg;
import com.operation.vo.params.ArticleSdMsgPart;
import com.operation.vo.params.BaseRecvMsg;
import com.operation.vo.params.BaseSdMsg;
import com.operation.vo.params.EventRecvMsg;
import com.operation.vo.params.ImgSdMsg;
import com.operation.vo.params.UserInfoMsg;

public class WxDefaultHandler implements WxHandler {

	private WxConnector connector = WxConnector.getConnector();
	private TokenManager tokenManager;
	private ParamsService paramsService;

	public WxConnector getConnector() {
		return connector;
	}

	public void setConnector(WxConnector connector) {
		this.connector = connector;
	}

	public TokenManager getTokenManager() {
		return tokenManager;
	}

	public void setTokenManager(TokenManager tokenManager) {
		this.tokenManager = tokenManager;
	}

	public ParamsService getParamsService() {
		return paramsService;
	}

	public void setParamsService(ParamsService paramsService) {
		this.paramsService = paramsService;
	}

	public BaseSdMsg getHandleRecvMsg(String xml) {
		BaseSdMsg baseSdMsg = null;
		try {
			System.out.println(xml);
			tokenManager.getWxAccessToken();
			BaseRecvMsg msg = MsgParser.parseXml(xml);
			if (msg.getMsgType().equals(WxConstant.MSGTYPE_EVENT)
					&& msg instanceof EventRecvMsg) {
				System.out.println("openId:" + msg.getFromUserName());
				System.out.println("paramsService:" + paramsService);
				EventRecvMsg eventRecvMsg = (EventRecvMsg) msg;
				if (eventRecvMsg.getEvent().equals("subscribe")) {
					System.out.println("关注");
					//查询是否以前关注过,
					// 关注生成图文消息
					baseSdMsg = replyArticleSdMsg(msg.getFromUserName());
					
				} else if (eventRecvMsg.getEvent().equals("unsubscribe")) {
					System.out.println("取消关注");
					// 取消关注
					//paramsService.deleteAttention(attentionVO);
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return baseSdMsg;
	}

	public UserInfoMsg getUserInfoMsg(String openId) throws Exception {
		UserInfoMsg userInfoMsg = null;
		String msg = this.connector.reqGet(WxConstant.getUserInfoApplyUrl(
				tokenManager.getWxAccessToken(), openId));
		if (null != msg && msg.contains("nickname")) {
			JSONObject json = new JSONObject(msg);
			userInfoMsg = new UserInfoMsg();
			userInfoMsg.fromJson(json);
		}
		return userInfoMsg;
	}

	public String sendImgSdMsg(String openId, String imgUrl) throws Exception {
		String url = WxConstant.getUploadMediaUrl(tokenManager
				.getWxAccessToken(), "image");
		JSONObject jsonObject = new JSONObject(connector.uploadMedia(url,
				new File(imgUrl)));
		ImgSdMsg is = new ImgSdMsg(openId, WxConstant.SELF_OPENID);
		is.setMediaId(jsonObject.getString("media_id"));
		String jsonString = MsgParser.sendMsgToJson(is);
		String result = connector.reqPost(WxConstant.getSendMsgUrl(tokenManager
				.getWxAccessToken()), jsonString);
		return result;
	}

	public ImgSdMsg replyImgSdMsg(String openId, String imgUrl)
			throws Exception {
		String url = WxConstant.getUploadMediaUrl(tokenManager
				.getWxAccessToken(), "image");
		System.out.println("上传图片url:" + url);
		JSONObject jsonObject = new JSONObject(connector.uploadMedia(url,
				new File(imgUrl)));
		System.out.println(jsonObject);
		ImgSdMsg is = new ImgSdMsg(openId, WxConstant.SELF_OPENID);
		is.setMediaId(jsonObject.getString("media_id"));
		return is;
	}

	public ImgSdMsg replyImgSdMsgByMaterial(String openId, String imgUrl)
			throws Exception {
		String url = WxConstant.getMaterialUrl(tokenManager.getWxAccessToken(),
				"image");
		System.out.println("上传图片url:" + url);
		JSONObject jsonObject = new JSONObject(connector.uploadMedia(url,
				new File(imgUrl)));
		System.out.println(jsonObject);
		ImgSdMsg is = new ImgSdMsg(openId, WxConstant.SELF_OPENID);
		is.setMediaId(jsonObject.getString("media_id"));
		return is;
	}

	public ArticleSdMsg replyArticleSdMsg(String openId) {
		System.out.println("开始生成图文消息");
		ArticleSdMsg msg = new ArticleSdMsg(openId, WxConstant.SELF_OPENID);
		Set<ArticleSdMsgPart> msgParts = new HashSet<ArticleSdMsgPart>();

		ArticleSdMsgPart msgPart = new ArticleSdMsgPart();
		msgPart.setTitle("有新货啦~");
		msgPart.setDescription("生活用品");
		msgPart.setPicUrl("http://www.huaxiashenghuo.com/img/food.jpg");
		msgPart.setUrl("https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx91802a313bcf4ef8&redirect_uri=http://www.huaxiashenghuo.com/queryCatagoryList.html?method=queryCatagoryList&response_type=code&scope=snsapi_userinfo&state=12#wechat_redirect");
		msgParts.add(msgPart);
		msg.setParts(msgParts);
		return msg;
	}

}
以上用于用户关注之后推送一个消息。

获取用户信息:使用OAuth2.0 获取用户信息,首先配置回调域名,在接口权限里面。

配置菜单:可以开发菜单接口,这里没做创建菜单接口,在接口测试里面把菜单加上去:

{
    "button": [
        {
            "type": "view",
            "name": "微商城",
            "url": "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx91802a313bcf4ef8&redirect_uri=http://www.*******.com/queryCatagoryList.html?method=queryCatagoryList&response_type=code&scope=snsapi_userinfo&state=12#wechat_redirect"
        }
    ]
}

定义一个baseAction 每个链接都会调用的一个方法
里面实现

// 验证用户权BEGIN
里面<pre name="code" class="html">WX_GET_CODE_URL=https://api.weixin.qq.com/sns/oauth2/access_token?appid=WX_APPID&secret=WX_SECRET&code=WX_CODE&grant_type=authorization_code
<pre name="code" class="html">WX_GET_USER_INFO_URL=https://api.weixin.qq.com/sns/userinfo?access_token=WX_ACCESS_TOKEN&openid=WX_OPENID&lang=zh_CN

  try {/*UserVO userVO = (UserVO) getRequest().getSession().getAttribute(Constant.LOGIN_USERINFO);if(null == userVO || "".equals(userVO)){String code = getRequest().getParameter("code");String url = WxConstant.WX_GET_CODE_URL.replaceAll("WX_APPID", WxConstant.WX_APP_ID).replaceAll("WX_SECRET", WxConstant.WX_APP_KEY).replaceAll("WX_CODE", code);JSONObject json = doGet(url);System.out.println("获取accessToken的json="+json);String acctoken = json.getString("access_token");System.out.println("获取accessToken"+acctoken);String openId = json.getString("openid");//根据openId查询是否绑定过用户信息UserVO user = new UserVO();user.setOpenId(openId);user = userService.queryUserList(user);if(null == user || "".equals(user)){String urls = WxConstant.WX_GET_USER_INFO_URL.replaceAll("WX_ACCESS_TOKEN", acctoken).replaceAll("WX_OPENID", openId);JSONObject jsons = doGet(urls);String nickname = jsons.getString("nickname");String city = jsons.getString("city");String headimgurl = jsons.getString("headimgurl");user = new UserVO();user.setOpenId(openId);user.setAddress(city);user.setUserName(nickname);user.setLogoUrl(headimgurl);userService.addUser(user);}else{String urls = WxConstant.WX_GET_USER_INFO_URL.replaceAll("WX_ACCESS_TOKEN", acctoken).replaceAll("WX_OPENID", openId);System.out.println("拉取用户信息的Url"+urls);JSONObject jsons = doGet(urls);System.out.println("拉取用户信息="+jsons);String nickname = jsons.getString("nickname");String city = jsons.getString("city");String headimgurl = jsons.getString("headimgurl");user.setOpenId(openId);user.setAddress(city);user.setUserName(nickname);user.setLogoUrl(headimgurl);userService.updateUserInfo(user);}UserVO userInfo = new UserVO();userInfo.setOpenId(openId);userInfo = userService.queryUserList(userInfo);getRequest().getSession().setAttribute(Constant.LOGIN_USERINFO, userInfo);//ShoppingVO shoppingVO = new ShoppingVO();//shoppingVO.setSysUserId(userInfo.getUserId());//List<ShoppingVO> slist = shoppingService.selectShoppingList(shoppingVO);//getRequest().setAttribute("shoppingNumber", slist.size());}*/} catch (Exception e) {e.printStackTrace();return _result;} 
 使用session保存用户信息 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值