手把手教你如何微信公众号开发「建议收藏」

您所在的位置:网站首页 微信公众号如何开发自助预约 手把手教你如何微信公众号开发「建议收藏」

手把手教你如何微信公众号开发「建议收藏」

2024-07-06 11:39| 来源: 网络整理| 查看: 265

大家好,又见面了,我是你们的朋友全栈君。

最近的话,发现微信开发其实也有很多挺有意思的地方,比如最近很火的一款游戏“跳一跳”,也让我如此着迷。。但是,今天我所要讲的并不是对于小程序的开发,而是要说一下,关于微信开发的另外一个内容,那就是微信公众号。。

关于,什么是微信公众号,微信公众号怎么申请,这个我就不多说,这些基本的概念不在这里进行讲解,自己可以直接百度就可以找到很多的资源。而我主要讲解一下关于微信公众号开发中,一些比较重要和常见的知识点,所以,这个也并不是基础篇的文章哦~!好歹也要对微信公众号有一点了解才行。~!

一:实现外网域名访问本地服务项目

描述:我们在刚开始接触微信公众号开发的时候,我想,一般情况下,很多人都是没有服务器的,简单点说,就是没有服务器IP,或者是公网访问的域名。然而,要想能够实现微信公众能能够与我们后台代码进行交互,那么肯定就需要有一个公网能够访问的地址,那么这怎么办好呢?

解法一:很简单呀,直接去新浪云,阿里云,华为云,买一个服务器呗,而且是学生的话,还有优惠,多好。。但是,这个又比较繁琐,里面又有配置内容啥的,一堆(比如,tomcat,mysql,jdk等等)。那么,看看第二种方法。。。。(但是,请记住,这个是想做服务端开发必须会的,如果你连部署项目都不会,你觉得公司对你的感觉如何?多一个技能就是一个优势)

解法二:反向代理。。如果,你是第一次听说这个名词,那么就赶紧恶补一下,这个名词的含义。我简单点说,就是通过反向代理的模式,来代理你本地的ip,以便能够在公网地址能够访问到本地的项目。。具体,请看下面,如何进行~!~!

步骤:(1)下载ogrok客户端———也就是反向代理的客户端,当然还有很多类似的,我这里就使用这个而已。

这个可以通过该链接进行下载ogrok下载链接

(2)解压刚下载好的客户端文件到自己的一个目录下

手把手教你如何微信公众号开发「建议收藏」手把手教你如何微信公众号开发「建议收藏」

(3)通过cmd命令,进入DOS,并且进入到刚刚解压的ogrok目录下

(4)执行 ngrok -config=ngrok.cfg -subdomain xxx 8080 //(xxx 是你自定义的域名前缀)

比如,我这里就是xxx就是用myjavttest

结果:

手把手教你如何微信公众号开发「建议收藏」手把手教你如何微信公众号开发「建议收藏」

(5)这样的话,我们就可以通过上面的地址进行访问本地的项目了。(原来都是用的localhost:8080/login.jsp或者127.0.0.1:8080/login.jsp),当然,前提是本地有一个开启的项目,这样才可以,别本地都没有项目开启,就用公网去访问,你觉得,它能够访问么?所以,请别忘记这一点。

手把手教你如何微信公众号开发「建议收藏」手把手教你如何微信公众号开发「建议收藏」(二)微信公众号客户端与后台进行验证身份

首先,我们通过第一步,我们就能够得到一个以公网地址访问的一个IP(域名),那么既然要使得微信公众号能够与后台进行关联,那么肯定需要配置微信公众号的具体对应的服务器地址了。

步骤:(1)首先,进入微信公众号开发官网,并且进行登陆

(2)

手把手教你如何微信公众号开发「建议收藏」手把手教你如何微信公众号开发「建议收藏」

(3)

手把手教你如何微信公众号开发「建议收藏」手把手教你如何微信公众号开发「建议收藏」

(4)

手把手教你如何微信公众号开发「建议收藏」手把手教你如何微信公众号开发「建议收藏」

OK,配置到这个的话,就简单的,将基本的配置进行设置好了。。那么,下面才是关键,进入真正的开发阶段。。

