当前位置:   article > 正文

正式开始使用springboot进行微信公众号开发_springboot 微信公众号开发

springboot 微信公众号开发

对公众号还没有一定的了解的,请先阅读此博客 使用springboot进行微信公众号开发的准备!_码上编程的博客-CSDN博客_springboot微信公众号开发   之后再来阅读此博客

此博客将手把手教你从0开始用springboot进行微信公众号的开发。当然了,这里只是介绍初步的使用以及学习方法,详细使用或者更深层次的使用,则详细阅读微信公众号官方文档, 官方文档就是最好的教材!!

官方文档: 微信公众平台开发概述 | 微信开放文档 

本项目的源代码在gitee中,使用git clone https://gitee.com/liu-wenxin/gongzhonghao.git即可下载

1、读取流的方式接受用户消息 

公众号发送对应的消息,详细信息类型请看官方文档

目标结果    可以发现是xml数据包

代码实现

  1. public class WeixinService {
  2. /**
  3. * 读取公众号发送过来的消息
  4. * @param request
  5. * @return
  6. * @throws IOException
  7. */
  8. public static String getWeixinMessage(HttpServletRequest request) throws IOException {
  9. ServletInputStream is = request.getInputStream();
  10. byte[] b=new byte[1024];
  11. int len;
  12. StringBuilder sb=new StringBuilder();
  13. while((len=is.read(b))!=-1){
  14. sb.append(new String(b,0,len));
  15. }
  16. return sb.toString();
  17. }
  18. }
  1. @RestController
  2. public class TestweixinController {
  3. @RequestMapping(value="/testWeixin",method = {RequestMethod.POST,RequestMethod.GET})
  4. public void testWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException {
  5. request.setCharacterEncoding("utf-8");
  6. response.setCharacterEncoding("utf-8");
  7. PrintWriter out = response.getWriter();
  8. String signature = request.getParameter("signature");
  9. String timestamp = request.getParameter("timestamp");
  10. String nonce = request.getParameter("nonce");
  11. String echostr = request.getParameter("echostr");
  12. if(Utils.check(timestamp,nonce,signature)){
  13. //校验正确并返回echostr,才能正式成为一名公众号开发者,即填写的URL和TOKEN才能生效
  14. //out.print(echostr);
  15. //查看用户从公众号发送过来的信息
  16. String result = WeixinService.getWeixinMessage(request);
  17. System.out.println(result);
  18. }else{
  19. //校验失败
  20. out.print("---请到公众号执行相应操作---");
  21. }
  22. out.flush();
  23. out.close();
  24. }
  25. }

2、将读取的xml数据映射成map数据格式

上述方式读取公众号发送过来的信息也没毛病,但是, 当我想要获取某个节点的值就显得不是那么灵活了,并且也不方便,能不能将xml数据映射出map数据,通过操作map方式去操作xml数据

答案是:  可以的!!!

需要导入的依赖:

  1. <!--解析xml数据-->
  2. <dependency>
  3. <groupId>dom4j</groupId>
  4. <artifactId>dom4j</artifactId>
  5. <version>1.6.1</version>
  6. </dependency>

代码实现:

  1. public class WeixinService {
  2. //以Map形式读取公众号的所有消息
  3. public static Map<String, String> parseRequest(InputStream is) throws IOException {
  4. //将输入流解析成Map
  5. Map<String, String> map = new HashMap<>();
  6. try {
  7. //读取输入流获取文档对象
  8. SAXReader reader = new SAXReader();
  9. Document document = reader.read(is);
  10. //根据文档对象获取根节点
  11. Element root = document.getRootElement();
  12. //获取所有的子节点
  13. List<Element> elements = root.elements();
  14. for (Element e : elements) {
  15. map.put(e.getName(), e.getStringValue());
  16. }
  17. } catch (DocumentException e) {
  18. e.printStackTrace();
  19. }
  20. return map;
  21. }
  22. }
  1. @RestController
  2. public class TestweixinController {
  3. @RequestMapping(value="/testWeixin",method = {RequestMethod.POST,RequestMethod.GET})
  4. public void testWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException {
  5. request.setCharacterEncoding("utf-8");
  6. response.setCharacterEncoding("utf-8");
  7. PrintWriter out = response.getWriter();
  8. String signature = request.getParameter("signature");
  9. String timestamp = request.getParameter("timestamp");
  10. String nonce = request.getParameter("nonce");
  11. String echostr = request.getParameter("echostr");
  12. if(Utils.check(timestamp,nonce,signature)){
  13. //校验正确并返回echostr,才能正式成为一名公众号开发者,即填写的URL和TOKEN才能生效
  14. //out.print(echostr);
  15. //查看用户从公众号发送过来的信息
  16. Map<String, String> requestMap=WeixinService.parseRequest(request.getInputStream());
  17. System.out.println(requestMap);
  18. }else{
  19. //校验失败
  20. out.print("---请到公众号执行相应操作---");
  21. }
  22. out.flush();
  23. out.close();
  24. }
  25. }

