
接入微信公众平台开发,开发者需要按照如下步骤完成:
1、填写服务器配置
2、验证服务器地址的有效性
3、依据接口文档实现业务逻辑 好我们就开始:
1.登录微信公众平台,进入基本配置
修改配置,将自己的服务器的URL地址,配置在此处:
填写完成后,【先不用 提交】,先进行第二步 服务器端代码的配置
注意:
如果想使用 自定义菜单等相关接口权限,需要注意:
可以看到 个人订阅号是没有 使用自定义菜单的相关接口能力的,如果需要使用的话,需要注册服务号或使用测试号:
那么 在服务器端代码中使用的 测试AppId/Secret/Token等都需要重新设置为测试号的相关信息!
2.服务器端配置相关
服务器端相关代码 思路:
1>首先搭建web项目,使用maven管理架包,项目架构用spring+spring MVC+hibernate,pom.xml文件中,关于微信端开发的配置就是,就是使用weixin-java-tools项目使用java进行微信端开发
<!-- 微信开发工具包 --> <!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-common -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId>
<version>2.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-mp -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>2.2.0</version>
</dependency>
完整pom.xml文件信息
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sxd.wx1</groupId>
<artifactId>wxSecond</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<version>3.0</version>
</configuration>
</plugin>
</plugins>
</build> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.1.4.RELEASE</spring.version>
<hibernate.version>4.3.8.Final</hibernate.version>
</properties> <dependencies>
<!-- https://mvnrepository.com/artifact/javax.persistence/persistence-api -->
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
</dependency>
<!-- 进行加密操作 -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency> <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency> <!-- 微信开发工具包 --> <!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-common -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId>
<version>2.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-mp -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>2.2.0</version>
</dependency> <!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency> <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.4</version>
</dependency> <!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency> <!-- 使用SpringMVC需配置 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring cglib 代理 -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<!-- 关系型数据库整合时需配置 如hibernate jpa等 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency> <!-- hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency> <dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>${hibernate.version}</version>
</dependency> <!-- 二级缓存ehcache -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.9.0</version>
</dependency> <!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency> <!-- mysql连接 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency> <!-- c3p0数据源 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5-pre10</version>
</dependency> <!-- json --> <!-- 1号 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.1</version>
</dependency>
<!-- 2号 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.8.1</version>
</dependency> <!-- 3号 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.1</version>
<exclusions>
<exclusion>
<artifactId>jackson-core</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
<exclusion>
<artifactId>jackson-annotations</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
</exclusions>
</dependency> <!-- 4号 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
<!-- 5号 -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<!-- 5号json-lib还需要以下依赖包 -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency> <!-- aop -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.4</version>
</dependency> <!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
<scope>provided</scope>
</dependency> <dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- guava 集合的交并操作 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-collections</artifactId>
<version>r03</version>
</dependency> <!-- 文件上传 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency> </dependencies>
</project>
2>服务器端代码:
CenterController.java
package com.sxd.controller; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import com.sxd.util.ButtonMenuUtils;
import com.sxd.util.Dom4jUtils;
import com.sxd.util.RuleManager; /**
* *处理器
*
* @author Administrator
*
*/
@Controller
@RequestMapping("centercontroller")
public class CenterController { public WxMpInMemoryConfigStorage config;//微信基本配置信息+Access Token
public static WxMpService wxMpService; //微信API的Service
public WxMpMessageRouter wxMpMessageRouter;//微信消息路由器
public static String accessToken; /**
* 1.处理微信首次配置信息+创建按钮 【首次创建后可以 注释initWeiXin()方法 不用每次都执行】
* 2.验证接口配置信息 【如果过时重新获取】
* 3.消息转发---中转站 【每次微信端的信息都会从微信服务器转发到这里,然后从这里转发出去】
* @param request
* @param response
* @return
* @throws IOException
* @throws WxErrorException
*/
@RequestMapping("test")
public String test1(HttpServletRequest request, HttpServletResponse response) throws IOException, WxErrorException{
/**
* 1.处理微信首次配置信息+创建按钮
*/
// initWeiXin();
/**
* 2.验证接口配置信息 如果过时重新获取
*/
String echostr = request.getParameter("echostr");
if(echostr != null){
return "forward:/tokenCheckController/tokenCheck.htmls";
} /**
* 3.消息转发---中转站 每次微信端的消息都会来到这里进行分发
*/
WxMpXmlMessage message = WxMpXmlMessage.fromXml(request.getInputStream());
String msgType = message.getMsgType();
Dom4jUtils dom4El = new Dom4jUtils();
String url = dom4El.msgDispather(msgType);
if(url != null){
request.setAttribute("message", message);
return url;
} response.getWriter().write("无法辨识消息类型!!");
return null; } /**
* 初始化 微信相关配置 并且创建按钮
* @throws WxErrorException
*/
public void initWeiXin() throws WxErrorException{
config = new WxMpInMemoryConfigStorage();
config.setAppId("wx4848686e5bd4efce"); // 设置微信公众号的appid
config.setSecret("fc37ce345b3612d615d4ead83f21bdff"); // 设置微信公众号的app corpSecret
config.setToken("F0932398023"); // 设置微信公众号的token wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(config);//创建自己的service
if(config.getAccessToken() == null){
accessToken = wxMpService.getAccessToken(true);//手动刷新获取了Access Token
}
//创建菜单按钮
ButtonMenuUtils bm = new ButtonMenuUtils();
WxMenu menu = bm.createButtonMenu();
wxMpService.getMenuService().menuCreate(menu);
} }
TokenCheckController.java
package com.sxd.util.controller; import java.io.IOException; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import com.sxd.util.TokenCheckUtils; @Controller
@RequestMapping("tokenCheckController")
public class TokenCheckController { @RequestMapping("tokenCheck")
public void tokenCheck(HttpServletRequest request,HttpServletResponse response) throws IOException{
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
String echostr = request.getParameter("echostr"); TokenCheckUtils tokenCheckUtils = new TokenCheckUtils();
echostr = tokenCheckUtils.tokenCheck(signature, timestamp, nonce, echostr); response.getWriter().write(echostr);
}
}
TokenCheckUtils.java
package com.sxd.util; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import org.apache.commons.codec.digest.DigestUtils; /**
* 验证接口配置信息
* @author SXD
*
*/
public class TokenCheckUtils { /**
* 验证接口配置信息
* 加密/校验流程如下:
1. 将token、timestamp、nonce三个参数进行字典序排序
2. 将三个参数字符串拼接成一个字符串进行sha1加密
3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
*/
public String tokenCheck(String signature,String timestamp,String nonce,String echostr){
String token = "F0932398023";
List<String> list = new ArrayList<>();
list.add(timestamp);
list.add(token);
list.add(nonce); Collections.sort(list);//1.字典排序 String str = DigestUtils.sha1Hex(list.get(0)+list.get(1)+list.get(2));//2.sha1加密
if(signature.equals(str)){//3.判断是否微信信息 此处判断echostr!=null是为了进行下面的操作不影响此处原本的效果
return echostr;
// 也就是说 如果echostr!=null,那么此次的请求是在验证是否成为开发者的;否则就是其他的微信请求,不用跳出程序
}
return null;
}
}
msgTypeDispather.xml
<?xml version="1.0" encoding="UTF-8"?>
<WxDispather>
<WxMsgType type="text" url="forward:/textMsgController/msgDeal.htmls"></WxMsgType>
<WxMsgType type="image" url="forward:/imageMsgController/msgDeal.htmls"></WxMsgType>
<WxMsgType type="voice" url="forward:/voiceMsgController/msgDeal.htmls"></WxMsgType>
<WxMsgType type="video" url="forward:/videoMsgController/msgDeal.htmls"></WxMsgType>
<WxMsgType type="shortvideo" url="forward:/shortvideoMsgController/msgDeal.htmls"></WxMsgType>
<WxMsgType type="location" url="forward:/locationMsgController/msgDeal.htmls"></WxMsgType>
<WxMsgType type="link" url="forward:/linkMsgController/msgDeal.htmls"></WxMsgType>
<WxMsgType type="event" url="forward:/eventMsgController/msgDeal.htmls"></WxMsgType> </WxDispather>
Dom4jUtils.java
package com.sxd.util; import java.util.List; import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; import com.sxd.test.util.Dom4jTest; /**
* 根据微信端发送的消息,解析出消息类型,加载配置文件,根据消息类型,将消息转发到对应
* 消息类型对应的Controller中进行响应处理
* @author SXD
*
*/
public class Dom4jUtils { /**
* 使用dom4j解析消息类型配置文件,解析获得的相对应的服务器端的地址,进行访问
* @param msgType
* @return
*/
public String msgDispather(String msgType){
SAXReader sReader = new SAXReader();
Document document;
try {
document = sReader.read(Dom4jUtils.class.getResourceAsStream("/msgTypeDispather.xml"));
List<Element> list = document.getRootElement().elements();
for (Element element : list) {
if(msgType.equals(element.attributeValue("type"))){
return element.attributeValue("url");
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
return null;
}
}
EventMsgController.java
package com.sxd.message.controller; import java.util.stream.Stream; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import com.sxd.material.PermanentMaterialManager; /**
* event事件的服务端
* @author SXD
*
*/
@Controller
@RequestMapping("eventMsgController")
public class EventMsgController { @RequestMapping("msgDeal")
public void msgDeal(HttpServletRequest request, HttpServletResponse response) throws WxErrorException{
WxMpXmlMessage message = (WxMpXmlMessage) request.getAttribute("message");
//取消关注
if("unsubscribe".equals(message.getEvent())){
System.out.println("事件类型:"+message.getEvent());
}else if("subscribe".equals(message.getEvent())){//关注公众号
System.out.println("事件类型:"+message.getEvent());
}else{ //按钮点击事件
System.out.println("按钮的EventType:"+message.getEvent());
System.out.println("按钮的buttonKey:"+message.getEventKey());
}
}
}
TextMsgController.java
package com.sxd.message.controller; import java.io.IOException; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import me.chanjar.weixin.mp.api.WxMpService; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import com.sxd.controller.CenterController;
import com.sxd.util.RuleManager; /**
* Text文本类型消息的服务端
* @author SXD
*
*/
@Controller
@RequestMapping("textMsgController")
public class TextMsgController { /**
* Text消息处理逻辑
* @throws IOException
*/
@RequestMapping("msgDeal")
public void msgDeal(HttpServletRequest request, HttpServletResponse response) throws IOException{
WxMpService wxMpService = CenterController.wxMpService;
RuleManager rm = new RuleManager();
rm.dealRule(wxMpService, request, response);
}
}
RuleManager.java
package com.sxd.util; import java.io.IOException;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage; public class RuleManager { /**
* 消息处理逻辑
* Text消息处理规则
*/
public void dealRule(WxMpService wxMpService,HttpServletRequest request, HttpServletResponse response) throws IOException{ WxMpMessageHandler handlerText = new WxMpMessageHandler() { @Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) throws WxErrorException { WxMpXmlOutTextMessage outMessage = new WxMpXmlOutTextMessage();
outMessage.setToUserName(wxMessage.getFromUser());
outMessage.setFromUserName(wxMessage.getToUser());
outMessage.setCreateTime(System.currentTimeMillis()/1000);
outMessage.setContent("你发送的<"+wxMessage.getContent()+">是一首歌么");
return outMessage;
}
};
WxMpMessageHandler handlerText2 = new WxMpMessageHandler() { @Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService wxMpService,
WxSessionManager sessionManager) throws WxErrorException { WxMpXmlOutTextMessage outMessage = new WxMpXmlOutTextMessage();
outMessage.setToUserName(wxMessage.getFromUser());
outMessage.setFromUserName(wxMessage.getToUser());
outMessage.setCreateTime(System.currentTimeMillis()/1000);
outMessage.setContent("第二个满足了");
return outMessage;
}
}; /**
* 消息处理规则,下面示例两个并列的规则,粗细粒度
*/
WxMpMessageRouter router = new WxMpMessageRouter(wxMpService);
router.rule()
.async(false)
.msgType(WxConsts.XML_MSG_TEXT)
.content("我")
.handler(handlerText)
.end()
.rule()
.async(false)
.msgType(WxConsts.XML_MSG_TEXT)
.rContent(".*(我|你|他).*")
.handler(handlerText2)
.end(); WxMpXmlMessage message = (WxMpXmlMessage) request.getAttribute("message");
WxMpXmlOutMessage outMessage = router.route(message);
if(outMessage==null){
WxMpXmlOutTextMessage outMessageCopy = new WxMpXmlOutTextMessage();
outMessageCopy.setToUserName(message.getFromUser());
outMessageCopy.setFromUserName(message.getToUser());
outMessageCopy.setCreateTime(System.currentTimeMillis()/1000);
outMessageCopy.setContent(message.getContent());
response.getWriter().write(outMessageCopy.toXml());
return ;
}
response.getWriter().write(outMessage.toXml());
}
}
在这里,不仅验证了服务器,也初始化了 自定义菜单,并且微信端的消息都进行了 分发!
3.服务器端代码写好后,启动服务器,然后再回头点击微信公众平台这里的提交按钮【此处使用测试号】
提示提交成功后就知道配置成功与否了。