Java微信公众平台之消息管理

Java微信公众平台开发之消息管理,一定要先看下官方文档

微信消息管理分为接收普通消息、接收事件推送、发送消息(被动回复)、客服消息、群发消息、模板消息这几部分

一、接收普通消息

当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。

关于MsgId,官方给出解释,相当于每个消息ID,关于重试的消息排重,推荐使用msgid排重。微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。

比如文本消息的Xml示例

<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[this is a test]]></Content>
 <MsgId>1234567890123456</MsgId>
 </xml> 

其他的消息去官方文档查看,简单封装如下
消息抽象基类AbstractMsg.java

package com.phil.wechat.msg.model.req; 

import java.io.Serializable; 

/**
 * 基础消息类
 *
 * @author phil
 *
 */
public abstract class AbstractMsg implements Serializable { 

 private static final long serialVersionUID = -6244277633057415731L;
 private String ToUserName; // 开发者微信号
 private String FromUserName; // 发送方帐号(一个OpenID)
 private String MsgType = SetMsgType(); // 消息类型 例如 /text/image
 private long CreateTime; // 消息创建时间 (整型)
 private long MsgId; // 消息id,64位整型
 /**
  * 消息类型
  *
  * @return
  */
 public abstract String SetMsgType();
} 

文本消息TextMsg.java

package com.phil.wechat.msg.model.req; 

/**
 * 文本消息
 * @author phil
 * @date 2017年6月30日
 *
 */
public class TextMsg extends AbstractMsg { 

 private static final long serialVersionUID = -1764016801417503409L;
 private String Content; // 文本消息
 @Override
 public String SetMsgType() {
  return "text";
 }
} 

其他的依样画葫芦......

二、被动回复用户消息

微信服务器在将用户的消息发给公众号的开发者服务器地址(开发者中心处配置)后,微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次,如果在调试中,发现用户无法收到响应的消息,可以检查是否消息处理超时。假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。

如果出现“该公众号暂时无法提供服务,请稍后再试”,原因有两个

  • 开发者在5秒内未回复任何内容
  • 开发者回复了异常数据

比如回复的文本消息Xml示例

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml> 

简单封装下

回复消息抽象基类RespAbstractMsg.java

package com.phil.wechat.msg.model.resp; 

import java.io.Serializable; 

/**
 * 消息基类(公众帐号 -> 普通用户)
 *
 * @author phil
 *
 */
public abstract class RespAbstractMsg{
 // 接收方帐号(收到的OpenID)
 private String ToUserName;
 // 开发者微信号
 private String FromUserName;
 // 消息创建时间 (整型)
 private long CreateTime;
 // 消息类型(text/music/news)
 private String MsgType = setMsgType(); // 消息类型
 public abstract String setMsgType();
} 

回复文本消息RespTextMsg.java

package com.phil.wechat.msg.model.resp; 

/**
 * 回复图片消息
 *
 * @author phil
 * @data 2017年3月26日
 *
 */
public class RespImageMsg extends RespAbstractMsg {
 private Image Image;
 @Override
 public String setMsgType() {
  return "image";
 } 

 /**
  *
  * @author phil
  * @date 2017年7月19日
  *
  */
 public class Image { 

  // 通过素材管理中的接口上传多媒体文件,得到的id。
  private String MediaId; 

  public String getMediaId() {
   return MediaId;
  } 

  public void setMediaId(String mediaId) {
   MediaId = mediaId;
  }
 }
} 

其他消息类型依样画葫芦......

三、消息的处理

掌握xml解析

package com.phil.wechat.msg.controller; 

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Objects; 

import org.apache.commons.lang3.StringUtils;
import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; 

import com.phil.modules.config.WechatConfig;
import com.phil.modules.util.MsgUtil;
import com.phil.modules.util.SignatureUtil;
import com.phil.modules.util.XmlUtil;
import com.phil.wechat.base.controller.BaseController;
import com.phil.wechat.base.result.WechatResult;
import com.phil.wechat.msg.model.req.BasicMsg;
import com.phil.wechat.msg.model.resp.RespAbstractMsg;
import com.phil.wechat.msg.model.resp.RespNewsMsg;
import com.phil.wechat.msg.service.WechatMsgService; 

