105 lines
3.2 KiB
PHP
105 lines
3.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\StravaConnection;
|
|
use Illuminate\Http\Client\PendingRequest;
|
|
use Illuminate\Support\Carbon;
|
|
use Illuminate\Support\Facades\Http;
|
|
use RuntimeException;
|
|
|
|
class StravaClient
|
|
{
|
|
private const AUTHORIZE_URL = 'https://www.strava.com/oauth/mobile/authorize';
|
|
|
|
public function authorizationUrl(string $state): string
|
|
{
|
|
$clientId = config('services.strava.client_id');
|
|
|
|
if (! $clientId) {
|
|
throw new RuntimeException('Strava is not configured.');
|
|
}
|
|
|
|
return self::AUTHORIZE_URL.'?'.http_build_query([
|
|
'client_id' => $clientId,
|
|
'redirect_uri' => $this->redirectUri(),
|
|
'response_type' => 'code',
|
|
'approval_prompt' => 'auto',
|
|
'scope' => config('services.strava.scope', 'read,activity:read'),
|
|
'state' => $state,
|
|
], '', '&', PHP_QUERY_RFC3986);
|
|
}
|
|
|
|
public function exchangeCode(string $code): array
|
|
{
|
|
return $this->tokenRequest()
|
|
->post('/oauth/token', [
|
|
'client_id' => config('services.strava.client_id'),
|
|
'client_secret' => config('services.strava.client_secret'),
|
|
'code' => $code,
|
|
'grant_type' => 'authorization_code',
|
|
])
|
|
->throw()
|
|
->json();
|
|
}
|
|
|
|
public function refresh(StravaConnection $connection): StravaConnection
|
|
{
|
|
$payload = $this->tokenRequest()
|
|
->post('/oauth/token', [
|
|
'client_id' => config('services.strava.client_id'),
|
|
'client_secret' => config('services.strava.client_secret'),
|
|
'grant_type' => 'refresh_token',
|
|
'refresh_token' => $connection->refresh_token,
|
|
])
|
|
->throw()
|
|
->json();
|
|
|
|
$connection->update([
|
|
'access_token' => $payload['access_token'],
|
|
'refresh_token' => $payload['refresh_token'],
|
|
'expires_at' => Carbon::createFromTimestamp((int) $payload['expires_at']),
|
|
]);
|
|
|
|
return $connection->refresh();
|
|
}
|
|
|
|
public function activities(StravaConnection $connection, int $page, int $perPage): array
|
|
{
|
|
return Http::baseUrl('https://www.strava.com/api/v3')
|
|
->withToken($this->accessToken($connection))
|
|
->timeout(10)
|
|
->connectTimeout(3)
|
|
->retry([100, 500, 1000])
|
|
->get('/athlete/activities', [
|
|
'page' => $page,
|
|
'per_page' => $perPage,
|
|
])
|
|
->throw()
|
|
->json();
|
|
}
|
|
|
|
private function accessToken(StravaConnection $connection): string
|
|
{
|
|
if (! $connection->expires_at || $connection->expires_at->lte(now()->addMinutes(5))) {
|
|
$connection = $this->refresh($connection);
|
|
}
|
|
|
|
return $connection->access_token;
|
|
}
|
|
|
|
private function tokenRequest(): PendingRequest
|
|
{
|
|
return Http::baseUrl('https://www.strava.com')
|
|
->asForm()
|
|
->timeout(10)
|
|
->connectTimeout(3)
|
|
->retry([100, 500, 1000]);
|
|
}
|
|
|
|
private function redirectUri(): string
|
|
{
|
|
return rtrim((string) config('app.url'), '/').'/strava/callback';
|
|
}
|
|
}
|