微信公众号开发-----验证消息的确来自微信服务器(明文模式下)

阅读本文前,请先认真阅读微信官方文档:微信公众号技术文档之接入指南

接入概述

接入微信公众平台开发,开发者需要按照如下步骤完成:

1、填写服务器配置

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

3、依据接口文档实现业务逻辑

本文主要介绍第二个步骤的代码实现。

第二步:验证消息的确来自微信服务器

  1. 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上
    (由于消息加解密方式选择的为明文模式,需加密模式时从官方文档下载Java部分代码,去除注释部分代码即可)

    /**
     * 消息加解密接入
     */
    public class EntryController extends Controller {
    
        public void accept() throws IOException {
            String method = getRequest().getMethod();
            if ("GET".equals(method)) {
                doGet();//开发者模式验证
            }else {
                doPost();//接收消息
            }
        }
    
        /*
         * 响应get请求,微信默认token校验时使用get请求
         */
        private void doGet(){
            //接收微信用来校验信息的内置规定参数
            String msgSignature =getPara("signature");   // 微信加密签名
            String timeStamp = getPara("timestamp");  // 时间戳
            String nonce = getPara("nonce"); // 随机数
            String echoStr = getPara("echostr"); // 随机字符串
    
            //// 创建加密类
            //WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(WechartConst.Token, WechartConst.EncodingAESKey,WechartConst.appId);
            // // 比对msgSignature 用token, timeStamp, nonce加密的参数是否一致,一致证明该接口来自微信,异常则不是来自微信
            //String echostr = wxcpt.verifyUrl(msgSignature, timeStamp, nonce, echoStr);
    
            // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
            //获取微信服务器中配置的Token的值
            String token = SystemConfig.WECHAT_TOKEN;
            if (WechatUtil.checkSignature(msgSignature,token, timeStamp, nonce)){
                //原样返回echostr参数内容
                renderJson(echoStr);
            }
        }
    }
    
  2. 开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:
    1)将token、timestamp、nonce三个参数进行字典序排序
    2)将三个参数字符串拼接成一个字符串进行sha1加密
    3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

    public class WechatUtil {
     	/**
         * 验证消息的确来自微信服务器
         * @param msgSignature 微信加密签名
         * @param token 开发者填写的token参数
         * @param timeStamp 时间戳
         * @param nonce 随机数
         * @return
         * @throws
         */
        public static boolean checkSignature(String msgSignature, String token,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 = BytesParserUtil.byteToStr(digest);
                } catch (NoSuchAlgorithmException e) {
                    e.printStackTrace();
                }
    
                // 3.将sha1加密后的字符串可与signature对比,标识该请求来源于微信
                return tmpStr != null ? tmpStr.equals(msgSignature.toUpperCase()) : false;
            }
    }
    

    注:代码中使用到的工具类请参考: 字节转换工具---- BytesParserUtil

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章