Cómo insertar un post en WordPress a través de su API REST

Voy a mostrar un ejemplo de cómo insertar un post en una web bajo WordPress haciendo uso de su API REST desde otra web hecha en HTML-PHP. Todo esto lo voy a hacer desde mi entorno de desarrollo, bajo un servidor XAMPP.

Requisitos mínimos

  • Tener un certificado SSL autofirmado para el dominio donde está instalado el WordPress.
  • Generar una clave de API desde la web donde está instalado WordPress

Generar certificado SSL autofirmado.

Haciendo uso de la consola o terminal, nos movemos a la carpeta que queramos. En mi caso, voy a generar los certificados en mi carpeta personal, bajo la carpeta .ssh, y ejecuto un comando, tal que así:

cd ~/.ssh/
openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -keyout localhost.key -out localhost.crt

El primer comando es para cambiar de carpeta.

El segundo comando genera dos archivos localhost.key y localhost.crt. Asegúrate de cambiar “localhost” por el nombre de tu dominio en local. 36500 días es equivalente a 100 años. Tiempo más que suficiente para que lo tengamos que renovar, ¿no?

Cuando ejecutemos este segundo comando, hay que ir respondiendo las preguntas que nos van saliendo por pantalla.

Importante: cuando nos soliciten el “Common name” debemos introducir el dominio al que queremos asociar el certificado.

Bien, una vez generados y localizados los archivos .key y .crt es hora de indicarlo en la entrada del VHOSTS correspondiente.

En mi caso, el archivo está en /Applications/XAMPP/etc/extra/httpd-vhosts.conf. Una vez abierto, me dirigiré a la entrada de mi VHOSTS e indicaré dónde están estos archivos .key y .crt:

<VirtualHost dev.testwp:80>
  ServerName dev.testwp
  DocumentRoot "/Users/username/Sites/testwp"
  ErrorLog "/var/log/testwp-error.log"
  CustomLog "/var/log/testwp-access.log" common
</VirtualHost>
<VirtualHost dev.testwp:443>
   DocumentRoot "/Users/username/Sites/testwp"
   ServerName dev.testwp
   SSLEngine on
   SSLCertificateFile "/Users/username/.ssh/dev.testwp.crt"
   SSLCertificateKeyFile "/Users/username/.ssh/dev.testwp.key"
</VirtualHost>

Las líneas que buscamos insertar son:

SSLCertificateFile "/Users/username/.ssh/dev.testwp.crt"
   SSLCertificateKeyFile "/Users/username/.ssh/dev.testwp.key"

Con todo esto en marcha, sólo quedaría reiniciar Apache y comprobar que el certificado está correctamente configurado accediendo a nuestro dominio de desarrollo, en mi caso https://dev.testwp

Nos saltará el aviso de que el sitio no es seguro porque está autofirmado por nosotros, así que continuamos igualmente y luego pinchamos en el mensaje “no es seguro” que hay a la izquierda del https del navegador para ver los detalles del certificado. Si todo ha ido bien, veréis los datos que habéis insertado previamente cuando ejecutamos el comando openssl

Con esto ya habríamos terminado la parte de generar nuestro propio certificado SSL autofirmado.

Generar clave API desde nuestro site en WordPress

Antiguamente había que instalarse un plugin adicional pero WordPress ya ha incorporado esta característica de forma nativa.

Basta con ir a Usuarios -> elegir el usuario deseado (uno con permisos para insertar posts) y darle a Editar perfil.

Un vez en esta pantalla, dirigirse abajo del todo, donde veremos el título: “Contraseñas de aplicación”.

Donde pone “Nombre de la nueva contraseña de la aplicación” simplemente dad un nombre descriptivo para saber dónde se va a usar esta clave de API. Por ejemplo: API de pruebas

Pulsamos en “Añadir una nueva clave de aplicación” y la contraseña que se genera la deberemos copiar en algún sitio (porque una vez generada ya no se puede consultar más veces) para pegar luego en nuestro fichero que se encargará de conectarse al API de WordPress.

