Java企业微信对接(二)微信端回调到企业端

本文介绍了Java环境下企业微信回调服务的配置与实现,包括回调的必要性、配置的URL、Token和EncodingAESKey,以及如何实现两个回调接口,一个用于验证URL有效性,另一个用于接收回调数据。回调服务能够实现自定义服务行为和及时获取状态变化。文章提供了具体的代码示例,强调了回调域名的配置要求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

准备工作

先下载demo
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
下载完成后的目录,把这些类之间copy到工程里面就行,都是封装好的加密算法
在这里插入图片描述

回调配置

什么时候需要回调

在集成企业微信与内部系统时,我们往往需要搭建一个回调服务。回调服务,可以实现:

自定义丰富的服务行为。比如,用户向应用发消息时,识别消息关键词,回复不同的消息内容;用户点击应用菜单时,转化为指令,执行自动化任务。
可以及时获取到状态变化。比如,通讯录发生变化时,不需要定时去拉取通讯录对比,而是实时地获取到变化的通讯录结点,进行同步。

回调服务需要哪些配置

配置回调服务,需要有三个配置项,分别是:URL, Token, EncodingAESKey。
首先,URL为回调服务地址,由开发者搭建(需要满足接口要求,参考第3部分说明),用于接收通知消息或者事件。
在这里插入图片描述
其次,Token用于计算签名,由英文或数字组成且长度不超过32位的自定义字符串。开发者提供的URL是公开可访问的,这就意味着拿到这个URL,就可以往该链接推送消息。
在这里插入图片描述
最后,EncodingAESKey用于消息内容加密,由英文或数字组成且长度为43位的自定义字符串。由于消息是在公开的因特网上传输,消息内容是可被截获的,如果内容未加密,则截获者可以直接阅读消息内容。若消息内容包含一些敏感信息,就非常危险了。EncodingAESKey就是在这个背景基础上提出,将发送的内容进行加密,并组装成一定格式后再发送。
在这里插入图片描述

回调逻辑实现

需要有2个回调接口,
一个get请求,用来验证url 是否有效
一个post请求,用来接收回调数据

企业微信会先判断URL服务是否具备解析企业微信推送消息的能力。
具体方式是,企业微信往URL服务上发一条Get请求带签名及密文参数到URL服务上,如果URL服务检查签名通过,并能正确返回密文参数对应的明文字符串,则验证通过。此时在企业微信的配置就开始生效。
后续的业务请求(比如应用菜单的点击事件,用户消息等),都会类似的方式(签名+密文)向服务URL推送消息。URL服务验证签名通过后,需要将POST数据解密,就可以得到对应的业务消息明文。

在这里插入图片描述

话不多说,直接上代码,准备2个接口

    /**
     * 验证微信回调地址
     *
     * @author: what
     */
    String verifyURL(String msgSignature, String timestamp, String nonce, String echostr);

    /**
     * 企业微信回调数据
     *
     * @author: what
     */
    String decryptMsg(String msgSignature, String timestamp, String nonce, String postData);

实现类

定义常量

    public static final String CHANGE_TYPE = "ChangeType";
    public static final String CHANGE_TYPE_USER = "_user";
    public static final String CHANGE_TYPE_ORG = "_party";
    public static final String CHANGE_TYPE_ACTION_CREATE = "create";
    public static final String CHANGE_TYPE_ACTION_UPDATE = "update";
    public static final String CHANGE_TYPE_ACTION_DELETE = "delete";
    public static final String DATA_CHANGE_TYPE_USER = "UserID";
    public static final String DATA_CHANGE_TYPE_ORG = "ParentId";

    public static final String ERR_CODE = "errcode";
    public static final String ERR_MSG = "errmsg";
    public static final String UTF_8 = "utf-8";
    public static final String APPLICATION = "application/json";
    public static final String SECRET = "xJLwef4564dfgjc19fdfghd245sddfs-XSc";
    public static final String HTTP_URL_CREATE_USER = "https://qyapi.weixin.qq.com/cgi-bin/user/create?access_token=";
    public static final String HTTP_URL_UPDATE_USER = "https://qyapi.weixin.qq.com/cgi-bin/user/update?access_token=";
    public static final String HTTP_URL_DELETE_USER = "https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete?access_token=";
    public static final String HTTP_URL_CREATE_ORG = "https://qyapi.weixin.qq.com/cgi-bin/department/create?access_token=";
    public static final String HTTP_URL_UPDATE_ORG = "https://qyapi.weixin.qq.com/cgi-bin/department/update?access_token=";
    public static final String HTTP_URL_DELETE_ORG = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?access_token=";
    String sToken = callbackToken;--这个对应下图中的Token
    String sCorpID = appid;--这个对应企业ID
    String sEncodingAESKey = callbackAesKey;--这个对应下图中的EncodingAESKey

在这里插入图片描述

