feat(vip): implement layered membership expiry flow

This commit is contained in:
2026-08-11 16:58:01 +08:00
parent ddc762bfbd
commit 80283df6b2
8 changed files with 251 additions and 47 deletions
+34 -6
View File
@@ -478,6 +478,9 @@ trait VipServicePurchase {
if (sanitize_key((string) ($paid_order['product_type'] ?? '')) !== \AKSRT\Core\DomainModel::ORDER_PRODUCT_VIP) {
return;
}
if (sanitize_key((string) ($paid_order['payment_method'] ?? '')) === 'card_pass') {
return;
}
$user_id = (int) ($paid_order['user_id'] ?? 0);
if ($user_id <= 0) {
return;
@@ -493,6 +496,9 @@ trait VipServicePurchase {
if (empty($meta) && is_array($paid_order['meta_payload'] ?? null)) {
$meta = $paid_order['meta_payload'];
}
if (!empty($meta['card_pass']) || sanitize_key((string) ($meta['vip_pay_type'] ?? '')) === 'card_pass') {
return;
}
$level = (int) ($meta['level'] ?? 0);
$days = (int) ($meta['days'] ?? 0);
@@ -517,13 +523,17 @@ trait VipServicePurchase {
$previous_level = (int) get_user_meta($user_id, 'aksrt_vip_level', true);
$previous_expiry = (int) get_user_meta($user_id, 'aksrt_vip_expires', true);
$previous_base_level = (int) get_user_meta($user_id, 'aksrt_vip_base_level', true);
$previous_base_expiry = (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true);
$finite_duration = $time > 0 || $days > 0;
if ($previous_level > 0 && $previous_expiry === 0 && $level > $previous_level && $finite_duration) {
// Preserve a permanent lower tier while a finite higher-tier upgrade is active.
update_user_meta($user_id, 'aksrt_vip_base_level', $previous_level);
update_user_meta($user_id, 'aksrt_vip_base_expires', 0);
} else {
// Only a finite higher-tier upgrade may keep a layered base membership.
if ($previous_level > 0 && $level > $previous_level && $finite_duration) {
// Preserve the original lower tier while a finite higher-tier upgrade is active.
if ($previous_base_level <= 0 || ($previous_base_expiry > 0 && $previous_base_expiry < time())) {
update_user_meta($user_id, 'aksrt_vip_base_level', $previous_level);
update_user_meta($user_id, 'aksrt_vip_base_expires', max(0, $previous_expiry));
}
} elseif (!$finite_duration || $level < $previous_level) {
// Permanent grants and lower-tier grants do not retain a temporary overlay.
delete_user_meta($user_id, 'aksrt_vip_base_level');
delete_user_meta($user_id, 'aksrt_vip_base_expires');
}
@@ -574,6 +584,15 @@ trait VipServicePurchase {
}
$level = max(1, min(2, $level));
$current_level = (int) get_user_meta($user_id, 'aksrt_vip_level', true);
$current_expiry = max(0, (int) get_user_meta($user_id, 'aksrt_vip_expires', true));
if (!$keep_expiry && $days > 0 && $current_level > 0 && $level > $current_level) {
$base_level = (int) get_user_meta($user_id, 'aksrt_vip_base_level', true);
$base_expires = (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true);
if ($base_level <= 0 || ($base_expires > 0 && $base_expires < time())) {
update_user_meta($user_id, 'aksrt_vip_base_level', $current_level);
update_user_meta($user_id, 'aksrt_vip_base_expires', $current_expiry);
}
}
$new_level = max($current_level, $level);
update_user_meta($user_id, 'aksrt_vip_level', $new_level);
// Clear expired memory when re-granting.
@@ -611,6 +630,15 @@ trait VipServicePurchase {
$level = max(1, min(2, $level));
$unit = $unit === 'month' ? 'month' : 'day';
$current_level = (int) get_user_meta($user_id, 'aksrt_vip_level', true);
$current_expiry = max(0, (int) get_user_meta($user_id, 'aksrt_vip_expires', true));
if ($time > 0 && $current_level > 0 && $level > $current_level) {
$base_level = (int) get_user_meta($user_id, 'aksrt_vip_base_level', true);
$base_expires = (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true);
if ($base_level <= 0 || ($base_expires > 0 && $base_expires < time())) {
update_user_meta($user_id, 'aksrt_vip_base_level', $current_level);
update_user_meta($user_id, 'aksrt_vip_base_expires', $current_expiry);
}
}
$new_level = max($current_level, $level);
update_user_meta($user_id, 'aksrt_vip_level', $new_level);
delete_user_meta($user_id, 'aksrt_vip_level_expired');