目标结果:

3、xml的字符串形式发送消息给用户

来而不往非礼也,用户发送信息了,可能焦急的等待公众号的回复!  通过阅读官方文档可得知,返回的数据类型也是xml数据包格式,每种类型都有严格的格式,比如:

回复文本消息

  1. <xml>
  2. <ToUserName><![CDATA[toUser]]></ToUserName>
  3. <FromUserName><![CDATA[fromUser]]></FromUserName>
  4. <CreateTime>12345678</CreateTime>
  5. <MsgType><![CDATA[text]]></MsgType>
  6. <Content><![CDATA[你好]]></Content>
  7. </xml>

 回复图片消息

  1. <xml>
  2. <ToUserName><![CDATA[toUser]]></ToUserName>
  3. <FromUserName><![CDATA[fromUser]]></FromUserName>
  4. <CreateTime>12345678</CreateTime>
  5. <MsgType><![CDATA[image]]></MsgType>
  6. <Image>
  7. <MediaId><![CDATA[media_id]]></MediaId>
  8. </Image>
  9. </xml>

代码实现

  1. public class WeixinService {
  2. //以Map形式读取公众号的所有消息
  3. public static Map<String, String> parseRequest(InputStream is) throws IOException {
  4. //将输入流解析成Map
  5. Map<String, String> map = new HashMap<>();
  6. try {
  7. //读取输入流获取文档对象
  8. SAXReader reader = new SAXReader();
  9. Document document = reader.read(is);
  10. //根据文档对象获取根节点
  11. Element root = document.getRootElement();
  12. //获取所有的子节点
  13. List<Element> elements = root.elements();
  14. for (Element e : elements) {
  15. map.put(e.getName(), e.getStringValue());
  16. }
  17. } catch (DocumentException e) {
  18. e.printStackTrace();
  19. }
  20. return map;
  21. }
  22. }

这里有个坑,发送的xml数据不能有空格 ,  还有发送方与接收方的逻辑, 原来的发送方现在要变成接收方,原来的接收方要变成发送方

  1. @RestController
  2. public class TestweixinController {
  3. @RequestMapping(value="/testWeixin",method = {RequestMethod.POST,RequestMethod.GET})
  4. public void testWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException {
  5. request.setCharacterEncoding("utf-8");
  6. response.setCharacterEncoding("utf-8");
  7. PrintWriter out = response.getWriter();
  8. String signature = request.getParameter("signature");
  9. String timestamp = request.getParameter("timestamp");
  10. String nonce = request.getParameter("nonce");
  11. String echostr = request.getParameter("echostr");
  12. if(Utils.check(timestamp,nonce,signature)){
  13. //校验正确并返回echostr,才能正式成为一名公众号开发者,即填写的URL和TOKEN才能生效
  14. //out.print(echostr);
  15. //查看用户从公众号发送过来的信息
  16. Map<String, String> requestMap=WeixinService.parseRequest(request.getInputStream());
  17. System.out.println(requestMap);
  18. //返回 收到了!!!给用户
  19. String respXml="<xml>\n" +
  20. "<ToUserName><![CDATA["+requestMap.get("FromUserName")+"]]></ToUserName>\n" +
  21. "<FromUserName><![CDATA["+requestMap.get("ToUserName")+"]]></FromUserName>\n" +
  22. "<CreateTime>12345678</CreateTime>\n" +
  23. "<MsgType><![CDATA[text]]></MsgType>\n" +
  24. "<Content><![CDATA["+"收到了!!!"+"]]></Content>\n" +
  25. "</xml>\n";
  26. out.print(respXml);
  27. }else{
  28. //校验失败
  29. out.print("---请到公众号执行相应操作---");
  30. }
  31. out.flush();
  32. out.close();
  33. }
  34. }

