服务器配置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保存用户信息