微信第三方授权

前段时间做了一个微信第三方授权,一直想写一篇文章分享一下,但是总是忙,今天终于有空闲给写出来了,整个流程很简单清晰,在签名验证的地方可能有点儿小坑,并且在用户取消授权的时候,微信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的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中,这样,后续的相同的查询就不用操作表而直

posted @ 2017-06-01 17:25  湖边油纸伞  阅读(1502)  评论(0编辑  收藏  举报