目标结果

4、 将发送的数据解析成xml数据格式,通过操作对象的方式操作xml待返回的数据

上述方式也可以实现发送数据给用户,就是不灵活还有不方便,如果能通过操作对象的方式操作xml数据,那该有多好呀,  答案是可以实现的!!

导入的依赖

  1. <!--将信息封装成xml数据-->
  2. <dependency>
  3. <groupId>com.thoughtworks.xstream</groupId>
  4. <artifactId>xstream</artifactId>
  5. <version>1.4.8</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>xmlpull</groupId>
  9. <artifactId>xmlpull</artifactId>
  10. <version>1.1.3.1</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>xpp3</groupId>
  14. <artifactId>xpp3_min</artifactId>
  15. <version>1.1.4c</version>
  16. </dependency>

每种消息类型都含有 <ToUserName> <FromUserName> <CreateTime> <MsgType>

BaseMessage.java , 让所有的衍生类继承它,@XStreamAlias("xml")和@XStreamAlias("ToUserName") 解决映射成对象小写的问题

  1. /*
  2. * 所有消息的父类
  3. * */
  4. @Data
  5. @NoArgsConstructor
  6. @XStreamAlias("xml")
  7. public class BaseMessage {
  8. @XStreamAlias("ToUserName")
  9. private String toUserName;
  10. @XStreamAlias("FromUserName")
  11. private String fromUserName;
  12. @XStreamAlias("CreateTime")
  13. private String createTime;
  14. @XStreamAlias("MsgType")
  15. private String msgType;
  16. public BaseMessage(Map<String,String> requestMap){
  17. this.toUserName= (String) requestMap.get("FromUserName");
  18. this.fromUserName= (String) requestMap.get("ToUserName");
  19. this.createTime=System.currentTimeMillis()/1000+"";
  20. }
  21. }

TextMessage.java

  1. @Data
  2. @XStreamAlias("xml")
  3. public class TextMessage extends BaseMessage {
  4. @XStreamAlias("Content")
  5. private String content;
  6. public TextMessage(Map<String, String> requestMap, String content){
  7. //调用父类构造方法
  8. super(requestMap);
  9. //设置类型为文本类型
  10. this.setMsgType("text");
  11. this.content=content;
  12. }
  13. }

 ImageMessage.java

  1. @Data
  2. @XStreamAlias("xml")
  3. public class ImageMessage extends BaseMessage {
  4. @XStreamAlias("Image")
  5. private Image image;
  6. public ImageMessage(Map<String,String> requestMap,Image image){
  7. super(requestMap);
  8. this.setMsgType("image");
  9. this.image=image;
  10. }
  11. }

Image.java 

  1. @XStreamAlias("Image")
  2. @AllArgsConstructor
  3. @Data
  4. public class Image {
  5. @XStreamAlias("MediaId")
  6. private String mediaId;
  7. }

  1. public class WeixinService {
  2. //以Map形式读取公众号的所有消息
  3. public static Map<String, String> parseRequest(InputStream is) throws IOException {
  4. //将输入流解析成Map
  5. Map<String, String> map = new HashMap<>();
  6. try {
  7. //读取输入流获取文档对象
  8. SAXReader reader = new SAXReader();
  9. Document document = reader.read(is);
  10. //根据文档对象获取根节点
  11. Element root = document.getRootElement();
  12. //获取所有的子节点
  13. List<Element> elements = root.elements();
  14. for (Element e : elements) {
  15. map.put(e.getName(), e.getStringValue());
  16. }
  17. } catch (DocumentException e) {
  18. e.printStackTrace();
  19. }
  20. return map;
  21. }
  22. /*
  23. *封装公众号返回信息,用于处理所有的事件和消息的回复,返回的是xml数据包
  24. * */
  25. public static String getResponse(Map<String, String> requestMap) {
  26. BaseMessage msg = null;
  27. //获取用户发送消息的类型
  28. String msgType = (String) requestMap.get("MsgType");
  29. switch (msgType) {
  30. case "text":
  31. //处理文本类型
  32. msg = dealTextMessage(requestMap);
  33. //将图文信息转成xml数据包
  34. //msg=dealNewsMessage(requestMap);
  35. //System.out.println("---返回文字类型数据---");
  36. break;
  37. case "image":
  38. //处理图片信息
  39. msg = dealImageMessage(requestMap);
  40. break;
  41. default:
  42. break;
  43. }
  44. if (msg != null) {
  45. //将信息转成xml数据包
  46. return beanToXml(msg);
  47. }
  48. return null;
  49. }
  50. /*
  51. * 把消息对象转成xml数据
  52. * */
  53. private static String beanToXml(BaseMessage msg) {
  54. XStream stream = new XStream();
  55. /*
  56. * 使对应类上的注解生效
  57. * */
  58. stream.processAnnotations(BaseMessage.class);
  59. stream.processAnnotations(TextMessage.class);
  60. stream.processAnnotations(ImageMessage.class);
  61. String xml = stream.toXML(msg);
  62. return xml;
  63. }
  64. /*
  65. * 专门处理文本消息
  66. * */
  67. private static BaseMessage dealTextMessage(Map<String, String> requestMap) {
  68. TextMessage textMessage=new TextMessage(requestMap,"成功获取消息!!!");
  69. return textMessage;
  70. }
  71. /*
  72. *
  73. *专门处理回复图片消息 requestMap是从用户从公众号发过来的数据
  74. * */
  75. private static BaseMessage dealImageMessage(Map<String, String> requestMap) {
  76. return null;
  77. }
  78. }

  1. @RestController
  2. public class TestweixinController {
  3. @RequestMapping(value="/testWeixin",method = {RequestMethod.POST,RequestMethod.GET})
  4. public void testWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException {
  5. request.setCharacterEncoding("utf-8");
  6. response.setCharacterEncoding("utf-8");
  7. PrintWriter out = response.getWriter();
  8. String signature = request.getParameter("signature");
  9. String timestamp = request.getParameter("timestamp");
  10. String nonce = request.getParameter("nonce");
  11. String echostr = request.getParameter("echostr");
  12. if(Utils.check(timestamp,nonce,signature)){
  13. //校验正确并返回echostr,才能正式成为一名公众号开发者,即填写的URL和TOKEN才能生效
  14. //out.print(echostr);
  15. //查看用户从公众号发送过来的信息
  16. Map<String, String> requestMap=WeixinService.parseRequest(request.getInputStream());
  17. //返回信息给用户
  18. String resXml = WeixinService.getResponse(requestMap);
  19. out.print(resXml);
  20. }else{
  21. //校验失败
  22. out.print("---请到公众号执行相应操作---");
  23. }
  24. out.flush();
  25. out.close();
  26. }
  27. }

目标效果

5、获取access_token

有了access_token才能进行其它操作,比如素材管理、自定义菜单

记得将TOKEN、APPID、APPSECRET改成自己的值

