同步 WooCommerce 会员与 Discourse 群组

如果您不需要在一段时间后自动将用户从群组中移除,即他们购买的是群组的终身访问权限而非临时或周期性的访问权限,那么您可以在购买完成后通过钩子 woocommerce_payment_complete 将其添加到群组中。您也可以通过单点登录(SSO)钩子在用户登录时更新其所属群组。

1 个赞

谢谢 Jay!

一开始,我们将不为任何会员组提供终身访问选项。我们的“导师市场”的性质决定了用户将加入他们希望加入的教练/导师的群组。他们可能会尝试几个月,然后取消,并选择注册一个可能更符合其需求或期望的其他导师。

因此,我们需要一个活跃的 SYNC,以便当成员在 WP 中订阅自定义群组时,他们会被自动添加到 Discourse 中的相应群组;如果有人在 WP 上取消会员资格,他们也会被自动从 Discourse 的群组中移除。

如果您需要此代码的最新版本,可以在以下仓库中找到:https://github.com/paviliondev/discourse-woocommerce。

该代码已在生产环境中使用,并持续按描述正常工作。

步骤

  1. 将代码作为 WordPress 插件安装。
  2. 更新组和计划 ID。
  3. 每次会员状态变更时都会进行同步。

如果有人能将原帖(OP)整理成维基格式,我会更新为更详细的说明。

6 个赞

你好!我购买了 WooCommerce Memberships 插件。它能满足所有需求。之后一切问题都解决了。我在这里发布了我设置的完整集成教程。

1 个赞

那么你是先在 OP 中安装插件吗?

我和你一样,使用 Wordpress 作为我们 SSO 的提供商……而不是 Discourse(如本主题标题和 OP 中所述)

我知道原帖(OP)是关于当 Discourse 作为 SSO 提供商时同步群组的内容,但更新帖子标题并包含当 WordPress 作为 SSO 提供商时如何进行此同步的说明是否有意义呢?

@Ed_Bobkov 提供了一些细节,说明了如何在 SSO 提供商角色相反的情况下进行同步……

所以为了明确一下……

如果在原帖中包含两组不同的说明,那将非常棒,并且从长远来看可能对其他人更有帮助……

在以下情况下同步 WooCommerce 会员资格与 Discourse 群组:

  1. Discourse 是 SSO 提供商
  2. WordPress 是 SSO 提供商
2 个赞

你错了。我使用 Discourse 作为 SSO 提供商。但这并不改变核心意思。
你可以在这里找到当 WordPress 作为 SSO 提供商时的相关主题和说明。
关键在于:

  1. 无论 WordPress 是 SSO 提供商还是 Discourse 是 SSO 提供商,你都可以通过插件 “WooCommerce Memberships” 在 WordPress 中管理你的群组会员资格、订阅和条款。
  2. 要将 Discourse 的成员和群组与 WordPress 同步,在任何情况下都需要使用此插件:https://github.com/discourse/wp-discourse。在其设置中,你可以选择集成类型——是 WordPress 作为 SSO 提供商还是 Discourse 作为 SSO 提供商。
    此外,这个插件也可能有用:GitHub - paviliondev/discourse-woocommerce · GitHub
  3. 若要通过 cron 进行批量同步,需要使用此插件:WP Crontrol – WordPress plugin | WordPress.org
    详细说明请参见此主题(上方)。
4 个赞

该链接现在显示为 404 错误。它移动了吗?

1 个赞

主帖现已转为维基格式。

2 个赞

我已在主帖中更新了最新代码版本的链接和说明。

啊,我忘了将其设置为公开。谢谢。

@jord8on 正如 Ed 提到的,如果 Wordpress 是 SSO 提供商,你应该使用官方的 Discourse Wordpress 插件。

2 个赞

我遇到了一个关于 WooCommerce 与 Discourse 集成的问题。
如果用户购买了特定的会员资格,他们将自动分配到 Discourse 中的相应组。
这在大多数情况下都能正常工作。
但有时它不是自动化的。例如,在购买会员资格时,80% 的用户已分配到特定的 Discourse 组,但另外 20% 的用户没有。因此,我想为所有用户实现自动化。
有什么建议可以让我实现完全自动化吗?

:slight_smile:

你能帮我确认一下这些事情吗:

  1. 你正在使用 Discourse 作为你的 Discourse Connect 提供商(人们使用 Discourse 登录表单登录到 WordPress)
  2. 你正在 WordPress 中使用 WP Discourse 插件
  3. 你正在 WordPress 中使用我在此主题第一篇帖子中发布的代码

对吗?

您的第二个选项是正确的,我正在使用 discourse 插件。正如我提到的,我的用户在购买特定会员资格后会自动分配到特定组。

一切正常。只是几个月或更长时间后(偶尔)会出现这个问题,即一个随机用户在购买会员资格后未被分配到特定组。

我也想摆脱这种偶尔发生的问题。

如果只有第二个选项是正确的,那么这些说明将无法满足您的需求。这三者都需要为真。听起来您已经有一个同步在工作。为了让我理解,您是否\n\n1. 安装了 WP Discourse 插件;并且\n\n2. 编写了代码来同步您的 WooCommerce 群组(例如 如下所示)\u003c-- 您是否添加了此项?您能否分享您添加的内容?

2 个赞

不,我认为该插件完成了所有自动化,我不记得放置了任何集成代码。

