<?php
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\Request as Psr7Request;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use think\facade\Cache;
class HahaService
{
protected $client;
public function __construct()
{
$this->client = $this->createClientWithRetry();
}
protected function createClientWithRetry()
{
$handlerStack = HandlerStack::create();
$handlerStack->push(Middleware::retry(
function ($retry, RequestInterface $request, ResponseInterface $response = null, $exception = null) {
if ($retry >= 3) {
return false;
}
if ($response && $response->getStatusCode() == 401) {
$newToken = $this->refreshToken();
$request = $request->withHeader('Authorization', 'Bearer ' . $newToken);
return true;
}
if ($exception instanceof \GuzzleHttp\Exception\ConnectException) {
return true;
}
return false;
},
function ($retry) {
return 1000 * pow(2, $retry);
}
));
return new Client([
'handler' => $handlerStack,
'timeout' => 10.0,
]);
}
protected function refreshToken()
{
try {
$tokenResponse = $this->originalRequest('POST', '/token', [
'form_params' => [
'grant_type' => 'client_credentials',
]
]);
$newToken = $tokenResponse['access_token'];
Cache::set('haha_access_token', $newToken, 7200);
return $newToken;
} catch (\Exception $e) {
throw new \RuntimeException('Failed to refresh token: ' . $e->getMessage());
}
}
protected function originalRequest($method, $uri, $options = [])
{
$defaultClient = new Client();
$response = $defaultClient->request($method, $this->baseUrl . $uri, $options);
return json_decode($response->getBody()->getContents(), true);
}
public function request($method, $uri, $options = [])
{
$token = Cache::get('haha_access_token');
if (!$token) {
$token = $this->refreshToken();
}
$options['headers']['Authorization'] = 'Bearer ' . $token;
return $this->client->request($method, $uri, $options);
}
}