EquaSign_Repo::api_key_default(), 'Accept' => 'application/json', // Forward the operator's REST nonce so the loopback authenticates as the // logged-in admin (cookie auth requires it). Harmless in the Pro build // (external key auth ignores it); REQUIRED in the Free build, whose REST // closure additionally demands a manage_equasign session (arbitration #4). 'X-WP-Nonce' => wp_create_nonce( 'wp_rest' ), ), $extra ); } /** * Loopback cookies: forward the current operator's auth cookies so the plugin's own * admin request authenticates as that user. Only meaningful in the Free build (the * REST closure requires a session); inert in Pro (key auth). See arbitration #4. * * @return array */ private static function cookies() { $jar = array(); foreach ( (array) $_COOKIE as $name => $value ) { // phpcs:ignore WordPress.Security.NonceVerification if ( is_string( $value ) ) { $jar[] = new WP_Http_Cookie( array( 'name' => sanitize_text_field( wp_unslash( $name ) ), 'value' => wp_unslash( $value ) ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- operator's own cookie forwarded verbatim on an authenticated internal loopback request } } return $jar; } /** * Normalizes an HTTP response into { code, body }. * * @param array|WP_Error $response wp_remote_* response. * @return array */ private static function normalize( $response ) { if ( is_wp_error( $response ) ) { return array( 'code' => 0, 'body' => array( 'error' => array( 'code' => 'transport', 'message' => $response->get_error_message() ) ), ); } $code = (int) wp_remote_retrieve_response_code( $response ); $body = json_decode( wp_remote_retrieve_body( $response ), true ); return array( 'code' => $code, 'body' => is_array( $body ) ? $body : array(), ); } /** * Creates a task (POST /tasks). * * @param array $payload Payload. * @return array */ public static function create( array $payload ) { $response = wp_remote_post( trailingslashit( self::base() ) . 'tasks', array( 'timeout' => 30, 'sslverify' => true, 'headers' => self::headers( array( 'Content-Type' => 'application/json' ) ), 'cookies' => self::cookies(), 'body' => wp_json_encode( $payload ), 'data_format' => 'body', ) ); return self::normalize( $response ); } /** * Fetches a task (GET /tasks/{ref}). * * @param string $ref Opaque reference. * @return array */ public static function fetch( $ref ) { $response = wp_remote_get( trailingslashit( self::base() ) . 'tasks/' . rawurlencode( $ref ), array( 'timeout' => 20, 'sslverify' => true, 'headers' => self::headers(), 'cookies' => self::cookies(), ) ); return self::normalize( $response ); } /** * Retrieves the proof (GET /tasks/{ref}/proof). * * @param string $ref Opaque reference. * @return array */ public static function proof( $ref ) { $response = wp_remote_get( trailingslashit( self::base() ) . 'tasks/' . rawurlencode( $ref ) . '/proof', array( 'timeout' => 30, 'sslverify' => true, 'headers' => self::headers(), 'cookies' => self::cookies(), ) ); return self::normalize( $response ); } /** * Revokes or renews (POST /tasks/{ref}/lifecycle). * * @param string $ref Opaque reference. * @param string $action revoke|renew. * @return array */ public static function cycle( $ref, $action ) { $response = wp_remote_post( trailingslashit( self::base() ) . 'tasks/' . rawurlencode( $ref ) . '/lifecycle', array( 'timeout' => 20, 'sslverify' => true, 'headers' => self::headers( array( 'Content-Type' => 'application/json' ) ), 'cookies' => self::cookies(), 'body' => wp_json_encode( array( 'action' => $action ) ), 'data_format' => 'body', ) ); return self::normalize( $response ); } }