微信第三方获取component_verify_ticket接口

时间:2024-04-11 21:41:13

在第三方平台创建审核通过后,微信服务器会向其“授权事件接收URL”每隔10分钟定时推送component_verify_ticket。第三方平台方在收到ticket推送后也需进行解密(详细请见【消息加解密接入指引】),接收到后必须直接返回字符串success。

1. 获取component_verify_ticket接口配置

        接口名要与微信开发平台第三方平台上配置的"授权事件接收URL"接口名对应。

例:getComponentVerifyTicket

微信第三方获取component_verify_ticket接口

  微信第三方获取component_verify_ticket接口

微信第三方获取component_verify_ticket接口

2. 写接口

/**
    * 接收component_verify_ticket 或 authorized事件
    */
   @SuppressWarnings({ "rawtypes", "unchecked" })
   @ApiOperation(value = "接收component_verify_ticket 或 authorized事件", notes = "接收component_verify_ticket 或 authorized事件", response = String.class)
   @RequestMapping(value = "getComponentVerifyTicket")
   public void getComponentVerifyTicket(HttpServletRequest request, HttpServletResponse response) throws Exception {
      logger.info("接收component_verify_ticket 或 authorized事件");
      String nonce = request.getParameter("nonce");
      String timestamp = request.getParameter("timestamp");
      String msgSignature = request.getParameter("msg_signature");

      StringBuilder sb = new StringBuilder();
      BufferedReader in = request.getReader();
      String line;
      while((line = in.readLine()) != null) {
         sb.append(line);
      }
      String postData = sb.toString();
      logger.info("nonce: " + nonce);
      logger.info("timestamp: " + timestamp);
      logger.info("msgSignature: " + msgSignature);
      logger.info("postData: " + postData);
      thirdPartyService.getComponentVerifyTicket(timestamp, nonce, msgSignature, postData);
      responseUtil(response, "success");
//    return "success";
   }
@Override
public void getComponentVerifyTicket(String timestamp, String nonce, String msgSignature, String postData) throws Exception {
   // 需要加密的明文
   WXBizMsgCrypt pc = new WXBizMsgCrypt(TOKEN, ENCODING_AES_KEY, THIRD_PARTY_APP_ID);

   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
   dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
   dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
   dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
   dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
   dbf.setXIncludeAware(false);
   dbf.setExpandEntityReferences(false);
   DocumentBuilder db = dbf.newDocumentBuilder();
   StringReader sr = new StringReader(postData);
   InputSource is = new InputSource(sr);
   Document document = db.parse(is);

   Element root = document.getDocumentElement();
   NodeList nodelist1 = root.getElementsByTagName("Encrypt");
   String encrypt = nodelist1.item(0).getTextContent();

   String format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%1$s]]></Encrypt></xml>";
   String fromXML = String.format(format, encrypt);

   String result = pc.decryptMsg(msgSignature, timestamp, nonce, fromXML);
   logger.info("解密后: " + result);

   //获取ComponentVerifyTicket
   Map<String, String> xmlMap = xmlToMap(result);
   String componentVerifyTicket = xmlMap.get("ComponentVerifyTicket");
   if(StringUtils.isNotBlank(componentVerifyTicket)) {
      //获取ticket,没有则为authorized事件
      RedisUtils.set("ComponentVerifyTicket", componentVerifyTicket);
      logger.info("ComponentVerifyTicket: " + componentVerifyTicket);
   }
}

3. 坑

a. 需要注意的是这个接口会有两种数据形式访问,一个是component_verify_ticket,解密后有ComponentVerifyTicket这个参数,另一个是authorized事件,解密后没有ComponentVerifyTicket这个参数,因此在获取componentVerifyTicket时要加个判断。

微信第三方获取component_verify_ticket接口

b. 同时需要注意的是,解密时要加上<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%1$s]]></Encrypt></xml>

微信第三方获取component_verify_ticket接口

原因是官方的demo文件里,类XMLParse.java里,提取出xml数据包中的加密消息这个方法(extract(String xmltext))有一步需要获取字段ToUserName,

 

微信第三方获取component_verify_ticket接口

而原数据没有这个字段,所以或报异常。

c. 在全网发布检测时“组件ticket正确接收”一直失败但日志显示无异常的原因:方法要返回’success‘,并且不能直接return 'success',要使用response输出’success‘。

注:

1. TOKEN , ENCODING_AES_KEY, THIRD_PARTY_APP_ID 都是第三方的配置参数

其中TOKEN为消息校验Token, ENCODING_AES_KEY为消息加解密Key, THIRD_PARTY_APP_ID 为第三方平台的app_id

微信第三方获取component_verify_ticket接口

2.注意要把自己测试的机子的ip在自己的微信开发平台第三方平台里加入白名单

 

微信第三方获取component_verify_ticket接口

3. 测试

登入微信开放平台https://open.weixin.qq.com/

登入账号进入第三方平台,点击全网发布

 

微信第三方获取component_verify_ticket接口

微信第三方获取component_verify_ticket接口

点击确认后可进行测试。

 

微信第三方获取component_verify_ticket接口

 

参考文档:授权流程技术说明 https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1453779503&token=&lang=