feat(pay): enforce VIP free-download daily quota like zibll
This commit is contained in:
1 parent
7cce3ff275
commit
8b50687e9d
4 files changed
+199
-4
No files matched your search
@@ -171,6 +171,14 @@ class AKSRT_Content_Visibility {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Zibll daily free-download quota.
|
||||||
|
if ($cost <= 0 && function_exists('aksrt_check_free_download_quota')) {
|
||||||
|
$quota = aksrt_check_free_download_quota($uid, $cost);
|
||||||
|
if (is_wp_error($quota)) {
|
||||||
|
return $quota;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($paid_settings['download_credit']) && $cost > 0) {
|
if (!empty($paid_settings['download_credit']) && $cost > 0) {
|
||||||
$balance = class_exists('AKSRT_Credits') ? AKSRT_Credits::balance($uid) : 0;
|
$balance = class_exists('AKSRT_Credits') ? AKSRT_Credits::balance($uid) : 0;
|
||||||
if ($balance < $cost) {
|
if ($balance < $cost) {
|
||||||
|
|||||||
@@ -124,10 +124,13 @@ class AKSRT_Download {
|
|||||||
'post_id' => $post_id,
|
'post_id' => $post_id,
|
||||||
'price' => (float) $meta['price'],
|
'price' => (float) $meta['price'],
|
||||||
'cost' => $cost,
|
'cost' => $cost,
|
||||||
'require_login' => !empty($paid_settings['download_login']) || !empty($meta['require_login']),
|
'require_login' => !empty($paid_settings['download_login']) || !empty($meta['require_login']) || (!empty($paid_settings['free_logged_show']) && $cost <= 0),
|
||||||
'require_captcha' => $need_captcha,
|
'require_captcha' => $need_captcha,
|
||||||
'logged_in' => $uid > 0,
|
'logged_in' => $uid > 0,
|
||||||
'balance' => $uid > 0 && class_exists('AKSRT_Credits') ? AKSRT_Credits::balance($uid) : 0,
|
'balance' => $uid > 0 && class_exists('AKSRT_Credits') ? AKSRT_Credits::balance($uid) : 0,
|
||||||
|
'free_limit' => $uid > 0 && function_exists('aksrt_get_user_free_download_limit') ? aksrt_get_user_free_download_limit($uid) : 0,
|
||||||
|
'free_used' => $uid > 0 && function_exists('aksrt_get_user_free_downloaded_number') ? aksrt_get_user_free_downloaded_number($uid) : 0,
|
||||||
|
'free_surplus' => $uid > 0 && function_exists('aksrt_get_free_download_surplus') ? aksrt_get_free_download_surplus($uid) : null,
|
||||||
'sources' => array_map(function ($row, $idx) {
|
'sources' => array_map(function ($row, $idx) {
|
||||||
$extract_code = trim((string) ($row['extract_code'] ?? ''));
|
$extract_code = trim((string) ($row['extract_code'] ?? ''));
|
||||||
return [
|
return [
|
||||||
@@ -162,6 +165,17 @@ class AKSRT_Download {
|
|||||||
if (is_wp_error($gate)) return $gate;
|
if (is_wp_error($gate)) return $gate;
|
||||||
|
|
||||||
$paid_settings = AKSRT_Settings::get_paid_content_settings();
|
$paid_settings = AKSRT_Settings::get_paid_content_settings();
|
||||||
|
$uid = get_current_user_id();
|
||||||
|
$cost = aksrt_resource_download_cost($post);
|
||||||
|
|
||||||
|
// Daily free-download quota (Zibll).
|
||||||
|
if ($cost <= 0 && $uid > 0 && function_exists('aksrt_check_free_download_quota')) {
|
||||||
|
$quota = aksrt_check_free_download_quota($uid, $cost);
|
||||||
|
if (is_wp_error($quota)) {
|
||||||
|
return $quota;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$need_captcha = !empty($paid_settings['download_captcha']) || !empty($meta['require_captcha']);
|
$need_captcha = !empty($paid_settings['download_captcha']) || !empty($meta['require_captcha']);
|
||||||
// 下载双开关:cms_features.download_captcha(或单资源强制)且场景未停用。
|
// 下载双开关:cms_features.download_captcha(或单资源强制)且场景未停用。
|
||||||
if ($need_captcha && function_exists('aksrt_require_captcha')) {
|
if ($need_captcha && function_exists('aksrt_require_captcha')) {
|
||||||
@@ -176,8 +190,6 @@ class AKSRT_Download {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$uid = get_current_user_id();
|
|
||||||
$cost = aksrt_resource_download_cost($post);
|
|
||||||
if ($cost > 0 && $uid > 0 && class_exists('AKSRT_Credits')) {
|
if ($cost > 0 && $uid > 0 && class_exists('AKSRT_Credits')) {
|
||||||
$deducted = AKSRT_Credits::deduct($uid, $cost, 'download', ['type' => 'post', 'id' => $post_id]);
|
$deducted = AKSRT_Credits::deduct($uid, $cost, 'download', ['type' => 'post', 'id' => $post_id]);
|
||||||
if (is_wp_error($deducted)) return $deducted;
|
if (is_wp_error($deducted)) return $deducted;
|
||||||
@@ -191,6 +203,11 @@ class AKSRT_Download {
|
|||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Record free download against daily quota after token issued.
|
||||||
|
if ($cost <= 0 && $uid > 0 && function_exists('aksrt_record_user_free_download')) {
|
||||||
|
aksrt_record_user_free_download($uid, $post_id);
|
||||||
|
}
|
||||||
|
|
||||||
$dl_url = home_url('/' . self::ENDPOINT . '/' . $token);
|
$dl_url = home_url('/' . self::ENDPOINT . '/' . $token);
|
||||||
if ($uid > 0 && function_exists('aksrt_add_user_notification')) {
|
if ($uid > 0 && function_exists('aksrt_add_user_notification')) {
|
||||||
aksrt_add_user_notification($uid, [
|
aksrt_add_user_notification($uid, [
|
||||||
|
|||||||
@@ -149,6 +149,160 @@ function aksrt_get_vip_badge_text(): string {
|
|||||||
return sanitize_text_field($vip_settings['badge_text'] ?? 'VIP');
|
return sanitize_text_field($vip_settings['badge_text'] ?? 'VIP');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Daily free-download limit for a user (0 = unlimited).
|
||||||
|
* Aligns with zibll pay_download_limit / pay_download_limit_vip_{n}.
|
||||||
|
*/
|
||||||
|
if (!function_exists('aksrt_get_user_free_download_limit')) {
|
||||||
|
function aksrt_get_user_free_download_limit(int $user_id = 0): int {
|
||||||
|
if ($user_id <= 0) {
|
||||||
|
$user_id = get_current_user_id();
|
||||||
|
}
|
||||||
|
if ($user_id <= 0 || !class_exists('AKSRT_Settings')) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$vip = AKSRT_Settings::get_payment_vip_settings();
|
||||||
|
$level = function_exists('aksrt_get_user_vip_level') ? aksrt_get_user_vip_level($user_id) : 0;
|
||||||
|
$levels = is_array($vip['levels'] ?? null) ? $vip['levels'] : [];
|
||||||
|
$benefit = is_array($vip['benefit'] ?? null) ? $vip['benefit'] : [];
|
||||||
|
|
||||||
|
if ($level >= 1 && !empty($levels[$level]['enabled'])) {
|
||||||
|
return max(0, (int) ($levels[$level]['download_limit'] ?? 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return max(0, (int) ($benefit['download_limit'] ?? 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download speed cap in KB/s for a user (0 = unlimited).
|
||||||
|
*/
|
||||||
|
if (!function_exists('aksrt_get_user_download_speed')) {
|
||||||
|
function aksrt_get_user_download_speed(int $user_id = 0): int {
|
||||||
|
if ($user_id <= 0) {
|
||||||
|
$user_id = get_current_user_id();
|
||||||
|
}
|
||||||
|
if ($user_id <= 0 || !class_exists('AKSRT_Settings')) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$vip = AKSRT_Settings::get_payment_vip_settings();
|
||||||
|
$level = function_exists('aksrt_get_user_vip_level') ? aksrt_get_user_vip_level($user_id) : 0;
|
||||||
|
$levels = is_array($vip['levels'] ?? null) ? $vip['levels'] : [];
|
||||||
|
$benefit = is_array($vip['benefit'] ?? null) ? $vip['benefit'] : [];
|
||||||
|
|
||||||
|
if ($level >= 1 && !empty($levels[$level]['enabled'])) {
|
||||||
|
return max(0, (int) ($levels[$level]['download_speed'] ?? 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return max(0, (int) ($benefit['download_speed'] ?? 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count free downloads used today for a user (zibll pay_down_number).
|
||||||
|
*/
|
||||||
|
if (!function_exists('aksrt_get_user_free_downloaded_number')) {
|
||||||
|
function aksrt_get_user_free_downloaded_number(int $user_id = 0): int {
|
||||||
|
if ($user_id <= 0) {
|
||||||
|
$user_id = get_current_user_id();
|
||||||
|
}
|
||||||
|
if ($user_id <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$day = current_time('Y-m-d');
|
||||||
|
$mate = get_user_meta($user_id, 'aksrt_pay_down_number', true);
|
||||||
|
if (!is_array($mate) || empty($mate[$day]) || !is_array($mate[$day])) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return count($mate[$day]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record a free download for daily quota (zibll pay_down_number).
|
||||||
|
*/
|
||||||
|
if (!function_exists('aksrt_record_user_free_download')) {
|
||||||
|
function aksrt_record_user_free_download(int $user_id, int $post_id): void {
|
||||||
|
if ($user_id <= 0 || $post_id <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$day = current_time('Y-m-d');
|
||||||
|
$mate = get_user_meta($user_id, 'aksrt_pay_down_number', true);
|
||||||
|
if (!is_array($mate)) {
|
||||||
|
$mate = [];
|
||||||
|
}
|
||||||
|
// Drop old days to keep meta small.
|
||||||
|
foreach (array_keys($mate) as $k) {
|
||||||
|
if ($k !== $day) {
|
||||||
|
unset($mate[$k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isset($mate[$day]) || !is_array($mate[$day])) {
|
||||||
|
$mate[$day] = [];
|
||||||
|
}
|
||||||
|
$mate[$day][(string) $post_id] = 1;
|
||||||
|
update_user_meta($user_id, 'aksrt_pay_down_number', $mate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a free download is allowed under daily quota.
|
||||||
|
* Paid downloads (cost > 0) always pass.
|
||||||
|
*
|
||||||
|
* @return true|WP_Error
|
||||||
|
*/
|
||||||
|
if (!function_exists('aksrt_check_free_download_quota')) {
|
||||||
|
function aksrt_check_free_download_quota(int $user_id, int $cost = 0) {
|
||||||
|
if ($cost > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ($user_id <= 0) {
|
||||||
|
return true; // login gate handled elsewhere
|
||||||
|
}
|
||||||
|
|
||||||
|
$limit = aksrt_get_user_free_download_limit($user_id);
|
||||||
|
if ($limit <= 0) {
|
||||||
|
return true; // unlimited
|
||||||
|
}
|
||||||
|
|
||||||
|
$used = aksrt_get_user_free_downloaded_number($user_id);
|
||||||
|
if ($used >= $limit) {
|
||||||
|
return new WP_Error(
|
||||||
|
'aksrt_download_limit',
|
||||||
|
__('您今日下载免费资源个数已超限,请明日再下载。', 'aksrt'),
|
||||||
|
[
|
||||||
|
'status' => 429,
|
||||||
|
'limit' => $limit,
|
||||||
|
'used' => $used,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remaining free downloads today (null = unlimited).
|
||||||
|
*/
|
||||||
|
if (!function_exists('aksrt_get_free_download_surplus')) {
|
||||||
|
function aksrt_get_free_download_surplus(int $user_id = 0): ?int {
|
||||||
|
if ($user_id <= 0) {
|
||||||
|
$user_id = get_current_user_id();
|
||||||
|
}
|
||||||
|
$limit = aksrt_get_user_free_download_limit($user_id);
|
||||||
|
if ($limit <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$used = aksrt_get_user_free_downloaded_number($user_id);
|
||||||
|
return max(0, $limit - $used);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染 VIP 徽标 HTML
|
* 渲染 VIP 徽标 HTML
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -282,7 +282,23 @@ $currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name()
|
|||||||
</ul>
|
</ul>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="resource-download-box__guarantees">
|
<?php
|
||||||
|
if (is_user_logged_in() && $cost <= 0 && function_exists('aksrt_get_user_free_download_limit')) {
|
||||||
|
$dl_limit = aksrt_get_user_free_download_limit();
|
||||||
|
if ($dl_limit > 0) {
|
||||||
|
$dl_used = function_exists('aksrt_get_user_free_downloaded_number') ? aksrt_get_user_free_downloaded_number() : 0;
|
||||||
|
$dl_surplus = max(0, $dl_limit - $dl_used);
|
||||||
|
$vip_lv = function_exists('aksrt_get_user_vip_level') ? aksrt_get_user_vip_level() : 0;
|
||||||
|
if ($dl_surplus <= 0) {
|
||||||
|
echo '<div class="resource-download-box__quota-notice"><span class="badg c-red btn-block">' . esc_html__('您今日下载免费资源个数已超限,请明日再下载。', 'aksrt') . '</span></div>';
|
||||||
|
} else {
|
||||||
|
$who = $vip_lv > 0 ? esc_html__('您是尊贵的会员,', 'aksrt') : esc_html__('您', 'aksrt');
|
||||||
|
echo '<div class="resource-download-box__quota-notice"><span class="badg c-red btn-block">' . $who . esc_html(sprintf(__('今日还可下载 %s 个免费资源', 'aksrt'), number_format_i18n($dl_surplus))) . '</span></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<div class="resource-download-box__guarantees">
|
||||||
<?php
|
<?php
|
||||||
if (function_exists('aksrt_get_pay_service_html')) {
|
if (function_exists('aksrt_get_pay_service_html')) {
|
||||||
echo aksrt_get_pay_service_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
echo aksrt_get_pay_service_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
|||||||
Reference in new issue
Block a user