接收到公众号发来的消息后的流程是(个人意见):
step 1:将xml格式的消息转化为对象。
step 2:让消息进消息网关,按消息类型作分发。
step 3:如果消息为事件,则进入事件网关,按事件类型进行分发,非事件则无此步骤。
step 4:根据消息进行业务处理
step 5:若需要回复消息,则发送xml格式的消息给公众号用户。
Controller层代码:
/**
* 接收及回复微信消息
*
* @param token
* @param signature
* @param timestamp
* @param nonce
* @param echostr
* @param request
* @param response
* @return
* @throws ServletException
* @throws IOException
*/
@RequestMapping("ansy/weixinMessage")
@ResponseBody
public Callable<Object> weixinMessage(String token, String signature, String timestamp, String nonce,
String echostr, HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
return new Callable<Object>() {
OutData out = new OutData();
public Object call() throws Exception {
if (request.getMethod().toLowerCase().equals("get")) {
doGet(signature, timestamp, nonce, echostr, response);
} else {
doPost(request, response);
}
out.setCode(1);
out.setData(null);
out.setMsg("success");
return out;
}
};
}
/**
* get方式验证token
*/
public void doGet(String signature, String timestamp, String nonce, String echostr, HttpServletResponse response) {
//第一个值是服务器配置的token,我们自定义的,和微信的access_token无关
String[] ArrTmp = { "liboyi921216liboyisdfsdfsdfsdf", timestamp, nonce };
Arrays.sort(ArrTmp);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < ArrTmp.length; i++) {
sb.append(ArrTmp[i]);
}
String pwd = WeixinMessageDigestUtil.getInstance().encipher(sb.toString());
if (pwd.equals(signature)) {
if (!"".equals(echostr) && echostr != null) {
try {
PrintWriter writer = response.getWriter();
writer.print(echostr);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 处理微信服务器发来的消息
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 将请求、响应的编码均设置为UTF-8(防止中文乱码)
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// 调用核心业务类接收消息、处理消息
String respMessage = coreService.processRequest(request);
// 响应消息
PrintWriter out = response.getWriter();
out.print(respMessage);
out.flush();
out.close();
}
Service层代码:
/**
* 处理微信发来的请求
*
* @param request
* @return
* @throws Exception
*/
public String processRequest(HttpServletRequest request) throws Exception {
// xml请求解析
Map<String, String> requestMap = WeixinMessageUtil.parseXml(request);
// 消息类型
String msgType = requestMap.get("MsgType");
// 回复消息
return msgGateWay(msgType, requestMap);
}
/**
* 获取微信公众号平台接口的ACCESS_TOKEN
* @return
*/
public String getWeixinAccessToken(){
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
ServletContext application = webApplicationContext.getServletContext();
if(application.getAttribute("tokenMap")!=null){
WeixinAccessToken tempToken=(WeixinAccessToken) application.getAttribute("tokenMap");
if(System.currentTimeMillis()>tempToken.getExpirationTime()){
return tempToken.getAccessToken();
}else{
return getAccessToken();
}
}else{
return getAccessToken();
}
}
private String getAccessToken() {
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
ServletContext application = webApplicationContext.getServletContext();
String appId=appid;
String appSecret=secret;
String url="https://api.weixin.qq.com/cgi-bin/token";
String returnData=Common.sendGet(url,"grant_type=client_credential&appid="+appId+"&secret="+appSecret);
JSONObject json=JSONObject.fromObject(returnData);
if(json.containsKey("access_token")){
if(json.get("access_token")!=null&&!json.get("access_token").equals("")){
application.setAttribute("tokenMap", new WeixinAccessToken(json.get("access_token").toString(),
System.currentTimeMillis()+Integer.parseInt(json.get("expires_in").toString())));
return json.get("access_token").toString();
}
}
return null;
}
/**
* 消息网关
* @param msgType
* @throws Exception
*/
private String msgGateWay(String msgType,Map<String, String> requestMap) throws Exception {
String toUserName=requestMap.get("ToUserName");
String fromUserName=requestMap.get("FromUserName");
String initMsg="Hi,我是美少女小冷。我还处于成长阶段,目前不能理解你说了什么。呜呜呜……";
WeixinMessageXmlUtil messageUtil=null;
String responseMsg="";
if (msgType.equals(WeixinMsgType.text.toString())) { // 文本消息
messageUtil=new WeixinMessageXmlUtil(fromUserName,toUserName,System.currentTimeMillis(),
WeixinMsgType.text.toString(),initMsg);
responseMsg= WeixinMessageXmlUtil.objectToXml(messageUtil);
}else if (msgType.equals(WeixinMsgType.image.toString())) { // 图片消息
}else if (msgType.equals(WeixinMsgType.voice.toString())) { // 语音消息
}else if (msgType.equals(WeixinMsgType.video.toString())) {// 视频消息
}else if (msgType.equals(WeixinMsgType.shortvideo.toString())) { // 小视频消息
}else if (msgType.equals(WeixinMsgType.location.toString())) { // 地理位置消息
}else if (msgType.equals(WeixinMsgType.link.toString())) { // 链接消息
}else if (msgType.equals(WeixinMsgType.music.toString())) { // 音乐消息
}else if (msgType.equals(WeixinMsgType.news.toString())) { // 图文消息
}else if (msgType.equals(WeixinMsgType.event.toString())) { // 事件消息
String eventType = requestMap.get("Event");
if(eventType!=null&&!eventType.equals("")){
return eventGateWay(eventType,requestMap);
}
}
return responseMsg;
}
/**
* 事件网关
* @param eventType
* @throws Exception
*/
private String eventGateWay(String eventType, Map<String, String> requestMap) throws Exception {
if (eventType == null || requestMap == null) {
return null;
}
// 发送方帐号(open_id)
String fromUserName = requestMap.get("FromUserName");
// 公众帐号
String toUserName = requestMap.get("ToUserName");
if (eventType.equals(WeixinEventType.subscribe.toString())) { // 关注
if (requestMap.containsKey("EventKey")) {
if (!requestMap.get("EventKey").equals("") && requestMap.get("EventKey") != null) {
// 拿到参数(用户id)
String userId = requestMap.get("EventKey").substring(8);
WeixinUserInfo userWeixinInfo=getWeixinUserInfoByOpenId(fromUserName);
if(userWeixinInfo==null){
userWeixinInfo=new WeixinUserInfo();
}
//业务处理代码
}
}
String loginUrl="https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxe91c058fd370ab41&redirect_uri=http://www.coldle.com/weike/"
+ "api/wxuser/ansy/getAccessToken.shtml?iswebchat=1&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect ";
StringBuffer msgContent=new StringBuffer();
msgContent.append("Coldle冷暖在线欢迎您\n");
msgContent.append("冷暖在线是服务于制冷、空调、暖通专业的第三方平台,涉及的方面如下:\n");
msgContent.append("1、项目的方案、设计及施工的发布与承接。\n");
msgContent.append("2、设备、阀件的采购和团购。\n");
msgContent.append("3、项目运营物业管理与远程维保。\n");
msgContent.append("4、项目的招标与投标信息发布。\n");
msgContent.append("5、冷库、冷藏车的出租与承租。\n");
msgContent.append("6、专业人才的求职与招聘。\n");
msgContent.append("7、专业资料查询及疑难问题的咨询。\n");
msgContent.append("<a href=\""+loginUrl+"\">登录注册</a>冷暖在线官网http://www.coldle.com了解更多。\n");
// String msgContent = "感谢您关注蝌蚪冷暖在线公众号!";
String msgXml = WeixinMessageXmlUtil.objectToXml(new WeixinMessageXmlUtil(fromUserName, toUserName,
System.currentTimeMillis(), WeixinMsgType.text.toString(), msgContent.toString()));
return msgXml;
} else if (eventType.equals(WeixinEventType.unsubscribe.toString())) { // 取消关注
} else if (eventType.equals(WeixinEventType.SCAN.toString())) { // 扫码
} else if (eventType.equals(WeixinEventType.LOCATION.toString())) {// 上报地理位置信息
} else if (eventType.equals(WeixinEventType.CLICK.toString())) {// 自定义菜单点击
}
return "success";
}
WeixinMessageXmlUtil将文字消息转为xml:
package com.exp.util;
import java.io.StringWriter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "xml")
public class WeixinMessageXmlUtil {
private String ToUserName; //接收方帐号(收到的OpenID)
private String FromUserName; //开发者微信号
private long CreateTime; //创建时间
private String MsgType; //消息类型
private String Content; //内容
public WeixinMessageXmlUtil(){
}
public WeixinMessageXmlUtil(String ToUserName,String FromUserName,long CreateTime,String MsgType,String Content){
this.ToUserName=ToUserName;
this.FromUserName=FromUserName;
this.CreateTime=CreateTime;
this.MsgType=MsgType;
this.Content=Content;
}
/**
* 对象转为xml格式
* @param tx
* @return
* @throws Exception
*/
public static String objectToXml(WeixinMessageXmlUtil tx) throws Exception{
StringWriter sw = new StringWriter();
JAXBContext jbc=JAXBContext.newInstance(tx.getClass()); //传入要转换成xml的对象类型
Marshaller marshaller = jbc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");// //编码格式
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);// 是否格式化生成的xml串
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);// 是否省略xm头声明信息
marshaller.marshal(tx, sw);
String msg=sw.toString();
msg= msg.replace("content", "Content");
msg= msg.replace("createTime", "CreateTime");
msg= msg.replace("fromUserName", "FromUserName");
msg= msg.replace("msgType", "MsgType");
msg= msg.replace("toUserName", "ToUserName");
return msg;
}
public String getToUserName() {
return ToUserName;
}
public void setToUserName(String toUserName) {
ToUserName = toUserName;
}
public String getFromUserName() {
return FromUserName;
}
public void setFromUserName(String fromUserName) {
FromUserName = fromUserName;
}
public long getCreateTime() {
return CreateTime;
}
public void setCreateTime(long createTime) {
CreateTime = createTime;
}
public String getMsgType() {
return MsgType;
}
public void setMsgType(String msgType) {
MsgType = msgType;
}
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
public static void main(String[] args){
WeixinMessageXmlUtil tx =new WeixinMessageXmlUtil("111111", "2222222", 21312321, "test","呵呵");
String xmlMsg="";
try {
xmlMsg = tx.objectToXml(tx);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(xmlMsg);
}
}
注:微信端需要的xml格式,不需要xml声明头,并且属性名需要首字母大写。
格式要严格匹配,否则消息发送不成功。