springboot的微信公众号(六)文本消息
这个功能再微信公众号开发文档里面叫做被动回复用户消息;假如说用户触发了某一个业务,然后需要你来推送一些东西的时候用,当然比较多的还是模板消息,比如
这个之后说
我们现在说普通的消息
先看一下微信的开发文档
不难看出,就是说当用户发送消息过来的时候你可以获取到,然后我们返回给微信一个xml类型的数据到response中,即可回复给用户消息
话不多说,上代码,我这里将所有的消息发送放在了service,然后将请求的request转换成了map,后面会贴出这个工具类,
这段代码的前面是之前的接入验证,然后是转换request,然后就是业务逻辑层了
public void wxLogin(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException{
//设置编码,不然接收到的消息乱码
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String signature = request.getParameter("signature");//微信加密签名
String timestamp = request.getParameter("timestamp");//时间戳
String nonce = request.getParameter("nonce");//随机数
String echostr = request.getParameter("echostr");//随机字符串
PrintWriter out = null;
//接入验证
if(WeiXinUtil.checkSignature(signature, timestamp, nonce)){
if (echostr!=null) {
System.out.println(echostr);
try {
out = response.getWriter();
} catch (IOException e) {
e.printStackTrace();
}
out.write(echostr);//验证成功返回的值
return;
}
//从这里开始
Map<String, String> reqXmlData;
try {
reqXmlData = XMLUtils.parseXmlFromRequest(request);
weiXinService.doRequestXmlData(request.getQueryString(), reqXmlData,response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
业务逻辑代码
这里首先提取一下request中的参数
String msgType = reqXmlData.get(XMLUtils.c_xml_msg_key_MsgType);//获取消息类型
String content = reqXmlData.get(XMLUtils.c_xml_msg_key_Content);//获取消息内容
String event = reqXmlData.get(XMLUtils.c_xml_msg_key_Event);//获取事件类型
String openId = reqXmlData.get(XMLUtils.c_xml_msg_key_FromUserName);//获取发送者openID
String formUser = reqXmlData.get(XMLUtils.c_xml_msg_key_ToUserName);//获取接受者ID
String eventKey = reqXmlData.get(XMLUtils.c_xml_msg_key_EventKey);//获取扫码事件的key
文本消息的类型是text,也就是说用户发送的文本,你被动接收。比如
然后处理
//文本消息
if(XMLUtils.c_xml_msg_type_text.equals(msgType)){
doMsg(response, content, openId, formUser);
}
注意这里的fromUser和openid,当用户发送消息给公众号的时候,用户是发送者,但是我们是给用户回复消息,所以我们是发送者,容易混淆
doMsg
if ("?".equals(content)||"?".equals(content)) {
MsgUtil.sendTextMsgToUser("帮助命令:1、接收文本消息 2、接收图片消息 3、接收图文消息 "
+ "4、接收模板消息 5、生成带参数的二维码 ", openId,formUser,response);
}
if ("1".equals(content)) {
MsgUtil.sendTextMsgToUser("文本消息", openId,formUser,response);
}
我这里写了一个帮助信息,辅助自己测试,你们不清楚可以打断点跟踪一下,看看用户发送来的消息是什么
sendTextMsgToUser这个方法就是将消息封装
/**
* 发送文本消息
* @param msg
* @param toUser
*/
public static void sendTextMsgToUser(String msg, String toUser,String formUser,HttpServletResponse resp) {
TextMsg textMsg = new TextMsg();
textMsg.setContent(msg);
textMsg.setToUserName(toUser);
textMsg.setFromUserName(formUser);
sendMsg(resp, textMsg);
}
然后textMsg的消息类,由于这边用到的消息比较多,所以我封装了一个basemsg
import java.util.Date;
/**
*
* @author Administrator
*
*/
public class TextMsg extends BaseMessage {
private String Content;
private String MsgId;
public TextMsg(){
this.setMsgType("text");
this.setCreateTime(new Date().getTime());
}
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
public String getMsgId() {
return MsgId;
}
public void setMsgId(String msgId) {
MsgId = msgId;
}
}
public class BaseMessage {
private String ToUserName;
private String FromUserName;
private long CreateTime;
private String MsgType;
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;
}
}
文本消息主要包含这些东西就行,你只需要把这些属性封装即可
然后是
/**
* 抽取的发送消息的方法
* @param resp
* @param msg
*/
private static void sendMsg(HttpServletResponse response, BaseMessage msg) {
//将封装的消息转为xml
String textMessageToXml = XMLUtils.textMessageToXml(msg);
logger.info("发送的消息是-------"+textMessageToXml);
PrintWriter out=null;
try {
out = response.getWriter();
//写入返回的response中
out.println(textMessageToXml);
} catch (IOException e) {
logger.error("发送微信消息失败",e);
e.printStackTrace();
}finally{
//注意关流,不然会发送失败
out.close();
}
}
这个注释很清楚了,就不再多说了
发送成功的日志消息
如果失败就按照返回错误码排查
下面贴出来xmlutil工具类
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.example.weixin.demo.message.BaseMessage;
import com.example.weixin.demo.message.News;
import com.thoughtworks.xstream.XStream;
/**
*
* @author Administrator
*
*/
public abstract class XMLUtils {
// xml消息体的key定义
public static final String c_xml_msg_key_ToUserName ="ToUserName";
public static final String c_xml_msg_key_FromUserName ="FromUserName";
public static final String c_xml_msg_key_CreateTime="CreateTime";
public static final String c_xml_msg_key_MsgType ="MsgType";
public static final String c_xml_msg_key_Event ="Event";
public static final String c_xml_msg_key_EventKey="EventKey";
public static final String c_xml_msg_key_Ticket="Ticket";
// xml消息类型定义
public static final String c_xml_msg_type_event = "event";
public static final String c_xml_msg_type_text = "text";
public static final String c_xml_msg_type_location = "location";
// 事件类型定义
public static final String c_xml_msg_event_photo = "pic_photo_or_album";
public static final String c_xml_msg_event_subscribe = "subscribe";
public static final String c_xml_msg_event_unsubscribe = "unsubscribe";
public static final String c_xml_msg_event_scan = "SCAN";
public static final String c_xml_msg_event_click = "CLICK";
public static final String c_xml_msg_key_Content = "Content";
/**
* 请求xml转为map
* @param request
* @return
* @throws Exception
*/
public static Map<String,String> parseXmlFromRequest(HttpServletRequest request) throws Exception{
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(request.getInputStream());
List<Element> elements = document.getRootElement().elements();
Map<String,String> msgMap = new HashMap<>();
for(int m=0,len=elements.size();m<len;m++){
Element element = elements.get(m);
msgMap.put(element.getName(),element.getText());
}
return msgMap;
}
/**
* map转为xml
* @param map
* @return
* @throws Exception
*/
public static String parseMapToXml(Map<String, String> map) throws Exception{
Document document = DocumentHelper.createDocument();
Element rootElement = document.addElement("xml");
for (Map.Entry<String, String> me : map.entrySet()) {
Element empName = rootElement.addElement(me.getKey());
empName.setText(me.getValue());
}
return document.asXML();
}
/**
* 消息类转为xml
* @param msg
* @return
*/
public static String textMessageToXml(BaseMessage msg){
XStream xstream = new XStream();
xstream.alias("xml", msg.getClass());
return xstream.toXML(msg);
}
/**
* 新闻消息转为xml
* @param msg
* @return
*/
public static String newsMessageToXml(BaseMessage msg){
XStream xstream = new XStream();
xstream.alias("xml", msg.getClass());
xstream.alias("item",new News().getClass());
return xstream.toXML(msg);
}
}