/**
 * @author phil
 * @date 2017年9月19日
 *
 */
@Controller
@RequestMapping("/wechat")
public class WechatMsgController extends BaseController { 

 private Logger logger = LoggerFactory.getLogger(this.getClass()); 

 @Autowired
 private WechatMsgService wechatMsgService; 

 /**
  * 校验信息是否是从微信服务器发出,处理消息
  * @param out
  * @throws IOException
  */
 @RequestMapping(value = "/handler", method = { RequestMethod.GET, RequestMethod.POST })
 public void processPost() throws Exception {
  this.getRequest().setCharacterEncoding("UTF-8");
  this.getResponse().setCharacterEncoding("UTF-8");
  boolean ispost = Objects.equals("POST", this.getRequest().getMethod().toUpperCase());
  if (ispost) {
   logger.debug("接入成功,正在处理逻辑");
   String respXml = defaultMsgDisPose(this.getRequest().getInputStream());//processRequest(request, response);
   if (StringUtils.isNotBlank(respXml)) {
    this.getResponse().getWriter().write(respXml);
   }
  } else {
   String signature = this.getRequest().getParameter("signature");
   // 时间戳
   String timestamp = this.getRequest().getParameter("timestamp");
   // 随机数
   String nonce = this.getRequest().getParameter("nonce");
   // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
   if (SignatureUtil.checkSignature(signature, timestamp, nonce)) {
    // 随机字符串
    String echostr = this.getRequest().getParameter("echostr");
    logger.debug("接入成功,echostr {}", echostr);
    this.getResponse().getWriter().write(echostr);
   }
  }
 } 

 /**
  * 默认处理方法
  * @param input
  * @return
  * @throws Exception
  * @throws DocumentException
  */
 private String defaultMsgDisPose(InputStream inputStream) throws Exception {
  String result = null;
  if (inputStream != null) {
   Map<String, String> params = XmlUtil.parseStreamToMap(inputStream);
   if (params != null && params.size() > 0) {
    BasicMsg msgInfo = new BasicMsg();
    String createTime = params.get("CreateTime");
    String msgId = params.get("MsgId");
    msgInfo.setCreateTime((createTime != null && !"".equals(createTime)) ? Integer.parseInt(createTime) : 0);
    msgInfo.setFromUserName(params.get("FromUserName"));
    msgInfo.setMsgId((msgId != null && !"".equals(msgId)) ? Long.parseLong(msgId) : 0);
    msgInfo.setToUserName(params.get("ToUserName"));
    WechatResult resultObj = coreHandler(msgInfo, params);
    if(resultObj == null){ //
     return null;
    }
    boolean success = resultObj.isSuccess(); //如果 为true,则表示返回xml文件, 直接转换即可,否则按类型
    if (success) {
     result = resultObj.getObject().toString();
    } else {
     int type = resultObj.getType(); // 这里规定 1 图文消息 否则直接转换
     if (type == WechatResult.NEWSMSG) {
      RespNewsMsg newsMsg = (RespNewsMsg) resultObj.getObject();
      result = MsgUtil.newsMsgToXml(newsMsg);
     } else {
      RespAbstractMsg basicMsg = (RespAbstractMsg) resultObj.getObject();
      result = MsgUtil.msgToXml(basicMsg);
     }
    }
   } else {
    result = "msg is wrong";
   }
  }
  return result;
 } 

