首页 > 微信公众平台access_token问题

微信公众平台access_token问题

微信公众平台的接口基本都要access_token验证,为了避免每次调用接口都获取一次acces_token,我把获取到的access_token写到了文件中,再过期之前会去重新请求。

现在有一个问题就是,假如在当天23:24获取到了access_token,access_token的过期时间会在第二天的01:24,但是此时获取到的access_token不对,请求接口的时候一直报错,错误为"invalid access_token"。其他时段都正常,不知道 问题出在哪里了。

微信接口类:

<?php
namespace Common\Wechat;
use \Common\Wechat\WechatUtil;

class WechatBase extends WechatUtil{
    // 接口公用URL前缀
    const API_URL_PREFIX = 'https://api.weixin.qq.com/cgi-bin';
    const API_BASE_URL_PREFIX = 'https://api.weixin.qq.com'; 
    const OAUTH_PREFIX = 'https://open.weixin.qq.com/connect/oauth2';
    const AUTH_URL = '/token?grant_type=client_credential&';
    const CALLBACKSERVER_GET_URL = '/getcallbackip?';

    // 接口所需参数
    public $token;
    public $encodingAesKey;
    public $appid;
    public $appsecret;
    public $mchid;
    public $apikey;

    public $access_token;

    public function __construct($options){
        $this->token = isset($options['token'])?$options['token']:'';
        $this->encodingAesKey = isset($options['encodingaeskey'])?$options['encodingaeskey']:'';
        $this->appid = isset($options['appid'])?$options['appid']:'';
        $this->appsecret = isset($options['appsecret'])?$options['appsecret']:'';
        $this->mchid = isset($options['mchid'])?$options['mchid']:'';
        $this->apikey = isset($options['apikey'])?$options['apikey']:'';
        $this->account =  isset($options['account'])?$options['account']:'';
    }

    /**
     * For weixin server validation
     */
    private function checkSignature($str=''){
        $signature = isset($_GET["signature"])?$_GET["signature"]:'';
        $signature = isset($_GET["msg_signature"])?$_GET["msg_signature"]:$signature; //如果存在加密验证则用加密验证段
        $timestamp = isset($_GET["timestamp"])?$_GET["timestamp"]:'';
        $nonce = isset($_GET["nonce"])?$_GET["nonce"]:'';

        $token = $this->token;
        $tmpArr = array($token, $timestamp, $nonce,$str);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode( $tmpArr );
        $tmpStr = sha1( $tmpStr );

        if( $tmpStr == $signature ){
            return true;
        }else{
            return false;
        }
    }

    /**
     * For weixin server validation
     * @param bool $return 是否返回
     */
    public function valid($return=false)
    {
        $encryptStr="";
        if ($_SERVER['REQUEST_METHOD'] == "POST") {
            $postStr = file_get_contents("php://input");
            $array = (array)simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $this->encrypt_type = isset($_GET["encrypt_type"]) ? $_GET["encrypt_type"]: '';
            if ($this->encrypt_type == 'aes') { //aes加密
                $this->log($postStr);
                $encryptStr = $array['Encrypt'];
                $pc = new Prpcrypt($this->encodingAesKey);
                $array = $pc->decrypt($encryptStr,$this->appid);
                if (!isset($array[0]) || ($array[0] != 0)) {
                    if (!$return) {
                        die('decrypt error!');
                    } else {
                        return false;
                    }
                }
                $this->postxml = $array[1];
                if (!$this->appid)
                    $this->appid = $array[2];//为了没有appid的订阅号。
            } else {
                $this->postxml = $postStr;
            }
        } elseif (isset($_GET["echostr"])) {
            $echoStr = $_GET["echostr"];
            if ($return) {
                if ($this->checkSignature())
                    return $echoStr;
                else
                    return false;
            } else {
                if ($this->checkSignature())
                    die($echoStr);
                else
                    die('no access');
            }
        }

        if (!$this->checkSignature($encryptStr)) {
            if ($return)
                return false;
            else
                die('no access');
        }
        return true;
    }

    /**
     * 设置缓存,按需重载
     * @param string $cachename
     * @param mixed $value
     * @param int $expired
     * @return boolean
     */
    public function setCache($cachename,$value,$expired){
        $cache_info = array(
                $cachename=>$value,
                'expired'=>$expired+time(),
            );
        $cache_info = json_encode($cache_info);
        file_put_contents(DATA_PATH.$cachename.'.json', $cache_info);
    }