De esta manera estaremos generando una clave de API con nuestro usuario sin exponer nuestra clave de acceso al site, para evitar cualquier susto en caso de que nos roben esta clave, ya que se puede anular rápida y fácilmente con el botón anular que se muestra en el listado de claves de aplicación generadas.

Hecho esto, nos ponemos con los archivos para hacer la conexión con el API REST de WP e insertar un post.

Archivo con el formulario

En primer lugar, crearemos, desde nuestra aplicación PHP un archivo que contendrá el formulario HTML así como el script en jQuery necesario para enviar la información.

Mi app en PHP está bajo el dominio https://dev.miapp y el archivo lo he alojado en una carpeta llamada scripts/ quedando tal que así la ruta completa: https://dev.miapp/scripts/test-wp-api-rest.php

El código queda tal que así:

<?php
?>
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Test WP API REST</title>
</head>
<body>
<form id="postForm">
  <label for="title">Title:</label>
  <input type="text" id="title" name="title" required>
  <label for="description">Description:</label>
  <textarea id="description" name="description" required></textarea>
  <button type="submit">Submit</button>
</form>
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
<script>
$(document).ready(function() {
  // Handle form submission
  $('#postForm').submit(function(e) {
    e.preventDefault();
    // Get form data
    var title = $('#title').val();
    var description = $('#description').val();
    // Create the post object
    var postData = {
      title: title,
      content: description
    };
    // Make the API request
    $.ajax({
      url: 'https://dev.miapp/scripts/test-proxy-wp-api-rest.php',
      method: 'POST',
      data: JSON.stringify(postData),
			contentType: 'application/json',
      success: function(response) {
        console.log('Post created successfully!');
        console.log(response);
      },
      error: function(xhr, status, error) {
        console.error('Error creating post:', error);
      }
    });
  });
});
</script>
</body>
</html>

Archivo proxy

Y después, por otra parte, tendremos otro script en PHP que ejercerá de proxy con la conexión al API REST. Lo hacemos con PHP debido a que no podemos ejecutar la llamada al API de WP desde otro dominio diferente por JS debido a restricciones de CORS (cross-origin resource sharing).

El archivo estará alojado en mi caso en https://dev.miapp/scripts/test-proxy-wp-api-rest.php y su código es tal que así:

<?php
// Define the target WordPress site URL
$targetUrl = 'https://dev.testwp/wp-json/wp/v2/posts';
// Get the request body from the HTML form
$requestBody = file_get_contents('php://input');
// Set the appropriate headers for the request
$headers = array(
	'Content-Type: application/json',
	'Content-Length: ' . strlen( $requestBody ),
	'Authorization: Basic ' . base64_encode('mi_user_de_wp:clave_de_api_generada'),
);
// Initialize a cURL session
$curl = curl_init($targetUrl);
// Set the cURL options
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $requestBody);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_VERBOSE, true);
// Execute the cURL request
$response = curl_exec($curl);
if ($response === false) {
	$error = curl_error($curl);
	echo 'cURL error: ' . $error;
	die;
}
// Get the HTTP status code
$httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
// Close the cURL session
curl_close($curl);
// Set the appropriate response headers
header('Content-Type: application/json');
http_response_code($httpStatus);
// Output the response from the WordPress API
echo $response;

Los tres puntos más importantes de este archivo son:

  • el endpoint del API REST que usaremos para insertar los posts, en nuestro caso: https://dev.testwp/wp-json/wp/v2/posts
  • El usuario con permisos para publicar posts en nuestra web en WP
  • La password generada a través del generador de contraseñas para aplicaciones que hemos generado unos pasos atrás

Los dos últimos puntos se muestran en esta variable, en la parte de Authorization:

$headers = array(
	'Content-Type: application/json',
	'Content-Length: ' . strlen( $requestBody ),
	'Authorization: Basic ' . base64_encode('mi_user_de_wp:clave_de_api_generada'),
);

Hecho todo esto, si ejecutamos en el navegador nuestro script que contiene el formulario HTML, rellenamos los datos de título y descripción y pulsamos en el botón de Enviar, nos habrá insertado un post en modo “Borrador” en nuestra instalación de WordPress vía API REST.