php 缓存token在session的问题?
不知道为什么第一次请求的token为空(过期之后请求的第一次 ) 第二次就可以 请求大神帮忙看看我要把token保存起来,要不然请求的接口次数不够用
<?php
header("Content-type:text/html;charset=utf-8");
session_start();
//接收post过来的 json数据
$data = json_decode(file_get_contents('php://input'), true);
$userPhone=$data['userPhone'];
$message=$data['message'];
$serNumber=$data['serNumber'];//编号
$username=$data['username'];//发起人
$processCategory=$data['processCategory'];//流程类别
$remark=$data['remark'];//备注
$sendTimestr=$data['sendTimestr'];//发起时间
//var_dump($data);die;
//print_r($sendTimestr);die;
$conn = mysqli_connect("192.168.0.232", "root", "@jjgw6201", "user_wechat");
$wxresult=mysqli_query($conn,"select * from user_wechat where PHONE_NUM = '$userPhone'");
$result = mysqli_fetch_array($wxresult, MYSQLI_ASSOC);
if(!empty($_SESSION['access_token']) && $_SESSION['expire_time'] > time() ) {
//var_dump($_SESSION['access_token']."|".$_SESSION['expire_time']."|".time());die();
$url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . $_SESSION['access_token'];
// var_dump(date("Y-m-d H:i:s", $_SESSION["expire_time"]));die();
$template = [
'touser' => $result['OPEN_ID'], //openid
'template_id' => "Jg8Ow95NYuepZ08J91bDbNzyZM5e9SZSC4eJ4PCe3HA", //前面新增的模板id
'data' => array(
'first' => ['value' => urlencode("$message")],
'keyword1' => array('value' => urlencode("$serNumber")),//编号
'keyword2' => array('value' => urlencode("$username")),//发起人
'keyword3' => array('value' => "$sendTimestr"), //发起时间
'keyword4' => array('value' => urlencode("$processCategory")), //流程类别
'remark' => array('value' => urlencode("$remark")) //备注
)
];
$json_template = json_encode($template);
$json_template1 = urldecode($json_template);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl,CURLOPT_POSTFIELDS,$json_template1);
$output = curl_exec($curl);
//curl_close($curl);
$output = json_decode($output,true);
var_dump($output);
}
else
{
//echo "2";die;
// 过期了
//print_r($result['OPEN_ID']);die();
$app_id = 'xxx';
$app_secret = 'xxx';
//请求微信接口获取access_token
$token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$app_id}&secret={$app_secret}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $token_url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// curl_setopt($ch, CURLOPT_HTTPHEADER,$headerArray);
$output = curl_exec($ch);
//curl_close($ch);
$output = json_decode($output,true);
//var_dump($output);
$access_token = $output["access_token"];
//存储session
$_SESSION['access_token']=$access_token;
$_SESSION['expire_time']=time()+120; //秒
return $_SESSION['access_token'];
}
回复
1个回答
test
2024-07-09
恕我直言啊,你把这个token存session里没啥意义啊。
- 首先呢,这个token有效期为2个小时,也就是7200秒,那么你这120秒也降低不了多少请求。
- 你存session里,那么如果有1000个用户在线,你就要给1000个用户请求这个token并存进去,你这个请求数也降不下来啊。
另外呢,你这个if else
判断,那么第一次没有access_token
的时候,只执行access_token
获取逻辑,然后根本不走业务代码的(参见else
)里的逻辑;如果有session
里有access_token
才走业务逻辑;抛开以上不谈,正常人的做法不应该是:
- 如果没有
access_token
,请求access_token
,然后继续执行业务逻辑; - 如果有
access_token
,直接走业务逻辑就行了,也就是说只要加一个判断if(empty($_SESSION['access_token']) || $_SESSION['expire_time'] <= time() )
然后取access_token
就行了啊,根本不需要else
。
另外呢,你没有redis
之类的缓存,还不如直接用文件缓存,所有用户用这个access_token
就行,然后没隔7000秒(小于2小时,但是缓存时间又足够用,避免生成需要时间)
。缓存的文件里的数据格式为都给你想好了:
cache_time access_token
然后读取这个文件,之后,把这文件里的这行数据:[$cacheTime, $accessToken] = explode(' ', $str);
切割之后就能拿到上次生成时间,校验一下不过期就不重新取,另外这个文件里的字符为空就重新取(相当于初始化)。
另外这个文件缓存,为了防止并发读写错误,加上一个文件锁就行:flock
;读的时候首先flock($filename,LOCK_SH);
写的时候加一个写锁:flock($filename,LOCK_EX);
;
当然了,最好的方式是写一个定时脚本,每间隔7000
秒更新一下这个文件里的数据,这样从根源上解决并发写的问题,至于读的话问题不大。
不过正常项目来说都是用定时任务执行脚本获取后把这个access_token
放到redis
啊memcached
啊这种缓存里。
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容