    /**
     * 获取缓存,按需重载
     * @param string $cachename
     * @return mixed
     */
    protected function getCache($cachename){
        $cache_info = file_get_contents(DATA_PATH.$cachename.'.json');
        $cache_info = json_decode($cache_info, true);
        if (time() <= $cache_info['expired']) {
            return $cache_info[$cachename];
        }
        return false;
    }

    /**
     * 清除缓存,按需重载
     * @param string $cachename
     * @return boolean
     */
    protected function removeCache($cachename){
        return false;
    }

    /**
     * 获取access_token
     * @param string $appid 如在类初始化时已提供,则可为空
     * @param string $appsecret 如在类初始化时已提供,则可为空
     * @param string $token 手动指定access_token,非必要情况不建议用
     */
    public function checkAuth($appid='',$appsecret='',$token=''){
        if (!$appid || !$appsecret) {
            $appid = $this->appid;
            $appsecret = $this->appsecret;
        }
        if ($token) { //手动指定token,优先使用
            $this->access_token=$token;
            return $this->access_token;
        }

        $authname = 'wechat_access_token_'.$appid;
        if ($rs = $this->getCache($authname))  {
            $this->access_token = $rs;
            return $rs;
        }
        $result = $this->http_get(self::API_URL_PREFIX.self::AUTH_URL.'appid='.$appid.'&secret='.$appsecret);
        if ($result)
        {
            $json = json_decode($result,true);
            if (!$json || isset($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            $this->access_token = $json['access_token'];
            $expire = $json['expires_in'] ? intval($json['expires_in'])-180 : 3600;
            $this->setCache($authname,$this->access_token,$expire);
            return $this->access_token;
        }
        return false;
    }

    /**
     * 删除验证数据
     * @param string $appid
     */
    public function resetAuth($appid=''){
        if (!$appid) $appid = $this->appid;
        $this->access_token = '';
        $authname = 'wechat_access_token'.$appid;
        $this->removeCache($authname);
        return true;
    }

    /**
     * 获取微信服务器IP地址列表
     * @return array('127.0.0.1','127.0.0.1')
     */
    public function getServerIp(){
        if (!$this->access_token && !$this->checkAuth()) return false;
        $result = $this->http_get(self::API_URL_PREFIX.self::CALLBACKSERVER_GET_URL.'access_token='.$this->access_token);
        if ($result)
        {
            $json = json_decode($result,true);
            if (!$json || isset($json['errcode'])) {
                $this->errCode = $json['errcode'];
                $this->errMsg = $json['errmsg'];
                return false;
            }
            return $json['ip_list'];
        }
        return false;
    }

}
?>

存到文件里的access_token示例:

{"wechat_access_token_wx3ec688XXXXXXXXd":"37vCDdOYC1nbgDZD__-Qs_poFtAmYkumU7xxxxx6Lj66_xJ8bj8LDFY3SwvBe1QHQ4HT_fzMjSAZeeQ-BhvVvUh8K00j4CWFOVa-N4QQTcAFAVVY","expired":1451410983}

上面已经有答案了,补充下,accesstoken有刷新接口,有效期一周


1.微信的 AccessToken 有效期为两个小时,每日调用接口上限为 2000次,也就是说,你一分钟调用一次完全可以的,精确到秒必然会在某些情况下出错。

2.还有就是看了一下楼主的代码,每次都要去读取文件,然后比较时间差。其实完全没必要这样,如果单纯用文件做缓存的话,比较文件修改时间就可以了。


千万不要两小时才刷新 这个坑把我折腾死了 最好是一小时刷新一次 然后检测到错误或者失效再主动获取一次


access_token只有两个小时的有效时间,要定时重新获取


上面已经有答案了,补充下,accesstoken可以刷新

详情见 http://mp.weixin.qq.com/wiki/4/9ac2e7b1f1d22e9e57260f6553822520.html



为什么要过期了才刷新呢,可以提前一些时间试试,我都是一个小时刷新一次,没出过问题.
你看看你刷新了之后,存到文件里面的accesstoken是否改变了

【热门文章】
【热门文章】