代码部分

  1. public class Utils {
  2. public static final String TOKEN="aabbccdd"; //TOKEN就是自己填写的
  3. public static final String APPID="wx18d322f947cdf313";
  4. public static final String APPSECRET="addf7e78f784c940ce69557cbe58b31b";
  5. //用于存储access_token
  6. private static AccessToken at;
  7. /*
  8. * 获取accessToken,有效期2小时
  9. * */
  10. private static void getToken() {
  11. String url = " https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
  12. String result = "";
  13. BufferedReader in = null;
  14. try {
  15. String urlNameString = url + "&appid=" + APPID + "&secret=" + APPSECRET;
  16. URL realUrl = new URL(urlNameString);
  17. // 打开和URL之间的连接
  18. URLConnection connection = realUrl.openConnection();
  19. // 设置通用的请求属性
  20. connection.setRequestProperty("accept", "*/*");
  21. connection.setRequestProperty("connection", "Keep-Alive");
  22. connection.setRequestProperty("Accept-Charset", "utf-8");
  23. connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
  24. // 建立实际的连接
  25. connection.connect();
  26. // 获取所有响应头字段
  27. Map<String, List<String>> map = connection.getHeaderFields();
  28. // 定义 BufferedReader输入流来读取URL的响应
  29. in = new BufferedReader(new InputStreamReader(
  30. connection.getInputStream(),"utf-8"));
  31. String line;
  32. while ((line = in.readLine()) != null) {
  33. result += line;
  34. }
  35. } catch (Exception e) {
  36. System.out.println("发送GET请求出现异常!" + e);
  37. e.printStackTrace();
  38. }
  39. // 使用finally块来关闭输入流
  40. finally {
  41. try {
  42. if (in != null) {
  43. in.close();
  44. }
  45. } catch (Exception e2) {
  46. e2.printStackTrace();
  47. }
  48. }
  49. Gson gson = new Gson();
  50. HashMap hashMap = gson.fromJson(result, HashMap.class);
  51. String access_token = (String) hashMap.get("access_token");
  52. Double expires_in = (Double) hashMap.get("expires_in");
  53. //创建access_token,并存起来
  54. at = new AccessToken(access_token, expires_in);
  55. }
  56. /*
  57. * 获取access_token的方法 直接HttpRequest.getAccessToken()即可返回access_token值
  58. * */
  59. public static String getAccessToken() {
  60. if (at == null || at.isExpired()) {
  61. //过期则创建新的access_token
  62. getToken();
  63. }
  64. //返回access_token
  65. return at.getAccess_token();
  66. }
  67. /*
  68. * 验证签名
  69. * */
  70. public static boolean check(String timestamp, String nonce, String signature) {
  71. //1、将token、timestamp、nonce进行字典排序
  72. String[] strs = new String[]{TOKEN, timestamp, nonce};
  73. Arrays.sort(strs);
  74. //2、将三个参数字符串拼接成一个字符串进行sha1加密
  75. String str = strs[0] + strs[1] + strs[2];
  76. String mysignature = sha1(str);
  77. //返回对比结果
  78. return mysignature.equalsIgnoreCase(signature);
  79. }
  80. /*
  81. * 加密方法
  82. * */
  83. private static String sha1(String src) {
  84. try {
  85. //获取一个加密对象
  86. MessageDigest md = MessageDigest.getInstance("sha1");
  87. //加密
  88. byte[] digest = md.digest(src.getBytes());
  89. char[] chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  90. StringBuffer sb = new StringBuffer();
  91. //处理结果集
  92. for (byte b : digest) {
  93. sb.append(chars[(b >> 4) & 15]);
  94. sb.append(chars[b & 15]);
  95. }
  96. return sb.toString();
  97. } catch (NoSuchAlgorithmException e) {
  98. e.printStackTrace();
  99. }
  100. return null;
  101. }
  102. }
  1. @SpringBootTest
  2. class GongzhonghaoApplicationTests {
  3. @Test
  4. void contextLoads() {
  5. System.out.println("---access_token---\n"+ Utils.getAccessToken());
  6. }
  7. }

目标结果

6、自定义菜单

无论是点击菜单、二级菜单、视图菜单,都有一个name的属性, 菜单的刷新需要你先取消关注公众号,然后在重新关注才能看到效果

  1. @Data
  2. @AllArgsConstructor
  3. public abstract class AbstractButon {
  4. private String name;
  5. }

官网要求的菜单类型数据

  1. {
  2. "button":[
  3. {
  4. "type":"click",
  5. "name":"今日歌曲",
  6. "key":"V1001_TODAY_MUSIC"
  7. },
  8. {
  9. "name":"菜单",
  10. "sub_button":[
  11. {
  12. "type":"view",
  13. "name":"搜索",
  14. "url":"http://www.soso.com/"
  15. },
  16. {
  17. "type":"miniprogram",
  18. "name":"wxa",
  19. "url":"http://mp.weixin.qq.com",
  20. "appid":"wx286b93c14bbf93aa",
  21. "pagepath":"pages/lunar/index"
  22. },
  23. {
  24. "type":"click",
  25. "name":"赞一下我们",
  26. "key":"V1001_GOOD"
  27. }]
  28. }]
  29. }

  1. @Data
  2. public class Button {
  3. private List<AbstractButon> button=new ArrayList<>();
  4. }

点击菜单

  1. public class ClickButton extends AbstractButon {
  2. private String type="click";
  3. private String key;
  4. public ClickButton(String name,String key){
  5. super(name);
  6. this.key=key;
  7. }
  8. public String getType() {
  9. return type;
  10. }
  11. public void setType(String type) {
  12. this.type = type;
  13. }
  14. public String getKey() {
  15. return key;
  16. }
  17. public void setKey(String key) {
  18. this.key = key;
  19. }
  20. }

