微信公众平台开发概述

微信公众平台是运营者通过公众号为微信用户提供资讯和服务的平台,而公众平台开发接口则是提供服务的基础,开发者在公众平台网站中创建公众号、获取接口权限后,可以通过阅读接口文档来帮助开发。

微信公众号文档地址: https://mp.weixin.qq.com/wiki

每个接口都有每日接口调用频次限制,可以在公众平台官网-开发者中心处查看具体频次。在开发出现问题时,可以通过接口调用的返回码,以及报警排查指引(在公众平台官网-开发者中心处可以设置接口报警),来发现和解决问题。

微信公众平台注册

非开发人员

从2014年开始,对于个人注册微信公众号的一律只能申请订阅号,也就意味着不能随便申请微信认证。要想微信认证,只能申请服务号或者是企业号,而微信认证后的公众号能获得更多的api接口功能(其中包括微信支付等)。不过,对于初学开发者来说,微信为其提供了测试号,测试号可使用所有微信api接口。

wechat_login.png

点击右上方的立即注册,对于个人而言,点击订阅号开始注册,注册前得先准备一个邮箱账号(最好是QQ邮箱,毕竟是自家的东西嘛),得输入个人身份证号,然后得设置此订阅号的名称等相关信息,按照指引一步一步完成注册。注册完成后,回到登录页面,输入邮箱密码登录。

weixin_dev.png

对于非开发人员来说,此图形界面已经非常容易上手自己的订阅号,基本的上传素材、定义菜单、定义模板、发布文章等功能对于只是写个文章之类的个人用户来说已经基本可以满足了。

开发人员

weixin_config.png

weixin_basic.png

要想自己开发微信公众号,必须得有在外网能访问的80端口或443端口地址(要想成为开发者,必须得响应来自微信服务器通过Get方法传递的参数信息,因而需要外网能访问的地址),支持http/https。如上图,在基本配置中,可以配置启用自己的服务器地址和令牌Token。一般在开发阶段租用云服务器或云应用引擎比较奢侈,而且不易调试。一般是开发完后才放在上面,来稳定地提供服务。

笔者是通过购买花生壳域名,然后启用内网穿透来映射到本地ip:8080端口上来,在自己搭建的Tomcat8.5.34服务器下进行开发的,这样对于初学者来说非常容易调试。在这一系列开发中,我非常建议使用测试号来进行开发。

微信公众平台测试号申请

在申请到认证公众号之前,你可以先通过测试号申请系统,快速申请一个接口测试号,立即开始接口测试开发。在开发过程中,可以使用接口调试工具来在线调试某些接口

debug_cgi.png

微信公众测试号申请:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

debug_config.png

参数大概说明:

  • appID和appsecret:主要用来获得access_token的值,access_token值具有唯一性,有识别公众号的作用,可以把它比喻成一个钥匙,通过access_token,微信公众号才能调用微信接口,如微信服务器 IP的获取接口,长链接转短链接接口、获取微信关注用户列表及获取用户基本信息的接口等等。

  • URL:你的服务器地址,外网能访问的80或443端口。

  • Token:此值后面会用来和微信服务器传过来的参数timestamp、nonce进行SHA1加密,然后一样跟传过来的参数signature比较,若相等,则输出一并传过来的参数echostr到微信服务器。

开始认证成为开发者

选择eclipse或者Intellij IDE作为环境,首先建立一个web application, 然后测试外网访问该web默认的index页面(在其页面上随便写上一句话),如下即表明成功:

justquiet.png

要想响应微信服务器发过来的请求信息,得写个coreServlet:

/**
 * created by mayn on 2019/3/31
 *
 * 来接收微信服务器传来信息
 *
 */
public class CoreServlet extends javax.servlet.http.HttpServlet {
    /**
     * 确认请求来自微信服务器
     */
    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws IOException {

        // 微信加密签名
        String signature = request.getParameter("signature");
        // 时间戳
        String timestamp = request.getParameter("timestamp");
        // 随机数
        String nonce = request.getParameter("nonce");
        // 随机字符串
        String echostr = request.getParameter("echostr");

        // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
        if(signature != null && timestamp != null && nonce != null && echostr != null) {
            if (SignUtil.checkSignature(signature, timestamp, nonce)) {
                PrintWriter out = response.getWriter();
                out.write(echostr);
                out.flush();
            }
        }
    }

工具类SignUtil:

/**
 * created by mayn on 2019/3/31
 *
 * 检验signature工具类
 *
 */
public class SignUtil {
    // 与接口配置信息中的Token要一致
    private static final String token = "livejqweixin";

    /**
     * 方法名:checkSignature
     * 详述:验证签名
     * 开发人员:livejq
     * 创建时间:2019-03-31
     * @param signature
     * @param timestamp
     * @param nonce
     * @return
     * @throws
     */
    public static boolean checkSignature(String signature, String timestamp,String nonce) {
        // 1.将token、timestamp、nonce三个参数进行字典序排序
        String[] arr = new String[] { token, timestamp, nonce };
        Arrays.sort(arr);

        // 2. 将三个参数字符串拼接成一个字符串进行sha1加密
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        MessageDigest md = null;
        String tmpStr = null;
        try {
            md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        // 3.将sha1加密后的字符串可与signature对比,标识该请求来源于微信
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
    }

/**
     * 方法名:byteToStr</br>
     * 详述:将字节数组转换为十六进制字符串</br>
     * 开发人员:livejq </br>
     * 创建时间:2019-3-31  </br>
     * @param byteArray
     * @return
     * @throws
     */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    /**
     * 方法名:byteToHexStr</br>
     * 详述:将字节转换为十六进制字符串</br>
     * 开发人员:livejq</br>
     * 创建时间:2019-3-31  </br>
     * @param mByte
     * @return
     * @throws
     */
    private static String byteToHexStr(byte mByte) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A','B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];
        String s = new String(tempArr);
        return s;
    }
}

别忘了在web.xml中声明coreServlet

写完后开启服务器,在测试号中填入:你的访问地址/coreServlet,然后提交,接着显示认证成功信息。

持续更新中…