get( $endpoint_id ); } catch ( Exception $e ) { // The endpoint ID exists, but the endpoint no longer exists on Stripe. return false; } return $endpoint; } /** * Determines if a Stripe webhook endpoint is still valid. * * @since 4.4.2 * * @param \SimplePay\Vendor\Stripe\WebhookEndpoint $endpoint Webhook endpoint to validate. * @return bool True if the webhook does not need to be updated. */ public function is_valid( $endpoint ) { $enabled_events = $endpoint->enabled_events; // Enabled events are not * and do not match the defined whitelist. if ( ! in_array( '*', $enabled_events, true ) ) { // Check if all events in the whitelist are present in the enabled events. $whitelist = $this->get_event_whitelist(); foreach ( $whitelist as $event ) { if ( ! in_array( $event, $enabled_events, true ) ) { return false; } } } // URL mismatch. if ( simpay_get_webhook_url() !== $endpoint->url ) { return false; } // Disabled. if ( 'enabled' !== $endpoint->status ) { return false; } return true; } /** * Retrieves a Stripe webhook endpoint. * * @since 4.4.2 * * @param string $endpoint_id Stripe endpoint ID. * @return \SimplePay\Vendor\Stripe\WebhookEndpoint */ public function get( $endpoint_id ) { return Stripe_API::request( 'WebhookEndpoint', 'retrieve', $endpoint_id, $this->get_api_request_args() ); } /** * Creates a Stripe webhook endpoint with the current plugin and site settings. * * @since 4.4.2 * * @return \SimplePay\Vendor\Stripe\WebhookEndpoint */ public function create() { // Use an existing endpoint if one already exists from a previous setup. $endpoint = $this->get_manual_endpoint(); if ( ! $endpoint instanceof \SimplePay\Vendor\Stripe\WebhookEndpoint ) { $endpoint = Stripe_API::request( 'WebhookEndpoint', 'create', array( 'url' => simpay_get_webhook_url(), 'enabled_events' => $this->get_event_whitelist(), 'connect' => false, 'api_version' => SIMPLE_PAY_STRIPE_API_VERSION, // @phpstan-ignore-line 'description' => sprintf( 'WP Simple Pay (WordPress plugin) endpoint (%s Mode)', simpay_is_test_mode() ? 'Test' : 'Live' ), ), $this->get_api_request_args() ); } $this->persist( $endpoint ); return $endpoint; } /** * Updates a Stripe webhook endpoint with the current site and plugin settings. * * @since 4.4.2 * * @param \SimplePay\Vendor\Stripe\WebhookEndpoint $endpoint Webhook endpoint to update. * @return \SimplePay\Vendor\Stripe\WebhookEndpoint */ public function update( $endpoint ) { $enabled_events = $endpoint->enabled_events; // Existing webhook does not accept all events. Merge the new whitelist. if ( ! in_array( '*', $enabled_events, true ) ) { $enabled_events = array_values( array_unique( array_merge( $enabled_events, $this->get_event_whitelist() ) ) ); } $endpoint = Stripe_API::request( 'WebhookEndpoint', 'update', $endpoint->id, array( 'url' => simpay_get_webhook_url(), 'enabled_events' => $enabled_events, 'disabled' => false, ), $this->get_api_request_args() ); $this->persist( $endpoint ); return $endpoint; } /** * Returns a list of Stripe webhook events that are supported by the plugin. * * @since 4.4.2 * * @return array */ public function get_event_whitelist() { return array_keys( Webhooks\get_event_whitelist() ); } /** * Persists a Stripe webhook endpoint's information. * * @since 4.4.2 * * @param \SimplePay\Vendor\Stripe\WebhookEndpoint $endpoint Webhook endpoint to persist. * @return void */ private function persist( $endpoint ) { $prefix = simpay_is_test_mode() ? 'test' : 'live'; simpay_update_setting( "{$prefix}_webhook_endpoint_id", $endpoint->id ); simpay_update_setting( "{$prefix}_webhook_endpoint_events", $endpoint->enabled_events ); simpay_update_setting( "{$prefix}_webhook_endpoint_url", $endpoint->url ); // Secret is only returned on initial creation. if ( isset( $endpoint->secret ) ) { simpay_update_setting( "{$prefix}_webhook_endpoint_secret", $endpoint->secret ); // Clear out from a previous connection. } else { simpay_update_setting( "{$prefix}_webhook_endpoint_secret", '' ); } simpay_update_setting( "{$prefix}_webhook_endpoint_created", $endpoint->created ); } /** * Returns per-request arguments to be passed to the Stripe API. * * @since 4.4.2 * * @return array */ private function get_api_request_args() { return array( 'api_key' => simpay_get_secret_key(), ); } /** * Attemps to locate an endpoint that was manually created prior to 4.4.2. * * If we find an endpoint with an exact URL match, persist it and return it. * * @since 4.4.2 * * @return bool|\SimplePay\Vendor\Stripe\WebhookEndpoint Existing webhook endpoint if one matches the expected URL. * False if no endpoint matches. */ private function get_manual_endpoint() { $endpoints = Stripe_API::request( 'WebhookEndpoint', 'all', array( 'limit' => 100, ), $this->get_api_request_args() ); foreach ( $endpoints->data as $endpoint ) { if ( simpay_get_webhook_url() === $endpoint->url ) { // Ensure the remote endpoint has the expected events. Update if needed. $remote_events = $endpoint->enabled_events; $local_events = $this->get_event_whitelist(); if ( count( $remote_events ) < count( $local_events ) ) { $endpoint = $this->update( $endpoint ); } // Persist the endpoint information locally. $this->persist( $endpoint ); return $endpoint; } } return false; } }