StravaPHP

repository·develop·Indexed 41 days ago

https://github.com/basvandorst/stravaphp

A PHP client for the Strava V3 API featuring integrated support for OAuth authentication and webhook management. It provides a comprehensive set of methods to access athlete, activity, club, and segment data, including support for activity uploads, data streams, and leaderboard retrieval. The library includes a Factory class for simplified client instantiation and a Webhook class for handling subscription challenges and event processing.

Tokens
9.1K
Snippets
25
Records
32
Agent score
51%

What's inside StravaPHP

  1. Handle Strava Webhook Events and Challenges

    develop

    The Strava\API\Webhook class provides static methods to handle the two main stages of webhook integration:

    1. Subscription Challenge: When you first create a subscription, Strava sends a challenge to your endpoint. Use Webhook::handleSubscriptionChallenge($verifyToken) to extract the challenge and Webhook::sendChallengeResponse($challenge) to respond.
    2. Event Processing: To process incoming activity or athlete updates, use Webhook::processEvent(). This returns an array containing a success boolean and either the event data or an error message.

    Always return a 200 OK response to Strava upon successful processing to prevent repeated delivery attempts.

    // Handle subscription challenge
    $verifyToken = 'your_random_verify_token';
    $challengeResult = Webhook::handleSubscriptionChallenge($verifyToken);
    
    if ($challengeResult['success']) {
        Webhook::sendChallengeResponse($challengeResult['challenge']);
    }
    
    // Process incoming webhook events
    $eventResult = Webhook::processEvent();
    
    if ($eventResult['success']) {
        $event = $eventResult['event'];
        // ... process event ...
        http_response_code(200);
        echo json_encode(['status' => 'success']);
    } else {
        http_response_code(400);
        echo json_encode(['error' => $eventResult['error']]);
    }
  2. Handle OAuth authentication with Stravaº

    develop

    The Strava\API\OAuth class manages the two-step OAuth process: redirecting the user to Strava for authorization and exchanging the resulting authorization code for an access token.

    1. Authorization: Use getAuthorizationUrl() to generate a link where users can approve your application. You can specify required scopes (e.g., read, read_all, activity:read_all).
    2. Token Exchange: After the user is redirected back to your redirectUri with a code in the query string, use getAccessToken() with the authorization_code grant type to retrieve the token.
    use Strava\ÁPI\OAuth;
    use Strava\API\Exception;
    
    $options = [
        'clientId'     => 1234,
        'clientSecret' => 'APP-TOKEN',
        'redirectUri'  => 'http://my-app/callback.php'
    ];
    $oauth = new OAuth($options);
    
    if (!isset($_GET['code'])) {
        // Step 1: Redirect user to Strava
        $url = $oauth->getAuthorizationUrl([
            'scope' => ['read']
        ]);
        print '<a href="'.$url.'">Connect</a>';
    } else {
        // Step 2: Exchange code for token
        $token = $oauth->getAccessToken('authorization_code', [
            'code' => $_GET['code']
        ]);
        print $token->getToken();
    }
  3. Install StravaPHP via Composer

    develop

    To use StravaPHP in your project, add it to your composer.json file. This package provides a PHP implementation of the Strava V3 API with OAuth authentication support.

    {
        "require": {
            "basvandorst/stravaphp": "^2.0.0"
        }
    }
  4. Initialize the Strava\API\Client

    develop

    To make API calls, you must instantiate a Strava\API\Client. This requires a service object (typically Strava\API\Service\REST) which in turn requires an HTTP adapter (such as GuzzleHttp\Client) and a valid user access token.

    Note: The REST service is the standard implementation, but Service\Stub is available for testing.

    use GuzzleHttp\Client as GuzzleClient;
    use Strava\API\Service\REST;
    use Strava\API\Client;
    
    // 1. Setup the HTTP adapter
    $adapter = new GuzzleClient(['base_uri' => 'https://www.strava.com/api/v3/']);
    
    // 2. Setup the service with the user's access token
    $service = new REST('USER_ACCESS_TOKEN', $adapter);
    
    // 3. Initialize the client
    $client = new Client($service);
    
    // 4. Use the client
    $athlete = $client->getAthlete();
  5. Initialize the Strava Client

    develop

    The Strava\API\Client class is the primary entry point for interacting with the Strava API. It requires an implementation of ServiceInterface passed via its constructor.

    There are two main service implementations available:

    • Strava\API\Service\REST: Use this for making live calls to the Strava API.
    • Strava\API\Service\Stub: Use this for unit testing purposes (a service stub).

    All methods in the client wrap service calls and catch Strava\API\Service\Exception. If a service exception occurs, the client re-throws it as a Strava\API\Exception prefixed with [SERVICE].

    use Strava\API\Client;
    use Strava\API\Service\REST;
    
    // For live API usage
    $client = new Client(new REST());
  6. Understand the Strava API OAuth class

    develop

    The Strava\API\OAuth class is an implementation of the League\OAuth2\Client\Provider\AbstractProvider. It handles the OAuth2 authentication flow specifically for Strava's API. It manages authorization URLs, token exchange, and maps Strava's athlete profile data to a standardized stdClass object.

    Key characteristics:

    • Default Scopes: By default, it requests the ['write'] scope.
    • User Data Mapping: When retrieving user details via the /athlete endpoint, it maps Strava's response fields to a simplified object containing uid, name, firstName, lastName, email, location, imageUrl, and gender.
  7. Use Webhook helper methods for event parsing

    develop

    The Strava\API\Webhook class includes utility methods to easily inspect the contents of a webhook event payload:

    • getEventType($event): Returns the string event type (e.g., activity.create).
    • isObjectType($event, $type): Returns true if the event belongs to a specific object type like activity or athlete.
    • isAspectType($event, $aspect): Returns true if the event represents a specific action like create, update, or delete.
    • verifySignature($payload, $signature, $secret): Validates the webhook signature for security.
    // Get event type (e.g., 'activity.create')
    $eventType = Webhook::getEventType($event);
    
    // Check if event is for specific object type
    $isActivity = Webhook::isObjectType($event, 'activity');
    $isAthlete = Webhook::isObjectType($event, 'athlete');
    
    // Check if event is specific aspect type
    $isCreate = Webhook::isAspectType($event, 'create');
    $isUpdate = Webhook::isAspectType($event, 'update');
    $isDelete = Webhook::isAspectType($event, 'delete');
    
    // Verify webhook signature
    $isValid = Webhook::verifySignature($payload, $signature, $secret);
  8. Manage Strava Webhook Subscriptions

    develop

    Use the Strava\API\Client instance to manage your webhook subscriptions. You can create new subscriptions, list existing ones, and delete them using your Strava application credentials (clientId, clientSecret) and a callbackUrl and verifyToken of your choice.

    To use these methods, you must first initialize a Client with a REST service and a Guzzle HTTP adapter.

    // Create API client
    $adapter = new GuzzleClient(['base_uri' => 'https://www.strava.com/api/v3/']);
    $service = new REST('YOUR_ACCESS_TOKEN', $adapter);
    $client = new Client($service);
    
    $clientId = 12345;
    $clientSecret = 'your_client_secret';
    $callbackUrl = 'https://yourdomain.com/webhook-endpoint.php';
    $verifyToken = 'your_random_verify_token';
    
    try {
        // Create a webhook subscription
        $subscription = $client->createWebhookSubscription(
            $clientId,
            $clientSecret,
            $callbackUrl,
            $verifyToken
        );
        
        // List existing subscriptions
        $subscriptions = $client->listWebhookSubscriptions($clientId, $clientSecret);
        
        // Delete a subscription
        $client->deleteWebhookSubscription($clientId, $clientSecret, $subscription['id']);
        
    } catch (Exception $e) {
        echo "Error: " . $e->getMessage() . "\n";
    }
  9. Use Strava\API\Factory to create clients

    develop

    The Strava\API\Factory class provides a simplified way to instantiate OAuth and API clients using your application credentials.

    use Strava\API\Factory;
    
    $factory = new Factory();
    
    // Create an OAuth client
    $OAuthClient = $factory->getOAuthClient(1234, 'APP-TOKEN', 'http://my-app/callback.php');
    
    // Create an API client using a token
    $apiClient = $factory->getAPIClient($token);
  10. Configure the REST service verbosity

    develop

    When instantiating the Strava\API\Service\REST class, you can specify the responseVerbosity level to control the detail of the returned HTTP response.

    • 0 (default): Basic mode. Returns only the decoded JSON body of the response.
    • 1: Enhanced mode. Returns an associative array containing headers, body, success (boolean), and status (HTTP status code).
    // Basic mode (default)
    $rest = new REST($token, $guzzleClient, 0);
    $data = $rest->getAthlete(); // Returns just the body array
    
    // Enhanced mode
    $rest = new REST($token, $guzzleClient, 1);
    $response = $rest->getAthlete(); 
    // Returns ['headers' => [...], 'body' => [...], 'success' => true, 'status' => 200]
  11. Reference: Strava\API\Client methods

    develop

    The Strava\API\Client class provides methods to interact with various Strava resources. Below is a list of available methods for retrieving and managing data.

    // Athlete methods
    $client->getAthlete($id = null);
    $client->getAthleteStats($id);
    $client->getAthleteClubs();
    $client->getAthleteRoutes($id, $type = null, $after = null, $page = null, $per_page = null);
    $client->getAthleteActivities($before = null, $after = null, $page = null, $per_page = null);
    $client->getAthleteFriends($id = null, $page = null, $per_page = null);
    $client->getAthleteFollowers($id = null, $page = null, $per_page = null);
    $client->getAthleteBothFollowing($id, $page = null, $per_page = null);
    $client->getAthleteKom($id, $page = null, $per_page = null);
    $client->getAthleteZones();
    $client->getAthleteStarredSegments($id = null, $page = null, $per_page = null);
    $client->updateAthlete($city, $state, $country, $sex, $weight);
    
    // Activity methods
    $client->getActivityFollowing($before = null, $page = null, $per_page = null); 
    $client->getActivity($id, $include_all_efforts = null);
    $client->getActivityComments($id, $markdown = null, $page = null, $per_page = null);
    $client->getActivityKudos($id, $page = null, $per_page = null);
    $client->getActivityPhotos($id, $size = 2048, $photo_sources = 'true');
    $client->getActivityZones($id);
    $client->getActivityLaps($id);
    $client->getActivityUploadStatus($id);
    $client->createActivity($name, $type, $start_date_local, $elapsed_time, $description = null, $distance = null);
    $client->uploadActivity($file, $activity_type = null, $name = null, $description = null, $private = null, $commute = null, $trainer = null, $data_type = null, $external_id = null);
    $client->updateActivity($id, $name = null, $type = null, $private = false, $commute = false, $trainer = false, $gear_id = null, $description = null);
    $client->deleteActivity($id);
    
    // Club, Route, Segment, and Stream methods
    $client->getGear($id);
    $client->getClub($id);
    $client->getClubMembers($id, $page = null, $per_page = null);
    $client->getClubActivities($id, $page = null, $per_page = null);
    $client->getRoute($id);
    $client->getRouteAsGPX($id);
    $client->getRouteAsTCX($id);
    $client->getSegment($id);
    $client->getSegmentLeaderboard($id, $gender = null, $age_group = null, $weight_class = null, $following = null, $club_id = null, $date_range = null, $page = null, $per_page = null);
    $client->getSegmentExplorer($bounds, $activity_type = 'riding', $min_cat = null, $max_cat = null);
    $client->getSegmentEffort($id, $athlete_id = null, $start_date_local = null, $end_date_local = null, $page = null, $per_page = null);
    $client->getStreamsActivity($id, $types, $resolution = null, $series_type = 'distance');
    $client->getStreamsEffort($id, $types, $resolution = null, $series_type = 'distance');
    $client->getStreamsSegment($id, $types, $resolution = null, $series_type = 'distance');
    $client->getStreamsRoute($id);
    
    // Webhook methods
    $client->createWebhookSubscription($clientId, $clientSecret, $callbackUrl, $verifyToken);
    $client->listWebhookSubscriptions($clientId, $clientSecret);
    $client->deleteWebhookSubscription($clientId, $clientSecret, $subscriptionId);
  12. Reference: Supported Webhook Event Types

    develop

    Strava webhooks support the following event types which can be parsed using the Webhook helper methods.

    ### Activity Events:
    - `activity.create` - New activity created
    - `activity.update` - Activity updated
    - `activity.delete` - Activity deleted
    
    ### Athlete Events:
    - `athlete.update` - Athlete profile updated