微信公众平台的接口基本都要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}
千万不要两小时才刷新 这个坑把我折腾死了 最好是一小时刷新一次 然后检测到错误或者失效再主动获取一次