大家都知道,微信中調(diào)用訂閱用戶接口中需要Access_token,而根據(jù)微信官方文檔中說明:access_token是公眾號的全局唯一票據(jù),公眾號調(diào)用各接口時都需使用access_token。正常情況下access_token有效期為7200秒,重復(fù)獲取將導(dǎo)致上次獲取的access_token失效 所以這就導(dǎo)致我們每次去獲取訂閱用戶相關(guān)信息的時候都去重新取access_token。這就造成兩個問題。 1. 慢,因為取access_token是遠(yuǎn)程在騰訊提供的API網(wǎng)址上,所以會有一定的延遲。 2. 訪問次數(shù)越多,超出接口調(diào)用限制,會被騰訊限制。我就遭過。后來查API手冊才知道有這句話: 默認(rèn)每個公眾賬號都不能超過下面的頻率限制。 當(dāng)超出調(diào)用接口頻率限制,調(diào)用對應(yīng)接口將會收到如下錯誤信息: {"errcode":45009,"errmsg":"api freq out of limit"}
接口名稱 頻率限制
獲取憑證接口 200(次/天)
自定義菜單創(chuàng)建接口 100(次/天)
自定義菜單查詢接口 1000(次/天)
自定義菜單刪除接口 100(次/天)
所以針對此問題,我想出了用文本文件或XML來存取動態(tài)的access_token。反正2小時才過期,寫入又不頻繁。當(dāng)然你也可以存取到數(shù)據(jù)庫。
同樣的我用到了SAE的Storage
然后對訪問用戶相關(guān)信息和得到AccessToken的類 進(jìn)行了封裝:
//得到訂閱用戶 (返回數(shù)組)
public function GetUserList()
{
$strjson = $this -> GetUrlReturn("https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s");
$openidarr= $strjson->data->openid;
//print_r($openidarr); 調(diào)試
return $openidarr;
}
//得到訂閱用戶詳情(返回對象)
public function GetUserDetail($openid)
{
$url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid={$openid}";
$strjson = $this -> GetUrlReturn($url);
return $strjson;
}
/*
*
* 私有成員變量 存token值
* 因為//access_token是公眾號的全局唯一票據(jù),公眾號調(diào)用各接口時都需使用access_token。
* 正常情況下access_token有效期為7200秒,重復(fù)獲取將導(dǎo)致上次獲取的access_token失效。
*/
private $_token ;
/*
*
* 私有方法
*
*/
//得到Token對象并寫入到配置文件
private function InitToken()
{
$url = sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",APPID, SECRET);
//echo APPID;
$ch = curl_init(); //創(chuàng)建一個新url資源
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$a = curl_exec($ch);
$strjson=json_decode($a);
$token = $strjson->access_token;
if (empty($token))
{
//修改 {"errcode":45009,"errmsg":"api freq out of limit"}
echo "錯誤:取得token無效,可能是調(diào)用太頻繁!"; //$strjson
throw new Exception('錯誤:取得token無效');
}
$obj = fopen("saestor://weixindata/token.txt","w+"); //SAE禁用fopen本地文件,這里需要Storage
fwrite($obj,$token);
$this -> _token = $token;
}
//封裝私有方法,調(diào)用得到Get的參數(shù),$needToken默認(rèn)為false, 不取值,這里有一個潛規(guī)則,%s為 self::$_token
private function GetUrlReturn($url, $needToken = false)
{
//第一次為空,則從文件中讀取
if (empty($this -> _token))
{
$obj = fopen("saestor://weixindata/token.txt","r");
$this -> _token = fgets($obj,1000);
}
//為空則重新取值
if (empty($this -> _token) || $needToken)
{
$this ->InitToken();
}
$newurl = sprintf($url, $this -> _token);
$ch = curl_init(); //創(chuàng)建一個新url資源
curl_setopt($ch, CURLOPT_URL,$newurl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$a = curl_exec($ch);
$strjson=json_decode($a);
//var_dump($strjson); //開啟可調(diào)試
if (!empty($strjson-> errcode))
{
switch ($strjson-> errcode){
case 40001:
$this -> GetUrlReturn($url, true); //重新取值,可能是過期導(dǎo)致
break;
case 41001:
throw new Exception("缺少access_token參數(shù):".$strjson->errmsg);
break;
default:
throw new Exception($strjson->errmsg); //其他錯誤,拋出
break;
}
}
return $strjson;
}
這是我想到的辦法,歡迎大家給出更好的方法,相互學(xué)習(xí),相互提高。 |
|
|
來自: star_xiong > 《php》