제 cURL 요청에 문제가 있는 이유는 무엇인가요?

안녕하세요! WordPress 사이트에서 Discourse를 woo subscriptions과 통합하기 위해 cURL 요청을 작성하려고 합니다. 아래는 제 함수인데, 작동하지 않는 것 같습니다. 놓친 부분이 있을까요?

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);
    }
}

안녕하세요,

어떤 오류가 발생하나요? 응답이 무엇을 반환하나요?
이 정보가 문제 파악에 도움이 될 것입니다.

문제는 오류나 확인 메시지가 전혀 표시되지 않는다는 것입니다. cURL이 단순히 작동하지 않는 것으로 보입니다. cURL 실행 시 Discourse API 키가 사용되었음을 확인할 수 있으므로 일부는 성공했지만, 의도대로 사용자가 그룹에 추가되거나 제거되지 않습니다. 변수들이 모두 정확하다는 것은 확인했습니다.

성공하거나 실패할 때 페이로드를 반환해야 합니다.

$response의 내용을 확인해 보셨나요?

또한, usernames 매개변수 형식은 “username1,username2,...” 형태의 문자열이어야 한다고 생각합니다.

제가 무언가를 잘못하고 있지 않다면, "/groups/${group_id}/members.json"에 대한 요청 방식은 직관적이지 않습니다. 또한 이 요청은 문서화되어 있지 않고, 그룹 페이지에서 Discourse의 “사용자 추가” 양식을 제출할 때 브라우저의 네트워크 탭에서도 확인할 수 없습니다. 다시 한번 말하지만, 제가 잘못하고 있는 것일 수도 있습니다.

어쨌든, 요청의 경로는 /groups/${group_id}/members.json이며, group_id에는 그룹의 숫자 ID가 대입됩니다. 요청 본문에는 group_id 매개변수가 필요하지만, 이 매개변수는 그룹의 name으로 설정해야 합니다. 따라서 인수는 다음과 같은 형태가 됩니다:

$group_id = 45;
$group_name = 'publishers';
$args     = array(
    'method' => 'DELETE', // 또는 'PUT'
	'body'   => array(
		// 'group_id'  => $group_name, 수정: 이 매개변수는 필요하지 않습니다. 테스트할 때 무슨 일이 있었는지 확실하지 않습니다.
		'usernames' => 'sally,Ben',
	)
);

// 경로:
/groups/${group_id}/members.json

WordPress 사이트에 WP Discourse 플러그인이 구성되어 있다면, curl을 사용할 필요가 없도록 정적 discourse_request 헬퍼 함수를 사용할 수 있습니다. 참고로 plugin-utilities 파일에 있는 정적 함수에 링크를 걸었지만, 외부 요청에 사용할 네임스페이스는 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'으로 사용자를 추가하고; 'DELETE'로 사용자를 제거합니다
	$args     = array(
		'method' => $method,
		'body'   => array(
			// 'group_id'  => $group_name, 수정: 이 매개변수는 필요하지 않습니다
			'usernames' => 'sally,Ben',
		)
	);
	$response = DiscourseUtilities::discourse_request( "/groups/${group_id}/members.json", $args );
    // 응답을 반환하거나, 로그를 기록하거나, 처리합니다
}

WordPress를 Discourse의 SSO 제공자로 사용 중이라면, _한 명_의 사용자를 하나 이상의 그룹에 추가할 수 있는 헬퍼 함수가 있습니다:

function zalg_sso_add_users_to_group() {
    $user_id = 1; // 사용자의 WordPress 사용자 ID
    $group_names = 'foo,bar,baz'; // 쉼표로 구분된 하나 이상의 그룹 이름, 쉼표 뒤에는 공백이 없어야 합니다!
    DiscourseUtilities::add_user_to_discourse_group($user_id, $group_names);
}

여러 사용자를 단일 그룹에 추가하려면 여전히 첫 번째 코드 예제에 있는 discourse_request 메서드를 사용해야 합니다.

응답은 그냥 500 오류입니다 :frowning:

