You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.4 KiB
119 lines
3.4 KiB
2 weeks ago
|
<?php
|
||
|
|
||
|
declare(strict_types=1);
|
||
|
|
||
|
namespace App\Utils;
|
||
|
|
||
|
use App\Dictionary\WeChat\Official\OpenApi;
|
||
|
use EasyWeChat\Kernel\Contracts\RefreshableAccessToken;
|
||
|
use HttpException;
|
||
|
use Illuminate\Support\Facades\Redis;
|
||
|
use JsonException;
|
||
|
use JetBrains\PhpStorm\ArrayShape;
|
||
|
use Psr\Container\ContainerExceptionInterface;
|
||
|
use Psr\Container\NotFoundExceptionInterface;
|
||
|
use Symfony\Component\HttpClient\HttpClient;
|
||
|
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||
|
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
|
||
|
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||
|
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||
|
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||
|
|
||
|
class CentralControlAccessToken implements RefreshableAccessToken
|
||
|
{
|
||
|
public function __construct(){}
|
||
|
|
||
|
/**
|
||
|
* Access Token Save Key.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function getKey(): string
|
||
|
{
|
||
|
return 'mini_platform:access_token';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get Access Token.
|
||
|
*
|
||
|
* @return string
|
||
|
*
|
||
|
* @throws ClientExceptionInterface
|
||
|
* @throws ContainerExceptionInterface
|
||
|
* @throws DecodingExceptionInterface
|
||
|
* @throws HttpException
|
||
|
* @throws JsonException
|
||
|
* @throws NotFoundExceptionInterface
|
||
|
* @throws RedirectionExceptionInterface
|
||
|
* @throws ServerExceptionInterface
|
||
|
* @throws TransportExceptionInterface
|
||
|
*/
|
||
|
public function getToken(): string
|
||
|
{
|
||
|
$token = Redis::get($this->getKey());
|
||
|
|
||
|
if ($token && is_string($token)) {
|
||
|
return $token;
|
||
|
}
|
||
|
|
||
|
return $this->refresh();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get Access Token For Query Params.
|
||
|
*
|
||
|
* @return array<string, string>
|
||
|
*
|
||
|
* @throws ClientExceptionInterface
|
||
|
* @throws ContainerExceptionInterface
|
||
|
* @throws DecodingExceptionInterface
|
||
|
* @throws HttpException
|
||
|
* @throws JsonException
|
||
|
* @throws NotFoundExceptionInterface
|
||
|
* @throws RedirectionExceptionInterface
|
||
|
* @throws ServerExceptionInterface
|
||
|
* @throws TransportExceptionInterface
|
||
|
*/
|
||
|
#[ArrayShape(['access_token' => "string"])]
|
||
|
public function toQuery(): array
|
||
|
{
|
||
|
return ['access_token' => $this->getToken()];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return string
|
||
|
*
|
||
|
* @throws HttpException
|
||
|
* @throws JsonException
|
||
|
* @throws ClientExceptionInterface
|
||
|
* @throws DecodingExceptionInterface
|
||
|
* @throws RedirectionExceptionInterface
|
||
|
* @throws ServerExceptionInterface
|
||
|
* @throws TransportExceptionInterface
|
||
|
*/
|
||
|
public function refresh(): string
|
||
|
{
|
||
|
$client = HttpClient::create(['base_uri' => 'https://api.weixin.qq.com/']);
|
||
|
$response = $client->request(
|
||
|
'GET',
|
||
|
OpenApi::GET_ACCESS_TOKEN->value,
|
||
|
[
|
||
|
'query' => [
|
||
|
'grant_type' => 'client_credential',
|
||
|
'appid' => config('wechat.mini.app_id'),
|
||
|
'secret' =>config('wechat.mini.secret'),
|
||
|
],
|
||
|
]
|
||
|
)->toArray(false);
|
||
|
|
||
|
if (empty($response['access_token'])) {
|
||
|
throw new HttpException('Failed to get access_token: '. json_encode($response, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
Redis::setex($this->getKey(), (int)$response['expires_in'] - 300, $response['access_token']);
|
||
|
|
||
|
return $response['access_token'];
|
||
|
}
|
||
|
}
|