¿Cuál es el problema con mi solicitud cURL?

¡Hola! Estoy intentando escribir una solicitud cURL para mi sitio de Wordpress para integrar Discourse con suscripciones de woo. Aquí está mi función, que no parece funcionar. ¿Me falta algo?

function execute_discourse_curl_request($subscription) {

    $subscription_status = $subscription->get_status();

    $user_id = $subscription->get_user_id();
    $user = get_user_by('ID', $user_id);
    $username = $user->user_login;

    $request = "";

    if ($subscription_status == 'active') {
        $request = "PUT";
    }

    if ($subscription_status == 'cancelled' || $subscription_status == 'on-hold') {
        $request = "DELETE";
    }

    $api_key = get_option( 'discourse_custom_api_key' );

    $group_id = 41;
    $api_url = 'https://forum.example.com/groups/' . $group_id . '/members.json';
    
    $data = [
        'usernames' => [$username],
    ];
    
    $curl = curl_init();
    curl_setopt_array($curl, [
        CURLOPT_URL => $api_url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING => "",
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => $request,
        CURLOPT_POSTFIELDS => json_encode($data),
        CURLOPT_HTTPHEADER => [
            "Api-Key: " . $api_key,
            "Api-Username: system",
            "Content-Type: application/json"
        ],
    ]);
    
    $response = curl_exec($curl);
    $err = curl_error($curl);
    
    curl_close($curl);

    if ($err) {
        $to = 'hello@example.com';
        $subject = 'Error in Discourse User Update cURL Request';
        $message = 'There was an error';
        wp_mail($to, $subject, $message);
    }
}
1 me gusta

Hola,

¿Qué error obtienes? ¿Qué devuelve la respuesta?
Esto debería ayudar a comprender el problema.

El problema es que no recibo ningún error ni confirmación. Parece que cURL simplemente no funciona. Puedo ver que se usó la clave API de Discourse cuando se ejecuta cURL, así que hay cierto éxito, pero el usuario no se agrega ni se elimina del grupo según lo previsto. Sin embargo, puedo confirmar que todas las variables son correctas.

Debería devolver una carga útil en caso de éxito o fracaso.

¿Has comprobado el contenido de $response?

Además, creo que el formato del parámetro usernames debería ser una cadena de texto “username1,username2,...” en su lugar.

1 me gusta

A menos que esté haciendo algo mal, la solicitud a "/groups/${group_id}/members.json" es un tanto poco intuitiva. Tampoco parece estar documentada y no se puede ver en la pestaña de red del navegador al enviar el formulario “Añadir usuario” de Discourse en la página de un grupo. De nuevo, podría estar haciendo algo mal.

En cualquier caso, la ruta para la solicitud es /groups/${group_id}/members.json, con el ID numérico del grupo sustituido por group_id. El cuerpo de la solicitud requiere un parámetro group_id, pero ese parámetro debe establecerse en el name del grupo. Así que los argumentos quedan algo así:

$group_id = 45;
$group_name = 'publishers';
$args     = array(
    'method' => 'DELETE', // o 'PUT'
	'body'   => array(
		// 'group_id'  => $group_name, edit: este parámetro no es necesario, no estoy seguro de lo que estaba pasando cuando lo estaba probando.
		'usernames' => 'sally,Ben',
	)
);

// ruta:
/groups/${group_id}/members.json

Si tiene el plugin WP Discourse configurado en su sitio de WordPress, puede usar su función de ayuda estática discourse_request para evitar tener que usar curl. Tenga en cuenta que enlacé a la función estática que está en el archivo plugin-utilities, pero el espacio de nombres que necesita usar para las solicitudes externas es de https://github.com/discourse/wp-discourse/blob/main/lib/utilities.php.

use WPDiscourse\\Utilities\\Utilities as DiscourseUtilities;

function zalg_add_users_to_group() {
	$group_id = 45;
    $group_name = 'publishers';
    $method = 'PUT'; // 'PUT' para añadir usuarios; 'DELETE' para eliminar usuarios
	$args     = array(
		'method' => $method,
		'body'   => array(
			// 'group_id'  => $group_name, edit: este parámetro no es necesario
			'usernames' => 'sally,Ben',
		)
	);
	$response = DiscourseUtilities::discourse_request( "/groups/${group_id}/members.json", $args );
    // devolver, registrar o manejar la respuesta
}

Si está utilizando WordPress como proveedor de SSO para Discourse, hay una función de ayuda que le permite añadir un usuario a uno o más grupos:

function zalg_sso_add_users_to_group() {
    $user_id = 1; // el ID de usuario de WordPress
    $group_names = 'foo,bar,baz'; // uno o más nombres de grupo separados por comas, ¡sin espacios después de las comas!
    DiscourseUtilities::add_user_to_discourse_group($user_id, $group_names);
}

Para añadir varios usuarios a un solo grupo, todavía necesitaría usar el método discourse_request que se encuentra en el primer ejemplo de código.

3 Me gusta

La respuesta es solo un error 500 :frowning:

Esta es una ayuda heroica, ¡gracias Simon! Sería mucho más fácil si pudiera utilizar las funciones de ayuda existentes en el plugin WP Discourse. Estoy usando mi sitio de Wordpress para SSO.

Sin embargo, todavía obtengo un error crítico en mi caso cuando se activa la función. No estoy seguro de por qué. Lo que dices está un poco por encima de mi nivel, pero esto es lo que estoy usando en mi functions.php:

<?php

use WPDiscourse\Utilities\Utilities as DiscourseUtilities;

add_action('woocommerce_subscription_status_cancelled', 'zalg_sso_add_users_to_group', 10, 3);

function zalg_sso_add_users_to_group($subscription) {
    $user_id = $subscription->get_user_id();
    $group_names = 'premium';
    DiscourseUtilities::remove_user_to_discourse_group($user_id, $group_names);
}

¿No estoy seguro de qué me estoy perdiendo?

La función para eliminar a un usuario de uno o más grupos se llama remove_user_from_discourse_group, la has llamado remove_user_to_discourse_group.

Las funciones para agregar y eliminar a un usuario de uno o más grupos están aquí: wp-discourse/lib/utilities.php at 99325e15190f3a705284dbf582f1c4b2c0b21492 · discourse/wp-discourse · GitHub.

3 Me gusta

¡Tienes razón! Qué tontería. Gracias por tu ayuda, Simon. Ojalá hubiera un bote para propinas. Hazme saber si hay algo que pueda hacer por ti. ¡Saludos!

1 me gusta

Para ampliar esto, ¿sabe dónde podría encontrar funciones de ayuda para editar más el perfil de usuario? Sería genial si pudiera establecer la foto de perfil y la biografía del usuario, si es posible.

Hay una función de ayuda en el archivo Utilities para esto:

DiscourseUtilities::sync_sso_record( $sso_params );

Ayer publiqué un ejemplo de cómo usarla: I cannot add user to the discouse forum from a wordpress website when user added in a membership - #10 by simon. La parte complicada es crear la matriz para el argumento sso_params. Esa matriz debe contener el campo external_id. Se establece en el ID de WordPress del usuario:

	$sso_params = array(
		'external_id' => $user_id,
	);

Puedes incluir cualquier campo de esta lista en la carga útil: discourse/lib/discourse_connect_base.rb at 8f52fd1051e20fdff41321c5cff99fda05af86c1 · discourse/discourse · GitHub. Ten en cuenta la matriz BOOLS que se muestra justo debajo de la lista ACCESSORS que enlacé. Indica cuáles de las opciones posibles son booleans (verdadero/falso). Al realizar solicitudes desde WordPress, los campos booleanos deben establecerse con las cadenas 'true' o 'false', no con los valores true o false de PHP.

Para actualizar el avatar, establece el campo avatar_url en la matriz $sso_params y también establece el campo avatar_force_update en 'true'.

Hay un campo bio que se puede usar para establecer la biografía.

El plugin WP Discourse ya está estableciendo los campos bio y avatar_url. También tiene una configuración de “Forzar actualización de avatar” en su configuración de SSO. El problema podría ser que estas configuraciones solo se actualizan cuando un usuario inicia sesión en Discourse a través del sitio de WordPress. La función sync_sso_record actualiza los campos inmediatamente, sin requerir que el usuario inicie sesión en Discourse.

Además, si descubres que las biografías de los usuarios no se están estableciendo en Discourse, podría ser que no se estén estableciendo en tu sitio de WordPress donde el plugin espera que estén: wp-discourse/lib/plugin-utilities.php at 99325e15190f3a705284dbf582f1c4b2c0b21492 · discourse/wp-discourse · GitHub. Si Woocommerce tiene un campo diferente para las biografías, podrías acceder a ese campo y usarlo en una llamada a sync_sso_record.

3 Me gusta

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.