欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微信开放平台_第三方平台授权流程_验证票据

程序员文章站 2023-12-23 09:41:10
...

一、验证票据

1.1 官方说明:

验证票据(component_verify_ticket):在第三方平台创建审核通过后,微信服务器会向其“授权事件接收URL” 每隔 10 分钟以 POST 的方式推送 component_verify_ticket

接收 POST 请求后,只需直接返回字符串 success。为了加强安全性,postdata 中的 xml 将使用服务申请时的加解密 key 来进行加密,具体请见《加密解密技术方案》, 在收到推送后需进行解密(详细请见《消息加解密接入指引》

作用:获取令牌时,需要使用票据值作为参数(component_verify_ticket)。

1.2 获取流程及示意代码

微信服务器会向其 ”授权事件接收URL” 每隔 10 分钟以 POST 的方式推送( component_verify_ticket)

授权事件接收URL:“在开放平台管理中心”中寻找,如下图。填写完整的URL请求路径。

(比如请求路径填写为:http://登录授权的发起页域名/项目名/api/wx/open/getComponentVerifyTicket

微信开放平台_第三方平台授权流程_验证票据

 

获取票据(componentVerifyTicket),示意代码:

SpringMVC形式的Controller层:

    /**
     * 接收微信服务器发送的component_verify_ticket
     */
    @PostMapping("/getComponentVerifyTicket")
    public String getComponentVerifyTicket(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("接收微信服务器发送的component_verify_ticket  begin");
        try {
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            // 微信加密签名
            String msg_signature = request.getParameter("msg_signature");
            // 时间戳
            String timestamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            // 从请求中读取整个post数据
            InputStream inputStream;
            String postData = null;
            inputStream = request.getInputStream();
            postData=IOUtils.toString(inputStream, "UTF-8");    //获取接收到消息里的XML密文,存放在postData中
            log.info("postData:"+postData);

            WXBizMsgCrypt wxcpt = null;
            log.info("postData:"+postData);
            log.info("msg_signature:"+msg_signature);
            log.info("timestamp:"+timestamp);
            log.info("nonce:"+nonce);
            log.info("getServetoken:"+ComponentConfig.TOKEN);        //token
            log.info("getServeencodingaeskey:"+ComponentConfig.AESKEY);       //aeskey
            log.info("getServeappid:"+ComponentConfig.APPID);         //appid
            log.info("ip:"+ NetworkUtil.getIpAddress(request));

            //从XML中获取<Encrypt></Encrypt>标签内的密文文本
            String encrypt = XMLUtil2.getLabelFromXml(postData,"Encrypt");
            log.info("Encrypt:"+encrypt);
            //格式化密文文本,否则没有<ToUserName>标签,会解密失败,参考官方的加解密代码JAVA版本
            String format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%1$s]]></Encrypt></xml>";
            String fromXML = String.format(format, encrypt);

            String msg = "";   //解密后的明文
            if(StringUtil.isEmpty(encrypt)) {
                msg = fromXML;
            } else {
                wxcpt = new WXBizMsgCrypt(ComponentConfig.TOKEN,ComponentConfig.AESKEY,ComponentConfig.APPID);
                // 解密消息
                msg = wxcpt.decryptMsg(msg_signature, timestamp, nonce, fromXML);
            }
            log.info("msg:"+msg);
            //将XML格式字符串转为Map类型
            Map<String, String> msgMap = XMLUtil.xmlToMap(msg);
            String infotype = msgMap.get("InfoType");  //获取infotype,注:微信开放平台文档中标明固定为:"component_verify_ticket",但参考其他代码,还包含authorized???
            log.info(infotype);
            switch (infotype){
                case "component_verify_ticket":   //验证票据
                    String ComponentVerifyTicket = msgMap.get("ComponentVerifyTicket");  
                    webChatCatchUtil.setWeixinOpenComponentVerifyTicket(ComponentVerifyTicket);   //将票据值写入Redis缓存中
                    log.info("component_verify_ticket:"+ComponentVerifyTicket);
                    break;
                case "unauthorized"://用户取消授权
                    break;
            }
        } catch (Exception e) {
            log.error("Exception",e);
        }
        return "success";
    }

使用wxcpt.decryptMsg获取到的解密后的result示例:

<xml>
<
AppId>some_appid</AppId>
<
CreateTime>1413192605</CreateTime>
<
InfoType>component_verify_ticket</InfoType>
<
ComponentVerifyTicket>some_verify_ticket</ComponentVerifyTicket>
</
xml>

注意:

component_verify_ticket 的有效时间较 component_access_token 更长,建议保存最近可用的component_verify_ticket,在 component_access_token 过期之前可以直接使用该 component_verify_ticket 进行更新,避免出现因为 component_verify_ticket 接收失败而无法更新 component_access_token 的情况。

 

上一篇:

下一篇: