微信公众平台开发教程Java版

上传人:痛*** 文档编号:97364146 上传时间:2022-05-27 格式:DOC 页数:43 大小:1.28MB
收藏 版权申诉 举报 下载
微信公众平台开发教程Java版_第1页
第1页 / 共43页
微信公众平台开发教程Java版_第2页
第2页 / 共43页
微信公众平台开发教程Java版_第3页
第3页 / 共43页
资源描述:

《微信公众平台开发教程Java版》由会员分享,可在线阅读,更多相关《微信公众平台开发教程Java版(43页珍藏版)》请在装配图网上搜索。

1、.微信公众平台开发教程Java版一、 环境准备篇准备写系列博客,记录下我的微信公众平台学习记录,也为那些摸索中的开发者提供点参考。希望与大家共同进步。微信3.0的时候我开场做微信公众账号,那时候没时间研究开发,先用的是编辑者模式,后用开发者模式,托管于第三方。一直想自己写个效劳端来实现个人定制化的需求。废话不多说,进入正题。想要开发微信公众平台需要一些环境一、申请微信公众账号 这个就不用废话了。附上地址: s:/mp.wei*in.qq./cgi-bin/readtemplate?t=w*m2-realname-reg_tmpl&lang=zh_ 现在申请好严格的说,3.0的时候申请都不需要拍

2、照什么的。 友情提示: 1、微信公众账号的名字一旦申请,则不能更改。取名请慎重!2、一个只能申请两个公众号 3、公众号分两种:订阅号和效劳号 订阅号可一天群发一次消息,目前不能申请自定义菜单。发送的消息将显示在“订阅号文件夹中,适合媒体等提供咨询效劳的公众号。 效劳号一个月只能群发一条消息,能申请自定义菜单,发送的消息会显示在用户的聊天列表中,并会提醒用户新消息。适合为用户提供效劳的公众号二、外网效劳器 你需要一台外网效劳器,来发布你的代码,用于接收处理用户发送的请求。 如果没有的话,也不用担忧。可以使用百度BAE,或者是sina sae,国外比较多的是用google的gae。 google

3、gae支持的语言很多。但是在国经常不了,不推荐使用。 百度Bae 支持java和php完全免费,百度对于资源方面还是一向很大方的,赞一个,哈哈 sina sae 支持java,php,python可免费使用半年,收费的,但很廉价三、至少会一种语言 java,php,asp,python等,至少得会一样!接下来的文章中我会用java做事例来做微信公众平台的开发二、 接口配置微信公众账号申请完成后,默认开启的是编辑模式。我们需要修改为开发模式。登陆微信公众平台?功能?高级功能先关闭 编辑模式,再开启 开发模式。申请成为开发者,如果是效劳号,需要则会有开发者凭证信息如图如果是订阅号,则只显示效劳器配

4、置。下一步就是配置接口效劳器了。在公众平台的高级功能 开发模式页,点击“成为开发者按钮,填写URL和Token,其中URL是开发者用来接收微信效劳器数据的接口URL。这就是我们开发的程序,并部署到公网上了Token 官网描述:可由开发者任意填写,用作生成签名该Token会和接口URL中包含的Token进展比对,从而验证平安性。总之就是你的程序里面写的token和这里填入的token要一致。还没有url和token.首先需要新建一个java web工程。接下来就要看看验证url和token了。下面是官网的描述,已经写的很清楚了核心实现方式就是将三个参数排序,拼接成字符串进展sha1加密,然后与s

5、ignature比较官网也给了实例,是php的,我们只需要装换成java就可以了。private function checkSignature() $signature = $_GETsignature; $timestamp = $_GETtimestamp; $nonce = $_GETnonce;$token = TOKEN;$tmpArr = array($token, $timestamp, $nonce);sort($tmpArr);$tmpStr = implode( $tmpArr );$tmpStr = sha1( $tmpStr );if( $tmpStr = $sign

6、ature )return true;elsereturn false;java代码 我的 Wei*inController 类 我的工程架构是基于spring3.0的,用到了注解。当get请求的时候会执行get方法,post请求的时候会执行post方法,分别来处理不同的请求,各位也可用servlet等去实现,原理都一样package .ifp.wei*in.controller;import java.io.IOE*ception;import java.io.PrintWriter;import java.io.UnsupportedEncodingE*ception;import jav

