想自己开一个公众号,先学习一下用 Java 进行微信公众号的开发。
微信公众号的管理有开发模式和编辑模式两种,两者是互斥的。
腾讯是这么讲的: 编辑模式:编辑模式指所有的公众号运营者都可以通过简单的编辑,设置“按关键字回复”等功能。您可以设定常用的文字/语言/图片/录音作为回复消息,并制定自动回复的规则。当订阅用户的行为符合自动回复规则的时候,就会收到自动回复的消息。 开发模式:开发模式是为开发者提供与用户进行消息交互的能力。对于成功接入消息接口的公众账号,当用户发消息给公众号,微信公众平台服务器会使用http请求对接入的网址进行消息推送,第三方服务器可通过响应包回复特定结构,从而达到回复消息的目的。
所以接下来要讲的是如果使用微信的开发模式。
地址映射工具
微信的 URL 要求必须是: http:// 80端口,且必须是能够在公网访问的,本地的不行。所以这里用到一个映射工具叫做 ngrok 。下载之后使用,需要切换到下载ngrok文件目录下,cmd
ngrok http 8080
这个ngrok软件开了不能关,而且每次关闭后重新开启给你分配的外网域名不一样,需要去微信服务器配置url中修改!
红色地址就是外网映射地址,80端口:替换了localhost:8080.
进入微信公众平台地址(https://mp.weixin.qq.com/),进入基本配置,点击启用开发者模式。
在服务器配置下的,修改配置,详细配置见截图
开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,我们这里用通过 servlet 的 GET 请求进行校验
GET请求携带四个参数,参数解释如下:
我们的servlet需要对以上四个参数进行校验,将 timestamp,nonce,token 三者排序拼接成字符串,再进行 Sha1 加密之后,如果和 signature 相同则表示校验通过,具体验证过程在DoCheckServlet中的doGet方法,其中CheckWX验证消息是否来自服务器,SHA1是加密算法:
之后点击修改配置下面的提交按钮,就会开始验证,如果成功,网页会有提示: 提交成功 .
此时就可以开启开发者模式了:
注:开启开发者模式后,自动回复消息和自定义菜单会失效。此时菜单需要通过自定义菜单接口去创建,回复消息也只能后台程序里回复。也可以停用开发者模式,回到初始状态。
数据交互的过程如上图所示,通过 Post 请求进行。根据请求类型的不同,微信规定了不同的参数,并且通过 XML 的格式进行传递。通过查看开发文档,我们就可以了解所需要的参数。又由于是通过 XML 的格式传递的,为了便于后台程序的解析,所以将 XML 装换成集合类型。
通过微信文档可以知道,文本消息传递的参数列表如上图所示,所以要新建一个 实体 类:TextMessage 一一对应微信发送的xml格式。
public class TextMessage { private String ToUserName;
private String FromUserName;
private long CreateTime;
private String MsgType;
private String Content;
private String MsgId;
添加 get, set方法
MessageUtil 类:设置了消息的类型,以及xml转map方法,文本信息转 XML等方法。
public class MessageUtil {
// 各种消息类型,除了扫带二维码事件
/**
* 文本消息
*/
public static final String MESSAGE_TEXT = "text";
/**
* 图片消息
*/
public static final String MESSAtGE_IMAGE = "image";
/**
* 图文消息
*/
public static final String MESSAGE_NEWS = "news";
/**
* 语音消息
*/
public static final String MESSAGE_VOICE = "voice";
/**
* 视频消息
*/
public static final String MESSAGE_VIDEO = "video";
/**
* 小视频消息
*/
public static final String MESSAGE_SHORTVIDEO = "shortvideo";
/**
* 地理位置消息
*/
public static final String MESSAGE_LOCATION = "location";
/**
* 链接消息
*/
public static final String MESSAGE_LINK = "link";
/**
* 事件推送消息
*/
public static final String MESSAGE_EVENT = "event";
/**
* 事件推送消息中,事件类型,subscribe(订阅)
*/
public static final String MESSAGE_EVENT_SUBSCRIBE = "subscribe";
/**
* 事件推送消息中,事件类型,unsubscribe(取消订阅)
*/
public static final String MESSAGE_EVENT_UNSUBSCRIBE = "unsubscribe";
/**
* 事件推送消息中,上报地理位置事件
*/
public static final String MESSAGE_EVENT_LOCATION_UP = "LOCATION";
/**
* 事件推送消息中,自定义菜单事件,点击菜单拉取消息时的事件推送
*/
public static final String MESSAGE_EVENT_CLICK = "CLICK";
/**
* 事件推送消息中,自定义菜单事件,点击菜单跳转链接时的事件推送
*/
public static final String MESSAGE_EVENT_VIEW = "VIEW";
/**
* 拼接文本消息
* @param toUserName
* @param fromUserName
* @param content
* @return
*/
public static String initText(String toUserName,String fromUserName,String content){
TextMessage text = new TextMessage();
text.setFromUserName(toUserName);
text.setToUserName(fromUserName);
text.setMsgType(MessageUtil.MESSAGE_TEXT);
text.setCreateTime(new Date().getTime());
text.setContent(content);
return textMessageToXml(text);
}
/**
* 关注回复
* @return
*/
public static String menuText(){
StringBuffer sb = new StringBuffer();
sb.append("欢迎关注公众号浩Coding:\n\n");
sb.append("1 回复关键字1\n");
sb.append("2 回复关键字2\n");
sb.append("3 回复关键字3\n\n");
sb.append("本公众号还在开发中,没啥能看的,别玩坏了哈~~");
return sb.toString();
}
/***
* 文本信息转 XML
* @param textMessage
* @return
*/
public static String textMessageToXml(TextMessage textMessage){
XStream xstream = new XStream();
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
/**
* XML 转 Map集合
* @param request
* @return
* @throws IOException
* @throws DocumentException
*/
public static Map<String,String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException{
Map<String,String> map = new HashMap<String,String>();
SAXReader reader = new SAXReader();
InputStream ins = request.getInputStream();
Document doc = reader.read(ins);
//获取根节点
Element root = doc.getRootElement();
List<Element> list = root.elements();
for(Element e : list){
map.put(e.getName(), e.getText());
}
ins.close();
return map;
}
}
其中servlet doPost 负责接收响应消息:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); try {
Map<String,String> map = MessageUtil.xmlToMap(request); String fromUserName = map.get("FromUserName"); String toUserName = map.get("ToUserName"); String msgType = map.get("MsgType"); String content = map.get("Content"); String message = null; if("text".equals(msgType)){ TextMessage text = new TextMessage(); text.setFromUserName(toUserName); //原来的信息发送者,将变成信息接受者 text.setToUserName(fromUserName); //原理的接受者,变成发送者 text.setMsgType("text"); //表示消息的类型是text类型 text.setCreateTime(new Date().getTime()); text.setContent("您发送的信息是:" + content); message = MessageUtil.textMessageToXml(text); //装换成 xml 格式发送给微信解析 System.out.println(message); } out.print(message); } catch (DocumentException e) { e.printStackTrace(); } }
接下来需要启动 tomcat 运行程序。运行效果如下所示:
这样消息回复的效果已经完成了,最后来让他能够接收更多类型的消息。比如常见的一些:关注后的消息回复,取消关注之后的消息回复,还有关键字的消息回复。
参考文章:https://blog.csdn.net/shuicsdn/article/details/71023212
https://blog.csdn.net/z69183787/article/details/53673316