一直想尝试一下微信公众号开发,上上周开始弄的,碰到不少坑,如今把经验分析一下html
微信开发有公众平台和开放平台两种,公众平台是给关注用户推送信息用的,提供一些接口给开发者,开放平台是给成熟的app或网站提供接入、支付、分享的功能java
在公众平台上注册的帐号有三种:订阅号、服务号、企业号,通常我的只能申请订阅号,并且不能认证,遗憾的是公众平台的一些高级接口和开发者自定义菜单功能只开放给认证的用户git
我申请的是未认证的订阅号,很快就经过了,几乎没有什么门槛,不过开启开发者模式之后,就失去了自定义菜单的功能github
微信开放平台地址:https://mp.weixin.qq.comjson
微信开放平台开发文档:https://mp.weixin.qq.com/wiki服务器
要开启开发者模式,须要对服务器url进行接入认证微信
在接入认证的时候,微信会对URL发送get请求(以后接收用户消息时,微信会改成对URL发送post请求)微信开发
在基本配置页面,URL是服务器的地址,Token是约定好的一串字符串,EncodingAESKey是用于验证的字符串app
验证方法里面须要对三个参数作必定规则的运算,获得结果和echostr同样,而后返回,就能经过微信接入认证微信公众平台
示例代码:
/** * 接入验证 */ @ResponseBody @RequestMapping(method = {RequestMethod.GET }, produces = "application/json;charset=UTF-8") public String verifyAccess(VerifyAccessReq req) { try { if(!StringUtils.isEmpty(req.getEchostr())) { String token = Global.getConfig("wx.token"); String[] ArrTmp = {token, req.getTimestamp(), req.getNonce()}; //进行字典序排序 Arrays.sort(ArrTmp); StringBuffer sb = new StringBuffer(); for (int i = 0; i < ArrTmp.length; i++) { sb.append(ArrTmp[i]); } //进行sha1加密 String pwd = Encodes.Encrypt(sb.toString()); //若是相同就返回 if(!StringUtils.isEmpty(pwd) && pwd.equals(req.getSignature())) { log.info("认证经过"); return req.getEchostr(); } } } catch (Exception e) { log.debug("认证失败"); e.printStackTrace(); } log.info("认证失败"); return ""; }
接入指南:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319
用户消息是经过post在xml流里传过来的,先要解析成map对象:
/** * 解析微信发来的xml请求 * @param request * @return * @throws Exception */ @SuppressWarnings("unchecked") public static Map<String, String> parseXml(HttpServletRequest request) throws Exception { //将解析结果存储在HashMap中 Map<String, String> map = new HashMap<String, String>(); //从request中取得输入流 InputStream inputStream = request.getInputStream(); //读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); //获得xml根元素 Element root = document.getRootElement(); //获得根元素的全部子节点 List<Element> elementList = root.elements(); //遍历全部子节点 for (Element e : elementList) { map.put(e.getName(), e.getText()); } //释放资源 inputStream.close(); inputStream = null; return map; }
消息类型有文本消息、图片消息、语音消息、视频消息、地理位置消息、连接消息
目前我只用到文本消息:
//从流中获取xml数据转入map Map<String, String> reqMap = MessageUtil.parseXml(request); //获得接收消息实体 BaseMsgReq msgReq = new BaseMsgReq(); msgReq.setToUserName(reqMap.get("ToUserName")); msgReq.setFromUserName(reqMap.get("FromUserName")); msgReq.setCreateTime(reqMap.get("CreateTime")); msgReq.setMsgType(reqMap.get("MsgType")); msgReq.setMsgId(reqMap.get("MsgId")); msgReq.setContent(reqMap.get("Content")); msgReq.setEvent(reqMap.get("Event"));
收到用户消息,进过处理之后,公众号须要返回信息给用户,微信的回复消息是xml结构的,有约定的格式要求,好比文本消息:
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[你好]]></Content> </xml>
转换xml的示例代码:
/** * 文本消息对象转换成xml * @param textMsgRes * @return */ public static String textMessageToXml(TextMsgRes textMsgRes) { xstream.alias("xml", textMsgRes.getClass()); return xstream.toXML(textMsgRes); } /** * 接收消息对象转换成xml * @param msgReq * @return */ public static String msgReqToXml(BaseMsgReq msgReq, String content) { TextMsgRes textMsgRes = new TextMsgRes(); textMsgRes.setToUserName(msgReq.getFromUserName()); textMsgRes.setFromUserName(msgReq.getToUserName()); textMsgRes.setCreateTime(new Date().getTime()); textMsgRes.setMsgType("text"); textMsgRes.setContent(content); return textMessageToXml(textMsgRes); }
参考的教程:http://blog.csdn.net/u011466609/article/details/50886858
这两周作的,欢迎来玩