1.最近的话,发现微信开发其实也有很多挺有意思的地方,比如最近很火的一款游戏“跳一跳”,也让我如此着迷。。但是,今天我所要讲的并不是对于小程序的开发,而是要说一下,关于微信开发的另外一个内容,那就是微信公众号。。
2.关于,什么是微信公众号,微信公众号怎么申请,这个我就不多说,这些基本的概念不在这里进行讲解,自己可以直接百度就可以找到很多的资源。而我主要讲解一下关于微信公众号开发中,一些比较重要和常见的知识点,所以,这个也并不是基础篇的文章哦~!好歹也要对微信公众号有一点了解才行。~!
一:实现外网域名访问本地服务项目3.描述:我们在刚开始接触微信公众号开发的时候,我想,一般情况下,很多人都是没有服务器的,简单点说,就是没有服务器IP,或者是公网访问的域名。然而,要想能够实现微信公众能能够与我们后台代码进行交互,那么肯定就需要有一个公网能够访问的地址,那么这怎么办好呢?
4.解法一:很简单呀,直接去新浪云,阿里云,华为云,买一个服务器呗,而且是学生的话,还有优惠,多好。。但是,这个又比较繁琐,里面又有配置内容啥的,一堆(比如,tomcat,mysql,jdk等等)。那么,看看第二种方法。。。。(但是,请记住,这个是想做服务端开发必须会的,如果你连部署项目都不会,你觉得公司对你的感觉如何?多一个技能就是一个优势)
5.解法二:反向代理。。如果,你是第一次听说这个名词,那么就赶紧恶补一下,这个名词的含义。我简单点说,就是通过反向代理的模式,来代理你本地的ip,以便能够在公网地址能够访问到本地的项目。。具体,请看下面,如何进行~!~!
6.步骤:(1)下载ogrok客户端---------也就是反向代理的客户端,当然还有很多类似的,我这里就使用这个而已。
7.这个可以通过该链接进行下载ogrok下载链接
8.(2)解压刚下载好的客户端文件到自己的一个目录下
9.(3)通过cmd命令,进入DOS,并且进入到刚刚解压的ogrok目录下
10.(4)执行ngrok-config=ngrok.cfg-subdomainxxx8080//(xxx是你自定义的域名前缀)
11.比如,我这里就是xxx就是用myjavttest
12.结果:
13.(5)这样的话,我们就可以通过上面的地址进行访问本地的项目了。(原来都是用的localhost:8080/login.jsp或者127.0.0.1:8080/login.jsp),当然,前提是本地有一个开启的项目,这样才可以,别本地都没有项目开启,就用公网去访问,你觉得,它能够访问么?所以,请别忘记这一点。
(二)微信公众号客户端与后台进行验证身份14.首先,我们通过第一步,我们就能够得到一个以公网地址访问的一个IP(域名),那么既然要使得微信公众号能够与后台进行关联,那么肯定需要配置微信公众号的具体对应的服务器地址了。
15.步骤:(1)首先,进入微信公众号开发官网,并且进行登陆
16.(2)
17.(3)
18.(4)
19.OK,配置到这个的话,就简单的,将基本的配置进行设置好了。。那么,下面才是关键,进入真正的开发阶段。。
20.如果微信端,要与后台进行关联,那么当用户进行与后台交互的时候,后台就需要采取,身份验证,而这个是通过GET方式的请求,而只有通过的才可以进行后续的处理。所以,如何进行,那么就看下面的代码:这里讲解两种形式~~~~
21.第一种:(采取Servlet)
@WebServlet(name="ConnectWeChatServlet")publicclassConnectWeChatServletextendsHttpServlet{@OverrideprotectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{}/***进行验证是否身份匹配*@paramrequest*@paramresponse*@throwsServletException*@throwsIOException*/@OverrideprotectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{Stringsignature=request.getParameter("signature");Stringtimestamp=request.getParameter("timestamp");Stringnonce=request.getParameter("nonce");Stringechostr=request.getParameter("echostr");System.out.println(""+signature+"@"+timestamp+"$"+nonce+"^"+echostr);PrintWriterout=response.getWriter();if(CheckConnectUtils.checkConncetWithWeChat(signature,timestamp,nonce)){out.print(echostr);}}22.验证的代码:
packagecom.hnu.scw.utils;importjava.security.MessageDigest;importjava.security.NoSuchAlgorithmException;importjava.util.Arrays;/***@authorscw*@create2018-01-179:28*@desc检查微信和服务器是否链接成功**/publicclassCheckConnectUtils{privatestaticfinalStringtoken="wechat";//这个就是微信公众号之前配置的token,必须保持一致/***判断是否链接匹配*@paramsignature*@paramtimestamp*@paramnonce*@return*/publicstaticbooleancheckConncetWithWeChat(Stringsignature,Stringtimestamp,Stringnonce){String[]arr=newString[]{token,timestamp,nonce};//排序Arrays.sort(arr);//生成字符串StringBuilderstringBuilder=newStringBuilder();for(Stringstr:arr){stringBuilder.append(str);}//进行SHA1加密StringencodeString=passSha1Encode(stringBuilder.toString());if(signature.equals(encodeString)){returntrue;}else{returnfalse;}}/***字符串进行SHA1加密*@paramstr*@return*/publicstaticStringpassSha1Encode(Stringstr){if(str==null||str.length()==0){returnnull;}charhexDigits[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};try{MessageDigestmdTemp=MessageDigest.getInstance("SHA1");mdTemp.update(str.getBytes());byte[]md=mdTemp.digest();intj=md.length;char[]buf=newchar[j*2];intk=0;for(inti=0;ij;i++){bytebyte0=md[i];buf[k++]=hexDigits[byte040xf];buf[k++]=hexDigits[byte00xf];}returnnewString(buf);}catch(NoSuchAlgorithmExceptione){returnnull;}}}23.第二种:(采取框架,比如SpringMVC+Spring+Hibernate)
/***@authorscw*@create2018-01-1811:38*@desc微信前端连接的主要控制类**/@ControllerpublicclassWeChatDogPrimaryController{/***进行微信用户验证,只能是Get方法*@paramrequest*@paramresponse*/@RequestMapping(value="/wechat",method=RequestMethod.GET)publicvoidconnectValidate(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{Stringsignature=request.getParameter("signature");Stringtimestamp=request.getParameter("timestamp");Stringnonce=request.getParameter("nonce");Stringechostr=request.getParameter("echostr");System.out.println(""+signature+"@"+timestamp+"$"+nonce+"^"+echostr);PrintWriterout=response.getWriter();if(CheckConnectUtils.checkConncetWithWeChat(signature,timestamp,nonce)){out.print(echostr);}}/***客户端进行的消息处理*@paramrequest*@paramresponse*/@RequestMapping(value="/wechat",method=RequestMethod.POST)publicvoiddisposeClientMessage(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{}24.(三)微信客户端与后台进行消息交互(比如,文本,图片,视频,音频)
25.消息的实体类:
packagecom.hnu.scw.model;/***@authorscw*@create2018-01-1713:37*@desc对于所有消息的基本父类**/publicclassBaseMessage{privateStringToUserName;privateStringFromUserName;privateStringCreateTime;privateStringMsgType;publicStringgetToUserName(){returnToUserName;}publicvoidsetToUserName(StringtoUserName){ToUserName=toUserName;}publicStringgetFromUserName(){returnFromUserName;}publicvoidsetFromUserName(StringfromUserName){FromUserName=fromUserName;}publicStringgetCreateTime(){returnCreateTime;}publicvoidsetCreateTime(StringcreateTime){CreateTime=createTime;}publicStringgetMsgType(){returnMsgType;}publicvoidsetMsgType(StringmsgType){MsgType=msgType;}}packagecom.hnu.scw.model;/***@authorSCW*@create2018-01-1715:08*@desc图片的基本类**/publicclassImageBase{privateStringMediaId;publicStringgetMediaId(){returnMediaId;}publicvoidsetMediaId(StringmediaId){MediaId=mediaId;}}packagecom.hnu.scw.model;/***@authorscw*@create2018-01-1715:09*@desc图片消息**/publicclassImageMessageextendsBaseMessage{privateImageBaseImage;publicImageBasegetImageBase(){returnImage;}publicvoidsetImageBase(ImageBaseImage){this.Image=Image;}}packagecom.hnu.scw.model;/***@authorAdministrator*@create2018-01-1716:45*@desc音乐类型的基本类**/publicclassMusicBase{privateStringTitle;privateStringDescription;privateStringMusicUrl;privateStringHQMusicUrl;privateStringThumbMediaId;publicStringgetTitle(){returnTitle;}publicvoidsetTitle(Stringtitle){Title=title;}publicStringgetDescription(){returnDescription;}publicvoidsetDescription(Stringdescription){Description=description;}publicStringgetMusicUrl(){returnMusicUrl;}publicvoidsetMusicUrl(StringmusicUrl){MusicUrl=musicUrl;}publicStringgetHQMusicUrl(){returnHQMusicUrl;}publicvoidsetHQMusicUrl(StringHQMusicUrl){this.HQMusicUrl=HQMusicUrl;}publicStringgetThumbMediaId(){returnThumbMediaId;}publicvoidsetThumbMediaId(StringthumbMediaId){ThumbMediaId=thumbMediaId;}}packagecom.hnu.scw.model;/***@authorAdministrator*@create2018-01-1716:46*@desc用于包装音乐的实体**/publicclassMusicMessageextendsBaseMessage{privateMusicBaseMusic;publicMusicBasegetMusic(){returnMusic;}publicvoidsetMusic(MusicBasemusic){Music=music;}}packagecom.hnu.scw.model;/***@authorscw*@create2018-01-1710:03*@desc文本消息的内容**/publicclassMyTestMessageextendsBaseMessage{privateStringContent;privateStringMsgId;publicStringgetContent(){returnContent;}publicvoidsetContent(Stringcontent){Content=content;}publicStringgetMsgId(){returnMsgId;}publicvoidsetMsgId(StringmsgId){MsgId=msgId;}}packagecom.hnu.scw.model;/***@authorscw*@create2018-01-1713:38*@desc对于图文消息最内层结构的实体类**/publicclassNewsBase{privateStringTitle;privateStringDescription;privateStringPicUrl;privateStringUrl;publicStringgetTitle(){returnTitle;}publicvoidsetTitle(Stringtitle){Title=title;}publicStringgetDescription(){returnDescription;}publicvoidsetDescription(Stringdescription){Description=description;}publicStringgetPicUrl(){returnPicUrl;}publicvoidsetPicUrl(StringpicUrl){PicUrl=picUrl;}publicStringgetUrl(){returnUrl;}publicvoidsetUrl(Stringurl){Url=url;}}packagecom.hnu.scw.model;importjava.util.List;/***@authorscw*@create2018-01-1713:35*@desc对于图文消息的实体类**/publicclassNewsMessageextendsBaseMessage{privateintArticleCount;privateListNewsBaseArticles;publicintgetArticleCount(){returnArticleCount;}publicvoidsetArticleCount(intarticleCount){ArticleCount=articleCount;}publicListNewsBasegetArticles(){returnArticles;}publicvoidsetArticles(ListNewsBasearticles){Articles=articles;}}26.消息封装工具类:
packagecom.hnu.scw.utils;importcom.hnu.scw.model.*;importcom.thoughtworks.xstream.XStream;importorg.dom4j.Document;importorg.dom4j.Element;importorg.dom4j.io.SAXReader;importjavax.servlet.http.HttpServletRequest;importjava.io.InputStream;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;/***@authorscw*@create2018-01-179:52*@desc用户转换消息的格式**/publicclassMessageUtils{/***定义多种消息类型*/publicstaticfinalStringMESSAGE_TEXT="text";publicstaticfinalStringMESSAGE_IMAGE="image";publicstaticfinalStringMESSAGE_VOICE="voice";publicstaticfinalStringMESSAGE_MUSIC="music";publicstaticfinalStringMESSAGE_VIDEO="video";publicstaticfinalStringMESSAGE_LINK="link";publicstaticfinalStringMESSAGE_LOCATION="location";publicstaticfinalStringMESSAGE_EVENT="event";publicstaticfinalStringMESSAGE_SUBSCRIBE="subscribe";publicstaticfinalStringMESSAGE_UNSUBSCRIBE="unsubscribe";publicstaticfinalStringMESSAGE_CLICK="CLICK";publicstaticfinalStringMESSAGE_VIEW="VIEW";//扫码事件publicstaticfinalStringMESSAGE_SCANCODE="scancode_push";/***XML格式转为map格式*@paramrequest*@return*/publicstaticMapString,StringxmlToMap(HttpServletRequestrequest){MapString,Stringmap=newHashMapString,String();try{InputStreaminputStream=null;inputStream=request.getInputStream();SAXReaderreader=newSAXReader();Documentdoc=reader.read(inputStream);ElementrootElement=doc.getRootElement();ListElementelements=rootElement.elements();for(Elementel:elements){map.put(el.getName(),el.getText());}inputStream.close();returnmap;}catch(Exceptione){e.printStackTrace();returnnull;}}/***文本消息对象转为xml格式*@parammyTestMessage*@return*/publicstaticStringtextMessage2Xml(MyTestMessagemyTestMessage){XStreamxStream=newXStream();xStream.alias("xml",myTestMessage.getClass());returnxStream.toXML(myTestMessage);}/***将图文消息对象转化为图文格式的XML*@return*/publicstaticStringnewsMessage2XML(NewsMessagenewsMessage){XStreamxStream=newXStream();//将需要修改的一些标签进行替换xStream.alias("xml",newsMessage.getClass());xStream.alias("item",newNewsBase().getClass());returnxStream.toXML(newsMessage);}/***设置需要返回的图文信息*@paramfromUserName*@paramtoUserName*@return*/publicstaticStringinitNewSMessage(StringfromUserName,StringtoUserName){Stringmessage=null;ListNewsBasenewList=newArrayListNewsBase();NewsMessagenewsMessage=newNewsMessage();NewsBasenewsBase=newNewsBase();newsBase.setTitle("我是图文消息");newsBase.setDescription("测试测试测试测试测试测试测试测试测试");newsBase.setPicUrl("https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=677717294,4155848424fm=27gp=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);//调用转为图文的XMLreturnMessageUtils.newsMessage2XML(newsMessage);}/***设置需要返回的文本信息*@paramfromUserName*@paramtoUserName*@paramcontent*@return*/publicstaticStringinitText(StringfromUserName,StringtoUserName,Stringcontent){MyTestMessagetext=newMyTestMessage();//注意接受消息和发送消息的顺序要烦过来text.setFromUserName(toUserName);text.setToUserName(fromUserName);text.setMsgType(MessageUtils.MESSAGE_TEXT);longtime=System.currentTimeMillis();text.setCreateTime(String.valueOf(time));text.setContent(content);returnMessageUtils.textMessage2Xml(text);}/***设置订阅时,返回菜单的内容*@return*/publicstaticStringmenuText(){StringBuilderstringBuilder=newStringBuilder();stringBuilder.append("菜单1:回复数字1,有惊喜");stringBuilder.append("菜单2:回复数字2,有惊喜");stringBuilder.append("菜单3:回复数字3,有惊喜");stringBuilder.append("菜单4:回复数字3,有惊喜");stringBuilder.append("菜单5:回复数字3,有惊喜");stringBuilder.append("菜单6:回复数字未知的东东,也还有有惊喜哦");returnstringBuilder.toString();}/***回复关键字"1"的时候的内容*@return*/publicstaticStringinputNumber1(){StringBuilderstringBuilder=newStringBuilder();stringBuilder.append("我是惊喜111,哈哈,惊喜不惊喜!");returnstringBuilder.toString();}/***回复关键字"2"的时候的内容*@return*/publicstaticStringinputNumber2(){StringBuilderstringBuilder=newStringBuilder();stringBuilder.append("我是惊喜2222,哈哈,惊喜不惊喜!");returnstringBuilder.toString();}/***返回图片消息(对于视频和音频都是一样的方式,只需要更改类型即可,即将Image修改为video,voice)*@paramfromUserName*@paramtoUserName*@return*/publicstaticStringinitImageMessage(StringfromUserName,StringtoUserName){ImageBaseimageBase=newImageBase();//这个media_Id是在之前执行过上传图片返回得到的信息imageBase.setMediaId("HK17wQmCupESK4B9u14PqI4w3gtteXhUtGgriJW6G5c8O-Y0OsjGbYfQYhGDbYDx");ImageMessageimageMessage=newImageMessage();imageMessage.setFromUserName(toUserName);imageMessage.setToUserName(fromUserName);imageMessage.setMsgType(MessageUtils.MESSAGE_IMAGE);longtime=System.currentTimeMillis();imageMessage.setCreateTime(String.valueOf(time));imageMessage.setImageBase(imageBase);returnimageMessage2XML(imageMessage);}/***将图片消息对象转化为图片格式的XML*@return*/publicstaticStringimageMessage2XML(ImageMessageimageMessage){XStreamxStream=newXStream();//将需要修改的一些标签进行替换xStream.alias("xml",imageMessage.getClass());xStream.alias("Image",newImageBase().getClass());returnxStream.toXML(imageMessage);}/***将音乐消息对象转化为图片格式的XML*@return*/publicstaticStringmusicMessage2XML(MusicMessagemusicMessage){XStreamxStream=newXStream();//将需要修改的一些标签进行替换xStream.alias("xml",musicMessage.getClass());xStream.alias("Music",newMusicBase().getClass());returnxStream.toXML(musicMessage);}/***返回音乐消息*@paramfromUserName*@paramtoUserName*@return*/publicstaticStringinitMusicMessage(StringfromUserName,StringtoUserName){MusicBasemusicBase=newMusicBase();//这个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");MusicMessagemusicMessage=newMusicMessage();musicMessage.setFromUserName(toUserName);musicMessage.setToUserName(fromUserName);//设置类型为音乐musicMessage.setMsgType(MessageUtils.MESSAGE_MUSIC);longtime=System.currentTimeMillis();musicMessage.setCreateTime(String.valueOf(time));musicMessage.setMusic(musicBase);returnmusicMessage2XML(musicMessage);}}27.交互主类:
packagecom.hnu.scw.controller;importcom.hnu.scw.utils.CheckConnectUtils;importcom.hnu.scw.utils.MessageUtils;importcom.hnu.scw.utils.WeiXinUserInfoUtiols;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestMethod;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjavax.servlet.http.HttpSession;importjava.io.IOException;importjava.io.PrintWriter;importjava.util.Map;/***@authorscw*@create2018-01-1811:38*@desc微信前端连接的主要控制类**/@ControllerpublicclassWeChatDogPrimaryController{/***进行微信用户验证,只能是Get方法*@paramrequest*@paramresponse*/@RequestMapping(value="/wechat",method=RequestMethod.GET)publicvoidconnectValidate(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{Stringsignature=request.getParameter("signature");Stringtimestamp=request.getParameter("timestamp");Stringnonce=request.getParameter("nonce");Stringechostr=request.getParameter("echostr");System.out.println(""+signature+"@"+timestamp+"$"+nonce+"^"+echostr);PrintWriterout=response.getWriter();if(CheckConnectUtils.checkConncetWithWeChat(signature,timestamp,nonce)){out.print(echostr);}}/***客户端进行的消息处理*@paramrequest*@paramresponse*/@RequestMapping(value="/wechat",method=RequestMethod.POST)publicvoiddisposeClientMessage(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{backTestFunction(request,response);}/***文字回复功能开发*@paramrequest*@paramresponse*@throwsServletException*@throwsIOException*/publicvoidbackTestFunction(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{//防止进行post提交和响应的消息乱码request.setCharacterEncoding("UTF-8");response.setHeader("Content-type","text/html;charset=UTF-8");response.setCharacterEncoding("UTF-8");PrintWriterout=response.getWriter();try{//将发送过来的消息XML形式转为map内容MapString,Stringmap=MessageUtils.xmlToMap(request);StringfromUserName=map.get("FromUserName");StringtoUserName=map.get("ToUserName");StringmsgType=map.get("MsgType");Stringcontent=map.get("Content");Stringmessage=null;if(MessageUtils.MESSAGE_TEXT.equals(msgType)){//进行关键字回复功能if("1".equals(content)){message=MessageUtils.initText(fromUserName,toUserName,MessageUtils.inputNumber1());}elseif("2".equals(content)){message=MessageUtils.initText(fromUserName,toUserName,MessageUtils.inputNumber2());}elseif("3".equals(content)){//客户端输入“3”,返回一条图文消息message=MessageUtils.initNewSMessage(fromUserName,toUserName);}elseif("4".equals(content)){//客户端输入“4”,返回一条图片消息message=MessageUtils.initImageMessage(fromUserName,toUserName);}elseif("5".equals(content)){//客户端输入“5”,返回一首音乐消息message=MessageUtils.initMusicMessage(fromUserName,toUserName);}elseif("6".equals(content)){//测试是否能够获取用户的信息message=MessageUtils.initText(fromUserName,toUserName,WeiXinUserInfoUtiols.getUserInfo(fromUserName));}elseif(content.startsWith("翻译")){//客户端输入“以翻译开头”,返回对应的翻译信息/*StringtranslateResult=TranslationUtils.translate(content.substring(2,content.length()));message=MessageUtils.initText(fromUserName,toUserName,translateResult);*/}else{message=MessageUtils.initText(fromUserName,toUserName,"你发送的消息是:"+content);}}elseif(MessageUtils.MESSAGE_EVENT.equals(msgType)){StringeventType=map.get("Event");//完成订阅时候返回的内容if(MessageUtils.MESSAGE_SUBSCRIBE.equals(eventType)){message=MessageUtils.initText(fromUserName,toUserName,MessageUtils.menuText());}elseif(MessageUtils.MESSAGE_CLICK.equals(eventType)){//进行的是click按钮的点击事件(这里就推送一下主菜单内容)message=MessageUtils.initText(fromUserName,toUserName,MessageUtils.menuText());}elseif(MessageUtils.MESSAGE_VIEW.equals(eventType)){//进行的是view按钮的点击事件(这里就推送一下主菜单内容)StringviewUrl=map.get("EventKey");message=MessageUtils.initText(fromUserName,toUserName,viewUrl);}elseif(MessageUtils.MESSAGE_SCANCODE.equals(eventType)){//进行的是扫码事件Stringkey=map.get("EventKey");message=MessageUtils.initText(fromUserName,toUserName,key);}}elseif(MessageUtils.MESSAGE_LOCATION.equals(msgType)){//进行的是地理位置信息Stringlabel=map.get("Label");message=MessageUtils.initText(fromUserName,toUserName,label);}//打印输出的xml格式内容,方便进行调试System.out.println(message);out.print(message);}catch(Exceptione){e.printStackTrace();}finally{out.close();}}}(四)获取Access_Token28.Access_Token是一个全局的票据,调用任何的高级接口,都需要这个,所以这个非常非常的重要
29.具体代码:
packagecom.hnu.scw.utils;importcom.hnu.scw.menu.BaseButton;importcom.hnu.scw.menu.ClickButton;importcom.hnu.scw.menu.CustomeMenu;importcom.hnu.scw.menu.ViewButton;importcom.hnu.scw.model.AccessToken;importcom.hnu.scw.projectconst.ProjectConst;importnet.sf.json.JSONObject;importorg.apache.http.HttpEntity;importorg.apache.http.HttpResponse;importorg.apache.http.client.ClientProtocolException;importorg.apache.http.client.methods.HttpGet;importorg.apache.http.client.methods.HttpPost;importorg.apache.http.entity.StringEntity;importorg.apache.http.impl.client.DefaultHttpClient;importorg.apache.http.util.EntityUtils;importorg.springframework.web.context.ContextLoader;importorg.springframework.web.context.WebApplicationContext;importjavax.servlet.ServletContext;importjava.io.IOException;importjava.io.UnsupportedEncodingException;/***@authorscw*@create2018-01-1714:13*@desc用户获取access_token,众号调用各接口时都需使用access_token**/publicclassWeiXinUtils{/***微信公众号的APPID和Appsecret,这个是每个微信公众号都唯一的,以后配置不同的公众号配置这里即可*/privatestaticfinalStringAPPID="自己公众号对应的内容";privatestaticfinalStringAPPSECRET="自己公众号对应的内容";//获取access_token的URLprivatestaticfinalStringACCESS_TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credentialappid=APPIDsecret=APPSECRET";//进行创建菜单的接口URLprivatestaticfinalStringCREATE_MENU_URL="https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";//菜单查询的接口URLprivatestaticfinalStringQUERY_MENU_URL="https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";//菜单删除的接口URLprivatestaticfinalStringDELETE_MENU_URL="https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";/***Get请求,方便到一个url接口来获取结果*@paramurl*@return*/publicstaticJSONObjectdoGetStr(Stringurl){DefaultHttpClientdefaultHttpClient=newDefaultHttpClient();HttpGethttpGet=newHttpGet(url);JSONObjectjsonObject=null;try{HttpResponseresponse=defaultHttpClient.execute(httpGet);HttpEntityentity=response.getEntity();if(entity!=null){Stringresult=EntityUtils.toString(entity,"UTF-8");jsonObject=JSONObject.fromObject(result);}}catch(ClientProtocolExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}returnjsonObject;}/***带参数的post请求,方便到一个url接口来获取结果*@paramurl*@paramoutStr*@return*/publicstaticJSONObjectdoPostStr(Stringurl,StringoutStr){DefaultHttpClientdefaultHttpClient=newDefaultHttpClient();HttpPosthttpPost=newHttpPost(url);JSONObjectjsonObject=null;try{httpPost.setEntity(newStringEntity(outStr,"UTF-8"));HttpResponseresponse=defaultHttpClient.execute(httpPost);HttpEntityentity=response.getEntity();if(entity!=null){Stringresult=EntityUtils.toString(entity,"UTF-8");jsonObject=JSONObject.fromObject(result);}}catch(UnsupportedEncodingExceptione){e.printStackTrace();}catch(ClientProtocolExceptione){e.printStackTrace();}catch(IOExceptione){e.printStackTrace();}returnjsonObject;}/***获取access_token*@return*/publicstaticAccessTokengetAccessToken(){AccessTokenaccessToken=newAccessToken();Stringurl=ACCESS_TOKEN_URL.replace("APPID",APPID).replace("APPSECRET",APPSECRET);JSONObjectjsonObject=doGetStr(url);if(jsonObject!=null){accessToken.setToken(jsonObject.getString("access_token"));accessToken.setExpireIn(jsonObject.getLong("expires_in"));}returnaccessToken;}30.测试是否成功获取:
packagecom.hnu.scw.test;importcom.hnu.scw.model.AccessToken;importcom.hnu.scw.utils.WeiXinAccessTokenKeepAlive;importcom.hnu.scw.utils.WeiXinUtils;importorg.junit.Test;/***@authorscw*@create2018-01-1815:21*@desc用于对Access_token内容相关的测试**/publicclassAccessTokenTest{/***获取到Access_Token,这个对于要想使用其他的微信接口,就必须要有这个进行验证*/@TestpublicvoidgetAccssTokenTest(){AccessTokenaccessToken=WeiXinUtils.getAccessToken();System.out.println("token:"+accessToken.getToken());System.out.println("有效时间:"+accessToken.getExpireIn());}}(五)自定义菜单31.下面的代码,就接着(四)中的类写就可以了,因为都属于微信开发的工具类
32.步骤:
33.(1)创建菜单按钮的实体对象类
34.BaseButton:
packagecom.hnu.scw.menu;/***@authorscw*@create2018-01-1717:20*@desc最基础的Button**/publicclassBaseButton{privateStringtype;privateStringname;//子按钮(也可以理解为二级菜单)privateBaseButton[]sub_button;publicStringgetType(){returntype;}publicvoidsetType(Stringtype){this.type=type;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicBaseButton[]getSub_button(){returnsub_button;}publicvoidsetSub_button(BaseButton[]sub_button){this.sub_button=sub_button;}}35.clickButton:
packagecom.hnu.scw.menu;/***@authorAdministrator*@create2018-01-1717:21*@descClick类型的Button实体**/publicclassClickButtonextendsBaseButton{privateStringkey;publicStringgetKey(){returnkey;}publicvoidsetKey(Stringkey){this.key=key;}}36.viewButton:
packagecom.hnu.scw.menu;/***@authorscw*@create2018-01-1717:22*@desc类型是View的按钮实体**/publicclassViewButtonextendsBaseButton{privateStringurl;publicStringgetUrl(){returnurl;}publicvoidsetUrl(Stringurl){this.url=url;}}37.CustomerMenu菜单定义:
packagecom.hnu.scw.menu;/***@authorscw*@create2018-01-1717:23*@desc自定义菜单的实体**/publicclassCustomeMenu{//对菜单按钮进行封装privateBaseButton[]button;publicBaseButton[]getButton(){returnbutton;}publicvoidsetButton(BaseButton[]button){this.button=button;}}38.(2)调用接口,进行菜单的创建
/***设置菜单的形式*@return*/publicstaticCustomeMenuinitMenu(){CustomeMenucustomeMenu=newCustomeMenu();ClickButtonclickButton=newClickButton();clickButton.setName("click菜单");clickButton.setType("click");clickButton.setKey("01");ViewButtonviewButton=newViewButton();viewButton.setName("view菜单");viewButton.setType("view");viewButton.setUrl("需要访问的地址");ClickButtonclickButton2=newClickButton();clickButton2.setName("扫码事件的click菜单");clickButton2.setType("scancode_push");clickButton2.setKey("02");ClickButtonclickButton3=newClickButton();clickButton3.setName("地理位置的click菜单");clickButton3.setType("location_select");clickButton3.setKey("03");BaseButtonbaseButton=newBaseButton();baseButton.setName("菜单");//将clickButton2,clickButton3作为一个子菜单中的按钮baseButton.setSub_button(newBaseButton[]{clickButton2,clickButton3});//把按钮分别放入到菜单中customeMenu.setButton(newBaseButton[]{clickButton,viewButton,baseButton});returncustomeMenu;}/***创建自定义菜单*@paramtoken*@parammenu*@return*/publicstaticintcreateMenu(Stringtoken,Stringmenu){intresult=0;Stringurl=CREATE_MENU_URL.replace("ACCESS_TOKEN",token);JSONObjectjsonObject=doPostStr(url,menu);if(jsonObject!=null){//接受返回回来的参数,如果是0,就是创建成功result=jsonObject.getInt("errcode");}returnresult;}/***对菜单进行查询*@paramtoken*@return*/publicstaticJSONObjectqueryMenu(Stringtoken){Stringurl=QUERY_MENU_URL.replace("ACCESS_TOKEN",token);JSONObjectjsonObject=doGetStr(url);returnjsonObject;}/***对菜单进行删除*@paramtoken*@return*/publicstaticJSONObjectdeleteMenu(Stringtoken){Stringurl=DELETE_MENU_URL.replace("ACCESS_TOKEN",token);JSONObjectjsonObject=doGetStr(url);returnjsonObject;}39.(3)生成菜单
packagecom.hnu.scw.test;importcom.hnu.scw.model.AccessToken;importcom.hnu.scw.utils.WeiXinUtils;importnet.sf.json.JSONObject;importorg.junit.Test;/***@authorscw*@create2018-01-1815:21*@desc菜单相关的测试**/publicclassMenuTest{/***创建菜单*/@TestpublicvoidcreatMenuTest(){//获取到access_tokenAccessTokenaccessToken=WeiXinUtils.getAccessToken();//获取到自定义菜单的格式(JSONObject将对象转为json,然后再需要转为字符串型)Stringmenu=JSONObject.fromObject(WeiXinUtils.initMenu()).toString();//调用创建菜单intresult=WeiXinUtils.createMenu(accessToken.getToken(),menu);if(result==0){//如果调用方法之后,返回的是0,那么就表示创建成功。System.out.println("创建成功");}else{System.out.println("创建失败");}}/***查询菜单*/@TestpublicvoidqueryMenuTest(){//获取到access_tokenAccessTokenaccessToken=WeiXinUtils.getAccessToken();//调用菜单查询的方法,返回是的一个Json格式JSONObjectjsonObject=WeiXinUtils.queryMenu(accessToken.getToken());System.out.println(jsonObject);}/***删除菜单*/@TestpublicvoiddeleteMenuTest(){//获取到access_tokenAccessTokenaccessToken=WeiXinUtils.getAccessToken();//调用菜单查询的方法,返回是的一个Json格式JSONObjectjsonObject=WeiXinUtils.deleteMenu(accessToken.getToken());if(jsonObject.getInt("errcode")==0){//返回0,表示的是删除成功System.out.println("删除成功");}else{System.out.println("删除失败");}}}40.上面就是一些基本的微信公众号的交互了,刚刚接触可能不是很熟,慢慢的就了解了之后,其实也很简单的,当然,对于其中的一些高级接口的使用,可以看看我其他的文章,都有提到。。如果有问题,不明白的地方,欢迎进行交流和留言~!另外,推荐了比较好的学习资源,就是慕课网,这里面对于比较基础的微信公众号开发还是讲解的比较好,再结合我的文章,肯定是没有任何问题的。。。。
Github的地址:41.https:https://github.com/qq496616246/WeChatCode.git
42.git地址:git@github.com:qq496616246/WeChatCode.git













