本文共 25043 字,大约阅读时间需要 83 分钟。
接入微信公众平台开发,开发者需要按照如下步骤完成:
1、填写服务器配置2、验证服务器地址的有效性3、依据接口文档实现业务逻辑 好我们就开始: 1.登录微信公众平台,进入基本配置
修改配置,将自己的服务器的URL地址,配置在此处:
填写完成后,【先不用 提交】,先进行第二步 服务器端代码的配置
注意:
如果想使用 自定义菜单等相关接口权限,需要注意:
可以看到 个人订阅号是没有 使用自定义菜单的相关接口能力的,如果需要使用的话,需要注册服务号或使用测试号:
那么 在服务器端代码中使用的 测试AppId/Secret/Token等都需要重新设置为测试号的相关信息!
2.服务器端配置相关
服务器端相关代码 思路:
1>首先搭建web项目,使用maven管理架包,项目架构用spring+spring MVC+hibernate,pom.xml文件中,关于微信端开发的配置就是,就是使用项目使用java进行微信端开发
com.github.binarywang weixin-java-common 2.2.0 com.github.binarywang weixin-java-mp 2.2.0
完整pom.xml文件信息
12 4.0.0 3com.sxd.wx1 4wxSecond 50.0.1-SNAPSHOT 6war 78 17 189 1610 15maven-war-plugin 1112 143.0 1319 23 24UTF-8 204.1.4.RELEASE 214.3.8.Final 2225 26 28227 31 32javax.persistence 28persistence-api 291.0 3033 37 38 39commons-codec 34commons-codec 351.10 3640 44 45 46 47 48 49dom4j 41dom4j 421.6.1 4350 54 55com.github.binarywang 51weixin-java-common 522.2.0 5356 60 61 62 63com.github.binarywang 57weixin-java-mp 582.2.0 5964 69 70 71junit 65junit 664.12 67test 6872 76 77 78com.github.pagehelper 73pagehelper 744.1.4 7579 83 84org.springframework 80spring-core 81${spring.version} 8285 89 90org.springframework 86spring-beans 87${spring.version} 8891 95 96org.springframework 92spring-context 93${spring.version} 9497 101 102org.springframework 98spring-tx 99${spring.version} 100103 107 108org.springframework 104spring-web 105${spring.version} 106109 114 115 116org.springframework 110spring-test 111${spring.version} 112test 113117 121 122org.springframework 118spring-webmvc 119${spring.version} 120123 127 128cglib 124cglib 1252.2.2 126129 133 134 135org.springframework 130spring-orm 131${spring.version} 132136 140 141org.hibernate 137hibernate-core 138${hibernate.version} 139142 146 147 148org.hibernate 143hibernate-ehcache 144${hibernate.version} 145149 153 154 155net.sf.ehcache 150ehcache 1512.9.0 152156 160 161 162log4j 157log4j 1581.2.17 159163 167 168 169mysql 164mysql-connector-java 1655.1.34 166170 174 175 176 177 178com.mchange 171c3p0 1720.9.5-pre10 173179 183 184com.fasterxml.jackson.core 180jackson-core 1812.8.1 182185 189 190 191com.fasterxml.jackson.core 186jackson-annotations 1872.8.1 188192 206 207 208com.fasterxml.jackson.core 193jackson-databind 1942.8.1 195196 205197 200jackson-core 198com.fasterxml.jackson.core 199201 204jackson-annotations 202com.fasterxml.jackson.core 203209 213 214com.google.code.gson 210gson 2112.7 212215 220 221net.sf.json-lib 216json-lib 2172.4 218jdk15 219222 226commons-lang 223commons-lang 2242.5 225227 231commons-beanutils 228commons-beanutils 2291.9.2 230232 236commons-collections 233commons-collections 2343.2.1 235237 241 242 243commons-logging 238commons-logging 2391.2 240244 248 249 250org.aspectj 245aspectjweaver 2461.8.4 247251 256 257javax.servlet 252servlet-api 2533.0-alpha-1 254provided 255258 262 263javax.servlet 259jstl 2601.2 261264 268com.google.guava 265guava 26619.0 267269 273 274 275com.google.guava 270guava-collections 271r03 272276 280 281commons-fileupload 277commons-fileupload 2781.3.1 279
2>服务器端代码:
CenterController.java
1 package com.sxd.controller; 2 3 import java.io.IOException; 4 import java.util.ArrayList; 5 import java.util.List; 6 import java.util.Map; 7 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 import me.chanjar.weixin.common.api.WxConsts; 12 import me.chanjar.weixin.common.bean.menu.WxMenu; 13 import me.chanjar.weixin.common.bean.menu.WxMenuButton; 14 import me.chanjar.weixin.common.exception.WxErrorException; 15 import me.chanjar.weixin.common.session.WxSessionManager; 16 import me.chanjar.weixin.mp.api.WxMpConfigStorage; 17 import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; 18 import me.chanjar.weixin.mp.api.WxMpMessageHandler; 19 import me.chanjar.weixin.mp.api.WxMpMessageRouter; 20 import me.chanjar.weixin.mp.api.WxMpService; 21 import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; 22 import me.chanjar.weixin.mp.bean.WxMpXmlMessage; 23 import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; 24 import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage; 25 26 import org.springframework.context.annotation.Lazy; 27 import org.springframework.stereotype.Controller; 28 import org.springframework.web.bind.annotation.RequestMapping; 29 import org.springframework.web.bind.annotation.ResponseBody; 30 31 import com.sxd.util.ButtonMenuUtils; 32 import com.sxd.util.Dom4jUtils; 33 import com.sxd.util.RuleManager; 34 35 36 /** 37 * 中央处理器 38 * 39 * @author Administrator 40 * 41 */ 42 @Controller 43 @RequestMapping("centercontroller") 44 public class CenterController { 45 46 public WxMpInMemoryConfigStorage config;//微信基本配置信息+Access Token 47 public static WxMpService wxMpService; //微信API的Service 48 public WxMpMessageRouter wxMpMessageRouter;//微信消息路由器 49 public static String accessToken; 50 51 52 /** 53 * 1.处理微信首次配置信息+创建按钮 【首次创建后可以 注释initWeiXin()方法 不用每次都执行】 54 * 2.验证接口配置信息 【如果过时重新获取】 55 * 3.消息转发---中转站 【每次微信端的信息都会从微信服务器转发到这里,然后从这里转发出去】 56 * @param request 57 * @param response 58 * @return 59 * @throws IOException 60 * @throws WxErrorException 61 */ 62 @RequestMapping("test") 63 public String test1(HttpServletRequest request, HttpServletResponse response) throws IOException, WxErrorException{ 64 /** 65 * 1.处理微信首次配置信息+创建按钮 66 */ 67 // initWeiXin(); 68 /** 69 * 2.验证接口配置信息 如果过时重新获取 70 */ 71 String echostr = request.getParameter("echostr"); 72 if(echostr != null){ 73 return "forward:/tokenCheckController/tokenCheck.htmls"; 74 } 75 76 /** 77 * 3.消息转发---中转站 每次微信端的消息都会来到这里进行分发 78 */ 79 WxMpXmlMessage message = WxMpXmlMessage.fromXml(request.getInputStream()); 80 String msgType = message.getMsgType(); 81 Dom4jUtils dom4El = new Dom4jUtils(); 82 String url = dom4El.msgDispather(msgType); 83 if(url != null){ 84 request.setAttribute("message", message); 85 return url; 86 } 87 88 response.getWriter().write("无法辨识消息类型!!"); 89 return null; 90 91 } 92 93 94 /** 95 * 初始化 微信相关配置 并且创建按钮 96 * @throws WxErrorException 97 */ 98 public void initWeiXin() throws WxErrorException{ 99 config = new WxMpInMemoryConfigStorage();100 config.setAppId("wx4848686e5bd4efce"); // 设置微信公众号的appid101 config.setSecret("fc37ce345b3612d615d4ead83f21bdff"); // 设置微信公众号的app corpSecret102 config.setToken("F0932398023"); // 设置微信公众号的token103 104 wxMpService = new WxMpServiceImpl();105 wxMpService.setWxMpConfigStorage(config);//创建自己的service106 if(config.getAccessToken() == null){107 accessToken = wxMpService.getAccessToken(true);//手动刷新获取了Access Token108 }109 //创建菜单按钮110 ButtonMenuUtils bm = new ButtonMenuUtils();111 WxMenu menu = bm.createButtonMenu();112 wxMpService.getMenuService().menuCreate(menu);113 }114 115 }
TokenCheckController.java
1 package com.sxd.util.controller; 2 3 import java.io.IOException; 4 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 8 import org.springframework.stereotype.Controller; 9 import org.springframework.web.bind.annotation.RequestMapping;10 import org.springframework.web.bind.annotation.ResponseBody;11 12 import com.sxd.util.TokenCheckUtils;13 14 @Controller15 @RequestMapping("tokenCheckController")16 public class TokenCheckController {17 18 @RequestMapping("tokenCheck")19 public void tokenCheck(HttpServletRequest request,HttpServletResponse response) throws IOException{20 String signature = request.getParameter("signature");21 String timestamp = request.getParameter("timestamp");22 String nonce = request.getParameter("nonce");23 String echostr = request.getParameter("echostr");24 25 TokenCheckUtils tokenCheckUtils = new TokenCheckUtils();26 echostr = tokenCheckUtils.tokenCheck(signature, timestamp, nonce, echostr);27 28 response.getWriter().write(echostr);29 }30 }
TokenCheckUtils.java
1 package com.sxd.util; 2 3 import java.util.ArrayList; 4 import java.util.Collections; 5 import java.util.List; 6 7 import org.apache.commons.codec.digest.DigestUtils; 8 9 /**10 * 验证接口配置信息11 * @author SXD12 *13 */14 public class TokenCheckUtils {15 16 /**17 * 验证接口配置信息18 * 加密/校验流程如下:19 1. 将token、timestamp、nonce三个参数进行字典序排序20 2. 将三个参数字符串拼接成一个字符串进行sha1加密21 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信22 */23 public String tokenCheck(String signature,String timestamp,String nonce,String echostr){24 String token = "F0932398023";25 Listlist = new ArrayList<>();26 list.add(timestamp);27 list.add(token);28 list.add(nonce);29 30 Collections.sort(list);//1.字典排序31 32 String str = DigestUtils.sha1Hex(list.get(0)+list.get(1)+list.get(2));//2.sha1加密33 if(signature.equals(str)){ //3.判断是否微信信息 此处判断echostr!=null是为了进行下面的操作不影响此处原本的效果34 return echostr;35 // 也就是说 如果echostr!=null,那么此次的请求是在验证是否成为开发者的;否则就是其他的微信请求,不用跳出程序36 }37 return null;38 }39 }
msgTypeDispather.xml
1 23 4 5 6 7 8 9 10 11 12
Dom4jUtils.java
1 package com.sxd.util; 2 3 import java.util.List; 4 5 import org.dom4j.Document; 6 import org.dom4j.DocumentException; 7 import org.dom4j.Element; 8 import org.dom4j.io.SAXReader; 9 10 import com.sxd.test.util.Dom4jTest;11 12 /**13 * 根据微信端发送的消息,解析出消息类型,加载配置文件,根据消息类型,将消息转发到对应14 * 消息类型对应的Controller中进行响应处理15 * @author SXD16 *17 */18 public class Dom4jUtils {19 20 /**21 * 使用dom4j解析消息类型配置文件,解析获得的相对应的服务器端的地址,进行访问22 * @param msgType23 * @return24 */25 public String msgDispather(String msgType){26 SAXReader sReader = new SAXReader();27 Document document;28 try {29 document = sReader.read(Dom4jUtils.class.getResourceAsStream("/msgTypeDispather.xml"));30 Listlist = document.getRootElement().elements();31 for (Element element : list) {32 if(msgType.equals(element.attributeValue("type"))){33 return element.attributeValue("url");34 }35 }36 } catch (DocumentException e) {37 e.printStackTrace();38 }39 return null;40 }41 }
EventMsgController.java
1 package com.sxd.message.controller; 2 3 import java.util.stream.Stream; 4 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 8 import me.chanjar.weixin.common.exception.WxErrorException; 9 import me.chanjar.weixin.mp.bean.WxMpXmlMessage;10 11 import org.springframework.stereotype.Controller;12 import org.springframework.web.bind.annotation.RequestMapping;13 14 import com.sxd.material.PermanentMaterialManager;15 16 /**17 * event事件的服务端18 * @author SXD19 *20 */21 @Controller22 @RequestMapping("eventMsgController")23 public class EventMsgController {24 25 26 @RequestMapping("msgDeal")27 public void msgDeal(HttpServletRequest request, HttpServletResponse response) throws WxErrorException{28 WxMpXmlMessage message = (WxMpXmlMessage) request.getAttribute("message");29 //取消关注30 if("unsubscribe".equals(message.getEvent())){31 System.out.println("事件类型:"+message.getEvent());32 }else if("subscribe".equals(message.getEvent())){ //关注公众号33 System.out.println("事件类型:"+message.getEvent());34 }else{ //按钮点击事件35 System.out.println("按钮的EventType:"+message.getEvent());36 System.out.println("按钮的buttonKey:"+message.getEventKey());37 }38 }39 }
TextMsgController.java
1 package com.sxd.message.controller; 2 3 import java.io.IOException; 4 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 8 import me.chanjar.weixin.mp.api.WxMpService; 9 10 import org.springframework.stereotype.Controller;11 import org.springframework.web.bind.annotation.RequestMapping;12 13 import com.sxd.controller.CenterController;14 import com.sxd.util.RuleManager;15 16 /**17 * Text文本类型消息的服务端18 * @author SXD19 *20 */21 @Controller22 @RequestMapping("textMsgController")23 public class TextMsgController {24 25 /**26 * Text消息处理逻辑27 * @throws IOException 28 */29 @RequestMapping("msgDeal")30 public void msgDeal(HttpServletRequest request, HttpServletResponse response) throws IOException{31 WxMpService wxMpService = CenterController.wxMpService;32 RuleManager rm = new RuleManager();33 rm.dealRule(wxMpService, request, response);34 }35 }
RuleManager.java
1 package com.sxd.util; 2 3 import java.io.IOException; 4 import java.util.Map; 5 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 9 import me.chanjar.weixin.common.api.WxConsts;10 import me.chanjar.weixin.common.exception.WxErrorException;11 import me.chanjar.weixin.common.session.WxSessionManager;12 import me.chanjar.weixin.mp.api.WxMpMessageHandler;13 import me.chanjar.weixin.mp.api.WxMpMessageRouter;14 import me.chanjar.weixin.mp.api.WxMpService;15 import me.chanjar.weixin.mp.bean.WxMpXmlMessage;16 import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;17 import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;18 19 public class RuleManager {20 21 /**22 * 消息处理逻辑 23 * Text消息处理规则24 */25 public void dealRule(WxMpService wxMpService,HttpServletRequest request, HttpServletResponse response) throws IOException{26 27 WxMpMessageHandler handlerText = new WxMpMessageHandler() {28 29 @Override30 public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,31 Mapcontext, WxMpService wxMpService,32 WxSessionManager sessionManager) throws WxErrorException {33 34 WxMpXmlOutTextMessage outMessage = new WxMpXmlOutTextMessage();35 outMessage.setToUserName(wxMessage.getFromUser());36 outMessage.setFromUserName(wxMessage.getToUser());37 outMessage.setCreateTime(System.currentTimeMillis()/1000);38 outMessage.setContent("你发送的<"+wxMessage.getContent()+">是一首歌么");39 return outMessage;40 }41 };42 WxMpMessageHandler handlerText2 = new WxMpMessageHandler() {43 44 @Override45 public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,46 Map context, WxMpService wxMpService,47 WxSessionManager sessionManager) throws WxErrorException {48 49 WxMpXmlOutTextMessage outMessage = new WxMpXmlOutTextMessage();50 outMessage.setToUserName(wxMessage.getFromUser());51 outMessage.setFromUserName(wxMessage.getToUser());52 outMessage.setCreateTime(System.currentTimeMillis()/1000);53 outMessage.setContent("第二个满足了");54 return outMessage;55 }56 };57 58 59 /**60 * 消息处理规则,下面示例两个并列的规则,粗细粒度61 */62 WxMpMessageRouter router = new WxMpMessageRouter(wxMpService);63 router.rule()64 .async(false)65 .msgType(WxConsts.XML_MSG_TEXT)66 .content("我")67 .handler(handlerText)68 .end()69 .rule()70 .async(false)71 .msgType(WxConsts.XML_MSG_TEXT)72 .rContent(".*(我|你|他).*")73 .handler(handlerText2)74 .end();75 76 WxMpXmlMessage message = (WxMpXmlMessage) request.getAttribute("message");77 WxMpXmlOutMessage outMessage = router.route(message);78 if(outMessage==null){79 WxMpXmlOutTextMessage outMessageCopy = new WxMpXmlOutTextMessage();80 outMessageCopy.setToUserName(message.getFromUser());81 outMessageCopy.setFromUserName(message.getToUser());82 outMessageCopy.setCreateTime(System.currentTimeMillis()/1000);83 outMessageCopy.setContent(message.getContent());84 response.getWriter().write(outMessageCopy.toXml());85 return ;86 }87 response.getWriter().write(outMessage.toXml());88 }89 }
在这里,不仅验证了服务器,也初始化了 自定义菜单,并且微信端的消息都进行了 分发!
3.服务器端代码写好后,启动服务器,然后再回头点击微信公众平台这里的提交按钮【此处使用测试号】
提示提交成功后就知道配置成功与否了。
转载地址:http://xdyyo.baihongyu.com/