二级菜单

  1. public class SubButton extends AbstractButon {
  2. private List<AbstractButon> sub_button=new ArrayList<>();
  3. public SubButton(String name){
  4. super(name);
  5. }
  6. public List<AbstractButon> getSub_button() {
  7. return sub_button;
  8. }
  9. public void setSub_button(List<AbstractButon> sub_button) {
  10. this.sub_button = sub_button;
  11. }
  12. }

发送post请求的方法:

  1. /**
  2. * 发送post请求
  3. * @param url 地址
  4. * @param data 参数
  5. * @return
  6. */
  7. public static String post(String url,String data){
  8. BufferedReader in = null;
  9. String result="";
  10. try {
  11. URL urlObj=new URL(url);
  12. URLConnection connection=urlObj.openConnection();
  13. //设置可发送状态
  14. connection.setDoOutput(true);
  15. connection.setDoInput(true);
  16. connection.setRequestProperty("connection", "Keep-Alive");
  17. connection.setRequestProperty("Accept-Charset", "utf-8");
  18. connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
  19. //获取输出流
  20. OutputStream os=connection.getOutputStream();
  21. //写出数据
  22. os.write(data.getBytes("UTF-8"));
  23. os.close();
  24. //获取输入流
  25. in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
  26. String line;
  27. while ((line = in.readLine()) != null) {
  28. result += line;
  29. }
  30. in.close();
  31. os.close();
  32. return result.toString();
  33. } catch (Exception e) {
  34. e.printStackTrace();
  35. }
  36. return null;
  37. }

测试

  1. @SpringBootTest
  2. class GongzhonghaoApplicationTests {
  3. @Test
  4. void contextLoads() {
  5. //一级菜单
  6. Button btn = new Button();
  7. btn.getButton().add(new ClickButton("一级菜单","1"));
  8. //二级菜单
  9. SubButton sb2=new SubButton("二级菜单");
  10. sb2.getSub_button().add(new ClickButton("1","21"));
  11. sb2.getSub_button().add(new ClickButton("2","22"));
  12. btn.getButton().add(sb2);
  13. Gson gson = new Gson();
  14. //向指定的url发送post请求,并携带上access_token和菜单数据
  15. String url="https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
  16. url=url.replace("ACCESS_TOKEN",Utils.getAccessToken());
  17. //返回结果集
  18. String result = Utils.post(url, gson.toJson(btn));
  19. System.out.println("---result---\n"+result);
  20. }
  21. }

目标结果

 

 

7、菜单事件

上述菜单虽然有了,但是点击却没有任何响应,这时需要为它添上事件处理!  菜单事件类型有click(点击事件)、view(跳转链接事件)、scancode_push(扫码推事件)、view_miniprogram(跳转小程序事件)等等,详情请看官方文档。

