首先推荐一个后来看到不错的教学:点击打开链接
一、 初始微信公众平台
微信公众平台,即我们平时所说的“公众号”,曾用名“官方平台”、“媒体平台”,但最终命名为“公众平台”。从微信的命名我可以发现,公众平台不只是官方、媒体使用的平台,而是对所有公众都开放的统一平台。
微信公众平台地址:https://mp.weixin.qq.com/
微信公众平台公分4大板块:订阅号、服务号、小程序、企业号。
简单的对比一下前三者的区别:
1、 订阅号和服务号均为传统意义的“公众号”,具有消息群发能力,详细区别可在官方平台查看:http://kf.qq.com/faq/140806zARbmm140826M36RJF.html 我们将注重于服务能力开发,而在服务方面,两者开发模式完全相同,只不过服务号可以使用更多的服务接口,而订阅号则是“阉割版”的服务号。因此,后续课程我们将使用服务号为案例进行操作。
2、 微信小程序,原本为“微信应用号”,即一个根植在微信生态系统内的APP。因苹果和谷歌的限制,“应用号”未上线便已夭折,取而代之的是适度阉割功能的“微信小程序”,而其堪比原生APP的操作体验,也使得小程序成为时下大火的开发方向。
二、 开发账号准备
1、 账号注册
进入微信公众平台https://mp.weixin.qq.com ,点击右上角立即注册,选择“服务号”或“订阅号”注册(服务号仅限机构用户注册,个人用户只能选择订阅号)
注册时需填写一系列信息,根据提示填写即可,此处不做赘述。
2、 测试账号申请
如果暂时不想注册账号,或者无法注册服务号,可选择官方提供的测试账号申请。申请地址:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login 点击后扫描二维码,即可获得一个测试账号,拥有服务号全部权限。
三、 开发环境准备
1、 外网映射工具
微信公众平台在访问后台时,必须提供能够正确访问的外网地址,微信平台对后台URL的要求有两点:
① 必须能够用公网访问 ② 必须使用80端口
要实现以上两点,我们可以选择购买外网服务器,例如:阿里云、百度云、腾讯云…都是不错的选择。如果没有服务器,可以选择用外网映射工具,将我们的内网链接映射为公网,比较不错的映射软件有:花生壳、ngrok、nat123等…
这几款软件都可以百度很容易搜索到并下载,下面简单讲解一下用法:
(1): Ngrock:
进入dos环境,切换到ngrock所在盘符,输入ngrock 8080 回车:
回车后等待一会,即可得到公网链接,下图所示阴影区域给出的链接,即可直接访问本机127.0.0.1:8080下的链接内容,分别是http协议和https协议对应的地址:
(2):花生壳、nat123,均可安装软件后,在软件中操作,详情可查看百度经验:http://jingyan.baidu.com/article/363872ec361d3f6e4ba16ff9.html 此处不做赘述 收费
(3):unny-Ngrok:
本来一开始看博客有人推荐了Ngrok,试了以后发现他服务器在国外,映射的网址访问慢的不行。
下面是Sunny-Ngrok的官网: 免费
1、首先在本站注册成为会员
2、开通隧道
在上图中表单信息解释:
隧道名称:可以随便填写,只是为了使用者在往后之后这个隧道是干嘛的
前置域名:服务器免费赠送的域名,请不要带上后缀,如果要sunny.ngrok.cc 只需要填写 sunny 即可 ,千万不要填写成sunny.ngrok.cc否则域名会是sunny.ngrok.cc.ngrok.cc
本地端口:可以为同一个局域网内任意一台机器进行映射,只需要填对ip和端口就行,例如:192.168.1.1:80
http验证用户名:非必填项,在需要的时候填写,否则可以不填
http验证密码:非必填项,在需要的时候填写,否则可以不填
3、下载客户端
根据自己的操作系统需求下载相对于版本
写到这里忘了说了,之后我们会用到Tomcat,不会配置的同学可以参考下面这篇漏文:
http://blog.csdn.net/geanwen/article/details/78410595
4、启动映射服务
window系统下:
方法一:
1、打开命令提示符
2、通过命令提示符窗口进入下载好的软件目录
3、启动隧道
命令解释:
sunny.exe 下载的软件内网映射隧道工具
clientid 通过隧道id启动,后面跟上隧道id,如果有多个隧道要一起启动那么使用英文逗号隔开第三个红色剪头所指的地方就是为了启动多个隧道
方法二:
通过下载的软件包里面的bat小工具启动,双击bat文件输入隧道id回车启动即可。
这里启动了两个隧道,使用了英文逗号隔开了。
其中:http://aool.ngrok.cc就是你本地路径映射后的结果。
5、访问服务
然后通过启动成功界面上的链接访问网站如果显示是内网搭建的web服务里面的内容就说明成功了
如果没有启动web服务将会看到下图提示
注意:tomcat默认的端口号为:8080
修改eclipse中tomcat端口的办法:
1:找到tomcat位置:打开eclipse,选择window->Preferences->Server->Runtime Environments选择你的tomcat然后点Edit,就会出现它的路径了。
2:打开Tomcat下,conf文件夹中的,server.xml文件
3:将port由8080修改为80
注意:正常情况下,这时重启tomcat服务器端口号就修改成功了。但是,如果你用的开发工具是Eclipse,这是你在Eclipse中重启tomcat服务器的话,会发现服务器用的依然是8080端口。这时需要你在Eclipse中将正在使用的服务器删掉,在重新装载一次。
四、 微信公众平台数据交互原理
搭建好公网访问地址后,我们自己开发的后台代码就可以放到公网地址了,那么用户是怎么样访问到我们的代码呢?
下面我们来看一下微信公众平台的数据交互原理:
从上图可以看到,微信公众平台实际只是起到一个桥梁作用,实际处理业务、提供服务的代码,依然是放在我们自己的服务器或者公网映射上面。
那么,我们就可以在我们自己的电脑(服务器)上面编写后台代码,并通过映射工具提供公网能够访问的URL,然后将此URL绑定到微信后台即可。
五、 开发模式接入
下面将进入实际开发过程,我们可以参考官方提供的开发文档:https://mp.weixin.qq.com/wiki
1、 填写服务器配置
进入微信公众平台,点击左侧【开发——基本配置】,选择【服务器配置】。即可进入配置页面:
其中:
URL:即我们上述所说的后台服务器公网访问地址
Token:开发者自定的验证口令
EncodingAESKey:随机字符串,如果消息加解密方式采用安全模式才需验证
2、 验证消息是否有效
当我们点击提交时,微信服务器将会发送一个Get请求,到我们上述地址,同时传递四个参数:
我们通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:
下面,我们实现代码操作。
六、 开发接入后台代码
代码也是我看文章找的:
- package servlet;
- import bean.TextMessage;
- import util.CheckUtil;
- import util.MessageUtils;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.util.Date;
- import java.util.Map;
- public class WechatServlet extends HttpServlet{
- /**
- * 接收微信服务器发送的4个参数并返回echostr
- */
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- // 接收微信服务器以Get请求发送的4个参数
- String signature = request.getParameter("signature");
- String timestamp = request.getParameter("timestamp");
- String nonce = request.getParameter("nonce");
- String echostr = request.getParameter("echostr");
- PrintWriter out = response.getWriter();
- if (CheckUtil.checkSignature(signature, timestamp, nonce)) {
- out.print(echostr); // 校验通过,原样返回echostr参数内容
- }
- }
- /**
- * 接收并处理微信客户端发送的请求
- */
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- request.setCharacterEncoding("UTF-8");
- response.setCharacterEncoding("UTF-8");
- response.setContentType("text/xml;charset=utf-8");
- PrintWriter out = response.getWriter();
- Map<String, String> map = MessageUtils.xmlToMap(request);
- String toUserName = map.get("ToUserName");
- String fromUserName = map.get("FromUserName");
- String msgType = map.get("MsgType");
- String content = map.get("Content");
- String message = null;
- if ("text".equals(msgType)) { // 对文本消息进行处理
- TextMessage text = new TextMessage();
- text.setFromUserName(toUserName); // 发送和回复是反向的
- text.setTouserName(fromUserName);
- text.setMsgType("text");
- text.setCreateTime(String.valueOf(new Date().getTime()));
- text.setContent("你发送的消息是:" + content);
- message = MessageUtils.textMessageToXML(text);
- System.out.println(message);
- }
- out.print(message); // 将回应发送给微信服务器
- }
- }
里面的工具类CheckUtils:
- package util;
- import java.security.MessageDigest;
- import java.util.Arrays;
- public class CheckUtil {
- private static final String token = "geanwen";
- public static boolean checkSignature(String signature, String timestamps, String nonce){
- String[] arr = new String[]{token, timestamps, nonce};
- // 排序
- Arrays.sort(arr);
- // 生成字符串
- StringBuilder content = new StringBuilder();
- for (int i = 0; i < arr.length; i++) {
- content.append(arr[i]);
- }
- // sha1加密
- String temp = encode(content.toString());
- return temp.equals(signature); // 与微信传递过来的签名进行比较
- }
- private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
- '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
- /**
- * Takes the raw bytes from the digest and formats them correct.
- *
- * @param bytes the raw bytes from the digest.
- * @return the formatted bytes.
- */
- private static String getFormattedText(byte[] bytes) {
- int len = bytes.length;
- StringBuilder buf = new StringBuilder(len * 2);
- // 把密文转换成十六进制的字符串形式
- for (int j = 0; j < len; j++) {
- buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
- buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
- }
- return buf.toString();
- }
- public static String encode(String str) {
- if (str == null) {
- return null;
- }
- try {
- MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
- messageDigest.update(str.getBytes());
- return getFormattedText(messageDigest.digest());
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- }
MessageUtils:
- package util;
- import bean.TextMessage;
- import com.thoughtworks.xstream.XStream;
- import org.dom4j.Document;
- import org.dom4j.DocumentException;
- import org.dom4j.Element;
- import org.dom4j.io.SAXReader;
- import javax.servlet.http.HttpServletRequest;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- public class MessageUtils {
- /**
- * xml转为map集合
- */
- public static Map<String, String> xmlToMap(HttpServletRequest request){
- Map<String, String> map = new HashMap<>();
- SAXReader reader = new SAXReader();
- try {
- // 从request中获取输入流
- InputStream ins = request.getInputStream();
- Document doc = reader.read(ins);
- // 获取xml中的跟元素
- Element root = doc.getRootElement();
- // 获取跟元素所有节点放到list中
- List<Element> list = root.elements();
- // 遍历
- for (Element e : list){
- map.put(e.getName(), e.getText());
- }
- ins.close();
- return map;
- } catch (IOException e) {
- e.printStackTrace();
- return null;
- } catch (DocumentException e) {
- e.printStackTrace();
- return null;
- }
- }
- /**
- * 将文本消息对象转换成XML
- */
- public static String textMessageToXML(TextMessage textMessage){
- XStream xstream = new XStream(); // 使用XStream将实体类的实例转换成xml格式
- xstream.alias("xml", textMessage.getClass()); // 将xml的默认根节点替换成“xml”
- return xstream.toXML(textMessage);
- }
- }
按照微信要求的实体类TextMessage:
- package bean;
- public class TextMessage {
- private String TouserName;
- private String FromUserName;
- private String CreateTime;
- private String MsgType;
- private String Content;
- private String 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 String getCreateTime() {
- return CreateTime;
- }
- public void setCreateTime(String createTime) {
- CreateTime = createTime;
- }
- public String getMsgType() {
- return MsgType;
- }
- public void setMsgType(String msgType) {
- MsgType = msgType;
- }
- public String getContent() {
- return Content;
- }
- public void setContent(String content) {
- Content = content;
- }
- public String getMsgId() {
- return MsgId;
- }
- public void setMsgId(String msgId) {
- MsgId = msgId;
- }
- }
Web.xml中添加配置Servlet:
- <servlet>
- <servlet-name>wechatServlet</servlet-name>
- <servlet-class>servlet.WechatServlet</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>wechatServlet</servlet-name>
- <url-pattern>/wx.do</url-pattern>
- </servlet-mapping>
最后一步:
将项目加到tomcat下 访问对应的控制器
成功!
如有问题加我QQ:2649416836
参考地址:https://www.sunnyos.com/article-show-71.html
https://www.cnblogs.com/jerehedu/p/6377759.html