微信公众号开发001-接入服务器
2018-02-02 09:39
288 查看
1.首先阅读公众号开发API,(这里要说明下微信公众号的API里面有好多坑,在实际项目中遇到在一一介绍)
2.公众号接入服务器:(参考公众号API文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319)
3.接入服务器的后台实现:(设置服务器地址时微信会注定给服务器发起GET请求,而用户关注,发消息等微信会给服务器发送POST请求)
4.将MP_verify_HwltXWk6Drzcw66N.txt文件放置根目录下(如果放置位置不正确域名将无法设置成功),如下图位置:
5.配置域名,如下图:
接下来就可以开始我们的开发了
2.公众号接入服务器:(参考公众号API文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319)
3.接入服务器的后台实现:(设置服务器地址时微信会注定给服务器发起GET请求,而用户关注,发消息等微信会给服务器发送POST请求)
package com.deshangshidai.wechat.controller; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.deshangshidai.exceptions.CreateExceptionMessage; import com.deshangshidai.wechat.subscribe.util.TopayUtil; import com.deshangshidai.wechat.subscribe.util.WechatGlobalConfig; @Controller public class WechatCallBackApiController { private static Logger log=LoggerFactory.getLogger(WechatCallBackApiController.class); private String token=WechatGlobalConfig.SYSTEM_TOKEN;//令牌token @RequestMapping("/") public void getSystemToken(HttpServletRequest req, HttpServletResponse resp) throws IOException{ log.info("进入效验系统方法"); req.setCharacterEncoding("UTF-8"); //微信服务器POST消息时用的是UTF-8编码,在接收时也要用同样的编码,否则中文会乱码; resp.setCharacterEncoding("UTF-8"); //在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上; boolean isGet = req.getMethod().toLowerCase().equals("get"); //请求方法是否是get try { //验证消息的确来自微信服务器 if(isGet){ log.info("进入get方法"); // 微信加密签名 String signature = req.getParameter("signature"); // 随机字符串 String echostr = req.getParameter("echostr"); // 时间戳 String timestamp = req.getParameter("timestamp"); // 随机数 String nonce = req.getParameter("nonce"); String[] str = { token, timestamp, nonce }; Arrays.sort(str); // 字典序排序 String bigStr = str[0] + str[1] + str[2]; MessageDigest md = null; String result=""; try { md = MessageDigest.getInstance("SHA-1"); byte [] digest=md.digest(bigStr.toString().getBytes()); result = byteTostr(digest); // 确认请求来至微信 if (result.equals(signature)) { resp.getWriter().print(echostr); } } catch (NoSuchAlgorithmException e) { CreateExceptionMessage.getMessage(e); resp.getWriter().print(CreateExceptionMessage.getMessage(e)); } }else{//post方法 log.info("进入post方法"); String respMessage = "异常消息!"; //自动回复消息事件 respMessage = TopayUtil.wxToMessage(req); resp.getWriter().print(respMessage); } } catch (Exception e) { CreateExceptionMessage.getMessage(e); resp.getWriter().print(CreateExceptionMessage.getMessage(e)); } } public static String byteTostr(byte[] str){ String strDigest = ""; for (int i = 0; i < str.length; i++) { strDigest+= byteToHexStr(str[i]); } return strDigest; } //将一个字节转换成十六进制的字符串 public static String byteToHexStr(byte mByte){ char [] Digest ={'0','1', '2', '3', '4', '5', '6','7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; char[] temp = new char[2]; temp[0] = Digest[(mByte>>4)&0x0f]; temp [1]= Digest[mByte&0x0f]; String s = new String(temp); return s; } }
/** * 自动回复消息util */ package com.deshangshidai.wechat.subscribe.util; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.deshangshidai.message.ImgPath; import com.deshangshidai.utils.FtpUtils; import com.deshangshidai.wechat.subscribe.message.resp.Article; import com.deshangshidai.wechat.subscribe.message.resp.NewsMessage; import com.deshangshidai.wechat.subscribe.message.resp.TextMessage; /** * <p>Title: </p> * <p>Description: </p> * <p>Company: 德商时代</p> * @author:卫凯强 * @date 2017年11月14日 下午4:37:01 **/ public class TopayUtil { private static Logger logger=LoggerFactory.getLogger(TopayUtil.class); public static String wxToMessage(HttpServletRequest req){ logger.info("进入自动回复消息方法"); String respMessage = null; try { 4000 Map<String, String> requestMap = MessageUtil.parseXml(req); // 发送方帐号(open_id) String fromUserName = requestMap.get("FromUserName"); // 公众帐号 String toUserName = requestMap.get("ToUserName"); // 消息类型 String msgType = requestMap.get("MsgType"); // 消息内容 //String content = requestMap.get("Content"); // 记录日志 logger.info("FromUserName is:" + fromUserName + ", ToUserName is:" + toUserName + ", MsgType is:" + msgType); // 文本消息 if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) { logger.info("进入文本回复方法"); //这里根据关键字执行相应的逻辑,只有你想不到的,没有做不到的 TextMessage text = new TextMessage(); text.setContent("欢迎关注《德商掌中城》官方微信!"); text.setToUserName(fromUserName); text.setFromUserName(toUserName); text.setCreateTime(new Date().getTime() + ""); text.setMsgType(msgType); respMessage = MessageUtil.textMessageToXml(text); } else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) { logger.info("进入关注事件方法"); String eventType = requestMap.get("Event");// 事件类型 // 订阅 if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) { logger.info("进入关注回复方法"); NewsMessage newMsg=new NewsMessage(); newMsg.setToUserName(fromUserName); newMsg.setFromUserName(toUserName); newMsg.setCreateTime(new Date().getTime() + ""); newMsg.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS); Article article=new Article(); article.setDescription("欢迎关注《德商掌中城》官方微信"); //图文消息的描述 article.setPicUrl(FtpUtils.IMG_URL+ImgPath.WxBannerImg+"/"+WechatGlobalConfig.guanzhutu); //图文消息图片地址 article.setTitle("德商掌中城"); //图文消息标题 article.setUrl(FileUtil.getHttp("off_line")+FileUtil.getHttp("domain_name")+FileUtil.get("menuOneUrl")); //图文url链接 List<Article> list=new ArrayList<Article>(); list.add(article); //这里发送的是单图文,如果需要发送多图文则在这里list中加入多个Article即可! newMsg.setArticleCount(list.size()); newMsg.setArticles(list); respMessage = MessageUtil.newsMessageToXml(newMsg); } } else if(msgType.equals(MessageUtil.RESP_MESSAGE_TYPE_VOICE)){ TextMessage text = new TextMessage(); text.setContent("您好,我是德商小管家,请联系我们的客服"); respMessage = MessageUtil.textMessageToXml(text); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return respMessage; } }
/** * 消息类型util */ package com.deshangshidai.wechat.subscribe.util; import java.io.InputStream; import java.io.Writer; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import com.deshangshidai.wechat.subscribe.message.resp.Article; import com.deshangshidai.wechat.subscribe.message.resp.ImageMessage; import com.deshangshidai.wechat.subscribe.message.resp.MusicMessage; import com.deshangshidai.wechat.subscribe.message.resp.NewsMessage; import com.deshangshidai.wechat.subscribe.message.resp.TextMessage; import com.deshangshidai.wechat.subscribe.message.resp.VideoMessage; import com.deshangshidai.wechat.subscribe.message.resp.VoiceMessage; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.core.util.QuickWriter; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; import com.thoughtworks.xstream.io.xml.XppDriver; public class MessageUtil { /** * 会员openId */ public static final String _USER_="openId"; /** * 返回消息类型:文本 */ public static final String RESP_MESSAGE_TYPE_TEXT = "text"; /** * 返回消息类型:音乐 */ public static final String RESP_MESSAGE_TYPE_MUSIC = "music"; /** * 返回消息类型:图文 */ public static final String RESP_MESSAGE_TYPE_NEWS = "news"; /** * 返回消息类型:图片 */ public static final String RESP_MESSAGE_TYPE_IMAGE = "image"; /** * 返回消息类型:语音 */ public static final String RESP_MESSAGE_TYPE_VOICE = "voice"; /** * 返回消息类型:视频 */ public static final String RESP_MESSAGE_TYPE_VIDEO = "video"; /** * 请求消息类型:文本 */ public static final String REQ_MESSAGE_TYPE_TEXT = "text"; /** * 请求消息类型:图片 */ public static final String REQ_MESSAGE_TYPE_IMAGE = "image"; /** * 请求消息类型:链接 */ public static final String REQ_MESSAGE_TYPE_LINK = "link"; /** * 请求消息类型:地理位置 */ public static final String REQ_MESSAGE_TYPE_LOCATION = "location"; /** * 请求消息类型:音频 */ public static final String REQ_MESSAGE_TYPE_VOICE = "voice"; /** * 请求消息类型:视频 */ public static final String REQ_MESSAGE_TYPE_VIDEO = "video"; /** * 请求消息类型:推送 */ public static final String REQ_MESSAGE_TYPE_EVENT = "event"; /** * 事件类型:subscribe(订阅) */ public static final String EVENT_TYPE_SUBSCRIBE = "subscribe"; /** * 事件类型:unsubscribe(取消订阅) */ public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe"; /** * 事件类型:CLICK(自定义菜单点击事件) */ public static final String EVENT_TYPE_CLICK = "CLICK"; /** * 事件类型:VIEW(自定义菜单URl视图) */ public static final String EVENT_TYPE_VIEW = "VIEW"; /** * 事件类型:LOCATION(上报地理位置事件) */ public static final String EVENT_TYPE_LOCATION = "LOCATION"; /** * 事件类型:SCAN(二维码扫描事件) */ public static final String EVENT_TYPE_SCAN = "SCAN"; /** *菜单view类型 */ public static final String MENU_TYPE_VIEW="2"; /** * 菜单click类型 */ public static final String MENU_TYPE_CLICK="1"; /** * @Description: 解析微信发来的请求(XML) * @param @param request * @param @return * @param @throws Exception */ 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; } /** * @Description: 文本消息对象转换成xml * @param @param textMessage * @param @return */ public static String textMessageToXml(TextMessage textMessage) { xstream.alias("xml", textMessage.getClass()); return xstream.toXML(textMessage); } /** * @Description: 图文消息对象转换成xml * @param @param newsMessage * @param @return */ public static String newsMessageToXml(NewsMessage newsMessage) { xstream.alias("xml", newsMessage.getClass()); xstream.alias("item", new Article().getClass()); return xstream.toXML(newsMessage); } /** * @Description: 图片消息对象转换成xml * @param @param imageMessage * @param @return */ public static String imageMessageToXml(ImageMessage imageMessage) { xstream.alias("xml", imageMessage.getClass()); return xstream.toXML(imageMessage); } /** * @Description: 语音消息对象转换成xml * @param @param voiceMessage * @param @return */ public static String voiceMessageToXml(VoiceMessage voiceMessage) { xstream.alias("xml", voiceMessage.getClass()); return xstream.toXML(voiceMessage); } /** * @Description: 视频消息对象转换成xml * @param @param videoMessage * @param @return */ public static String videoMessageToXml(VideoMessage videoMessage) { xstream.alias("xml", videoMessage.getClass()); return xstream.toXML(videoMessage); } /** * @Description: 音乐消息对象转换成xml * @param @param musicMessage * @param @return */ public static String musicMessageToXml(MusicMessage musicMessage) { xstream.alias("xml", musicMessage.getClass()); return xstream.toXML(musicMessage); } /** * 对象到xml的处理 */ private static XStream xstream = new XStream(new XppDriver() { public HierarchicalStreamWriter createWriter(Writer out) { return new PrettyPrintWriter(out) { // 对所有的xml节点的转换都增加CDATA标记 boolean cdata = true; @SuppressWarnings("rawtypes") public void startNode(String name, Class clzz) { super.startNode(name, clzz); } protected void writeText(QuickWriter writer, String text) { if (cdata) { writer.write("<![CDATA["); writer.write(text); writer.write("]]>"); } else { writer.write(text); } } }; } }); }
4.将MP_verify_HwltXWk6Drzcw66N.txt文件放置根目录下(如果放置位置不正确域名将无法设置成功),如下图位置:
5.配置域名,如下图:
接下来就可以开始我们的开发了
相关文章推荐
- java微信公众号开发 - 微信服务器的接入和验证
- 微信公众号开发--开发服务器接入微信服务器
- 微信公众号开发部署服务器
- 微信公众号开发-自定义菜单中链接用MUI前端框架写的网页以及发布到SAE服务器
- nodejs微信公众号开发第一步(接入指南)--wechat模块
- 微信公众号开发之测试号接口接入指南
- 使用C# .net开发微信公众号之服务器URL配置
- java微信公众号开发01 - 微信服务器的接入和验证
- 微信开发 公众号接入服务器
- C#/ASP.NET MVC微信公众号接口开发之从零开发(一) 接入微信公众平台
- 微信公众号开发一(接入配置)
- 微信公众号开发(一)微信验证开发者服务器接口
- JAVA微信公众号开发第1篇之环境配置与开发接入
- 微信公众号开发-服务器配置、关注后收到欢迎消息
- 阿里云服务器开发微信公众号,配置的时候总是TOKEN验证失败
- 小白版微信公众号开发第一节---服务器配置
- 微信公众号开发:用从微信服务器下载图片资源
- 微信公众号开发(一)服务器配置
- 微信公众号从头开发(接入与消息)