如果微信端,要与后台进行关联,那么当用户进行与后台交互的时候,后台就需要采取,身份验证,而这个是通过GET方式的请求,而只有通过的才可以进行后续的处理。所以,如何进行,那么就看下面的代码:这里讲解两种形式~~~~

第一种:(采取Servlet)

代码语言:javascript复制@WebServlet(name = "ConnectWeChatServlet") public class ConnectWeChatServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } /** * 进行验证是否身份匹配 * @param request * @param response * @throws ServletException * @throws IOException */ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); System.out.println(""+signature +"@"+timestamp +"$"+nonce +"^"+echostr); PrintWriter out = response.getWriter(); if(CheckConnectUtils.checkConncetWithWeChat(signature,timestamp,nonce)){ out.print(echostr); } }

验证的代码:

代码语言:javascript复制package com.hnu.scw.utils; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; /** * @author scw * @create 2018-01-17 9:28 * @desc 检查微信和服务器是否链接成功 **/ public class CheckConnectUtils { private static final String token = "wechat"; //这个就是微信公众号之前配置的token,必须保持一致 /** * 判断是否链接匹配 * @param signature * @param timestamp * @param nonce * @return */ public static boolean checkConncetWithWeChat(String signature,String timestamp,String nonce){ String[] arr = new String[]{token,timestamp,nonce}; //排序 Arrays.sort(arr); //生成字符串 StringBuilder stringBuilder = new StringBuilder(); for (String str:arr) { stringBuilder.append(str); } //进行SHA1加密 String encodeString = passSha1Encode(stringBuilder.toString()); if(signature.equals(encodeString)){ return true; }else{ return false; } } /** * 字符串进行SHA1加密 * @param str * @return */ public static String passSha1Encode(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()); byte[] md = mdTemp.digest(); int j = md.length; char[] buf = new char[j*2]; int k = 0; for(int i=0 ; i >>4 & 0xf]; buf[k++] = hexDigits[byte0 & 0xf]; } return new String(buf); } catch (NoSuchAlgorithmException e) { return null; } } }

第二种:(采取框架,比如SpringMVC+Spring+Hibernate)

代码语言:javascript复制/** * @author scw * @create 2018-01-18 11:38 * @desc 微信前端连接的主要控制类 **/ @Controller public class WeChatDogPrimaryController { /** * 进行微信用户验证,只能是Get方法 * @param request * @param response */ @RequestMapping(value = "/wechat" ,method = RequestMethod.GET) public void connectValidate(HttpServletRequest request , HttpServletResponse response) throws IOException { String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); System.out.println(""+signature +"@"+timestamp +"$"+nonce +"^"+echostr); PrintWriter out = response.getWriter(); if(CheckConnectUtils.checkConncetWithWeChat(signature,timestamp,nonce)){ out.print(echostr); } } /** * 客户端进行的消息处理 * @param request * @param response */ @RequestMapping(value = "/wechat" ,method = RequestMethod.POST) public void disposeClientMessage(HttpServletRequest request , HttpServletResponse response ) throws IOException { }

(三)微信客户端与后台进行消息交互(比如,文本,图片,视频,音频)

消息的实体类:

代码语言:javascript复制package com.hnu.scw.model; /** * @author scw * @create 2018-01-17 13:37 * @desc 对于所有消息的基本父类 **/ public class BaseMessage { private String ToUserName; private String FromUserName; private String 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 String getCreateTime() { return CreateTime; } public void setCreateTime(String createTime) { CreateTime = createTime; } public String getMsgType() { return MsgType; } public void setMsgType(String msgType) { MsgType = msgType; } }代码语言:javascript复制package com.hnu.scw.model; /** * @author SCW * @create 2018-01-17 15:08 * @desc 图片的基本类 **/ public class ImageBase { private String MediaId; public String getMediaId() { return MediaId; } public void setMediaId(String mediaId) { MediaId = mediaId; } }代码语言:javascript复制package com.hnu.scw.model; /** * @author scw * @create 2018-01-17 15:09 * @desc 图片消息 **/ public class ImageMessage extends BaseMessage { private ImageBase Image ; public ImageBase getImageBase() { return Image; } public void setImageBase(ImageBase Image) { this.Image = Image; } }代码语言:javascript复制package com.hnu.scw.model; /** * @author Administrator * @create 2018-01-17 16:45 * @desc 音乐类型的基本类 **/ public class MusicBase { private String Title; private String Description; private String MusicUrl; private String HQMusicUrl; private String ThumbMediaId; public String getTitle() { return Title; } public void setTitle(String title) { Title = title; } public String getDescription() { return Description; } public void setDescription(String description) { Description = description; } public String getMusicUrl() { return MusicUrl; } public void setMusicUrl(String musicUrl) { MusicUrl = musicUrl; } public String getHQMusicUrl() { return HQMusicUrl; } public void setHQMusicUrl(String HQMusicUrl) { this.HQMusicUrl = HQMusicUrl; } public String getThumbMediaId() { return ThumbMediaId; } public void setThumbMediaId(String thumbMediaId) { ThumbMediaId = thumbMediaId; } }代码语言:javascript复制package com.hnu.scw.model; /** * @author Administrator * @create 2018-01-17 16:46 * @desc 用于包装音乐的实体 **/ public class MusicMessage extends BaseMessage { private MusicBase Music; public MusicBase getMusic() { return Music; } public void setMusic(MusicBase music) { Music = music; } }代码语言:javascript复制package com.hnu.scw.model; /** * @author scw * @create 2018-01-17 10:03 * @desc 文本消息的内容 **/ public class MyTestMessage extends BaseMessage{ private String Content; private String MsgId; public String getContent() { return Content; } public void setContent(String content) { Content = content; } public String getMsgId() { return MsgId; } public void setMsgId(String msgId) { MsgId = msgId; } }代码语言:javascript复制package com.hnu.scw.model; /** * @author scw * @create 2018-01-17 13:38 * @desc 对于图文消息最内层结构的实体类 **/ public class NewsBase { private String Title; private String Description; private String PicUrl; private String Url; public String getTitle() { return Title; } public void setTitle(String title) { Title = title; } public String getDescription() { return Description; } public void setDescription(String description) { Description = description; } public String getPicUrl() { return PicUrl; } public void setPicUrl(String picUrl) { PicUrl = picUrl; } public String getUrl() { return Url; } public void setUrl(String url) { Url = url; } }代码语言:javascript复制package com.hnu.scw.model; import java.util.List; /** * @author scw * @create 2018-01-17 13:35 * @desc 对于图文消息的实体类 **/ public class NewsMessage extends BaseMessage{ private int ArticleCount; private List Articles; public int getArticleCount() { return ArticleCount; } public void setArticleCount(int articleCount) { ArticleCount = articleCount; } public List getArticles() { return Articles; } public void setArticles(List articles) { Articles = articles; } }

消息封装工具类:

代码语言:javascript复制package com.hnu.scw.utils; import com.hnu.scw.model.*; import com.thoughtworks.xstream.XStream; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import javax.servlet.http.HttpServletRequest; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author scw * @create 2018-01-17 9:52 * @desc 用户转换消息的格式 **/ public class MessageUtils { /** * 定义多种消息类型 */ public static final String MESSAGE_TEXT = "text"; public static final String MESSAGE_IMAGE = "image"; public static final String MESSAGE_VOICE = "voice"; public static final String MESSAGE_MUSIC = "music"; public static final String MESSAGE_VIDEO = "video"; public static final String MESSAGE_LINK = "link"; public static final String MESSAGE_LOCATION = "location"; public static final String MESSAGE_EVENT = "event"; public static final String MESSAGE_SUBSCRIBE = "subscribe"; public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe"; public static final String MESSAGE_CLICK = "CLICK"; public static final String MESSAGE_VIEW = "VIEW"; //扫码事件 public static final String MESSAGE_SCANCODE = "scancode_push"; /** * XML格式转为map格式 * @param request * @return */ public static Map xmlToMap(HttpServletRequest request){ Map map = new HashMap(); try { InputStream inputStream =null; inputStream = request.getInputStream(); SAXReader reader = new SAXReader(); Document doc = reader.read(inputStream); Element rootElement = doc.getRootElement(); List elements = rootElement.elements(); for (Element el:elements) { map.put(el.getName() , el.getText()); } inputStream.close(); return map ; } catch (Exception e) { e.printStackTrace(); return null ; } } /** * 文本消息对象转为xml格式 * @param myTestMessage * @return */ public static String textMessage2Xml(MyTestMessage myTestMessage){ XStream xStream = new XStream(); xStream.alias("xml" , myTestMessage.getClass()); return xStream.toXML(myTestMessage); } /** * 将图文消息对象转化为图文格式的XML * @return */ public static String newsMessage2XML(NewsMessage newsMessage){ XStream xStream = new XStream(); //将需要修改的一些标签进行替换 xStream.alias("xml" , newsMessage.getClass()); xStream.alias("item" , new NewsBase().getClass()); return xStream.toXML(newsMessage); } /** * 设置需要返回的图文信息 * @param fromUserName * @param toUserName * @return */ public static String initNewSMessage(String fromUserName , String toUserName ){ String message = null; List newList = new ArrayList(); NewsMessage newsMessage = new NewsMessage(); NewsBase newsBase = new NewsBase(); newsBase.setTitle("我是图文消息"); newsBase.setDescription("测试测试测试测试测试测试测试测试测试"); newsBase.setPicUrl("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=677717294,4155848424&fm=27&gp=0.jpg") newsBase.setUrl("www.baidu.com"); //添加图文消息的内容 newList.add(newsBase); //注意接受消息和发送消息的顺序要反过来,因为现在是从服务器进行发送了,而客户端是接收端了 newsMessage.setFromUserName(toUserName); newsMessage.setToUserName(fromUserName); newsMessage.setCreateTime(String.valueOf(System.currentTimeMillis())); newsMessage.setMsgType("news"); newsMessage.setArticleCount(newList.size()); newsMessage.setArticles(newList); //调用转为图文的XML return MessageUtils.newsMessage2XML(newsMessage); } /** * 设置需要返回的文本信息 * @param fromUserName * @param toUserName * @param content * @return */ public static String initText(String fromUserName , String toUserName , String content){ MyTestMessage text = new MyTestMessage(); //注意接受消息和发送消息的顺序要烦过来 text.setFromUserName(toUserName); text.setToUserName(fromUserName); text.setMsgType(MessageUtils.MESSAGE_TEXT); long time = System.currentTimeMillis(); text.setCreateTime(String.valueOf(time)); text.setContent(content); return MessageUtils.textMessage2Xml(text); } /** * 设置订阅时,返回菜单的内容 * @return */ public static String menuText(){ StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("菜单1:回复数字1,有惊喜\n"); stringBuilder.append("菜单2:回复数字2,有惊喜\n"); stringBuilder.append("菜单3:回复数字3,有惊喜\n"); stringBuilder.append("菜单4:回复数字3,有惊喜\n"); stringBuilder.append("菜单5:回复数字3,有惊喜\n"); stringBuilder.append("菜单6:回复数字未知的东东,也还有有惊喜哦\n"); return stringBuilder.toString(); } /** * 回复关键字"1"的时候的内容 * @return */ public static String inputNumber1(){ StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("我是惊喜111,哈哈,惊喜不惊喜!"); return stringBuilder.toString(); } /** * 回复关键字"2"的时候的内容 * @return */ public static String inputNumber2(){ StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("我是惊喜2222,哈哈,惊喜不惊喜!"); return stringBuilder.toString(); } /** * 返回图片消息(对于视频和音频都是一样的方式,只需要更改类型即可,即将Image修改为video,voice) * @param fromUserName * @param toUserName * @return */ public static String initImageMessage(String fromUserName , String toUserName ){ ImageBase imageBase = new ImageBase(); //这个media_Id是在之前执行过上传图片返回得到的信息 imageBase.setMediaId("HK17wQmCupESK4B9u14PqI4w3gtteXhUtGgriJW6G5c8O-Y0OsjGbYfQYhGDbYDx"); ImageMessage imageMessage = new ImageMessage(); imageMessage.setFromUserName(toUserName); imageMessage.setToUserName(fromUserName); imageMessage.setMsgType(MessageUtils.MESSAGE_IMAGE); long time = System.currentTimeMillis(); imageMessage.setCreateTime(String.valueOf(time)); imageMessage.setImageBase(imageBase); return imageMessage2XML(imageMessage); } /** * 将图片消息对象转化为图片格式的XML * @return */ public static String imageMessage2XML(ImageMessage imageMessage){ XStream xStream = new XStream(); //将需要修改的一些标签进行替换 xStream.alias("xml" , imageMessage.getClass()); xStream.alias("Image" , new ImageBase().getClass()); return xStream.toXML(imageMessage); } /** * 将音乐消息对象转化为图片格式的XML * @return */ public static String musicMessage2XML(MusicMessage musicMessage){ XStream xStream = new XStream(); //将需要修改的一些标签进行替换 xStream.alias("xml" , musicMessage.getClass()); xStream.alias("Music" , new MusicBase().getClass()); return xStream.toXML(musicMessage); } /** * 返回音乐消息 * @param fromUserName * @param toUserName * @return */ public static String initMusicMessage(String fromUserName , String toUserName ){ MusicBase musicBase = new MusicBase(); //这个ThumbMediaId是在之前执行过上传缩略图返回得到的信息(这个和上传图片的方法是一样的,都是调用pictureUtils中的上传方法) musicBase.setThumbMediaId("vJOi5E4_U91onQnsayPdkzxted6ZctEAEzcoLd3BJ8a00gJLuhEmTckF6S2XkS5R"); musicBase.setTitle("来一首音乐"); musicBase.setDescription("静静的听首歌吧!"); //设置高质量音质的歌曲路径,可以和一般音质音乐的路径一样 musicBase.setHQMusicUrl("http://myjava.ngrok.xiaomiqiu.cn/resource/mymusic.mp3"); //设置音乐的路径 musicBase.setMusicUrl("http://myjava.ngrok.xiaomiqiu.cn/resource/mymusic.mp3"); MusicMessage musicMessage = new MusicMessage(); musicMessage.setFromUserName(toUserName); musicMessage.setToUserName(fromUserName); //设置类型为音乐 musicMessage.setMsgType(MessageUtils.MESSAGE_MUSIC); long time = System.currentTimeMillis(); musicMessage.setCreateTime(String.valueOf(time)); musicMessage.setMusic(musicBase); return musicMessage2XML(musicMessage); } }

交互主类:

代码语言:javascript复制package com.hnu.scw.controller; import com.hnu.scw.utils.CheckConnectUtils; import com.hnu.scw.utils.MessageUtils; import com.hnu.scw.utils.WeiXinUserInfoUtiols; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.PrintWriter; import java.util.Map; /** * @author scw * @create 2018-01-18 11:38 * @desc 微信前端连接的主要控制类 **/ @Controller public class WeChatDogPrimaryController { /** * 进行微信用户验证,只能是Get方法 * @param request * @param response */ @RequestMapping(value = "/wechat" ,method = RequestMethod.GET) public void connectValidate(HttpServletRequest request , HttpServletResponse response) throws IOException { String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); System.out.println(""+signature +"@"+timestamp +"$"+nonce +"^"+echostr); PrintWriter out = response.getWriter(); if(CheckConnectUtils.checkConncetWithWeChat(signature,timestamp,nonce)){ out.print(echostr); } } /** * 客户端进行的消息处理 * @param request * @param response */ @RequestMapping(value = "/wechat" ,method = RequestMethod.POST) public void disposeClientMessage(HttpServletRequest request , HttpServletResponse response ) throws IOException { backTestFunction(request , response ); } /** * 文字回复功能开发 * @param request * @param response * @throws ServletException * @throws IOException */ public void backTestFunction(HttpServletRequest request , HttpServletResponse response ) throws IOException { //防止进行post提交和响应的消息乱码 request.setCharacterEncoding("UTF-8"); response.setHeader("Content-type", "text/html;"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); try{ //将发送过来的消息XML形式转为map内容 Map map = MessageUtils.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(MessageUtils.MESSAGE_TEXT.equals(msgType)){ //进行关键字回复功能 if("1".equals(content)){ message = MessageUtils.initText(fromUserName,toUserName,MessageUtils.inputNumber1()); }else if("2".equals(content)){ message = MessageUtils.initText(fromUserName,toUserName,MessageUtils.inputNumber2()); } else if("3".equals(content)){ //客户端输入“3”,返回一条图文消息 message = MessageUtils.initNewSMessage(fromUserName,toUserName); }else if("4".equals(content)){ //客户端输入“4”,返回一条图片消息 message = MessageUtils.initImageMessage(fromUserName,toUserName); }else if("5".equals(content)){ //客户端输入“5”,返回一首音乐消息 message = MessageUtils.initMusicMessage(fromUserName,toUserName); }else if("6".equals(content)){ //测试是否能够获取用户的信息 message = MessageUtils.initText(fromUserName,toUserName, WeiXinUserInfoUtiols.getUserInfo(fromUserName)); }else if(content.startsWith("翻译")){ //客户端输入“以翻译开头”,返回对应的翻译信息 /*String translateResult = TranslationUtils.translate(content.substring(2,content.length())); message = MessageUtils.initText(fromUserName,toUserName , translateResult);*/ }else { message = MessageUtils.initText(fromUserName,toUserName,"你发送的消息是:" + content); } }else if(MessageUtils.MESSAGE_EVENT.equals(msgType)){ String eventType = map.get("Event"); //完成订阅时候返回的内容 if(MessageUtils.MESSAGE_SUBSCRIBE .equals(eventType)){ message = MessageUtils.initText(fromUserName,toUserName , MessageUtils.menuText()); }else if(MessageUtils.MESSAGE_CLICK .equals(eventType)){ //进行的是click按钮的点击事件(这里就推送一下主菜单内容) message = MessageUtils.initText(fromUserName,toUserName , MessageUtils.menuText()); }else if(MessageUtils.MESSAGE_VIEW .equals(eventType)){ //进行的是view按钮的点击事件(这里就推送一下主菜单内容) String viewUrl = map.get("EventKey"); message = MessageUtils.initText(fromUserName,toUserName , viewUrl); }else if(MessageUtils.MESSAGE_SCANCODE .equals(eventType)) { //进行的是扫码事件 String key = map.get("EventKey"); message = MessageUtils.initText(fromUserName,toUserName , key); } }else if(MessageUtils.MESSAGE_LOCATION .equals(msgType)) { //进行的是地理位置信息 String label = map.get("Label"); message = MessageUtils.initText(fromUserName,toUserName , label); } //打印输出的xml格式内容,方便进行调试 System.out.println(message); out.print(message); }catch (Exception e){ e.printStackTrace(); }finally { out.close(); } } }(四)获取Access_Token

Access_Token是一个全局的票据,调用任何的高级接口,都需要这个,所以这个非常非常的重要

具体代码:

代码语言:javascript复制package com.hnu.scw.utils; import com.hnu.scw.menu.BaseButton; import com.hnu.scw.menu.ClickButton; import com.hnu.scw.menu.CustomeMenu; import com.hnu.scw.menu.ViewButton; import com.hnu.scw.model.AccessToken; import com.hnu.scw.projectconst.ProjectConst; import net.sf.json.JSONObject; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.clienthods.HttpGet; import org.apache.http.clienthods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.springframework.web.context.ContextLoader; import org.springframework.web.context.WebApplicationContext; import javax.servlet.ServletContext; import java.io.IOException; import java.io.UnsupportedEncodingException; /** * @author scw * @create 2018-01-17 14:13 * @desc 用户获取access_token,众号调用各接口时都需使用access_token **/ public class WeiXinUtils { /** * 微信公众号的APPID和Appsecret,这个是每个微信公众号都唯一的,以后配置不同的公众号配置这里即可 */ private static final String APPID = "自己公众号对应的内容"; private static final String APPSECRET = "自己公众号对应的内容"; //获取access_token的URL private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; //进行创建菜单的接口URL private static final String CREATE_MENU_URL ="https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN"; //菜单查询的接口URL private static final String QUERY_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN"; //菜单删除的接口URL private static final String DELETE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN"; /** * Get请求,方便到一个url接口来获取结果 * @param url * @return */ public static JSONObject doGetStr(String url){ DefaultHttpClient defaultHttpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); JSONObject jsonObject = null; try{ HttpResponse response = defaultHttpClient.execute(httpGet); HttpEntity entity = response.getEntity(); if(entity != null){ String result = EntityUtils.toString(entity, "UTF-8"); jsonObject = JSONObject.fromObject(result); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return jsonObject; } /** * 带参数的post请求,方便到一个url接口来获取结果 * @param url * @param outStr * @return */ public static JSONObject doPostStr(String url , String outStr) { DefaultHttpClient defaultHttpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(url); JSONObject jsonObject = null; try { httpPost.setEntity(new StringEntity(outStr , "UTF-8")); HttpResponse response = defaultHttpClient.execute(httpPost); HttpEntity entity = response.getEntity(); if(entity != null){ String result = EntityUtils.toString(entity, "UTF-8"); jsonObject = JSONObject.fromObject(result); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return jsonObject; } /** * 获取access_token * @return */ public static AccessToken getAccessToken(){ AccessToken accessToken = new AccessToken(); String url = ACCESS_TOKEN_URL.replace("APPID" ,APPID).replace("APPSECRET",APPSECRET); JSONObject jsonObject = doGetStr(url); if(jsonObject !=null){ accessToken.setToken(jsonObject.getString("access_token")); accessToken.setExpireIn(jsonObject.getLong("expires_in")); } return accessToken; }

测试是否成功获取:

代码语言:javascript复制package com.hnu.scw.test; import com.hnu.scw.model.AccessToken; import com.hnu.scw.utils.WeiXinAccessTokenKeepAlive; import com.hnu.scw.utils.WeiXinUtils; import org.junit.Test; /** * @author scw * @create 2018-01-18 15:21 * @desc 用于对Access_token内容相关的测试 **/ public class AccessTokenTest { /** * 获取到Access_Token,这个对于要想使用其他的微信接口,就必须要有这个进行验证 */ @Test public void getAccssTokenTest(){ AccessToken accessToken = WeiXinUtils.getAccessToken(); System.out.println("token:" +accessToken.getToken()); System.out.println("有效时间:" +accessToken.getExpireIn()); } }(五)自定义菜单

下面的代码,就接着(四)中的类写就可以了,因为都属于微信开发的工具类

步骤:

(1)创建菜单按钮的实体对象类

BaseButton:

代码语言:javascript复制package com.hnu.scw.menu; /** * @author scw * @create 2018-01-17 17:20 * @desc 最基础的Button **/ public class BaseButton { private String type; private String name; //子按钮(也可以理解为二级菜单) private BaseButton[] sub_button; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public BaseButton[] getSub_button() { return sub_button; } public void setSub_button(BaseButton[] sub_button) { this.sub_button = sub_button; } }

clickButton:

代码语言:javascript复制package com.hnu.scw.menu; /** * @author Administrator * @create 2018-01-17 17:21 * @desc Click类型的Button实体 **/ public class ClickButton extends BaseButton { private String key; public String getKey() { return key; } public void setKey(String key) { this.key = key; } }

viewButton:

代码语言:javascript复制package com.hnu.scw.menu; /** * @author scw * @create 2018-01-17 17:22 * @desc 类型是View的按钮实体 **/ public class ViewButton extends BaseButton{ private String url; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }

CustomerMenu菜单定义:

代码语言:javascript复制package com.hnu.scw.menu; /** * @author scw * @create 2018-01-17 17:23 * @desc 自定义菜单的实体 **/ public class CustomeMenu { //对菜单按钮进行封装 private BaseButton[] button; public BaseButton[] getButton() { return button; } public void setButton(BaseButton[] button) { this.button = button; } }

(2)调用接口,进行菜单的创建

代码语言:javascript复制 /** * 设置菜单的形式 * @return */ public static CustomeMenu initMenu(){ CustomeMenu customeMenu = new CustomeMenu(); ClickButton clickButton = new ClickButton(); clickButton.setName("click菜单"); clickButton.setType("click"); clickButton.setKey("01"); ViewButton viewButton = new ViewButton(); viewButton.setName("view菜单"); viewButton.setType("view"); viewButton.setUrl("需要访问的地址"); ClickButton clickButton2 = new ClickButton(); clickButton2.setName("扫码事件的click菜单"); clickButton2.setType("scancode_push"); clickButton2.setKey("02"); ClickButton clickButton3 = new ClickButton(); clickButton3.setName("地理位置的click菜单"); clickButton3.setType("location_select"); clickButton3.setKey("03"); BaseButton baseButton = new BaseButton(); baseButton.setName("菜单"); //将clickButton2,clickButton3作为一个子菜单中的按钮 baseButton.setSub_button(new BaseButton[]{clickButton2,clickButton3}); //把按钮分别放入到菜单中 customeMenu.setButton(new BaseButton[]{clickButton,viewButton,baseButton}); return customeMenu; } /** * 创建自定义菜单 * @param token * @param menu * @return */ public static int createMenu(String token , String menu){ int result = 0; String url = CREATE_MENU_URL.replace("ACCESS_TOKEN" ,token); JSONObject jsonObject = doPostStr(url, menu); if(jsonObject != null){ //接受返回回来的参数,如果是0,就是创建成功 result = jsonObject.getInt("errcode"); } return result; } /** * 对菜单进行查询 * @param token * @return */ public static JSONObject queryMenu(String token){ String url = QUERY_MENU_URL.replace("ACCESS_TOKEN" ,token); JSONObject jsonObject = doGetStr(url); return jsonObject; } /** * 对菜单进行删除 * @param token * @return */ public static JSONObject deleteMenu(String token){ String url = DELETE_MENU_URL.replace("ACCESS_TOKEN" ,token); JSONObject jsonObject = doGetStr(url); return jsonObject; }

(3)生成菜单

代码语言:javascript复制package com.hnu.scw.test; import com.hnu.scw.model.AccessToken; import com.hnu.scw.utils.WeiXinUtils; import net.sf.json.JSONObject; import org.junit.Test; /** * @author scw * @create 2018-01-18 15:21 * @desc 菜单相关的测试 **/ public class MenuTest { /** * 创建菜单 */ @Test public void creatMenuTest(){ //获取到access_token AccessToken accessToken = WeiXinUtils.getAccessToken(); //获取到自定义菜单的格式(JSONObject将对象转为json,然后再需要转为字符串型) String menu = JSONObject.fromObject(WeiXinUtils.initMenu()).toString(); //调用创建菜单 int result = WeiXinUtils.createMenu(accessToken.getToken(), menu); if(result == 0){ //如果调用方法之后,返回的是0,那么就表示创建成功。 System.out.println("创建成功"); }else{ System.out.println("创建失败"); } } /** * 查询菜单 */ @Test public void queryMenuTest(){ //获取到access_token AccessToken accessToken = WeiXinUtils.getAccessToken(); //调用菜单查询的方法,返回是的一个Json格式 JSONObject jsonObject = WeiXinUtils.queryMenu(accessToken.getToken()); System.out.println(jsonObject); } /** * 删除菜单 */ @Test public void deleteMenuTest(){ //获取到access_token AccessToken accessToken = WeiXinUtils.getAccessToken(); //调用菜单查询的方法,返回是的一个Json格式 JSONObject jsonObject = WeiXinUtils.deleteMenu(accessToken.getToken()); if(jsonObject.getInt("errcode") == 0){ //返回0,表示的是删除成功 System.out.println("删除成功"); }else{ System.out.println("删除失败"); } } }

上面就是一些基本的微信公众号的交互了,刚刚接触可能不是很熟,慢慢的就了解了之后,其实也很简单的,当然,对于其中的一些高级接口的使用,可以看看我其他的文章,都有提到。。如果有问题,不明白的地方,欢迎进行交流和留言~!另外,推荐了比较好的学习资源,就是慕课网,这里面对于比较基础的微信公众号开发还是讲解的比较好,再结合我的文章,肯定是没有任何问题的。。。。

Github的地址:

https:https://github.com/qq496616246/WeChatCode.git

git地址:[email protected]:qq496616246/WeChatCode.git

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/171591.html原文链接:https://javaforall.cn



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3