获取access_token https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
示例:
微信公众号中控服务器https://www.iyuu.cn:2130
前言
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效
。
公众平台的API调用所需的access_token的使用及生成方式说明:
1、建议公众号开发者使用中控服务器统一获取和刷新access_token,其他业务逻辑服务器所使用的access_token均来自于该中控服务器,不应该各自去刷新,否则容易造成冲突,导致access_token覆盖而影响业务;
2、目前access_token的有效期通过返回的expire_in来传达,目前是7200秒之内的值。中控服务器需要根据这个有效时间提前去刷新新access_token。在刷新过程中,中控服务器可对外继续输出的老access_token,此时公众平台后台会保证在5分钟内,新老access_token都可用,这保证了第三方业务的平滑过渡;
3、access_token的有效时间可能会在未来有调整,所以中控服务器不仅需要内部定时主动刷新,还需要提供被动刷新access_token的接口,这样便于业务服务器在API调用获知access_token已超时的情况下,可以触发access_token的刷新流程。
公众号和小程序均可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在“微信公众平台-开发-基本配置”页中获得(需要已经成为开发者,且帐号没有异常状态)。调用接口时,请登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中,点击查看设置方法,否则将无法调用成功。小程序无需配置IP白名单。
workerman源代码
start_token.php 源码
<?php
use Workerman\Worker;
use Workerman\Lib\Timer;
use Workerman\MySQL\Connection;
define('GLOBAL_HTTPS', 1);
define("APP_PATH", dirname(__FILE__));
require_once __DIR__ . '/../../vendor/autoload.php';
require_once APP_PATH . '/Library/Function.php';
require_once APP_PATH . '/Library/Config.php';
require_once APP_PATH . '/Library/Cache.php';
require_once APP_PATH . '/Library/Wechat.php';
$context = array(
'ssl' => array(
// 请使用绝对路径
'local_cert' => __DIR__ . '/../../Cert/www.iyuu.cn.crt', // 也可以是crt文件
'local_pk' => __DIR__ . '/../../Cert/www.iyuu.cn.key',
'verify_peer' => false,
//'allow_self_signed' => true, //如果是自签名证书需要开启此选项
)
);
$worker = new Worker("http://0.0.0.0:2130",$context);
$worker->transport = 'ssl';
$worker->name = 'WechatTokenService';
//单进程
$worker->count = 1;
$worker->onWorkerStart = function($worker)
{
sc('微信token服务进程 已启动!');
// 设置时区
date_default_timezone_set('PRC');
global $config, $redis, $db;
$dbName = 'mysql.typecho';
$config = \Config::get('application');
$redis = new \Cache();
//$db = new Connection($config[$dbName]['host'], $config[$dbName]['port'], $config[$dbName]['user'], $config[$dbName]['password'], $config[$dbName]['database']);
// 初始化任务
\Wechat::start();
// 启动定时器
Timer::add(5, function()
{
\Wechat::getAccessToken();
});
};
// 接收到浏览器发送的数据时回复hello world给浏览器
$worker->onMessage = function($connection, $data)
{
// 向浏览器发送hello world
$connection->send('hello world');
};
// 进程关闭时
$worker->onWorkerStop = function($worker)
{
//通知运维人员
sc('微信token服务进程异常退出,请检查');
};
// 如果不是在根目录启动,则运行runAll方法
if(!defined('GLOBAL_START'))
{
Worker::runAll();
}
/Library/Wechat.php 源码
<?php
require_once APP_PATH . '/Library/Config.php';
require_once APP_PATH . '/Library/HttpCurl.php';
class Wechat {
const API_URL_PREFIX = 'https://api.weixin.qq.com/cgi-bin';
const AUTH_URL = '/token?';
const TEMPLATE_SEND_URL = '/message/template/send?access_token=';
private static $access_token;
private static $expires_in;
//守护进程初次启动,从Redis读取
public static function start(){
global $redis;
self::$access_token = $redis->get('WCH_access_token');
self::$expires_in = $redis->get('WCH_expires_in');
wlog('系统启动');
}
/**
* 获取access_token
* @param bool $newToken 传入true可以强制刷新token
* @return string | null
*/
public static function getAccessToken($newToken = false){
global $redis;
if (self::valid_access_token() && !$newToken) {
//监测缓存token,如果被误删除,重新写入
if(empty($redis->get('WCH_access_token'))){
$redis->set('WCH_access_token', self::$access_token, self::$expires_in-time());
wlog('access_token被误删除,已恢复!!');
}
if(empty($redis->get('WCH_expires_in'))){
$redis->set('WCH_expires_in', self::$expires_in, self::$expires_in-time());
wlog('expires_in被误删除,已恢复!!');
}
return self::$access_token;
}else{
$options = Config::get('application', 'iyuucn');
if(isset($options['appid']) && isset($options['appsecret'])){
$params = array('grant_type' => 'client_credential','appid' => $options['appid'], 'secret' => $options['appsecret']);
$str = http_build_query($params);
$response = HttpCurl::get(self::API_URL_PREFIX.self::AUTH_URL.$str, 'json');
//记录日志
wlog($response);
if(isset($response->errcode)){
//获取access_token异常
return NULL;
}else{
//存数据库
#code...
//存类静态成员
self::$access_token = $response->access_token;
self::$expires_in = time()+$response->expires_in-300;
//存redis缓存
$redis->set('WCH_access_token',self::$access_token,$response->expires_in-300);
$redis->set('WCH_expires_in',self::$expires_in,$response->expires_in-300);
return $response->access_token;
}
}else{
//缺少开发者参数
throw new Exception("appid,appsecret not config");
}
}
}
/**
* 校验access_token是否过期
* @return bool
*/
private static function valid_access_token($access_token = '',$expires_in = '')
{
if(empty($access_token) && empty($expires_in)){
return isset(self::$access_token) && isset(self::$expires_in) && self::$expires_in > (time()+30);
}
return isset($access_token) && isset($expires_in) && $expires_in > (time()+30);
}
/**
* 发送模板消息
* @param array $data 消息结构
* @return boolean|array
*/
public static function sendTemplateMessage($data){
if (!self::valid_access_token()) {
if(!self::getAccessToken()){
return false;
}
}
$response = HttpCurl::post(self::API_URL_PREFIX.self::TEMPLATE_SEND_URL.self::$access_token, json_encode($data, JSON_UNESCAPED_UNICODE));
if($response){
$json = json_decode($response,true);
//记录日志
wlog($json);
//echo date("Y-m-d H:i:s")."\n\n";
//p($json);
if (!$json || !empty($json['errcode'])) {
return false;
}
return $json;
}
return false;
}
}
Linux开机以守护进程方式运行
打开/etc/rc.local
,在exit 0
前添加类似以下代码
/绝对路径/php /磁盘/路径/start.php start -d
版权属于:大卫科技Blog
本文链接:https://www.iyuu.cn/archives/200/
转载时须注明出处