
在许多WooCommerce订阅商店中,业务需求常常要求用户在同一时间只能持有一个活跃的订阅。例如,一个SaaS平台可能希望用户只能选择一个套餐级别(基础版、专业版、企业版),而不是同时拥有多个。然而,简单地通过购物车验证来阻止所有新的订阅购买,如果用户已经有活跃订阅,这会带来一个问题:它会阻止用户进行订阅的升级或降级操作。当用户尝试从一个低级订阅切换到高级订阅时,系统会将其识别为一次新的订阅购买,从而被阻止,这显然不符合预期。
挑战: 如何区分用户是想购买一个全新的、与现有活跃订阅无关的第二个订阅,还是想通过购买新套餐来替换(升级/降级)其现有活跃订阅?
解决方案: 关键在于在购物车验证逻辑中引入一个额外的判断。我们不仅要检查用户是否已经拥有活跃订阅,还要进一步判断当前用户尝试添加到购物车的订阅产品是否是其当前已经订阅的产品之一。
我们将利用WooCommerce提供的 woocommerce_add_to_cart_validation 钩子来拦截购物车添加操作,并执行我们的自定义逻辑。
以下是实现这一策略所需的PHP代码及其详细解析:
check_num_of_subscriptions 函数: 这是主要的验证函数,它挂载到 woocommerce_add_to_cart_validation 钩子。
has_active_subscription 函数: 此辅助函数用于查询当前登录用户是否拥有任何状态为 'wc-active' 的订阅。它通过 get_posts 查询 shop_subscription 帖子类型,并筛选出属于当前用户的活跃订阅。
has_woocommerce_subscription 函数: 这是区分“新订阅”和“升级/降级”的关键辅助函数。它利用 WooCommerce Subscriptions 插件提供的 WC_Subscriptions_Manager::user_has_subscription() 方法。这个方法能够精确地检查指定用户是否订阅了特定的产品。通过传递当前用户ID和即将添加到购物车的产品ID,我们可以判断用户是否已经拥有该产品的订阅。
将以下代码片段添加到您WordPress主题的 functions.php 文件中,或者更推荐的做法是创建一个自定义插件来管理此类功能。
<?php
/**
* 限制用户同时只能有一个活跃的WooCommerce订阅,但允许升级/降级。
*/
add_filter('woocommerce_add_to_cart_validation', 'check_num_of_subscriptions', 10, 2);
/**
* 购物车添加验证:检查用户是否已拥有活跃订阅,并允许订阅切换。
*
* @param bool $valid 当前验证结果。
* @param int $product_id 即将添加到购物车的产品ID。
* @return bool
*/
function check_num_of_subscriptions( $valid, $product_id ){
$product_to_add = wc_get_product( $product_id );
// 确保处理的是订阅产品
if ($product_to_add instanceof WC_Product_Subscription || $product_to_add instanceof WC_Product_Variable_Subscription){
// 检查用户是否已有活跃订阅
if ( has_active_subscription() ) {
// 如果用户已有活跃订阅,则进一步判断即将添加的产品是否是用户当前已订阅的产品
// has_woocommerce_subscription 返回 true 表示用户已订阅该产品(可能是升级/降级目标)
// 所以,如果用户有活跃订阅 AND 即将添加的产品不是用户已订阅的,则阻止
if (! has_woocommerce_subscription('', $product_id, '')) {
wc_clear_notices(); // 清除WooCommerce可能添加的其他通知
wc_add_notice(__('您已有一个活跃的订阅。如需更改套餐,请在“我的账户”页面进行切换。', 'woocommerce'), 'error');
return false; // 阻止产品添加到购物车
}
}
}
return $valid; // 允许添加,或非订阅产品则继续验证
}
/**
* 检查当前用户是否有任何活跃的WooCommerce订阅。
*
* @return bool 如果用户有活跃订阅则返回 true,否则返回 false。
*/
function has_active_subscription(){
$user_id = get_current_user_id();
if ( ! $user_id ) {
return false; // 未登录用户不考虑活跃订阅
}
$active_subscriptions = get_posts(array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $user_id,
'post_type' => 'shop_subscription',
'post_status' => 'wc-active' // 仅查询活跃状态的订阅
));
return !empty($active_subscriptions);
}
/**
* 检查指定用户是否订阅了特定产品。
*
* @param int $the_user_id 用户ID,可选,默认为当前用户。
* @param int $the_product_id 产品ID。
* @param string $the_status 订阅状态,可选。
* @return bool 如果用户订阅了该产品则返回 true,否则返回 false。
*/
function has_woocommerce_subscription($the_user_id, $the_product_id, $the_status) {
$current_user = wp_get_current_user();
if (empty($the_user_id)) {
$the_user_id = $current_user->ID;
}
// 确保 WC_Subscriptions_Manager 类存在,避免在插件未激活时报错
if (class_exists('WC_Subscriptions_Manager') && WC_Subscriptions_Manager::user_has_subscription( $the_user_id, $the_product_id, $the_status)) {
return true;
}
return false;
}通过上述实现,您的WooCommerce商店将能够有效地限制用户同时持有的活跃订阅数量,同时保持订阅升级和降级功能的流畅性,从而提供更灵活且符合业务需求的订阅管理体验。
以上就是WooCommerce订阅:实现单活跃订阅策略并允许套餐切换的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号