JAVA微信公众号开发

246 阅读4分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」。

1 说明

最近项目有一些微信公众号方面的需求,所以就去研究了一下公众号后台的开发,在这期间也请教了一些之前做过公众号开发的同事,也与一起进行开发的同事互相讨论,使得我们的开发工作有条不紊的进行下去,在此也将开发的过程和一些心得输出出来,方便后面的同事以及微信开发爱好者借鉴,如果有问题也请大家指正。

2、申请公众号

我们要进行微信公众号的开发,首先要申请一个微信公众号
大家可以百度搜索“微信公众号”,或者登陆网站mp.weixin.qq.com/,进行微信公众号的注册,如下图所示

image.png 注:个人用户数只能注册订阅号,由于本人已经注册,所以直接登录
选择订阅号,填写相关信息,注册成功后登陆。

3、接入流程解析

在我们的开发过程中无论如何最好的参考工具当然是我们的官方文档了 developers.weixin.qq.com/doc/offiacc…

3.1 基本配置

在进行微信公众号开发之前,我们在微信开发者文档中可以看到“接入指南”
接入微信公众平台开发,开发者需要按照如下步骤完成:

填写服务器配置 进入微信公众号主页后,将列表拉到最下方,选择“开发–>基本配置”,进行微信公众号的基本配置,如下图示

image.png

image.png 上图中开发者ID(AppID)和开发者密码(AppSecret)在后续的开发中会进行使用。
点击服务器配置中的修改配置

image.png

3.2 2. 验证服务器地址的有效性

看一下官方文档:mp.weixin.qq.com/wiki?t=reso… 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数如下

image.png 开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:

1)将token、timestamp、nonce三个参数进行字典序排序 2)将三个参数字符串拼接成一个字符串进行sha1加密 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

意思是说:对微信服务器发过来消息忠token、timestamp、nonce三个参数进行加密处理,然后加密得到的字符串与signature微信加密签名相比较,如果相等则返回echostr随机字符串。

4 开始搭建本地服务

我这边使用springboot框架为基础开发,创建微信验证controller

4.1 WeChatCheckController


    @RestController
    public class WeChatCheckController {
        private static final Logger LOGGER = LoggerFactory.getLogger(WeChatCheckController.class);
    
        /**
         * 开发者通过检验signature对请求进行校验
         *
         * @param request  request
         * @param response response
         * @return String
         */
        @RequestMapping(value= "/",method = RequestMethod.GET)
        public void doGet(HttpServletRequest request, HttpServletResponse response) {
            try {
                // 微信加密签名
                String signature = request.getParameter("signature");
                // 时间戳
                String timestamp = request.getParameter("timestamp");
                // 随机数
                String nonce = request.getParameter("nonce");
                // 随机字符串
                String echostr = request.getParameter("echostr");
                PrintWriter out = response.getWriter();
                // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
                if (SignUtil.checkSignature(signature, timestamp, nonce)) {
                    out.print(echostr);
                } else {
                    //校验失败返回其他
                    out.print(timestamp);
                }
                out.close();
            } catch (Exception e) {
                LOGGER.error("微信服务器校验失败,失败信息:", e);
            }
        }

4.2 SignUtil


    public class SignUtil {
    
        /**
         * 验证签名
         *
         * @param signature signature
         * @param timestamp timestamp
         * @param nonce nonce
         * @return boolean
         * @throws Exception
         */
        public static boolean checkSignature(String signature, String timestamp,
                                             String nonce) throws Exception {
            // 1.将token、timestamp、nonce三个参数进行字典序排序
            String[] arr = new String[] {Constants.WeChat.TOKEN, timestamp, nonce};
            Arrays.sort(arr);
            // 2. 将三个参数字符串拼接成一个字符串进行sha1加密
            StringBuilder content = new StringBuilder();
            for (String anArr : arr) {
                content.append(anArr);
            }
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            String tmpStr = byteToStr(digest);
            // 3.将sha1加密后的字符串可与signature对比,标识该请求来源于微信
            return tmpStr.equals(signature.toUpperCase());
        }
    
        private static String byteToStr(byte[] byteArray) {
            StringBuilder strDigest = new StringBuilder();
            for (byte aByteArray : byteArray) {
                strDigest.append(byteToHexStr(aByteArray));
            }
            return strDigest.toString();
        }
    
        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];
            return new String(tempArr);
        }
    }


5 说明

执行完以上步骤就可以进行正常的开发了,欢迎留言讨论