 /**
  * 核心处理
  *
  * @param msg
  *   消息基类
  * @param params
  *   xml 解析出来的 数据
  * @return
  */
 private WechatResult coreHandler(BasicMsg msg, Map<String, String> params) {
  WechatResult result = null;
  String msgType = params.get("MsgType");
  if (StringUtils.isEmpty(msgType)) {
   switch (msgType) {
   case WechatConfig.REQ_MESSAGE_TYPE_TEXT: // 文本消息
    result = wechatMsgService.textMsg(msg, params);
    break;
   case WechatConfig.REQ_MESSAGE_TYPE_IMAGE: // 图片消息
    result = wechatMsgService.imageMsg(msg, params);
    break;
   case WechatConfig.REQ_MESSAGE_TYPE_LINK: // 链接消息
    result = wechatMsgService.linkMsg(msg, params);
    break;
   case WechatConfig.REQ_MESSAGE_TYPE_LOCATION: // 地理位置
    result = wechatMsgService.locationMsg(msg, params);
    break;
   case WechatConfig.REQ_MESSAGE_TYPE_VOICE: // 音频消息
    result = wechatMsgService.voiceMsg(msg, params);
    break;
   case WechatConfig.REQ_MESSAGE_TYPE_SHORTVIDEO: // 短视频消息
    result = wechatMsgService.shortvideo(msg, params);
    break;
   case WechatConfig.REQ_MESSAGE_TYPE_VIDEO: // 视频消息
    result = wechatMsgService.videoMsg(msg, params);
    break;
   case WechatConfig.REQ_MESSAGE_TYPE_EVENT: // 事件消息
    String eventType = params.get("Event"); //
    if (eventType != null && !"".equals(eventType)) {
     switch (eventType) {
     case WechatConfig.EVENT_TYPE_SUBSCRIBE:
      result = wechatMsgService.subscribe(msg, params);
      break;
     case WechatConfig.EVENT_TYPE_UNSUBSCRIBE:
      result = wechatMsgService.unsubscribe(msg, params);
      break;
     case WechatConfig.EVENT_TYPE_SCAN:
      result = wechatMsgService.scan(msg, params);
      break;
     case WechatConfig.EVENT_TYPE_LOCATION:
      result = wechatMsgService.eventLocation(msg, params);
      break;
     case WechatConfig.EVENT_TYPE_CLICK:
      result = wechatMsgService.eventClick(msg, params);
      break;
     case WechatConfig.EVENT_TYPE_VIEW:
      result = wechatMsgService.eventView(msg, params);
      break;
     case WechatConfig.KF_CREATE_SESSION:
      result = wechatMsgService.kfCreateSession(msg, params);
      break;
     case WechatConfig.KF_CLOSE_SESSION:
      result = wechatMsgService.kfCloseSession(msg, params);
      break;
     case WechatConfig.KF_SWITCH_SESSION:
      result = wechatMsgService.kfSwitchSession(msg, params);
      break;
     default:
      wechatMsgService.eventDefaultReply(msg, params);
      break;
     }
    }
    break;
   default:
    wechatMsgService.defaultMsg(msg, params);
   }
  }
  return result;
 }
} 

