self::TIMEOUT, 'sslverify' => true, 'redirection' => 0, // A redirect must never carry the key to another host. 'headers' => array( 'Content-Type' => 'application/json', 'Accept' => 'application/json', ), 'body' => (string) wp_json_encode( array( 'code' => $code, 'store_url' => Config::store_url(), 'wc' => $key, 'site' => self::site_facts(), ) ), ) ); if ( is_wp_error( $response ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception message for logs/exceptions, not rendered output. throw new ConnectException( 'unreachable', $response->get_error_message() ); } $status = (int) wp_remote_retrieve_response_code( $response ); if ( 410 === $status ) { throw new ConnectException( 'code_invalid' ); } if ( 409 === $status ) { throw new ConnectException( 'store_mismatch' ); } if ( 0 === $status || $status >= 500 ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception message for logs/exceptions, not rendered output. throw new ConnectException( 'unreachable', 'HTTP ' . $status ); } if ( 200 !== $status ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Exception message for logs/exceptions, not rendered output. throw new ConnectException( 'rejected', 'HTTP ' . $status ); } $data = json_decode( wp_remote_retrieve_body( $response ), true ); $tenant = is_array( $data ) && isset( $data['tenant_id'] ) && is_string( $data['tenant_id'] ) ? trim( $data['tenant_id'] ) : ''; $secret = is_array( $data ) && isset( $data['webhook_secret'] ) && is_string( $data['webhook_secret'] ) ? $data['webhook_secret'] : ''; if ( '' === $tenant || strlen( $tenant ) > 64 || strlen( $secret ) < 16 || strlen( $secret ) > 256 ) { throw new ConnectException( 'bad_response' ); } $pixel = isset( $data['pixel_id'] ) && is_string( $data['pixel_id'] ) ? $data['pixel_id'] : ''; if ( '' !== $pixel && 1 !== preg_match( Options::PIXEL_ID_PATTERN, $pixel ) ) { throw new ConnectException( 'bad_response' ); } return array( 'tenant_id' => $tenant, 'webhook_secret' => $secret, 'pixel_id' => $pixel, ); } /** * @return array{plugin_version: string, wp_version: string, wc_version: string, php_version: string, currency: string} */ public static function site_facts(): array { return array( 'plugin_version' => Config::VERSION, 'wp_version' => (string) get_bloginfo( 'version' ), 'wc_version' => defined( 'WC_VERSION' ) ? (string) WC_VERSION : '', 'php_version' => PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION, 'currency' => get_woocommerce_currency(), ); } }