也许我的插件是 2.2.3 版本,并且已过时,因为可用的更新是 2.4.1。

也许是这个版本导致了这个问题。但我有点好奇,更新后是否会损害我目前的功能。

要同步 WooCommerce 和 Discourse 之间的群组,您需要一些自定义代码。WP Discourse 插件本身无法完成此操作。您很可能已经实现了此处所述的功能。

在我可以进一步帮助您之前,您需要先确定同步是如何发生的(不仅仅是 WP Discourse 插件)。

1 个赞

我在WordPress中添加了代码——这是@Ed_Bobkov发布的:

<?php

//wp+discourse
use WPDiscourse\Utilities\Utilities as DiscourseUtilities;

const MEMBERSHIP_PLAN_DISCOURSE_GROUP = [
“112” => “41”
];

//const ACTIVE_STATUSES = array( ‘wcm-active’ );
const ACTIVE_STATUSES = array( ‘wcm-active’, ‘wcm-free_trial’ );

function update_discourse_group_access( $user_id, $membership_plan_id, $membership_plan_name, $status ) {
$options = DiscourseUtilities::get_options();
$base_url = $options[‘url’];
$api_key = $options[‘api-key’];
$api_username = $options[‘publish-username’];

if ( empty( $base_url ) || empty( $api_key ) || empty( $api_username ) ) {
	return new \WP_Error( 'discourse_configuration_error', 'The WP Discourse plugin has not been properly configured.' );
}

$user_info         = get_userdata( $user_id );
$user_email        = $user_info->user_email;
$logger            = wc_get_logger();

$logger->info( sprintf( '%s membership of %s changed to %s', $user_email, $membership_plan_name, $status ) );

if ( in_array( $status, ACTIVE_STATUSES ) ) {
	$action = 'PUT';
} else {
	$action = 'DELETE';
}

$external_url = esc_url_raw( $base_url . "/groups/" . MEMBERSHIP_PLAN_DISCOURSE_GROUP[$membership_plan_id] . "/members" );

$logger->info( sprintf( 'Sending %s request to %s with %s', $action, $external_url, $user_email ) );

$response = wp_remote_request( $external_url,
	array(
		'method'  => $action,
		'headers' => array(
			'Api-Key'      => sanitize_key( $api_key ),
			'Api-Username' => sanitize_text_field( $api_username ),
		),
		'body'    => array( 'user_emails' => $user_email ),
	)
);

$logger->info( sprintf( 'Response from Discourse: %s %s',
	wp_remote_retrieve_response_code( $response ),
	wp_remote_retrieve_response_message( $response ) ) );

if ( ! DiscourseUtilities::validate( $response ) ) {

	return new \WP_Error( 'discourse_response_error', 'There has been an error in retrieving the user data from Discourse.' );
}
}

function handle_wc_membership_saved( $membership_plan, $args ) {
$logger = wc_get_logger();

$logger->info( sprintf( 'Running handle_wc_membership_saved %s, %s, %s', $args['user_id'], $args['user_membership_id'], $args['is_update'] ) );

$user_id            = $args['user_id'];

$membership         = wc_memberships_get_user_membership( $args['user_membership_id'] );

$membership_plan_id = $membership->plan->id;

if ( $membership && isset(MEMBERSHIP_PLAN_DISCOURSE_GROUP[$membership_plan_id])) {
	$membership_plan_name = $membership_plan->name;
	$status               = $membership->status;
	update_discourse_group_access( $user_id, $membership_plan_id, $membership_plan_name, $status );
}
}
add_action( ‘wc_memberships_user_membership_saved’, ‘handle_wc_membership_saved’, 10, 2 );

/* run_full_wc_membership_sync */
function full_wc_membership_sync() {
$allusers = get_users();
$logger = wc_get_logger();

$logger->info( sprintf('Running full_wc_membership_sync') );

foreach ( $allusers as $user ) {

   $user_id = $user->id;

   $membership = wc_memberships_get_user_membership($user_id);

   $membership_plan_id = $membership->plan->id;

   $logger->info( sprintf('Checking membership of %s', $user->user_login) );

   if ($membership  && isset(MEMBERSHIP_PLAN_DISCOURSE_GROUP[$membership_plan_id])) {
       
	  $membership_plan_name = $membership->plan->name;
      
	  $status = $membership->status;
      
	  $logger->info( sprintf('Updating group access of %s', $user->user_login) );

	  update_discourse_group_access($user_id, $membership_plan_id, $membership_plan_name, $status);

	  $logger->info( sprintf('Sleeping for 5 seconds') );
      
	  sleep(5);
   }
}
}

add_action(‘run_full_wc_membership_sync’, ‘full_wc_membership_sync’);

我还通过WP Crontrol添加并运行了run_full_wc_membership_sync

但遗憾的是……拥有活动会员资格(ID 112)的WordPress用户未被添加到Discourse群组(ID 41)。我在这里遗漏了什么?

由于这不断让人们感到困惑,我将发布一个完整的“操作指南”,介绍 WooCommerce 会员同步(无论 WordPress 还是 Discourse 是 DiscourseConnect 提供商):)。如果我还没有就此与您联系,请在下周初在此处查看。

3 个赞

谢谢!我刚试着弄明白……我甚至还用了一个插件 GitHub - paviliondev/discourse-woocommerce 但也没成功。

1 个赞