**

企业微信第三方应用开发–回调配置

**
前言:经过一段时间的研究,终于把相关配置成功实现。在这个过程中遇到各种坑,也查阅了不少的博客都未能解决问题,最后研究官方的java事例demo加已实现。下面会将流程和踩过的坑周一阐述,感谢浏览。

1.下载官方样例demo

1.1入口

java 解密企业微信回调 企业微信回调配置_spring


1.2选择连接下载

java 解密企业微信回调 企业微信回调配置_java_02


1.3解压后的demo结构

java 解密企业微信回调 企业微信回调配置_java 解密企业微信回调_03


会发现,我们无法直接验证;要对其进行改造

2对demo进行改造

2.1新建一个spring-boot项目,并将刚刚下载的demo移植过来,项目结构如下:

java 解密企业微信回调 企业微信回调配置_spring_04

当然,根据个人需要对原有的官方demo方法有一定的改造,这个就不详细说了。主要是针对WXBizMsgCrypt,去对比下就发现了。2.2项目启动端口8080,你需要通过Nginx代理下,回调地址需要域名的形式

java 解密企业微信回调 企业微信回调配置_spring_05

2.3Sample类demo

```java
package com.example.demo.controller;

import com.example.demo.controller.aes.MessageUtil;
import com.example.demo.controller.aes.QywechatCallback;
import com.example.demo.controller.aes.QywechatUserBean;
import com.example.demo.controller.aes.WXBizMsgCrypt;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.io.IOUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Map;

@Slf4j
@Controller
@RequestMapping("/api/qywechat")
public class Sample {

    /**
     * get 请求  验签.
     *
     * @param msgSignature 加密
     * @param timestamp    时间戳
     * @param nonce        随机
     * @param echostr      .
     * @param response     .
     * @throws Exception .
     */
    @GetMapping(value = "/callback")
    public void reveiceMsg(@RequestParam(name = "msg_signature") final String msgSignature,
                           @RequestParam(name = "timestamp") final String timestamp,
                           @RequestParam(name = "nonce") final String nonce,
                           @RequestParam(name = "echostr") final String echostr,
                           final HttpServletResponse response) throws Exception {
        //企业回调的url-----该url不做任何的业务逻辑,仅仅微信查看是否可以调通.
        QywechatCallback qywechatCallback = QywechatCallback.TEST;
        log.info(" msg_signature {}, timestamp {}, nonce {} , echostr {}", msgSignature, timestamp, nonce, echostr);
        WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(qywechatCallback, qywechatCallback.getCorpid());
        // 随机字符串
        String sEchoStr = wxcpt.VerifyURL(msgSignature, timestamp, nonce, echostr);
        PrintWriter out = response.getWriter();
        try {
            //必须要返回解密之后的明文
            if (StringUtils.isBlank(sEchoStr)) {
                log.info("URL验证失败");
            } else {
                log.info("验证成功!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        out.write(sEchoStr);
        out.flush();
    }

    /**
     * post 请求  验签.
     *
     * @param request
     * @throws Exception .
     */
    @RequestMapping(value = "/callback", method = RequestMethod.POST)
    public void reveiceMsg(HttpServletRequest request, HttpServletResponse response) throws Exception {
        QywechatCallback qywechatCallback = QywechatCallback.TEST;
        String sMsgSignature = request.getParameter("msg_signature");
        String sTimestamp = request.getParameter("timestamp");
        String sNonce = request.getParameter("nonce");
        InputStream inputStream = request.getInputStream();
        String sPostData = IOUtils.toString(inputStream, "UTF-8");
        PrintWriter out = response.getWriter();
        try {
            QywechatUserBean qywechatUserBean = new QywechatUserBean();
            qywechatUserBean.setMsgSignature(sMsgSignature);
            qywechatUserBean.setNonce(sNonce);
            qywechatUserBean.setQywechatCallback(qywechatCallback);
            qywechatUserBean.setTimestamp(sTimestamp);
            qywechatUserBean.setSPostData(sPostData);
            //下面这些操作都可以异步  如果处理请求比较慢,企业微信会重复推送 这里需要去重保证执行唯一
            WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(qywechatUserBean.getQywechatCallback(), qywechatCallback.getSuiteid());

            //解密
            String sMsg = wxcpt.DecryptMsg(qywechatUserBean);
            //将post数据转换为map
            Map<String, String> dataMap = MessageUtil.parseXml(sMsg);
            //处理逻辑
            log.info("===========>dataMap: " + dataMap);
            out.write("success");
        } catch (Exception e) {
            e.printStackTrace();
            out.write("fail");
        }
        out.flush();
    }

}

2.4将官方jar包作为本地jar包使用的原因
不应用情况下:
1)报错现象

Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible value. Expected the discarded bits to be zero. 异常

通过查阅博客会发现将:

aesKey = Base64.decodeBase64(encodingAesKey + "=");

改为:

aesKey = Base64.decodeBase64(UUID.randomUUID().toString().replaceAll("-","").getBytes());

可解决该错误

修改位置:

java 解密企业微信回调 企业微信回调配置_java_06


2)报错现象

在1)的情况下

Java heap space

查阅相关博客,说堆栈太小,通过一些列操作你发现修改无效。那是idea修改堆栈大小在帮助里

java 解密企业微信回调 企业微信回调配置_spring_07


java 解密企业微信回调 企业微信回调配置_spring_08


改了一通,重启idea,堆栈内存修改成功。但没用,心里一阵mmp啊。还是老老实实研究demo吧。2.5研究发现,虽然都是import org.apache.commons.codec.binary.Base64;,但不是同一个包。那就吧官方的包作为本地包使用吧。

java 解密企业微信回调 企业微信回调配置_java_09


注意:如果项目只有一个模块,到这里就解决问题了。但若是多个模块,你得把包添加到对应的模块中,才引用的到。

具体方法:点击模块,F4打开模块设置,添加

java 解密企业微信回调 企业微信回调配置_apache_10


java 解密企业微信回调 企业微信回调配置_apache_11


终于完事了。

看看有那写回调配置可以使用:

java 解密企业微信回调 企业微信回调配置_apache_12


java 解密企业微信回调 企业微信回调配置_spring_13


java 解密企业微信回调 企业微信回调配置_java_14


java 解密企业微信回调 企业微信回调配置_java 解密企业微信回调_15