Java开发微信公众号后台

源码

GitHub地址:https://github.com/erlieStar/weChat
效果图
这里写图片描述

流程图

这里写图片描述
如果不需要定制化的服务,只是推送一些文章的时候,没必要开发自己的服务器,步骤1和步骤4就足够了

本地测试

下载ngrok,解决外网访问内网问题

LZ用的是Sunny-Ngrok
下载地址:https://www.ngrok.cc/
LZ下载的是Win 64Bit版本,看了作者写的使用博客搭建好了
http://www.sunnyos.com/article-show-71.html
这里写图片描述
这样我就把本地的地址映射为http://erlie.free.ngrok.cc
不过国人的真心卡啊,果断用了另一个https://ngrok.com/
教程地址:https://jingyan.baidu.com/article/f006222826c2bcfbd3f0c885.html

ngrok http 80

进入软件所在路径,在命令行中运行上面的命令,这样就能把一个外网地址映射为内网,只不过每次重新启动域名会变

创建测试账号

地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
这里写图片描述
appID和appsecret以后都会用到
这里写图片描述
url填写的内容是http://erlie.free.ngrok.cc/server/system,其中/server/system是接口名字,因为是Spring Boot项目,所以不用写项目名字,token随便写,主要用于验证作用。此时点提交会显示配置失败,因为你得把本地的服务启动起来,并且让微信完成校验
这个是官方写的验证说明:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319

@Controller
@RequestMapping("server")
public class WeChatController {

    /*
     * 微信公众号服务器
     */

    private final String token = "erlie";

    @GetMapping(value = "system")
    public void doGet(HttpServletRequest request, HttpServletResponse response) {

        //获取参数值
        String signature = request.getParameter("signature");
        String timeStamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");

        PrintWriter out = null;
        try {
            out = response.getWriter();
            //开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
            if (CheckUtil.checkSignature(token, timeStamp, nonce).equals(signature)) {
                //作出响应,即原样返回随机字符串
                out.println(echostr);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            out.close();
        }
    }

}

public class CheckUtil {

    /*
     * 微信校验的帮助类
     */

    public static String checkSignature(String token, String timeStamp, String nonce) {

        String[] arr = new String[]{token, timeStamp, nonce};

        //将token、timestamp、nonce三个参数进行字典序排序
        Arrays.sort(arr);

        //生成字符串
        StringBuffer sb = new StringBuffer();
        for (int i=0;i<arr.length;i++){
            sb.append(arr[i]);
        }

        //将三个参数字符串拼接成一个字符串进行sha1加密
        String temp = getSha1(sb.toString());

        return temp;

    }


    public static String getSha1(String str) {

        if (str == null || str.length() == 0) {
            return null;
        }
        char hexDigite[] = {'0','1','2','3','4','5','6','7','8','9','a',
                'b','c','d','e','f'};

        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes("UTF-8"));

            byte[] md = mdTemp.digest();
            int j = md.length;
            char buf[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++){
                byte byte0 = md[i];
                buf[k++] = hexDigite[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigite[byte0 & 0xf];
            }
            return new String(buf);
        }catch (Exception e){
            return null;
        }
    }
}

把本地的服务开启,点击提交就成功了

框架结构

这里写图片描述

  1. api中有3个类,AccessTokenApi(获取token),IdAndSecretApi(保存appId和appSecret),MenuApi(菜单管理,LZ只写了创建菜单的函数。查询,删除可按照自己需求写)
  2. bean中有1个类保存token
  3. controller中有1个类是和微信进行交互的接口
  4. handler中有4个类,EventTypes(事件类型),MsgTypes(消息类型),MsgHandler(消息处理器),DefaultHandler(默认的消息处理器)
  5. msg中有3中类型的类,event包中是事件类型,in是接受消息的类型,out是发送消息的类型
  6. ui封装了菜单类和各种按钮类
  7. util中3个类,CheckUtil(微信校验的类),ResponseUtil(发送get和post的类),XMLUtil(将xml转为map的帮助类)
  8. MenuManager是用ui包中的各种图形控件,组成的界面

整体思路

这里写图片描述

  • 消息类的继承关系如图,收到的消息和发送的消息都继承一个基类,方便对消息进行统一的处理
  • 收到xml文件统一转为map,在MsgHandler中根据type类型判断数据属于哪个类型,用map构造这个消息类型,即工厂模式。并且将各种消息的处理过程交给各种抽象函数,而DefaultHandler实现了对各种消息的处理
  • 消息构造完毕往微信公众平台发送xml文件,我知道的有2种处理方式,一种是利用XStream库,将java对象转为xml类型,这种每次都得new对象,比较麻烦,我没有采用这种方法,而是重写了toString()函数,这样每次发送消息,由父类调用一下toString()函数即可,如下,但是对图文消息类型不怎么友好,LZ用图文消息比较少,所以还是用了toString()函数
    @Override
    public String toString() {
        String template = "<xml>\n" +
                "<ToUserName><![CDATA[toUser]]></ToUserName>\n" +
                "<FromUserName><![CDATA[fromUser]]></FromUserName>\n" +
                "<CreateTime>createTime</CreateTime>\n" +
                "<MsgType><![CDATA[msgType]]></MsgType>\n" +
                "<Content><![CDATA[content]]></Content>\n" +
                "</xml>";

        String xmlStr = template.replace("toUser", toUserName)
                .replace("fromUser", fromUserName)
                .replace("createTime", createTime)
                .replace("msgType", msgType)
                .replace("content", content);
        return xmlStr;
    }

数据测试

地址如下:https://mp.weixin.qq.com/debug/,可以查看返回的各种数据是否正确

参考博客

微信公众平台开发书籍推荐
[1]http://www.cnblogs.com/txw1958/p/weixin-book-dev.html

欢迎关注

喜欢本文的朋友们,欢迎关注公众号Java识堂,收看更多精彩内容
在这里插入图片描述

发布了375 篇原创文章 · 获赞 1220 · 访问量 70万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览