hbyzs

前段时间做了一个微信第三方授权,一直想写一篇文章分享一下,但是总是忙,今天终于有空闲给写出来了,整个流程很简单清晰,在签名验证的地方可能有点儿小坑,并且在用户取消授权的时候,微信api说的是会把消息推送到回调地址中,在这里强调一下这个回调地址不是授权时候的回调地址,而是你申请第三方平台时候填写的授权地址,闲话少说进入正题。(如有问题,可留言交流)

简单流程先描述

  用户点击授权按钮 -> 获取第三方令牌 -> 获取预授权码 -> 进入微信授权页面 -> 用户扫码授权 -> 微信推送授权结果

第一步 维护微信推送的 component_verify_ticket

  在第三方平台创建审核通过后,微信服务器会向其“授权事件接收URL”每隔10分钟定时推送component_verify_ticket,该ticket是加密的xml串,需要解码获取到ticket值(用于获取预授权码);

  解密用的是php的加解密模块(安装php自带的),代码用的是微信提供的。

  代码如下

     $timeStamp  = empty($_GET[\'timestamp\']) ? "" : trim($_GET[\'timestamp\']); // 时间戳
        $nonce      = empty($_GET[\'nonce\']) ? "" : trim($_GET[\'nonce\']); // 随机字符
        $msg_sign   = empty($_GET[\'msg_signature\']) ? "" : trim($_GET[\'msg_signature\']); // 签名(公钥)
        $encryptMsg = file_get_contents(\'php://input\'); // xml

        $xml_tree = new \DOMDocument();
        $xml_tree->loadXML($encryptMsg);
        $array_e = $xml_tree->getElementsByTagName(\'Encrypt\');
        $encrypt = $array_e->item(0)->nodeValue;
        $format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%s]]></Encrypt></xml>";
        $from_xml = sprintf($format, $encrypt);

        // 第三方收到公众号平台发送的消息
        $weixinConfig = Config::get(\'weixin\');
        $appId = $weixinConfig[\'app_id\'];
        $appKey = $weixinConfig[\'app_key\'];
        $appToken = $weixinConfig[\'app_token\'];

        $msg = \'\';
        $pc = new WXBizMsgCrypt( $appToken, $appKey, $appId );
        $errCode = $pc->decryptMsg($msg_sign, $timeStamp, $nonce, $from_xml, $msg);

        // 解密失败
        if ( $errCode != 0 ) {
            echo\'error\';
            return;
        }

        $xml = new \DOMDocument();
        $xml->loadXML($msg);
        $array_auth = $xml->getElementsByTagName(\'InfoType\');
        $infoType = $array_auth->item(0)->nodeValue;
        $array_e = $xml->getElementsByTagName(\'ComponentVerifyTicket\');
        $ticket = $array_e->item(0)->nodeValue;

第二步 获取第三方平台component_access_token

   第三方平台compoment_access_token是第三方平台的下文中接口的调用凭据,也叫做令牌(component_access_token)。每个令牌是存在有效期(2小时)的,且令牌的调用不是无限制的,请第三方平台做好令牌的管理,在令牌快过期时(比如1小时           50分)再进行刷新。 令牌的维护可以参考微信的中控,我的处理方式是通过微信给我推送component_verify_ticket的10分钟间隔来做的。

     代码如下

       $weixinConfig = Config::get(\'weixin\');
        $appId = $weixinConfig[\'app_id\'];
        $appSecret = $weixinConfig[\'app_secret\'];

        $postData = array(
            \'component_appid\' => $appId,
            \'component_appsecret\' => $appSecret,
            \'component_verify_ticket\' => $verifyTicket
        );
        $postData = json_encode( $postData );
        $result = $this->curl_post( \'https://api.weixin.qq.com/cgi-bin/component/api_component_token\', $postData );

第三步 获取预授权码pre_auth_code

  预授权码是每次要用的话通过access_token重新生成的,没有次数限制

  代码如下 

     $weixinConfig = Config::get(\'weixin\');
        $appId = $weixinConfig[\'app_id\'];

        $postData = array(
            \'component_appid\' => $appId
        );
        $postData = json_encode( $postData );
        $result = $this->curl_post( \'https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=\'.$accessToken, $postData );

第四步 进入微信授权页面

  进入微信授权页面会出现一个二维码,用户通过扫码在手机端进行授权操作,这里需要注意的一个东西是,进入微信授权页面时候需要传入一个回调地址,该回调地址后边可以跟参数,这样你本地代码和微信授权服务就一条线连起来了

  代码如下

     $weixinConfig = Config::get(\'weixin\');
        $appId = $weixinConfig[\'app_id\'];
        $hostMaps = Config::get(\'hostMaps\');
        $wxAuthCallback = $hostMaps[\'wx_auth_callback\'];
        $hostMaps = Config::get(\'hostMaps\');
        $wxAuthRequest = $hostMaps[\'wx_auth_request\'];

        $html_text = $this->buildRequestForm( array(), "POST", $wxAuthRequest.\'?component_appid=\'.$appId.\'&pre_auth_code=\'.$preAuthCode.\'&redirect_uri=\'.$wxAuthCallback.\'?callback_param=\'.$callbackParams, true );

    // 同步跳转方法(仿照支付宝)
     protected function buildRequestForm( array $param, $method, $target=\'\',$jump=false) {
          $sHtml = "<meta http-equiv=\'Content-Type\' content=\'text/html; charset=utf-8\' /><form id=\'autoSubmit\' action=\'".$target."\' method=\'".$method."\'>";

          if ( !empty( $param ) ) {
              foreach( $param as $key => $value ) {
                  $sHtml.= "<input type=\'hidden\' name=\'".$key."\' value=\'".urldecode($value)."\'/>";
              }
          }
          $sHtml .= "</form>";

          if($jump) $sHtml = $sHtml."<script>document.getElementById(\"autoSubmit\").submit();</script>";

          return $sHtml;
      }

第五步 微信授权消息推送

  用户授权之后微信接收到授权结果,然后把授权结果推送给你授权时候的回调地址,推送消息里边会有一个 auth_code,你需要通过auth_code获取授权方的access_token(接口调用凭证);

  不同平台需求可能不一样,逻辑简单所以代码就不放了。

  有一点需要注意的是调用凭证access_token有两个小时的有效期,并且access_token获取是有次数限制的,所以需要做好本地维护工作,切入点是获取access_token的时间,每次从数据库中获取access_token时可以先判定一下获取时间然后再决定

  是直接用还是重新获取。

  判定代码如下

strtotime("+ $verityAccessTime minutes", $createTime) < time()

 

微信第三方授权流程网址 https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1453779503&token=&lang=zh_CN

 

本文为原创,创作不易,如要转载请注明本文出处;

 

多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中,这样,后续的相同的查询就不用操作表而直

分类:

技术点:

相关文章: