微信公众号开发笔记之收发消息
来源:互联网 发布:抱歉 网络繁忙 编辑:程序博客网 时间:2024/06/07 14:12
最近项目需要开发一个微信公众号作为其中一个模块的功能入口,花了两天时间简单了解了一下微信公众号的开发流程,这里简单总结一下。
1. 效果图—发送消息简单的回复“您好,感谢关注本公众号!”
2. 学习用的是测试号,测试号申请流程:
(1)打开微信测试号地址:点此跳转登录后如下图
(2) 上图中需要填写url地址和token
开发者提交信息(包括URL、Token)后,微信服务器将发送Http Get请求到填写的URL上,GET请求携带四个参数:signature、timestamp、nonce和echostr。公众号服务程序应该按如下要求进行接入验证:
- 将token、timestamp、nonce三个参数进行字典序排序
- 将三个参数字符串拼接成一个字符串进行sha1加密
- 将加密后获得的字符串与signature对比,如果一致,则原样返回echostr参数内容
(3)使用Ngrok内网穿透工具将localhos:8080的本地地址映射到外网
详细教程请参考Sunny的博客,下载并开通好隧道服务以后,在ngrok解压后目录执行一下命令:
./sunny clientid 隧道id
此时就可以直接在浏览器输入地址,如http://example.ngrok.cc,来访问本地的服务器了
(4)进入正题,服务器介入验证(这里使用原生的servlet来实现)
在doget方法里取出四个参数
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); String signature = request.getParameter("signature"); PrintWriter out = response.getWriter(); if(CheckUtil.checkSignature(signature, timestamp, nonce)){//CheckUtil是验证工具类 out.print(echostr); } }
编写CheckUtil类进行sha1加密并与signature进行比较
public class CheckUtil { private static final String token = "example"; public static boolean checkSignature(String signature, String timestamp, String nonce){ ArrayList<String> list = new ArrayList<>(); list.add(token); list.add(timestamp); list.add(nonce); Collections.sort(list); StringBuffer content = new StringBuffer(); for(String item : list){ content.append(item);//连成字符串进行加密 } String result = getSha1(content.toString()); return signature.equals(result)?true:false; } /** * SHA1加密方法 */ public static String getSha1(String str) { if (str == null || str.length() == 0) { return null; } char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; try { MessageDigest mdTemp = MessageDigest.getInstance("SHA1"); mdTemp.update(str.getBytes("UTF-8")); byte[] md = mdTemp.digest(); int j = md.length; char buf[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; buf[k++] = hexDigits[byte0 >>> 4 & 0xf]; buf[k++] = hexDigits[byte0 & 0xf]; } return new String(buf); } catch (Exception e) { return null; } }}
如果checkSignature比较后返回true,说明该消息是来自微信服务器,则将echostr原样返回
(5)顺利的话,在测试号申请页面,点击提交按钮以后便会提示成功,并且出现如下界面
扫一下二维码就可以关注自己的公众号啦,虽然只是一个测试号,但是还是很激动滴。。。不过这时候你不论向公众号发送多少消息,返回的都是“该公众号暂时无法提供服务,请稍后再试”。。。。。
(6)接下来实现收发文本消息的功能。首先查看一下微信公众平台的开发者规范消息管理这部分:
消息管理
当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。
文本消息<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>
在doPost方法中接受消息:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); try { //将xml请求信息转换为map形式保存 Map<String, String> map = MsgUtils.xmlToMap(request); TextMessage respMsg = new TextMessage(); //返回"您好,感谢您关注本公众号!"消息 respMsg.setToUserName(map.get("FromUserName")); respMsg.setFromUserName(map.get("ToUserName")); respMsg.setCreateTime(new Date().toString()); respMsg.setContent("您好,感谢您关注本公众号!"); respMsg.setMsgType(MsgUtils.MESSAGE_TEXT); //将发送的信息转换为xml字符串 String respXml = MsgUtils.textToXml(respMsg); out.println(respXml); } catch (DocumentException e) { e.printStackTrace(); }finally{ out.close(); } }
上例中TextMessage是经过封装的一个消息的javabean类:
private String ToUserName; private String FromUserName; private String CreateTime; private String MsgType; private String Content;
MsgUtils是用于将消息文本和xml格式字符串相互转换的工具类:
public class MsgUtils { public static final String MESSAGE_TEXT = "text"; public static Map<String, String> xmlToMap(HttpServletRequest req) throws IOException, DocumentException{ Map<String, String> resultMap = new HashMap<>(); //获取SAXReader SAXReader reader = new SAXReader(); //获取request输入流 InputStream is = req.getInputStream(); //转换为Document对象 Document document = reader.read(is); //获取根节点 Element root = document.getRootElement(); //获取元素集合 List<Element> elements = root.elements(); for(Element e : elements){ System.out.println("e.getName()>>>"+e.getName()+" e.getText()>>>"+e.getText()); resultMap.put(e.getName(), e.getText()); } is.close(); return resultMap; } public static String textToXml(TextMessage textMessage){ Document document = DocumentHelper.createDocument(); //创建根节点<xml><xml> Element rootElement = document.addElement("xml"); //将节点添加到根节点中 Element ToUserName = rootElement.addElement("ToUserName"); ToUserName.setText(textMessage.getToUserName()); Element FromUserName = rootElement.addElement("FromUserName"); FromUserName.setText(textMessage.getFromUserName()); Element CreateTime = rootElement.addElement("CreateTime"); CreateTime.setText(textMessage.getCreateTime()); Element MsgType = rootElement.addElement("MsgType"); MsgType.setText(textMessage.getMsgType()); Element Content = rootElement.addElement("Content"); Content.setText(textMessage.getContent()); //将xml的document对象转化为字符串,打印查看一下 System.out.println(document.asXML()); return document.asXML(); } }
xml转换使用到了dom4j的jar包,经过上面的6步就实现了接受关注的用户发来的消息并且返回一条消息。再此之上,可以详细的封装一个消息内容详情类,比如收到“1”,返回“您发送了1”,等等文本信息。下一篇再写其他类型的消息,篇幅比较长,本人也是初学者,不对的地方还请指出来,互相学习
2 0
- 微信公众号开发笔记之收发消息
- 微信公众号开发自动收发消息
- C#开发微信公众号之消息自动回复
- 微信公众号开发之[发送模板消息]
- 微信公众号开发之接收普通消息
- 微信公众号开发之接收普通消息
- 3、微信公众号开发之接收用户消息
- 微信公众号开发之模板消息
- JAVA微信公众号开发之客服消息
- 微信公众号开发之文本消息自动回复
- 微信公众号开发之语音消息识别
- 微信公众号开发---群发消息
- 微信公众号开发--模板消息
- 微信公众号开发---群发消息
- java编写微信公众账号收发消息
- 微信开发(四)收发消息
- 微信公众平台开发之模板消息(Java)
- 微信公众平台开发之模板消息(Java)
- 对于面向对象的简单理解
- 自动化车队大队长开通了博客,欢迎大家来访
- 用原生js实现轮播图
- zoj 3960 What Kind of Friends Are You?
- ThreadLocal成员变量和普通的成员变量对比
- 微信公众号开发笔记之收发消息
- strsep使用,C语言截取字符串
- 4.26 在linux centos6.5的apache bench上安装虚拟主机做http服务
- STL中的set容器的一点总结
- ORB算法原理解读
- 最长连号
- JavaEE Bean生命周期
- 2017阿里算法工程师暑期实习笔试题目部分解析
- 人工智能学习了人类语言后为何有了种族偏见?