企业微信开发之回调

   注册企业微信,开发企业微信服务商管理后台,应用管理-网页应用,建立一个应用。具体如下:

企业微信开发之回调_第1张图片 图一
企业微信开发之回调_第2张图片 图二
企业微信开发之回调_第3张图片 图三

 

       数据回调和指令回调,可以是一个接口,也可以是分开,在这里我使用的是一个接口。

       数据回调是直接调用,查看是否接口可以调通。指令回调是给后端的接口传送推一些数据,比如suit_token等。

       整体逻辑: 

      1、从request中拿到签名(signature)、时间戳(timestamp)、随机字符串(nonce) 和验证回调的URL的有效性传入的字符串(echostr).

/**url中的签名**/
String signature = request.getParameter("msg_signature");
/**url中的时间戳*/
String timestamp = request.getParameter("timestamp");
/** url中的随机字符串 **/
String nonce = request.getParameter("nonce");
/** 创建套件时验证回调url有效性时传入**/
String echostr = request.getParameter("echostr");

      2、首先是一个不做任何操作,仅仅验证该url是否可以调用的操作。需要对echostr进行解密操作,然后再将解密后的值返回给企业微信,这样就证明这个URL可以对密文进行解密。是可以调通的。注意:这个时间在实例化WXBizMsgCrypt用的是corpId。 WXBizMsgCrypt是企业微信提供的工具类。

/**
 * 企业回调的url-----该url不做任何的业务逻辑,仅仅微信查看是否可以调通
 */
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(Token, EncodingAESKey, CorpID);
sEchoStr = wxcpt.verifyURL(signature, timestamp, nonce, echostr);
//必须要返回解密之后的明文
response.getWriter().write(sEchoStr);

 

WXBizMsgCrypt方法: 

/**
 * 构造函数
 * @param token 公众平台上,开发者设置的token
 * @param encodingAesKey 公众平台上,开发者设置的EncodingAESKey
 * @param receiveId企业的corpid/suiteID,
 *
 * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
 */
public WXBizMsgCrypt(String token, String encodingAesKey, String receiveId) throws AesException {
   if (encodingAesKey.length() != 43) {
      throw new AesException(AesException.IllegalAesKey);
   }

   this.token = token;
   this.receiveId= receiveId;
   aesKey = Base64.decodeBase64(encodingAesKey + "=");
}

   

      3、指令回调需要传递一些数据到后端接口,这时候需要将这些数据(request.getInputStream)转化为string,然后再将这个string进行解密,转化成xml文件,然后根据xml文件中的类型,进行操作。注意:这个在实例化的时候用的是suiteID。

       首先是将流转换为string的方法:

    然后是将流转换为string,然后方法得到的string解密,然后再解析xml,根据xml中的 InfoType得到不同类型的回调数据

/**
 * 数据回调URL,用于接收托管企业微信应用的用户消息和用户事件 系统将会把此应用的授权变更事件以及ticket参数等推送给此URL
 * */
String postData = getStringInputstream(request);
QywxCallBackInfo callBackInfo = QywxUtil.getDecryptCallBackInfo(postData, signature, timestamp, nonce, QywxBase.sSuiteID);
String infoType = callBackInfo.getInfoType();
logger.warn("infoType"+infoType);
if (!StringUtils.isBlank(infoType)) {
    switch (infoType) {
        /**
         * 开始推送---票据
         */
        case "suite_ticket":
            if (!StringUtils.isEmpty(callBackInfo.getSuiteTicket())) {
                      //得到suite_ticket
                logger.warn("suiteId"+callBackInfo.getSuiteId()+"ticket"+ callBackInfo.getSuiteTicket());
               
            }
            break;
        case "create_auth":
            /**
             * 开始授权----从企业微信应用市场发起授权时,企业微信后台会推送授权成功通知。
             * 服务商的响应必须在1000ms内完成,以保证用户安装应用的体验。建议在接收到此事件时,先记录下AuthCode,并立即回                               应企业微信,之后再做相关业务的处理。
             */
            break;
        case "change_auth":
            break;
        case "cancel_auth":
            /**
             * 取消授权
             */
            break;
        case "contact_sync":
            break;
        default:
            break;
    }
}
 //返回值,必须是success
response.getWriter().write("success");

 

上面的代码用到的相关方法如下:

/**
     * 根据不同的类型得到不同的回调
     */
    public static QywxCallBackInfo getDecryptCallBackInfo(String encryptPostData, String msgSignature, String timestamp, String nonce, String receiveId) throws Exception {
        QywxCallBackInfo callBackInfo = new QywxCallBackInfo();
            /**
             * 备注:在企业内部的工具类中有!from_corpid.equals(corpId)的校验,
             * 但是在第三方应用的时候,由于postDate解密得到的是安装该应用的fromCorpID,所以不能进行比较
             */
            WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(QywxBase.sToken, QywxBase.sEncodingAESKey, receiveId);
            String decryptPostData = wxBizMsgCrypt.DecryptMsg(msgSignature, timestamp, nonce, encryptPostData);
            System.out.println("decryptPostData" + decryptPostData);
            //开始解析xml
            Element root  = getXMLCDATA(decryptPostData);
            System.out.println("root" + root);
            Node infoTypeNode = root.getElementsByTagName("InfoType").item(0);
            Node suiteIdNode = root.getElementsByTagName("SuiteId").item(0);
            Node timestampNode = root.getElementsByTagName("TimeStamp").item(0);
            Node authCorpIdNode = root.getElementsByTagName("AuthCorpId").item(0);
            Node authCodeNode = root.getElementsByTagName("AuthCode").item(0);
            Node suiteTicketNode = root.getElementsByTagName("SuiteTicket").item(0);
            Node seqNode = root.getElementsByTagName("Seq").item(0);
            if (infoTypeNode != null) {
                callBackInfo.setInfoType(infoTypeNode.getTextContent());
            }
            if (suiteIdNode != null) {
                callBackInfo.setSuiteId(suiteIdNode.getTextContent());
            }
            if (timestampNode != null) {
                callBackInfo.setTimeStamp(timestampNode.getTextContent());
            }
            if (authCorpIdNode != null) {
                callBackInfo.setAuthCorpId(authCorpIdNode.getTextContent());
            }
            if (authCodeNode != null) {
                callBackInfo.setAuthCode(authCodeNode.getTextContent());
            }
            if (suiteTicketNode != null) {
                callBackInfo.setSuiteTicket(suiteTicketNode.getTextContent());
            }
            if (seqNode != null) {
                callBackInfo.setSeq(seqNode.getTextContent());
            }
        return callBackInfo;
    }

    public static Element getXMLCDATA(String requestStr) {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            StringReader sr = new StringReader(requestStr);
            InputSource is = new InputSource(sr);
            Document document = db.parse(is);
            Element root = document.getDocumentElement();
            return root;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    public static String getStringInputstream(HttpServletRequest request) {
        StringBuffer strb = new StringBuffer();
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
            String str = null;
            while (null != (str = reader.readLine())) {
                strb.append(str);
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return strb.toString();
    }

   

   QywxCallBackInfo 是一个实体类,里面就是几个字段。

    至此,已经完成了回调,如有不对之处,请指正。

 

 

 

 

 

 

你可能感兴趣的:(对接第三方)