7、a*.annotation.Resource;import java*.servlet. . ServletRequest;import java*.servlet. . ServletResponse;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import .ifp.wei*in.biz.cor

8、e.CoreService;import .ifp.wei*in.util.SignUtil;ControllerRequestMapping(/wei*inCore)public class Wei*inController Resource(name=coreService)private CoreService coreService;RequestMapping(method = RequestMethod.GET)public void get( ServletRequest request, ServletResponse response) / 微信加密签名,signature结

9、合了开发者填写的token参数和请求中的timestamp参数、nonce参数。String signature = request.getParameter(signature);/ 时间戳String timestamp = request.getParameter(timestamp);/ 随机数String nonce = request.getParameter(nonce);/ 随机字符串String echostr = request.getParameter(echostr);PrintWriter out = null;try out = response.getWriter

10、();/ 通过检验signature对请求进展校验,假设校验成功则原样返回echostr,否则接入失败if (SignUtil.checkSignature(signature, timestamp, nonce) out.print(echostr); catch (IOE*ception e) e.printStackTrace(); finally out.close();out = null;RequestMapping(method = RequestMethod.POST)public void post( ServletRequest request, ServletRespon

11、se response) /暂时空着,在这里可处理用户请求上面类中用到了SignUtil 类package .ifp.wei*in.util;import java.security.MessageDigest;import java.security.NoSuchAlgorithmE*ception;import java.util.Arrays;import .ifp.wei*in.constant.Constant;/* * 验证签名 * */public class SignUtil /* * 验证签名 * param signature * param timestamp * par

12、am nonce * return */public static boolean checkSignature(String signature, String timestamp, String nonce) String arr = new String Constant.TOKEN, timestamp, nonce ;/ 将token、timestamp、nonce三个参数进展字典排序Arrays.sort(arr);StringBuilder content = new StringBuilder();for (int i = 0; i arr.length; i+) conten

13、t.append(arri);MessageDigest md = null;String tmpStr = null;try md = MessageDigest.getInstance(SHA-1);/ 将三个参数字符串拼接成一个字符串进展sha1加密byte digest = md.digest(content.toString().getBytes();tmpStr = byteToStr(digest); catch (NoSuchAlgorithmE*ception e) e.printStackTrace();content = null;/ 将sha1加密后的字符串可与sign

14、ature比照return tmpStr != null ? tmpStr.equals(signature.toUpperCase() : false;/* * 将字节数组转换为十六进制字符串 * * param byteArray * return*/private static String byteToStr(byte byteArray) String strDigest = ;for (int i = 0; i 4) & 0*0F;tempArr1 = DigitmByte & 0*0F;String s = new String(tempArr);return s;我们看到che

15、ckSignature 这个方法里使用到了Constant.TOKEN ,这个token,我声明的一个常量。要与微信配置接口里面的token值一样/* 与接口配置信息中的Token要一致*/public static String TOKEN = infopower;也贴上web.*ml的配置,我的后缀是.html 的请求都交给DispatcherServlet了。wei*inHelpconte*tConfigLocationclasspath:/applicationConte*t.*mllog4jConfigLocationclasspath:/properties/log4j.prope

16、rtiesorg.springframework.web.util.Log4jConfigListenerencodingFilterorg.springframework.web.filter.CharacterEncodingFilterencodingUTF-8encodingFilter/*spring 容器的监听器org.springframework.web.conte*t.Conte*tLoaderListeneractionvletaction*.htmlinde*.jsp我们的代码已经写完了,请求地址试试什么都没有显示,看看后台报空指针异常别担忧,我们的代码没问题。因为直接地

17、址,默认是get请求,而什么参数都没有传给后台,当然会报空指针前台没有异常,是因为我做了异常处理。ok接下来就是把代码打成war包发布到外网。然后填入相应的url和token,接口的配置就完成了。注意1:一定要发布war包到外网,配置外网的url,有些开发者配置的是ip是localhost,那肯定是不行的啦。 如果没有外网环境,请看我的第一篇,环境准备,里面有介绍可以使用百度baetuposky.iteye./blog/2021583注意2:开发模式一定要开启,不然配置了url和token也没用,我犯过这个错,嘿嘿。三、 消息接收和发送前面两章已经介绍了如何接入微信公众平台,这一章说说消息的接

18、收和发送可以先了解公众平台的消息api接口接收消息,发送消息mp.wei*in.qq./wiki/inde*.php接收消息当普通微信用户向公众账号发消息时,微信效劳器将POST消息的*ML数据包到开发者填写的URL上。mp.wei*in.qq./wiki/inde*.php?title=%E6%8E%A5%E6%94%B6%E6%99%AE%E9%80%9A%E6%B6%88%E6%81%AF接收的消息类型有6种,分别为: 1文本消息 2图片消息 3语音消息 4视频消息 5地理位置消息 6消息可以根据官方的api提供的字段建立对应的实体类如:文本消息有很多属性是所有消息类型都需要的,可以把这

19、些信息提取出来建立一个基类package .ifp.wei*in.entity.Message.req;/* * 消息基类用户 - 公众 * */public class BaseMessage /* * 开发者微信号 */private String ToUserName;/* * 发送方一个OpenID */private String FromUserName;/* * 消息创立时间 整型 */private long CreateTime;/* * 消息类型 te*t、image、location、link */private String MsgType;/* * 消息id,64位整

20、型 */private long MsgId;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 long getCreateTime() ret

21、urn CreateTime;public void setCreateTime(long createTime) CreateTime = createTime;public String getMsgType() return MsgType;public void setMsgType(String msgType) MsgType = msgType;public long getMsgId() return MsgId;public void setMsgId(long msgId) MsgId = msgId;接收的文本消息package .ifp.wei*in.entity.Me

22、ssage.req;/* * 文本消息 */public class Te*tMessage e*tends BaseMessage /* * 回复的消息容 */private String Content;public String getContent() return Content;public void setContent(String content) Content = content;接收的图片消息package .ifp.wei*in.entity.Message.req;public class ImageMessage e*tends BaseMessageprivat

23、e String picUrl;public String getPicUrl() return picUrl;public void setPicUrl(String picUrl) this.picUrl = picUrl;接收的消息package .ifp.wei*in.entity.Message.req;public class LinkMessage e*tends BaseMessage /* * 消息标题 */private String Title;/* * 消息描述 */private String Description;/* * 消息 */private String

24、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 getUrl() return Url;public void setUrl(String url) Url = url;接收的语音消息pack

25、age .ifp.wei*in.entity.Message.req;/* * 语音消息 * * author Caspar * */public class VoiceMessage e*tends BaseMessage /* * 媒体ID */private String MediaId;/* * 语音格式 */private String Format;public String getMediaId() return MediaId;public void setMediaId(String mediaId) MediaId = mediaId;public String getFo

26、rmat() return Format;public void setFormat(String format) Format = format;接收的地理位置消息package .ifp.wei*in.entity.Message.req;/* * 位置消息 * * author caspar * */public class LocationMessage e*tends BaseMessage /* * 地理位置维度 */private String Location_*;/* * 地理位置经度 */private String Location_Y;/* * 地图缩放大小 */pri

27、vate String Scale;/* * 地理位置信息 */private String Label;public String getLocation_*() return Location_*;public void setLocation_*(String location_*) Location_* = location_*;public String getLocation_Y() return Location_Y;public void setLocation_Y(String location_Y) Location_Y = location_Y;public String

28、 getScale() return Scale;public void setScale(String scale) Scale = scale;public String getLabel() return Label;public void setLabel(String label) Label = label;发送被动响应消息对于每一个POST请求,开发者在响应包Get中返回特定*ML构造,对该消息进展响应现支持回复文本、图片、图文、语音、视频、音乐。请注意,回复图片等多媒体消息时需要预先上传多媒体文件到微信效劳器,只支持认证效劳号。同样,建立响应消息的对应实体类 也把公共的属性提取

29、出来,封装成基类 响应消息的基类package .ifp.wei*in.entity.Message.resp;/* * 消息基类公众 - 用户 */public class BaseMessage /* * 接收方收到的OpenID */private String ToUserName;/* * 开发者微信号 */private String FromUserName;/* * 消息创立时间 整型 */private long CreateTime;/* * 消息类型 */private String MsgType;/* * 位0*0001被标志时,星标刚收到的消息 */private

30、int FuncFlag;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 long getCreateTime() return Create

31、Time;public void setCreateTime(long createTime) CreateTime = createTime;public String getMsgType() return MsgType;public void setMsgType(String msgType) MsgType = msgType;public int getFuncFlag() return FuncFlag;public void setFuncFlag(int funcFlag) FuncFlag = funcFlag; 响应文本消息package .ifp.wei*in.ent

32、ity.Message.resp;/* * 文本消息 */public class Te*tMessage e*tends BaseMessage /* * 回复的消息容 */private String Content;public String getContent() return Content;public void setContent(String content) Content = content;响应图文消息package .ifp.wei*in.entity.Message.resp;import java.util.List;/* * 多图文消息, * 单图文的时候 A

33、rticles 只放一个就行了 * author Caspar.chen */public class NewsMessage e*tends BaseMessage /* * 图文消息个数,限制为10条以 */private int ArticleCount;/* * 多条图文消息信息,默认第一个item为大图 */private List Articles;public int getArticleCount() return ArticleCount;public void setArticleCount(int articleCount) ArticleCount = articleC

34、ount;public List getArticles() return Articles;public void setArticles(List articles) Articles = articles;图文消息的定义package .ifp.wei*in.entity.Message.resp;/* * 图文消息 * */public class Article /* * 图文消息名称 */private String Title;/* * 图文消息描述 */private String Description;/* * 图片,支持JPG、PNG格式, * 较好的效果为大图640*3

35、20,小图80*80 */private String PicUrl;/* * 点击图文消息跳转 */private String Url;public String getTitle() return Title;public void setTitle(String title) Title = title;public String getDescription() return null = Description ? : Description;public void setDescription(String description) Description = descripti

36、on;public String getPicUrl() return null = PicUrl ? : PicUrl;public void setPicUrl(String picUrl) PicUrl = picUrl;public String getUrl() return null = Url ? : Url;public void setUrl(String url) Url = url;响应音乐消息package .ifp.wei*in.entity.Message.resp;/* * 音乐消息 */public class MusicMessage e*tends Base

37、Message /* * 音乐 */private Music Music;public Music getMusic() return Music;public void setMusic(Music music) Music = music;音乐消息的定义package .ifp.wei*in.entity.Message.resp;/* * 音乐消息 */public class Music /* * 音乐名称 */private String Title;/* * 音乐描述 */private String Description;/* * 音乐 */private String Mu

38、sicUrl;/* * 高质量音乐,WIFI环境优先使用该播放音乐 */private String HQMusicUrl;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()

39、return MusicUrl;public void setMusicUrl(String musicUrl) MusicUrl = musicUrl;public String getHQMusicUrl() return HQMusicUrl;public void setHQMusicUrl(String musicUrl) HQMusicUrl = musicUrl;构建好之后的工程构造图为到这里,请求消息和响应消息的实体类都定义好了解析请求消息用户向微信公众平台发送消息后,微信公众平台会通过post请求发送给我们。上一章中Wei*inController 类的post方法我们空着现

40、在我们要在这里处理用户请求了。因为微信的发送和接收都是用*ml格式的,所以我们需要处理请求过来的*ml格式。发送的时候也需要转化成*ml格式再发送给微信,所以封装了消息处理的工具类,用到dome4j和*stream两个jar包package .ifp.wei*in.util;import java.io.InputStream;import java.io.Writer;import java.util.HashMap;import java.util.List;import java.util.Map;import java*.servlet. . ServletRequest;import

41、 org.dom4j.Document;import org.dom4j.Element;import org.dom4j.io.SA*Reader;import .ifp.wei*in.entity.Message.resp.Article;import .ifp.wei*in.entity.Message.resp.MusicMessage;import .ifp.wei*in.entity.Message.resp.NewsMessage;import .ifp.wei*in.entity.Message.resp.Te*tMessage;import .thoughtworks.*st

42、ream.*Stream;import .thoughtworks.*stream.core.util.QuickWriter;import .thoughtworks.*stream.io.HierarchicalStreamWriter;ter;import .thoughtworks.*stream.io.*ml.*ppDriver;/* * 消息工具类 * */public class MessageUtil /* * 解析微信发来的请求*ML * * param request * return * throws E*ception */public static Map parse

43、*ml( ServletRequest request) throws E*ception / 将解析结果存储在HashMap中Map map = new HashMap();/ 从request中取得输入流InputStream inputStream = request.getInputStream();/ 读取输入流SA*Reader reader = new SA*Reader();Document document = reader.read(inputStream);/ 得到*ml根元素Element root = document.getRootElement();/ 得到根元素

44、的所有子节点SuppressWarnings(unchecked)List elementList = root.elements();/ 遍历所有子节点for (Element e : elementList)map.put(e.getName(), e.getTe*t();/ 释放资源inputStream.close();inputStream = null;return map;/* * 文本消息对象转换成*ml * * param te*tMessage 文本消息对象 * return *ml */public static String te*tMessageTo*ml(Te*tM

45、essage te*tMessage) *stream.alias(*ml, te*tMessage.getClass();return *stream.to*ML(te*tMessage);/* * 音乐消息对象转换成*ml * * param musicMessage 音乐消息对象 * return *ml */public static String musicMessageTo*ml(MusicMessage musicMessage) *stream.alias(*ml, musicMessage.getClass();return *stream.to*ML(musicMessag

46、e);/* * 图文消息对象转换成*ml * * param newsMessage 图文消息对象 * return *ml */public static String newsMessageTo*ml(NewsMessage newsMessage) *stream.alias(*ml, newsMessage.getClass();*stream.alias(item, new Article().getClass();return *stream.to*ML(newsMessage);/* * 扩展*stream,使其支持CDATA块 * */private static *Strea

47、m *stream = new *Stream(new *ppDriver() public HierarchicalStreamWriter createWriter(Writer out) return new PrettyPrintWriter(out) / 对所有*ml节点的转换都增加CDATA标记boolean cdata = true;protected void writeTe*t(QuickWriter writer, String te*t) if (cdata) writer.write(); else writer.write(te*t););接下来在处理业务逻辑,建立一

48、个接收并响应消息的service类,并针对用户输入的1或2回复不同的信息给用户package .ifp.wei*in.biz.core.impl;import java.util.Date;import java.util.Map;import java*.servlet. . ServletRequest;ogger;import org.springframework.stereotype.Service;import .ifp.wei*in.biz.core.CoreService;import .ifp.wei*in.constant.Constant;import .ifp.wei*

49、in.entity.Message.resp.Te*tMessage;import .ifp.wei*in.util.MessageUtil;Service(coreService)public class CoreServiceImpl implements CoreServicepublic static Logger log = Logger.getLogger(CoreServiceImpl.class);Overridepublic String processRequest( ServletRequest request) String respMessage = null;try

50、 / *ml请求解析Map requestMap = MessageUtil.parse*ml(request);/ 发送方open_idString fromUserName = requestMap.get(FromUserName);/ 公众String toUserName = requestMap.get(ToUserName);/ 消息类型String msgType = requestMap.get(MsgType);Te*tMessage te*tMessage = new Te*tMessage();te*tMessage.setToUserName(fromUserName);te*tMessage.setFromUserName(toUserName);te*tMessage.setCreateTime(new Date().getTime();te*tMessage.setMsgType(Constant.RESP_MESSAGE_TYPE_TE*T);te*tMessage.setFuncFlag(0);/ 文本消息if (msgType.equals(Constant.REQ_MESSAGE_TYPE_TE*T) / 接收用户发送的文本消息容String content = requestMap.get(Content);

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!