只是提供个思路,如若参考代码请移步

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • java实现微信公众号发送模版消息

    前言: 在我们购买商品或其他操作的时候,这时候微信公众号会推送相关模版消息.接下来简单介绍开发流程:(本文以订单推送为例) 首先在测试号新建模版消息 格式如下: {{first.DATA}} 用户名:{{keyword1.DATA}} 订单号:{{keyword2.DATA}} 订单金额:{{keyword3.DATA}} 商品信息:{{keyword4.DATA}} {{remark.DATA}} 这里会生成一个模版ID,后面会用到 然后后台在上传订单接口,上传成功后调用发送模版消息,代码实现

  • java微信公众号发送消息模板

    本文实例为大家分享了java微信公众号发送消息模板的具体代码,供大家参考,具体内容如下 这段时间接触公众号开发,写下向用户发送消息模板的接口调用 先上接口代码 public static JSONObject sendModelMessage(ServletContext context,JSONObject jsonMsg) { System.out.println("消息内容:"+jsonMsg); boolean result = false; try { getWX_Acces

  • Java微信公众号安全模式消息解密

    本文实例为大家分享了Java微信公众号安全模式消息解密的具体代码,供大家参考,具体内容如下 1.微信公众平台下载解密工具,导入项目中,根据demo解密消息,解密工具官方下载地址:点击打开链接 public static String streamToString(HttpServletRequest request) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(requ

  • Java微信公众平台之消息管理

    Java微信公众平台开发之消息管理,一定要先看下官方文档 微信消息管理分为接收普通消息.接收事件推送.发送消息(被动回复).客服消息.群发消息.模板消息这几部分 一.接收普通消息 当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上. 关于MsgId,官方给出解释,相当于每个消息ID,关于重试的消息排重,推荐使用msgid排重.微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次. 比如文本消息的Xml示例 <xml> <ToU

  • Java微信公众平台之素材管理

    微信素材管理和群发这块文档对Java很不友好.本文只对新增临时素材,新增永久素材做介绍,其余获取.删除.修改自行补充 公众号经常有需要用到一些临时性的多媒体素材的场景,例如在使用接口特别是发送消息时,对多媒体文件.多媒体消息的获取和调用等操作,是通过media_id来进行的.素材管理接口对所有认证的订阅号和服务号开放. 素材的限制 图片(image): 2M,支持PNG\JPEG\JPG\GIF格式 语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式 视频(video):10

  • Java微信公众平台之群发接口(高级群发)

    再次吐槽下,微信素材管理和群发这块文档对Java很不友好,此文需要结合我前文和官方文档. 测试号调试群发只需看是否群发消息是否能组装成功,不需要看结果如何(反正不会发送成功的),因为微信还没开放这个功能(估计也不会开放的). 一.群发说明 在公众平台网站上,为订阅号提供了每天一条的群发权限,为服务号提供每月(自然月)4条的群发权限. 1.对于认证订阅号,群发接口每天可成功调用1次,此次群发可选择发送给全部用户或某个标签: 2.对于认证服务号虽然开发者使用高级群发接口的每日调用限制为100次,但是

  • Java微信公众平台之获取地理位置

    本部分需要用到微信的JS-SDK,微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用微信分享.扫一扫.卡券.支付等微信特有的能力,为微信用户提供更优质的网页体验. 官方文档 一.JS-SDK引入 1.先登录微信公众平台进入"公众号设置"的"功能设置"里填写"JS接口安全域名",和网页授权一样只是个域名. 2

  • Java微信公众平台开发(1) 接入微信公众平台

    前面几篇文章一直都在说微信公众平台的开发准备工作,那么从这篇开始我们就将正式的进入JAVA微信公众平台开发的整个流程,那么这篇我们开始聊聊如何将我们的服务端和微信公众平台对接! (一)接入流程解析 在我们的开发过程中无论如何最好的参考工具当然是我们的官方文档了:http://mp.weixin.qq.com/wiki/8/f9a0b8382e0b77d87b3bcc1ce6fbc104.html 通过上面我们可以看出其中接入微信公众平台开发,开发者需要按照如下步骤完成: 填写服务器配置 验证服务

  • Java微信公众平台开发(12) 微信用户信息的获取

    前面的文章有讲到微信的一系列开发文章,包括token获取.菜单创建等,在这一篇将讲述在微信公众平台开发中如何获取微信用户的信息,在上一篇我们有说道微信用户和微信公众账号之间的联系可以通过Openid关联,所以在这里我们就采用openid去获取用户微信信息,并实现一个简单场景应用:当微信新用户关注我们的微信公众平台的时候我们自动回复一篇图文消息,然后在图文消息中标题为:[尊敬的:XXX,你好!],而且在图文消息中的图片就是用户的微信头像,如下图: 有关获取微信用户信息的文档我们可以参照:http:

  • Java微信公众平台开发(6) 微信开发中的token获取

    (一)token的介绍 引用:access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token.开发者需要进行妥善保存.access_token的存储至少要保留512个字符空间.access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效! (二)token的获取参考文档 获取的流程我们完全可以参考微信官方文档:http://mp.weixin.qq.com/wiki/14/9f9c82c1af308e3b14

  • Java微信公众平台开发(10) 微信自定义菜单的创建实现

    自定义菜单这个功能在我们普通的编辑模式下是可以直接在后台编辑的,但是一旦我们进入开发模式之后我们的自定义菜单就需要自己用代码实现,所以对于刚开始接触的人来说可能存在一定的疑惑,这里我说下平时我们在开发模式下常用的两种自定义菜单的实现方式:①不用写实现代码,直接用网页测试工具Post json字符串生成菜单:②就是在我们的开发中用代码实现菜单生成!(参考文档:http://mp.weixin.qq.com/wiki/10/0234e39a2025342c17a7d23595c6b40a.html 

随机推荐