的access_token的擷取次數是是限制的,不知道我寫的代碼是不是正確的
//擷取access_token function get_access_token(){ $appid = C("APPID"); $appSecret = C("APPSECRET"); $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$appSecret"; $where = array( "appid" =>$appid, "appsecret" =>$appSecret, ); $res = M("as")->field('expire,accesssecret,timestamp')->where($where)->select(); if(!$res){//當as表裡沒有資料的時候 dump("!res"); $return = json_decode(curl($url)); $data['appid'] = $appid; $data['appsecret'] = $appSecret; $data['expire'] = $return->expires_in; $data['accesssecret'] = $return->access_token; $data['timestamp'] = time(); M("as")->add($data); $token = $data['accesssecret']; }else if($res[0]['expire']+$res[0]['timestamp']-30 < time()){//當時間到期的時候 dump("time out"); $return = json_decode(curl($url)); $data['expire'] = $return->expires_in; $data['accesssecret'] = $return->access_token; $data['timestamp'] = time(); M("as")->where("appid='".$appid."'")->save($data); $token = $data['accesssecret']; }else{ $token = $res[0]['accesssecret']; } return $token; }
回複內容:
的access_token的擷取次數是是限制的,不知道我寫的代碼是不是正確的
//擷取access_token function get_access_token(){ $appid = C("APPID"); $appSecret = C("APPSECRET"); $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$appSecret"; $where = array( "appid" =>$appid, "appsecret" =>$appSecret, ); $res = M("as")->field('expire,accesssecret,timestamp')->where($where)->select(); if(!$res){//當as表裡沒有資料的時候 dump("!res"); $return = json_decode(curl($url)); $data['appid'] = $appid; $data['appsecret'] = $appSecret; $data['expire'] = $return->expires_in; $data['accesssecret'] = $return->access_token; $data['timestamp'] = time(); M("as")->add($data); $token = $data['accesssecret']; }else if($res[0]['expire']+$res[0]['timestamp']-30 < time()){//當時間到期的時候 dump("time out"); $return = json_decode(curl($url)); $data['expire'] = $return->expires_in; $data['accesssecret'] = $return->access_token; $data['timestamp'] = time(); M("as")->where("appid='".$appid."'")->save($data); $token = $data['accesssecret']; }else{ $token = $res[0]['accesssecret']; } return $token; }
關於AccessToken
1.每天請求次數為2000次;
2.每個Access_Token有效期間為2小時;
儲存方案:
1.資料庫:通過介面擷取到 Access_Token 之後,將 Access_Token + 目前時間戳序列化儲存,每次需要 Access_Token 時,從資料庫取出,然後還原序列化對比時間戳記,如果到期,重新調用介面並更新資料庫記錄;
2.NoSQl:這裡以 Redis 為例子。通過介面擷取到 Access_Token 之後,存入 Redis 並設定到期時間,每次需要 Access_Token 時,去 Redis 查詢,如果沒有查詢到記錄說明上次擷取到的 Access_Token 已到期,重新擷取並更新記錄;
3.檔案儲存體:這個比較適合單一公眾號的情況。通過介面擷取到 Access_Token 之後,存入檔案,可以選擇性將時間戳記一併存入。每次需要 Access_Token 時,如果之前未記錄時間戳記,則比較檔案修改時間與目前時間,然後選擇讀取記錄或者重新調用介面更新記錄,否則先讀取檔案內容,然後對比之後選擇下一步行為。
NoSQL方案 > 資料庫 > 檔案管理
使用session加到期時間
那個,特麼才2000次調用,我怕我一抽筋就用完了,然後就被各種老大吊打,所以,我不會在請求裡面擷取這個傢伙。
因為沒涉及到業務我就一整個拷下來。。。應該可以吧
namespace Kinhom\Cli\Tasks;use Kinhom\Cli\Tasks\Impl\TaskInterface;use Phalcon\Cli\Task;use Phalcon\Di;/** * 用於更新access_token * * Class WeiXinAccessTokenTask * @package Kinhom\Cli\Tasks */class WeiXinAccessTokenTask extends Task implements TaskInterface{ # 最後申請時間 protected $lastApplyTime = 0; # 間隔時間 : 50秒內的申請算連擊,根據每天只能調用2000次估算出來 protected $intervalTime = 50; /** * 更新的accessToken */ public function runAction() { # token有效時間 $expTime = 0; # 提前20分鐘擷取token $pre = 20 * 60; $config = $this->getDI()->get('config')['weixin']->toArray(); $cache = $this->getCache(); $cacheKey = $config['cacheKey']; # 最後檢查cache時間,每隔一定時間會檢查cache是否存在 $cacheLastCheckTime = time(); while (true) { # 如果時間到了就更新token if ( $expTime <= time() - $pre ) { $expTime = $this->applyToken($config); continue; } # 3秒一次的cache檢查 if ( time() - $cacheLastCheckTime < 3 ) { continue; } # 如果cache裡沒有就更新token $token = $cache->get($cacheKey); if (!$token) { $expTime = $this->applyToken($config); $cacheLastCheckTime = time(); } } } /** * 申請token * @param $config * @return int */ protected function applyToken( $config ) { # 50 秒內不能查詢兩次,避免抽風一下子將整天的查詢都用光了 if ( time() - $this->lastApplyTime < $this->intervalTime ) { return time(); } $appId = $config['appId']; $secret = $config['appSecret']; $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$secret}"; $curl = curl_init($url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl,CURLOPT_HEADER, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); $data = curl_exec($curl); curl_close($curl); if ( ! $data ) { $this->getLogger()->error( '擷取公眾號token失敗,返回為空白' ); return time(); } $result = json_decode($data, true); if ( ! $result ) { $this->getLogger()->error( '擷取公眾號token失敗,返回異常:'.$data ); return time(); } $cache = $this->getCache(); $cacheKey = $config['cacheKey']; $cache->save($cacheKey,$result['access_token'],$result['expires_in']); return time() + $result['expires_in']; } /** * 擷取緩衝 * @return \Phalcon\Cache\BackendInterface */ protected function getCache() { return $this->getDI()->get('cache'); } /** * 擷取日誌 * @return \Phalcon\Logger\AdapterInterface */ protected function getLogger() { return $this->getDI()->get( 'logger' ); }}
文檔上好像說了吧,這個東西你要儲存到你本地的資料庫的
你做query的時候,先到本機資料庫尋找,
沒有合適的就query weixin api,使用獲得的結果,並且把結果儲存到資料庫中
下次使用的時候也先query資料庫
官方sdk有標準樣本。把值存到檔案,包括到期時間。每次用的時候比對時間,到期就去取,然後存。反之直接用。
我的方案是寫一個JSON檔案儲存體到伺服器上,
{ "access_token" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "prev_time" : "20140000000"}
用資料庫存過,原理一樣,但是覺得這樣操作簡單一些。
http://mp.weixin.qq.com/wiki/14/9f9c82c1af308e3b14ba9b973f99a8ba.html
官方文檔說了,推薦使用代理服務器專門負責access_token的事情,在代理服務器裡面做緩衝和到期重新擷取,所有需要擷取access_token都程式都到代理服務器去請求,這樣你就不用擔心超過2000次的問題,也更不用擔心多個程式請求access_token,後者重新整理了access_token,前者會不會失效的問題。
我的習慣是三層去擷取token
首先讀取緩衝(如memcache、redis或檔案快取都行)
如果緩衝讀取失敗,就讀取資料庫(並寫入緩衝。下次就直接讀取緩衝了)
最後通過API介面擷取,擷取後寫入到資料庫,並寫入到緩衝
其中1,2
步驟注意失效時間(最好比官方提早幾分鐘,以便更新的時候好過度)
每小時更新一次,用的時候直接取這個