代码部分

  1. public class WeixinService {
  2. //以Map形式读取公众号的所有消息
  3. public static Map<String, String> parseRequest(InputStream is) throws IOException {
  4. //将输入流解析成Map
  5. Map<String, String> map = new HashMap<>();
  6. try {
  7. //读取输入流获取文档对象
  8. SAXReader reader = new SAXReader();
  9. Document document = reader.read(is);
  10. //根据文档对象获取根节点
  11. Element root = document.getRootElement();
  12. //获取所有的子节点
  13. List<Element> elements = root.elements();
  14. for (Element e : elements) {
  15. map.put(e.getName(), e.getStringValue());
  16. }
  17. } catch (DocumentException e) {
  18. e.printStackTrace();
  19. }
  20. return map;
  21. }
  22. /*
  23. *封装公众号返回信息,用于处理所有的事件和消息的回复,返回的是xml数据包
  24. * */
  25. public static String getResponse(Map<String, String> requestMap) {
  26. BaseMessage msg = null;
  27. //获取用户发送消息的类型
  28. String msgType = (String) requestMap.get("MsgType");
  29. switch (msgType) {
  30. case "text":
  31. //处理文本类型
  32. msg = dealTextMessage(requestMap);
  33. //将图文信息转成xml数据包
  34. //msg=dealNewsMessage(requestMap);
  35. //System.out.println("---返回文字类型数据---");
  36. break;
  37. case "image":
  38. //处理图片信息
  39. msg = dealImageMessage(requestMap);
  40. break;
  41. case "event":
  42. //处理事件
  43. msg = dealEvent(requestMap);
  44. break;
  45. default:
  46. break;
  47. }
  48. if (msg != null) {
  49. //将信息转成xml数据包
  50. return beanToXml(msg);
  51. }
  52. return null;
  53. }
  54. /**
  55. * 判断菜单栏事件
  56. * @param requestMap
  57. * @return
  58. */
  59. private static BaseMessage dealEvent(Map<String, String> requestMap) {
  60. //判断什么事件
  61. String event = requestMap.get("Event");
  62. switch (event){
  63. case "CLICK":
  64. //详细处理点击事件
  65. return dealClick(requestMap);
  66. default:
  67. //其它事件
  68. break;
  69. }
  70. return null;
  71. }
  72. /**
  73. * 专门处理点击事件
  74. * @param requestMap
  75. * @return
  76. */
  77. private static BaseMessage dealClick(Map<String, String> requestMap) {
  78. //获取创建菜单时填的key值
  79. String key = requestMap.get("EventKey");
  80. switch (key){
  81. case "1":
  82. //点击一级菜单
  83. return new TextMessage(requestMap,"点击了一级菜单");
  84. case "21":
  85. //点击二级菜单的1
  86. return new TextMessage(requestMap,"点击二级菜单的1");
  87. case "22":
  88. //点击二级菜单的2
  89. return new TextMessage(requestMap,"点击二级菜单的2");
  90. default:
  91. break;
  92. }
  93. return null;
  94. }
  95. /*
  96. * 把消息对象转成xml数据
  97. * */
  98. private static String beanToXml(BaseMessage msg) {
  99. XStream stream = new XStream();
  100. /*
  101. * 使对应类上的注解生效
  102. * */
  103. stream.processAnnotations(BaseMessage.class);
  104. stream.processAnnotations(TextMessage.class);
  105. stream.processAnnotations(ImageMessage.class);
  106. String xml = stream.toXML(msg);
  107. return xml;
  108. }
  109. /*
  110. * 专门处理文本消息
  111. * */
  112. private static BaseMessage dealTextMessage(Map<String, String> requestMap) {
  113. TextMessage textMessage=new TextMessage(requestMap,"成功获取消息!!!");
  114. return textMessage;
  115. }
  116. /*
  117. *
  118. *专门处理回复图片消息 requestMap是从用户从公众号发过来的数据
  119. * */
  120. private static BaseMessage dealImageMessage(Map<String, String> requestMap) {
  121. return null;
  122. }
  123. }
  1. @RestController
  2. public class TestweixinController {
  3. @RequestMapping(value="/testWeixin",method = {RequestMethod.POST,RequestMethod.GET})
  4. public void testWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException {
  5. request.setCharacterEncoding("utf-8");
  6. response.setCharacterEncoding("utf-8");
  7. PrintWriter out = response.getWriter();
  8. String signature = request.getParameter("signature");
  9. String timestamp = request.getParameter("timestamp");
  10. String nonce = request.getParameter("nonce");
  11. String echostr = request.getParameter("echostr");
  12. if(Utils.check(timestamp,nonce,signature)){
  13. //校验正确并返回echostr,才能正式成为一名公众号开发者,即填写的URL和TOKEN才能生效
  14. //out.print(echostr);
  15. //查看用户从公众号发送过来的信息
  16. Map<String, String> requestMap=WeixinService.parseRequest(request.getInputStream());
  17. //返回信息给用户
  18. String resXml = WeixinService.getResponse(requestMap);
  19. out.print(resXml);
  20. }else{
  21. //校验失败
  22. out.print("---请到公众号执行相应操作---");
  23. }
  24. out.flush();
  25. out.close();
  26. }
  27. }

目标结果

微信公众号基础开发已经结束了!!!   不要光看,需要多练多看官方文档!!

 本项目的源代码在gitee中,使用git clone https://gitee.com/liu-wenxin/gongzhonghao.git即可下载

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/274291
推荐阅读
相关标签
  

闽ICP备14008679号