文档章节

微信开发:消息管理

点点与麦兜
 点点与麦兜
发布于 2016/09/29 16:53
字数 1834
阅读 204
收藏 1

 

一,接收微信消息

      上一篇博文是介绍如何进行服务器端配置,配置的相当于为微信的消息接口,微信向服务器端推送消息或者推送用户发送的消息就会推送到该配置的URL中,配置好了过后,我们就需要在服务器端接收用户发送的一系列消息。

       服务器端接收用户消息和接收微信推送消息是使用的同一个地址,但是有一个区别接收推送消息为GET方法,接收用户发送的消息为POST方法。

       使用流接收POST消息转为String结果为XML的消息体,如果是在微信后台选择的为安全模式则需要解密,若是明文模式,那就直接解析XML就是了,此处为加密模式需用到解密类,本博文使用的为微信提供的解密类。链接为:

微信加解密文档:
http://mp.weixin.qq.com/wiki/11/2d2d1df945b75605e7fea9ea2573b667.html
加解密代码:
http://mp.weixin.qq.com/wiki/static/assets/a5a22f38cb60228cb32ab61d9e4c414b.zip

 

环境为:SpringMvc4     
栗子:

    //微信接收消息接口
    @ResponseBody
	@RequestMapping(value = "signature",method = RequestMethod.POST)
	public String signature(HttpServletRequest request) throws AesException{
		try {
            //接收流
			ServletInputStream sis = request.getInputStream();
			StringBuilder xmlMsg = new StringBuilder();  
		        byte[] b = new byte[4096];  
		        for (int n; (n = sis.read(b)) != -1;) {  
		            xmlMsg.append(new String(b, 0, n, "UTF-8"));  
		     }  
			    System.out.println(xmlMsg);
                //接收加密的xml
				Object[] encrypt = XMLParse.extract(xmlMsg.toString());
				//解密
		        WXBizMsgCrypt  wxcpt = new WXBizMsgCrypt("token", 
				                                         "encodingAesKey",
				                                         "appid");
                //获取解密后的XML
		        String msg = wxcpt.decrypt(encrypt[1].toString());
                //转对象
		        WxMsgRequest wmr = this.convertWxMesgToObj(msg);
		        System.out.println(wmr);

                if(wmr.getMsgType().equals(WxRequestMsgType.MSG_TEXT)){
		        	WxTextMsgResponse wtmr = new WxTextMsgResponse();
		        	wtmr.setContent("点点与麦兜的TEST");
		        	Long createTime = System.currentTimeMillis() / 1000;
		        	wtmr.setCreateTime(createTime.toString());
		        	wtmr.setFromUserName(wmr.getToUserName());
		        	wtmr.setToUserName(wmr.getFromUserName());
		        	wtmr.setMsgType(WxRequestMsgType.MSG_TEXT);
		        	
		        	String returnStr = this.convertObjToXml(wtmr);
		        	return returnStr;
		        }

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	//微信验证接口
	@ResponseBody
	@RequestMapping(value = "signature",method=RequestMethod.GET)
	public String signature(String signature,
							String timestamp,
							String nonce,
							String echostr){
		try {	
			String shaPw = SHA1.getSHA1("xiaofli007", timestamp, nonce);
			if(signature.equals(shaPw))
				return echostr;
			else
				return null;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
		
	}
  //将xml数据解析为对象
  private WxMsgRequest convertWxMesgToObj(String msg) throws JAXBException{
		JAXBContext context = JAXBContext.newInstance(WxMsgRequest.class);  
        Unmarshaller unmarshaller = context.createUnmarshaller();  
        return (WxMsgRequest)unmarshaller.unmarshal(new StringReader(msg));
	}
  //将对象转为xml字符串
  public String convertObjToXml(Object obj) throws JAXBException{
		JAXBContext context = JAXBContext.newInstance(obj.getClass());  
        Marshaller marshaller = context.createMarshaller();  
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        StringWriter writer = new StringWriter();  
        marshaller.marshal(obj, writer);  
        String temp =  writer.toString();
        return  temp; 
	}

解密前消息: 

<xml>
    <ToUserName><![CDATA[gh_e1c44a3a9f81]]></ToUserName>
    <Encrypt><![CDATA[HusAtbuEO8XmYaH4tzuZHcdi7Kg2e6szJfZrzdQLnpEs6D0jrNWKLFYftafLyKLFy7sOPbQUYI8DaVPPV/0npFSRym2oskoN0ip3q93XXtunbz5OBmWlYsvKnJuYK/UlIttgrJbrRFJlz4AKiHYUnJx7vaSAFvErAlhudPA1rhPEa64sARRGRQhrP1m/zffbSRl6uI7Wz1jsIsfiZAPg0nxqfxdDXh9Gklcp6DNHhf3phAx9pt8kyZKh4n8yhHV1+R+WU0c86YEgwQ7NHgA0CaryQPemkNRF06YrWEvE0meToeT08sm2A0bZJUiGGmj8dD9/b6KsESaQmfsF2JzdRvSq79gLO+Mn0swQS4wjOnbrgw7otvlYCZnDu4+xcfv+lGgMIc0YfG/jtT4VH6pboBtm1xCRs01N14SHB8pGryA=]]></Encrypt>
</xml>

解密后的消息:

<xml>
<ToUserName><![CDATA[gh_e1c44a3a9f81]]></ToUserName>
<FromUserName><![CDATA[oMffXwBl4N4F29vbH3UAbrdhMq4Y]]></FromUserName>
<CreateTime>1475129963</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[11]]></Content>
<MsgId>6335634948877288984</MsgId>
</xml>

二,识别消息

      1、消息类型:

           文本消息(text)
           图片消息(image)
           语音消息(voice)
           视频消息(video)
           小视频消息 (shortvideo)
           地理位置消息(location)
           链接消息(link)

创建一个实体类,用于接受消息(为了方便我是全部字段写到一个类中,也可以先判断类型:再指定接受的类型):

@XmlRootElement(name = "xml")
public class WxMsgRequest {
	
    /*** 开发者微信号 */
	private String ToUserName;
	/*** 发送方帐号(一个OpenID)*/
	private String FromUserName;
	/*** 消息创建时间 (整型)*/
	private String CreateTime;
	/*** 消息类型有:text ; event ; 语音为voice*/
	private String MsgType;
	/*** 消息id*/
	private String MsgId;
	/*** 语音消息媒体id,可以调用多媒体文件下载接口拉取数据。*/
	private String MediaId;
	/*** 语音格式,如amr,speex等*/
	private String Format;
	/*** 视频消息缩略图的媒体id,可以调用多媒体文件下载接口拉取数据。*/
	private String ThumbMediaId;
	/*** 文本消息内容*/
	private String Content;
    /*** 图片消息URL*/
	private String picUrl;
	/*** 地理位置消息 地理位置纬度*/
	private String gpsX;
	/*** 地理位置消息 地理位置经度*/
	private String gpsY;
	/*** 地理位置消息 地图缩放大小*/
	private String scale;
	/*** 地理位置消息 地理位置信息*/
	private String label;
	/*** 链接消息 消息标题*/
	private String title;
	/*** 链接消息 消息描述*/
	private String description;
	/*** 链接消息 消息链接*/
	private String url;
    /**
	 * 事件类型,subscribe(订阅)、unsubscribe(取消订阅)、CLICK(自定义菜单点击事件)
	 * WeixinRequestMsgType#SUBSCRIBE_EVENT
	 */
	private String Event;
	/*** 事件KEY值,与自定义菜单接口中KEY值对应*/
	private String EventKey;
	/** 二维码的ticket,可用来换取二维码图片 **/
	private String Ticket;

	@XmlElement(name = "Ticket")
	public String getTicket() {
		return Ticket;
	}

	public void setTicket(String ticket) {
		Ticket = ticket;
	}
    //由于文章篇幅问题,下面的参数set方法和get方法就不展示了。。每个get方法加@XmlElement(name="参数名")
	}

将xml解析成对象:

private WxMsgRequest convertWxMesgToObj(String msg) throws JAXBException{
		JAXBContext context = JAXBContext.newInstance(WxMsgRequest.class);  
        Unmarshaller unmarshaller = context.createUnmarshaller();  
        return (WxMsgRequest)unmarshaller.unmarshal(new StringReader(msg));
	}

三,回复消息

        1、消息回复类型:

             文本消息(text)
             图片消息 ( image )
             语音消息 ( voice )
             视频消息 ( video )
             音乐消息 ( music )
             图文消息 ( picurl )

 此处栗子为文本消息回复。
 创建一个微信消息类型实体,用于判断消息类型:

public class WxRequestMsgType {

	/*** 请求的,应答的,文本推送消息 */
	public static final String MSG_TEXT = "text";

	/**** 请求的, 图片推送消息*/
	public static final String MSG_IMAGE = "image";

	/*** 请求的, 地理位置信息*/
	public static final String MSG_LOCATION = "location";

	/*** 请求的, 链接信息*/
	public static final String MSG_LINK = "link";

	/*** 请求的,事件推送消息*/
	public static final String MSG_EVENT = "event";

	/*** 应答的,图文消息体*/
	public static final String MSG_NEW = "news";

	/*** 请求的,语音推送消息*/
	public static final String MSG_VOICE = "voice";

    /*** 事件类型订阅*/
	public static final String EVENT_SUBSCRIBE = "subscribe";

	/*** 事件取消订阅*/
	public static final String EVENT_UNSUBSCRIBE = "unsubscribe";

	/*** 自定义菜单的点击事件*/
	public static final String EVENT_CLICK = "CLICK";

	public static final String EVENT_SCAN = "SCAN";
	/**
	 * 如果公众号处于开发模式,需要在接收到用户发送的消息时, 返回一个MsgType为transfer_customer_service的消息,
	 * 微信服务器在收到这条消息时,会把这次发送的消息转到多客服系统。 用户被客服接入以后,客服关闭会话以前,处于会话过程中,
	 * 用户发送的消息均会被直接转发至客服系统
	 */
	public static final String TRANSFER_CUSTOMER_SERVICE_MSG = "transfer_customer_service";
}

创建文本回复实体:

@XmlRootElement(name = "xml")
public class WxTextMsgResponse{
	/*** 开发者微信号*/
	private String ToUserName;
	/*** 发送方帐号(一个OpenID)*/
	private String FromUserName;
	/*** 消息创建时间 (整型)*/
	private String CreateTime;
	/*** 应答消息类型有: news ;text;*/
	private String MsgType;
	/*** 文本消息内容*/
	private String Content;
	/**
	 * 位0x0001被标志时,星标刚收到的消息。
	 */
	private String FuncFlag;

    @XmlElement(name = "Content")
	public String getContent() {
		return Content;
	}

	public void setContent(String content) {
		Content = content;
	}
   //省略其他get、set方法
}

           2,判断回复

JAXB2对象转为XML字符串:

public String convertObjToXml(Object obj) throws JAXBException{
		JAXBContext context = JAXBContext.newInstance(obj.getClass());  
        Marshaller marshaller = context.createMarshaller();  
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        StringWriter writer = new StringWriter();  
        marshaller.marshal(obj, writer);  
        String temp =  writer.toString();
        return  temp; 
	}

 在signature、POST方法中加入文本消息的判断进行回复:

if(wmr.getMsgType().equals(WxRequestMsgType.MSG_TEXT)){
		        	WxTextMsgResponse wtmr = new WxTextMsgResponse();
		        	wtmr.setContent("点点与麦兜的TEST");
		        	Long createTime = System.currentTimeMillis() / 1000;
		        	wtmr.setCreateTime(createTime.toString());
		        	wtmr.setFromUserName(wmr.getToUserName());
		        	wtmr.setToUserName(wmr.getFromUserName());
		        	wtmr.setMsgType(WxRequestMsgType.MSG_TEXT);
		        	
		        	String returnStr = this.convertObjToXml(wtmr);
		        	return returnStr;
         }

四,场景应用

此处只举例了消息接受和文本消息的回复,后面还有主动推送消息、还有其他事件,比如关注事件,取消关注事件等、这里就不一一举例了,其他事件接受和回复请查看微信开发文档(其实是大同小异)


1,这个回复其实可以做一个后台自动回复管理。比如后台设置关键字回复、被添加回复、自动回复,发送过来的消息进行内容识别,是否为关键字,或者自动回复等。

© 著作权归作者所有

共有 人打赏支持
点点与麦兜
粉丝 2
博文 5
码字总数 7359
作品 0
成都
程序员
C#开发微信门户及应用(2)--微信消息的处理和应答

微信应用如火如荼,很多公司都希望搭上信息快车,这个是一个商机,也是一个技术的方向,因此,有空研究下、学习下微信的相关开发,也就成为计划的安排事情之一了。本系列文章希望从一个循序渐...

walb呀
2017/12/04
0
0
C#开发微信门户及应用(8)-微信门户应用管理系统功能介绍

最近对微信接口进行深入的研究,通过把底层接口一步步进行封装后,逐步升级到自动化配置、自动化应答,以及后台处理界面的优化和完善上,力求搭建一个较为完善、适用的微信门户应用管理系统。...

walb呀
2017/12/04
0
0
C#开发微信门户及应用(25)-微信企业号的客户端管理功能

我们知道,微信公众号和企业号都提供了一个官方的Web后台,方便我们对微信账号的配置,以及相关数据的管理功能,对于微信企业号来说,有通讯录中的组织架构管理、标签管理、人员管理、以及消...

walb呀
2017/12/04
0
0
C#开发微信门户及应用(7)-微信多客服功能及开发集成

最近一直在弄微信的集成功能开发,发现微信给认证账户开通了一个多客服的功能,对于客户的咨询,可以切换至客服处理的方式,而且可以添加多个客服进行处理,这个在客户咨询比较多的时候,是一...

walb呀
2017/12/04
0
0
C#开发微信门户及应用(20)-微信企业号的菜单管理

前面几篇陆续介绍了很多微信企业号的相关操作,企业号和公众号一样都可以自定义菜单,因此他们也可以通过API进行菜单的创建、获取列表、删除的操作,因此本篇继续探讨这个主体,介绍企业号的...

walb呀
2017/12/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

TypeScript基础入门之高级类型的字符串字面量类型

转发TypeScript基础入门之高级类型的字符串字面量类型 高级类型 字符串字面量类型 字符串字面量类型允许你指定字符串必须的固定值。 在实际应用中,字符串字面量类型可以与联合类型,类型保护...

durban
18分钟前
2
0
iOS权限授权添加

<!-- 相册 --> <key>NSPhotoLibraryUsageDescription</key> <string>App需要您的同意,才能访问相册</string> <!-- 相册写入 --> <key>NSPhotoLibraryAddUsageDescription</key> <string>App......

RainOrz
22分钟前
1
0
支配树(Dominator Tree)

MAT中的支配树 在使用MAT分析项目的内存泄漏问题时,其中有一个支配树(Dominator)视图。如果我们把Java对象之间的引用关系看做一张有向图(可以存在环)的话,对象的支配树体现了对象之间的...

akane_oimo
24分钟前
1
0
xshell官网下载及安装(免费版本)

百度搜索xshell,点击xshell官网下载链接,如图 然后点击下图的按钮 点击Latest Products,可以下载最新版本,选择要下载的版本,点击下载 选择上面红框里面的,并填写内容,submit之后会有邮...

曾大大胖
29分钟前
2
0
Android 调用系统分享文字、图片、文件,可直达微信、朋友圈、QQ、QQ空间、微博

兼容SDK 18以上的系统,直接调用系统分享功能,分享文本、图片、文件到第三方APP,如:微信、QQ、微博等 因为偷懒,可直达微信、朋友圈、QQ、QQ空间、微博的分享仅写了图片分享的,其他的文本...

她叫我小渝
30分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部