*/ final class VerifyClient { /** * Base-uri key of the Actirise\Includes\Api client used for the callback. * * The verify endpoint is reached through the WordPress API base * (ACTIRISE_URL_API_V2) via its Kong route. * * @since 4.3.0 * @var string */ const ENDPOINT_KEY = 'api'; /** * Path of the verify endpoint, relative to the API base uri. * * @since 4.3.0 * @var string */ const ENDPOINT_PATH = 'push_notifications/verify'; /** * The Actirise API client. * * @since 4.3.0 * @var Api */ private $api; /** * Initialize the client. * * @since 4.3.0 */ public function __construct() { $this->api = new Api(); } /** * Verify a received notification against the Actirise API. * * @since 4.3.0 * @param string $event_id The notification event id. * @param string $payload_hash 'sha256:' + hex digest of the raw body. * @param mixed $website_id The plugin's local website id (forwarded as-is). * @return array Normalised verdict. Always contains a boolean * `verified` key. When false, a `reason` key. * When true, `website_id` and `event_type` when * the API supplies them. */ public function verify( $event_id, $payload_hash, $website_id ) { $token = Options::get( 'settings-analytics-token' ); if ( ! is_string( $token ) || '' === $token ) { return array( 'verified' => false, 'reason' => 'no_token', ); } // The verify contract (ยง6.1) types `website_id` as an integer, and the // API's strict denormalizer rejects a string (Options::get returns the id // as a string) with a 500 before the verify processor even runs. A site // with no usable id cannot be verified at all, so it short-circuits like // a missing token rather than sending an id the API is bound to reject. if ( ! is_numeric( $website_id ) ) { return array( 'verified' => false, 'reason' => 'no_website_id', ); } $body = array( 'event_id' => $event_id, 'payload_hash' => $payload_hash, 'website_id' => (int) $website_id, ); $response = $this->api->post( self::ENDPOINT_KEY, self::ENDPOINT_PATH, $body, $token ); if ( is_wp_error( $response ) || ! is_array( $response ) ) { return array( 'verified' => false, 'reason' => 'callback_error', ); } $verified = isset( $response['verified'] ) && true === $response['verified']; if ( ! $verified ) { $reason = isset( $response['reason'] ) && is_string( $response['reason'] ) ? $response['reason'] : 'rejected'; return array( 'verified' => false, 'reason' => $reason, ); } $verdict = array( 'verified' => true ); if ( isset( $response['website_id'] ) ) { $verdict['website_id'] = $response['website_id']; } if ( isset( $response['event_type'] ) && is_string( $response['event_type'] ) ) { $verdict['event_type'] = $response['event_type']; } return $verdict; } }