정말 큰 도움이 되네요, 시몬! 감사합니다! WP Discourse 플러그인에 이미 있는 헬퍼 함수를 활용할 수 있다면 훨씬 쉬울 것 같아요. 저는 SSO를 위해 워드프레스 사이트를 사용 중입니다.

하지만 제 경우엔 해당 함수가 실행될 때 여전히 치명적 오류가 발생해요. 이유를 모르겠네요. 말씀하신 내용은 제 수준을 좀 넘어가는 것 같지만, 제 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);
}

무엇을 놓치고 있는지 모르겠네요?

사용자를 하나 이상의 그룹에서 제거하는 함수는 remove_user_from_discourse_group인데, remove_user_to_discourse_group을 호출하셨습니다.

사용자를 하나 이상의 그룹에 추가하고 제거하는 함수는 여기에 있습니다: wp-discourse/lib/utilities.php at 99325e15190f3a705284dbf582f1c4b2c0b21492 · discourse/wp-discourse · GitHub.

맞아요! 어리석은 실수였네요. 시몬, 도움 주셔서 감사합니다. 팁을 드릴 수 있는 곳이 있으면 좋겠어요. 제가 도와드릴 일이 있으면 말씀해 주세요. 감사합니다!

이 내용을 더 확장해서 말씀드리자면, 사용자 프로필을 더 많이 편집할 수 있는 헬퍼 함수를 어디서 찾을 수 있는지 아시나요? 가능하다면 사용자 프로필 사진과 소개글을 설정할 수 있으면 좋겠습니다.

이를 위한 헬퍼 함수가 Utilities 파일에 있습니다:

DiscourseUtilities::sync_sso_record( $sso_params );

어제 사용법에 대한 예시를 게시했습니다: I cannot add user to the discouse forum from a wordpress website when user added in a membership - #10 by simon. 까다로운 부분은 sso_params 인수를 위한 배열을 만드는 것입니다. 이 배열에는 external_id 필드가 포함되어야 합니다. 이 필드는 사용자의 WordPress ID로 설정됩니다:

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

페이로드에는 다음 목록의 어떤 필드를 포함시킬 수 있습니다: discourse/lib/discourse_connect_base.rb at 8f52fd1051e20fdff41321c5cff99fda05af86c1 · discourse/discourse · GitHub. 제가 링크한 ACCESSORS 목록 바로 아래에 표시된 BOOLS 배열에 유의하십시오. 이는 가능한 옵션 중 어떤 것이 booleans(true/false)인지 나타냅니다. WordPress에서 요청을 할 때, 모든 boolean 필드는 PHP의 true 또는 false 값이 아닌 문자열 'true' 또는 'false'로 설정해야 합니다.

아바타를 업데이트하려면 $sso_params 배열에서 avatar_url 필드를 설정하고 avatar_force_update 필드도 'true'로 설정하십시오.

자기소개(Bio)를 설정하는 데 사용할 수 있는 bio 필드가 있습니다.

WP Discourse 플러그인은 이미 bio 및 avatar_url 필드를 설정하고 있습니다. 또한 SSO 설정에 “Force Avatar Update” 설정이 있습니다. 문제는 이러한 설정이 사용자가 WordPress 사이트를 통해 Discourse에 로그인할 때만 업데이트될 수 있다는 점입니다. sync_sso_record 함수는 사용자가 Discourse에 로그인할 필요 없이 필드를 즉시 업데이트합니다.

또한, Discourse에서 사용자 자기소개가 설정되지 않는 것으로 보인다면, 플러그인이 기대하는 위치인 WordPress 사이트에서 자기소개가 설정되지 않았기 때문일 수 있습니다: wp-discourse/lib/plugin-utilities.php at 99325e15190f3a705284dbf582f1c4b2c0b21492 · discourse/wp-discourse · GitHub. WooCommerce에 자기소개를 위한 다른 필드가 있다면, 해당 필드에 접근하여 sync_sso_record 호출에 사용할 수 있습니다.