java微信公众号开发案例
微信公众号开发一般是针对企业和组织的,个人一般只能申请订阅号,并且调用的接口有限,下面我们就来简单的描述下接入公众号的步骤:
1、首先你需要一个邮箱在微信公众号平台进行注册;
注册的方式有订阅号、公众号、小程序和企业号,个人我们这里只能选择订阅号
2、注册完后,我们登录到公众号平台--->开发--->基本配置,这里需要填写URL和token,URL就是我们使用服务器的接口;
3、JavaWeb服务器程序编译好且在服务器上部署可以运行的话,可在微信公众号进行在线接口调试:
1)、选择合适的接口
2)、系统会生成该接口的参数表,您可以直接在文本框内填入对应的参数值(红色星号表示该字段必填)
3)、点击检查问题按钮,即可得到相应的调试信息
eg:获取access_token的步骤:
1)、接口类型:基础支持
2)、接口列表:获取access_token接口/token
3)、填写相应的参数:grant_type、appid、secret
4)、点击检查问题
5)、验证成功会返回结果和提示,结果为:200ok,提示:Requestsuccessful即表示验证成功
我们这里验证比较多的是消息接口调试:文本消息、图片消息、语音消息、视频消息、etc
4、接口有不理解的地方,可进入开发-->开发者工具-->开发者文档进行查询
5、接口权限:订阅号主要有基础支持、接收消息及网页服务里面的一些接口
下面我们主要讲订阅号怎么样接收消息的案例:
1、需要申请一个个人微信订阅号
2、url服务器和服务器端代码部署(可以用腾讯云or阿里云服务器)
1)、AccountsServlet.java类,验证来自微信服务器和微信服务器的消息处理
packagecn.jon.wechat.servlet; importjava.io.IOException; importjava.io.PrintWriter; importjavax.servlet.ServletException; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; importcn.jon.wechat.service.AccountsService; importcn.jon.wechat.utils.SignUtil; publicclassAccountsServletextendsHttpServlet{ publicAccountsServlet(){ super(); } publicvoiddestroy(){ super.destroy(); //Putyourcodehere } /** *确认请求来自于微信服务器 */ publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ System.out.println("接口测试开始!!!"); //微信加密签名 Stringsignature=request.getParameter("signature"); //时间戳 Stringtimestamp=request.getParameter("timestamp"); //随机数 Stringnonce=request.getParameter("nonce"); //随机字符串 Stringechostr=request.getParameter("echostr"); PrintWriterout=response.getWriter(); //通过校验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 if(SignUtil.checkSignature(signature,timestamp,nonce)){ out.print(echostr); } out.close(); out=null; //response.encodeRedirectURL("success.jsp"); } /** *处理微信服务器发来的消息 */ publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse) throwsServletException,IOException{ //消息的接受、处理、响应 request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); //调用核心业务类型接受消息、处理消息 StringrespMessage=AccountsService.processRequest(request); //响应消息 PrintWriterout=response.getWriter(); out.print(respMessage); out.close(); } publicvoidinit()throwsServletException{ //Putyourcodehere } }
2)、SignUtil.java类,请求校验工具类,token需要和微信中填写的token一致
packagecn.jon.wechat.utils; importjava.security.MessageDigest; importjava.security.NoSuchAlgorithmException; importjava.util.Arrays; importjava.util.Iterator; importjava.util.Map; importjava.util.Set; importjava.util.concurrent.ConcurrentHashMap; /** *请求校验工具类 *@authorjon */ publicclassSignUtil{ //与微信配置中的的Token一致 privatestaticStringtoken=""; publicstaticbooleancheckSignature(Stringsignature,Stringtimestamp, Stringnonce){ String[]arra=newString[]{token,timestamp,nonce}; //将signature,timestamp,nonce组成数组进行字典排序 Arrays.sort(arra); StringBuildersb=newStringBuilder(); for(inti=0;i<arra.length;i++){ sb.append(arra[i]); } MessageDigestmd=null; StringstnStr=null; try{ md=MessageDigest.getInstance("SHA-1"); byte[]digest=md.digest(sb.toString().getBytes()); stnStr=byteToStr(digest); }catch(NoSuchAlgorithmExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } //释放内存 sb=null; //将sha1加密后的字符串与signature对比,标识该请求来源于微信 returnstnStr!=null?stnStr.equals(signature.toUpperCase()):false; } /** *将字节数组转换成十六进制字符串 *@paramdigestArra *@return */ privatestaticStringbyteToStr(byte[]digestArra){ //TODOAuto-generatedmethodstub StringdigestStr=""; for(inti=0;i<digestArra.length;i++){ digestStr+=byteToHexStr(digestArra[i]); } returndigestStr; } /** *将字节转换成为十六进制字符串 */ privatestaticStringbyteToHexStr(bytedByte){ //TODOAuto-generatedmethodstub char[]Digit={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; char[]tmpArr=newchar[2]; tmpArr[0]=Digit[(dByte>>>4)&0X0F]; tmpArr[1]=Digit[dByte&0X0F]; Strings=newString(tmpArr); returns; } publicstaticvoidmain(String[]args){ /*bytedByte='A'; System.out.println(byteToHexStr(dByte));*/ Map<String,String>map=newConcurrentHashMap<String,String>(); map.put("4","zhangsan"); map.put("100","lisi"); Setset=map.keySet(); Iteratoriter=set.iterator(); while(iter.hasNext()){ //StringkeyV=(String)iter.next(); Stringkey=(String)iter.next(); System.out.println(map.get(key)); //System.out.println(map.get(iter.next())); } /*for(inti=0;i<map.size();i++){ }*/ } }
3)、AccountsService.java服务类,主要是消息的请求和响应处理,并且当用户关注你的公众号的时候,可以设置默认推送消息
packagecn.jon.wechat.service; importjava.util.Date; importjava.util.Map; importjavax.servlet.http.HttpServletRequest; importcn.jon.wechat.message.req.ImageMessage; importcn.jon.wechat.message.req.LinkMessage; importcn.jon.wechat.message.req.LocationMessage; importcn.jon.wechat.message.req.VideoMessage; importcn.jon.wechat.message.req.VoiceMessage; importcn.jon.wechat.message.resp.TextMessage; importcn.jon.wechat.utils.MessageUtil; /** *解耦,使控制层与业务逻辑层分离开来,主要处理请求,响应 *@authorjon */ publicclassAccountsService{ publicstaticStringprocessRequest(HttpServletRequestrequest){ StringrespMessage=null; //默认返回的文本消息内容 StringrespContent="请求处理异常,请稍后尝试!"; try{ //xml请求解析 Map<String,String>requestMap=MessageUtil.pareXml(request); //发送方账号(open_id) StringfromUserName=requestMap.get("FromUserName"); //公众账号 StringtoUserName=requestMap.get("ToUserName"); //消息类型 StringmsgType=requestMap.get("MsgType"); //默认回复此文本消息 TextMessagedefaultTextMessage=newTextMessage(); defaultTextMessage.setToUserName(fromUserName); defaultTextMessage.setFromUserName(toUserName); defaultTextMessage.setCreateTime(newDate().getTime()); defaultTextMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_TEXT); defaultTextMessage.setFuncFlag(0); //由于href属性值必须用双引号引起,这与字符串本身的双引号冲突,所以要转义 defaultTextMessage.setContent("欢迎访问<ahref=\"http://blog.csdn.net/j086924\">jon的博客</a>!"); //defaultTextMessage.setContent(getMainMenu()); //将文本消息对象转换成xml字符串 respMessage=MessageUtil.textMessageToXml(defaultTextMessage); //文本消息 if(msgType.equals(MessageUtil.MESSSAGE_TYPE_TEXT)){ //respContent="Hi,您发送的是文本消息!"; //回复文本消息 TextMessagetextMessage=newTextMessage(); //textMessage.setToUserName(toUserName); //textMessage.setFromUserName(fromUserName); //这里需要注意,否则无法回复消息给用户了 textMessage.setToUserName(fromUserName); textMessage.setFromUserName(toUserName); textMessage.setCreateTime(newDate().getTime()); textMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_TEXT); textMessage.setFuncFlag(0); respContent="Hi,你发的消息是:"+requestMap.get("Content"); textMessage.setContent(respContent); respMessage=MessageUtil.textMessageToXml(textMessage); } //图片消息 elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_IMAGE)){ ImageMessageimageMessage=newImageMessage(); imageMessage.setToUserName(fromUserName); imageMessage.setFromUserName(toUserName); imageMessage.setCreateTime(newDate().getTime()); imageMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_IMAGE); //respContent=requestMap.get("PicUrl"); imageMessage.setPicUrl("http://img24.pplive.cn//2013//07//24//12103112092_230X306.jpg"); respMessage=MessageUtil.imageMessageToXml(imageMessage); } //地理位置 elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_LOCATION)){ LocationMessagelocationMessage=newLocationMessage(); locationMessage.setToUserName(fromUserName); locationMessage.setFromUserName(toUserName); locationMessage.setCreateTime(newDate().getTime()); locationMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_LOCATION); locationMessage.setLocation_X(requestMap.get("Location_X")); locationMessage.setLocation_Y(requestMap.get("Location_Y")); locationMessage.setScale(requestMap.get("Scale")); locationMessage.setLabel(requestMap.get("Label")); respMessage=MessageUtil.locationMessageToXml(locationMessage); } //视频消息 elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_VIDEO)){ VideoMessagevideoMessage=newVideoMessage(); videoMessage.setToUserName(fromUserName); videoMessage.setFromUserName(toUserName); videoMessage.setCreateTime(newDate().getTime()); videoMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_VIDEO); videoMessage.setMediaId(requestMap.get("MediaId")); videoMessage.setThumbMediaId(requestMap.get("ThumbMediaId")); respMessage=MessageUtil.videoMessageToXml(videoMessage); } //链接消息 elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_LINK)){ LinkMessagelinkMessage=newLinkMessage(); linkMessage.setToUserName(fromUserName); linkMessage.setFromUserName(toUserName); linkMessage.setCreateTime(newDate().getTime()); linkMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_LINK); linkMessage.setTitle(requestMap.get("Title")); linkMessage.setDescription(requestMap.get("Description")); linkMessage.setUrl(requestMap.get("Url")); respMessage=MessageUtil.linkMessageToXml(linkMessage); } //语音消息 elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_VOICE)){ VoiceMessagevoiceMessage=newVoiceMessage(); voiceMessage.setToUserName(fromUserName); voiceMessage.setFromUserName(toUserName); voiceMessage.setCreateTime(newDate().getTime()); voiceMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_VOICE); voiceMessage.setMediaId(requestMap.get("MediaId")); voiceMessage.setFormat(requestMap.get("Format")); respMessage=MessageUtil.voiceMessageToXml(voiceMessage); } //事件推送 elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_EVENT)){ //事件类型 StringeventType=requestMap.get("Event"); //订阅 if(eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)){ respContent="谢谢关注!"; } //取消订阅 elseif(eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)){ // System.out.println("取消订阅"); } elseif(eventType.equals(MessageUtil.EVENT_TYPE_CLICK)){ //自定义菜单消息处理 System.out.println("自定义菜单消息处理"); } } }catch(Exceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } returnrespMessage; } publicstaticStringgetMainMenu() { StringBufferbuffer=newStringBuffer(); buffer.append("您好,我是jon,请回复数字选择服务:").append("\n"); buffer.append("1、我的博客").append("\n"); buffer.append("2、歌曲点播").append("\n"); buffer.append("3、经典游戏").append("\n"); buffer.append("4、聊天打牌").append("\n\n"); buffer.append("回复"+"0"+"显示帮助菜单"); returnbuffer.toString(); } }
4)、MessageUtil.java帮助类,包括常量的定义和xml消息转换和处理
packagecn.jon.wechat.utils; importjava.io.InputStream; importjava.io.Writer; importjava.util.HashMap; importjava.util.List; importjava.util.Map; importjavax.servlet.http.HttpServletRequest; importorg.dom4j.Document; importorg.dom4j.Element; importorg.dom4j.io.SAXReader; importcn.jon.wechat.message.req.ImageMessage; importcn.jon.wechat.message.req.LinkMessage; importcn.jon.wechat.message.req.LocationMessage; importcn.jon.wechat.message.req.VideoMessage; importcn.jon.wechat.message.req.VoiceMessage; importcn.jon.wechat.message.resp.Article; importcn.jon.wechat.message.resp.MusicMessage; importcn.jon.wechat.message.resp.NewsMessage; importcn.jon.wechat.message.resp.TextMessage; importcom.thoughtworks.xstream.XStream; importcom.thoughtworks.xstream.core.util.QuickWriter; importcom.thoughtworks.xstream.io.HierarchicalStreamWriter; importcom.thoughtworks.xstream.io.xml.PrettyPrintWriter; importcom.thoughtworks.xstream.io.xml.XppDriver; /** *各种消息的处理类 *@authorjon */ publicclassMessageUtil{ /** *文本类型 */ publicstaticfinalStringMESSSAGE_TYPE_TEXT="text"; /** *音乐类型 */ publicstaticfinalStringMESSSAGE_TYPE_MUSIC="music"; /** *图文类型 */ publicstaticfinalStringMESSSAGE_TYPE_NEWS="news"; /** *视频类型 */ publicstaticfinalStringMESSSAGE_TYPE_VIDEO="video"; /** *图片类型 */ publicstaticfinalStringMESSSAGE_TYPE_IMAGE="image"; /** *链接类型 */ publicstaticfinalStringMESSSAGE_TYPE_LINK="link"; /** *地理位置类型 */ publicstaticfinalStringMESSSAGE_TYPE_LOCATION="location"; /** *音频类型 */ publicstaticfinalStringMESSSAGE_TYPE_VOICE="voice"; /** *推送类型 */ publicstaticfinalStringMESSSAGE_TYPE_EVENT="event"; /** *事件类型:subscribe(订阅) */ publicstaticfinalStringEVENT_TYPE_SUBSCRIBE="subscribe"; /** *事件类型:unsubscribe(取消订阅) */ publicstaticfinalStringEVENT_TYPE_UNSUBSCRIBE="unsubscribe"; /** *事件类型:click(自定义菜单点击事件) */ publicstaticfinalStringEVENT_TYPE_CLICK="CLICK"; /** *解析微信发来的请求XML */ @SuppressWarnings("unchecked") publicstaticMap<String,String>pareXml(HttpServletRequestrequest)throwsException{ //将解析的结果存储在HashMap中 Map<String,String>reqMap=newHashMap<String,String>(); //从request中取得输入流 InputStreaminputStream=request.getInputStream(); //读取输入流 SAXReaderreader=newSAXReader(); Documentdocument=reader.read(inputStream); //得到xml根元素 Elementroot=document.getRootElement(); //得到根元素的所有子节点 List<Element>elementList=root.elements(); //遍历所有的子节点取得信息类容 for(Elementelem:elementList){ reqMap.put(elem.getName(),elem.getText()); } //释放资源 inputStream.close(); inputStream=null; returnreqMap; } /** *响应消息转换成xml返回 *文本对象转换成xml */ publicstaticStringtextMessageToXml(TextMessagetextMessage){ xstream.alias("xml",textMessage.getClass()); returnxstream.toXML(textMessage); } /** *语音对象的转换成xml * */ publicstaticStringvoiceMessageToXml(VoiceMessagevoiceMessage){ xstream.alias("xml",voiceMessage.getClass()); returnxstream.toXML(voiceMessage); } /** *视频对象的转换成xml * */ publicstaticStringvideoMessageToXml(VideoMessagevideoMessage){ xstream.alias("xml",videoMessage.getClass()); returnxstream.toXML(videoMessage); } /** *音乐对象的转换成xml * */ publicstaticStringmusicMessageToXml(MusicMessagemusicMessage){ xstream.alias("xml",musicMessage.getClass()); returnxstream.toXML(musicMessage); } /** *图文对象转换成xml * */ publicstaticStringnewsMessageToXml(NewsMessagenewsMessage){ xstream.alias("xml",newsMessage.getClass()); xstream.alias("item",newArticle().getClass()); returnxstream.toXML(newsMessage); } /** *图片对象转换成xml * */ publicstaticStringimageMessageToXml(ImageMessageimageMessage) { xstream.alias("xml",imageMessage.getClass()); returnxstream.toXML(imageMessage); } /** *链接对象转换成xml * */ publicstaticStringlinkMessageToXml(LinkMessagelinkMessage) { xstream.alias("xml",linkMessage.getClass()); returnxstream.toXML(linkMessage); } /** *地理位置对象转换成xml * */ publicstaticStringlocationMessageToXml(LocationMessagelocationMessage) { xstream.alias("xml",locationMessage.getClass()); returnxstream.toXML(locationMessage); } /** *拓展xstream,使得支持CDATA块 * */ privatestaticXStreamxstream=newXStream(newXppDriver(){ publicHierarchicalStreamWritercreateWriter(Writerout){ returnnewPrettyPrintWriter(out){ //对所有的xml节点的转换都增加CDATA标记 booleancdata=true; @SuppressWarnings("unchecked") publicvoidstartNode(Stringname,Classclazz){ super.startNode(name,clazz); } protectedvoidwriteText(QuickWriterwriter,Stringtext){ if(cdata){ writer.write("<![CDATA["); writer.write(text); writer.write("]]>"); }else{ writer.write(text); } } }; } }); }
5)、BaseMessage.java消息基类(包括:开发者微信号、用户账户、创建时间、消息类型、消息ID变量),文本、视频、图片消息都会继承此基类,在此基础上扩展自己的变量,可根据开发者文档中的各种消息属性进行定义
packagecn.jon.wechat.message.req; /** *消息基类(普通用户-公众号) *@authorjon */ publicclassBaseMessage{ //开发者微信号 privateStringToUserName; //发送方账号(一个openId) privateStringFromUserName; //消息创建时间(整型) privatelongCreateTime; //消息类型(text/image/location/link...) privateStringMsgType; //消息id64位整型 privateStringMsgId; publicBaseMessage(){ super(); //TODOAuto-generatedconstructorstub } publicBaseMessage(StringtoUserName,StringfromUserName,longcreateTime, StringmsgType,StringmsgId){ super(); ToUserName=toUserName; FromUserName=fromUserName; CreateTime=createTime; MsgType=msgType; MsgId=msgId; } publicStringgetToUserName(){ returnToUserName; } publicvoidsetToUserName(StringtoUserName){ ToUserName=toUserName; } publicStringgetFromUserName(){ returnFromUserName; } publicvoidsetFromUserName(StringfromUserName){ FromUserName=fromUserName; } publiclonggetCreateTime(){ returnCreateTime; } publicvoidsetCreateTime(longcreateTime){ CreateTime=createTime; } publicStringgetMsgType(){ returnMsgType; } publicvoidsetMsgType(StringmsgType){ MsgType=msgType; } publicStringgetMsgId(){ returnMsgId; } publicvoidsetMsgId(StringmsgId){ MsgId=msgId; } }
6)、TextMessage.java文本消息,继承自5中基类,扩展内容属性
packagecn.jon.wechat.message.req; /** *文本消息 *@authorjon */ publicclassTextMessageextendsBaseMessage{ //消息内容 privateStringcontent; publicStringgetContent(){ returncontent; } publicvoidsetContent(Stringcontent){ this.content=content; } }
7)、ImageMessage.java图片消息
packagecn.jon.wechat.message.req; /** *图片消息 *@authorjon */ publicclassImageMessageextendsBaseMessage{ //图片链接 privateStringPicUrl; publicStringgetPicUrl(){ returnPicUrl; } publicvoidsetPicUrl(StringpicUrl){ PicUrl=picUrl; } }
8)、VideoMessage.java视频消息
packagecn.jon.wechat.message.req; publicclassVideoMessageextendsBaseMessage{ privateStringmediaId; privateStringthumbMediaId; publicStringgetMediaId(){ returnmediaId; } publicvoidsetMediaId(StringmediaId){ this.mediaId=mediaId; } publicStringgetThumbMediaId(){ returnthumbMediaId; } publicvoidsetThumbMediaId(StringthumbMediaId){ this.thumbMediaId=thumbMediaId; } }
其他消息类可根据开发者文档自行进行完成,另外,开发者也可以申请公众平台测试账号,对开发的相关内容进行测试。
本文已被整理到了《Android微信开发教程汇总》,《java微信开发教程汇总》欢迎大家学习阅读。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。