验证url是否有效,用于get请求

    /**
     * 验证微信回调地址
     *
     * @author: what
     */
    @Override
    public String verifyURL(String msgSignature, String timestamp, String nonce, String echostr){
        String sToken = callbackToken;
        String sCorpID = appid;
        String sEncodingAESKey = callbackAesKey;

        WXBizMsgCrypt wxcpt = null;
        String sEchoStr = null;
        try {
            wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID);
            sEchoStr = wxcpt.verifyURL(msgSignature, timestamp, nonce, echostr);
            log.info("验证微信回调地址------------------" + sEchoStr);
        } catch (AesException e) {
            e.printStackTrace();
        }
		return sEchoStr;
    }

接收回调数据,用于post请求

    /**
     * 企业微信回调数据(返回的数据是xml格式,需要把xml转换成json格式)
     *
     * @author: what
     */
    @Override
    public String decryptMsg(String msgSignature, String timestamp, String nonce, String postData){

        String result = "企业微信通讯录回调成功";
        String sToken = callbackToken;
        String sCorpID = appid;
        String sEncodingAESKey = callbackAesKey;
        WXBizMsgCrypt wxcpt = null;
        String sMsg = "";

            try {
                wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID);
                sMsg = wxcpt.decryptMsg(msgSignature, timestamp, nonce, postData);
                if(StringUtils.isNotBlank(sMsg)){
                    JSONObject jsonObject = Xml2JsonTool.xmltoJson(sMsg);
                    JSONObject xml = jsonObject.getJSONObject("xml");
                    //如果包含UserID,就是用户数据变更,如果包含ParentId,就是部门数据变更
                    if(sMsg.indexOf(PubConstant.DATA_CHANGE_TYPE_USER) > 0){
                        if(xml.getString(PubConstant.CHANGE_TYPE).equals(PubConstant.CHANGE_TYPE_ACTION_CREATE + PubConstant.CHANGE_TYPE_USER)){
                            //添加用户逻辑
                        }else if(xml.getString(PubConstant.CHANGE_TYPE).equals(PubConstant.CHANGE_TYPE_ACTION_UPDATE + PubConstant.CHANGE_TYPE_USER)){
                            //修改用户逻辑
                        }else if(xml.getString(PubConstant.CHANGE_TYPE).equals(PubConstant.CHANGE_TYPE_ACTION_DELETE + PubConstant.CHANGE_TYPE_USER)){
                            //删除用户逻辑
                        }
                    }else if(sMsg.indexOf(PubConstant.DATA_CHANGE_TYPE_ORG) > 0){
                        if(xml.getString(PubConstant.CHANGE_TYPE).equals(PubConstant.CHANGE_TYPE_ACTION_CREATE + PubConstant.CHANGE_TYPE_USER)){
							//添加部门逻辑
                        }else if(xml.getString(PubConstant.CHANGE_TYPE).equals(PubConstant.CHANGE_TYPE_ACTION_UPDATE + PubConstant.CHANGE_TYPE_USER)){
							//修改部门逻辑
                        }else if(xml.getString(PubConstant.CHANGE_TYPE).equals(PubConstant.CHANGE_TYPE_ACTION_DELETE + PubConstant.CHANGE_TYPE_USER)){
							//删除部门逻辑
                        }
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        
        return result;
    }

controller

get请求,用于验证url有效

    @ApiOperation(value = "企业微信回调接口验证", notes = "对接人:what")
    @RequestMapping(value = "/callback", method = RequestMethod.GET, produces = "application/json")
    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 {
        String sEchoStr = wxService.verifyURL(msgSignature, timestamp, nonce, echostr);
        PrintWriter out = response.getWriter();
        try {
            //必须要返回解密之后的明文
            if (StringUtils.isNotBlank(sEchoStr)) {
                log.info("企业微信回调接口验证成功~~~");
            } else {
                log.info("企业微信回调接口验证失败!!!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        out.write(sEchoStr);
        out.flush();
    }

post请求用户接收回调数据

    @ApiOperation(value = "企业微信回调接口", notes = "对接人:what")
    @RequestMapping(value = "/callback", method = RequestMethod.POST, produces = "application/json")
    public JsonResult reveiceMsg(final HttpServletRequest request,
                                 @RequestParam(name = "msg_signature") final String sMsgSignature,
                                 @RequestParam(name = "timestamp") final String sTimestamp,
                                 @RequestParam(name = "nonce") final String sNonce) throws Exception {

        InputStream inputStream = request.getInputStream();
        String sPostData = IOUtils.toString(inputStream, "UTF-8");
        log.info("回调数据返回================" + sPostData);
        String sEchoStr = wxService.decryptMsg(sMsgSignature, sTimestamp, sNonce, sPostData);
        return JsonResult.ok(sEchoStr);
    }

配置回调域名

一定要记得配置url,必须是备案域名,还有就是ip可信名单,其他的按照这里写基本就没问题了

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

珍妮玛•黛金

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值