feat(pay): wire VIP-tier pricing into cost, gates, and download box

Resolve user-facing pay amounts via aksrt_get_user_pay_price (cash/points +
VIP1/2 tiers), surface pay_modo/pay_limit through download meta and REST policy,
and tighten content-visibility / download-box UX for member-only and purchase
gates while improving local stream throttle math.
This commit is contained in:
2026-07-14 11:13:17 +08:00
parent 1c8e4d3919
commit abe2f57417
5 changed files with 459 additions and 127 deletions
+87 -22
View File
@@ -38,7 +38,17 @@ class AKSRT_Content_Visibility {
? aksrt_get_pay_meta($resource_post)
: AKSRT_Domain_Model::default_pay_meta();
$pay_type = AKSRT_Domain_Model::normalize_pay_type((string) ($pay_meta['pay_type'] ?? AKSRT_Domain_Model::PAY_TYPE_NO));
$price = (float) ($pay_meta['price'] ?? 0);
$priced = function_exists('aksrt_get_user_pay_price')
? aksrt_get_user_pay_price($resource_post, $uid)
: null;
$pay_modo = is_array($priced)
? ((($priced['modo'] ?? '0') === 'points') ? 'points' : '0')
: ((($pay_meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0');
$price = is_array($priced)
? (float) ($priced['amount'] ?? 0)
: (($pay_modo === 'points')
? (float) ($pay_meta['points_price'] ?? 0)
: (float) ($pay_meta['price'] ?? 0));
$paid_settings = class_exists('AKSRT_Settings')
? AKSRT_Settings::get_paid_content_settings()
: [
@@ -50,6 +60,7 @@ class AKSRT_Content_Visibility {
$state = [
'post_id' => $resource_post instanceof WP_Post ? (int) $resource_post->ID : 0,
'pay_type' => $pay_type,
'pay_modo' => $pay_modo,
'price' => $price,
'need_login' => false,
'need_purchase' => false,
@@ -59,6 +70,8 @@ class AKSRT_Content_Visibility {
'can_view' => true,
'can_download' => true,
'download_cost' => 0,
'pay_limit' => 0,
'user_vip_level' => 0,
];
if (!($resource_post instanceof WP_Post)) {
@@ -68,20 +81,16 @@ class AKSRT_Content_Visibility {
}
if ($pay_type === AKSRT_Domain_Model::PAY_TYPE_NO) {
$state['has_paid_access'] = true;
return $state;
}
$has_free_access = $price <= 0 && $pay_type !== AKSRT_Domain_Model::PAY_TYPE_VIP;
// Prefer points_price when pay_modo=points.
if (is_array($pay_meta) && (($pay_meta['pay_modo'] ?? '0') === 'points')) {
$price = (float) ($pay_meta['points_price'] ?? $price);
$state['price'] = $price;
$has_free_access = $price <= 0 && $pay_type !== AKSRT_Domain_Model::PAY_TYPE_VIP;
}
$pay_limit = (int) ($pay_meta['pay_limit'] ?? 0);
if (!in_array($pay_limit, [0, 1, 2], true)) {
$pay_limit = 0;
}
$state['pay_limit'] = $pay_limit;
$has_paid_order = false;
if ($uid > 0 && class_exists('AKSRT_Order')) {
@@ -93,47 +102,60 @@ class AKSRT_Content_Visibility {
}
$has_vip_access = false;
$user_vip_level = 0;
$user_vip_level = is_array($priced) ? (int) ($priced['vip_level'] ?? 0) : 0;
if ($uid > 0) {
if (function_exists('aksrt_get_user_vip_level')) {
if ($user_vip_level <= 0 && function_exists('aksrt_get_user_vip_level')) {
$user_vip_level = aksrt_get_user_vip_level($uid);
}
if (function_exists('aksrt_is_vip_exempt') && aksrt_is_vip_exempt($uid)) {
$has_vip_access = true;
$user_vip_level = max($user_vip_level, 2);
} elseif (function_exists('aksrt_is_vip') && ($pay_type === AKSRT_Domain_Model::PAY_TYPE_VIP || $pay_limit > 0)) {
} elseif ($pay_type === AKSRT_Domain_Model::PAY_TYPE_VIP || $pay_limit > 0) {
$has_vip_access = $user_vip_level >= max(1, $pay_limit);
} elseif ($user_vip_level > 0) {
// VIP tier pricing may zero cost; still track membership.
$has_vip_access = $pay_limit <= 0 || $user_vip_level >= $pay_limit;
}
}
$state['user_vip_level'] = $user_vip_level;
// Member-only purchase restriction (Zibll pay_limit).
if ($pay_limit > 0 && $pay_type !== AKSRT_Domain_Model::PAY_TYPE_NO) {
$state['need_vip'] = true;
$state['pay_limit'] = $pay_limit;
$allowed_member = $has_vip_access && $user_vip_level >= $pay_limit;
$allowed_member = $uid > 0 && $user_vip_level >= $pay_limit;
if ($pay_type === AKSRT_Domain_Model::PAY_TYPE_DOWNLOAD) {
$download_cost = function_exists('aksrt_resource_download_cost')
? (int) aksrt_resource_download_cost($resource_post)
: (int) ceil($price);
// If member is free via VIP price, cost is 0.
if ($allowed_member && $price <= 0) {
$download_cost = 0;
}
$state['download_cost'] = max(0, $download_cost);
$state['need_login'] = $uid <= 0;
$state['need_purchase'] = $allowed_member && $state['download_cost'] > 0 && !$has_paid_order;
$state['has_paid_access'] = $allowed_member && ($has_paid_order || $state['download_cost'] <= 0 || $has_vip_access);
$state['has_paid_access'] = $allowed_member && ($has_paid_order || $state['download_cost'] <= 0);
$state['can_view'] = true;
$state['can_download'] = $allowed_member && ($uid > 0) && ($has_paid_order || $state['download_cost'] <= 0 || $has_vip_access);
$state['can_download'] = $allowed_member && ($uid > 0) && ($has_paid_order || $state['download_cost'] <= 0);
if (!$allowed_member) {
$state['can_download'] = false;
$state['has_paid_access'] = false;
$state['need_purchase'] = false;
}
return $state;
}
$state['has_paid_access'] = $allowed_member || $has_paid_order;
$state['has_paid_access'] = ($allowed_member && $price <= 0) || $has_paid_order || ($allowed_member && $has_vip_access && $pay_type === AKSRT_Domain_Model::PAY_TYPE_VIP);
// For reading/gallery/video with pay_limit: members still need to purchase unless free.
if ($allowed_member) {
$state['has_paid_access'] = $has_paid_order || $price <= 0;
$state['need_purchase'] = !$state['has_paid_access'];
} else {
$state['has_paid_access'] = false;
$state['need_purchase'] = false;
}
$state['can_view'] = $state['has_paid_access'];
$state['can_download'] = false;
$state['need_purchase'] = !$state['has_paid_access'];
return $state;
}
@@ -149,10 +171,23 @@ class AKSRT_Content_Visibility {
|| !empty($pay_meta['require_login'])
|| ($free_logged_show && $state['download_cost'] <= 0);
$state['require_captcha'] = !empty($paid_settings['download_captcha']) || !empty($pay_meta['require_captcha']);
$state['need_purchase'] = !$has_vip_access && $state['download_cost'] > 0;
$state['has_paid_access'] = $has_vip_access || $has_paid_order || !$state['need_purchase'];
// Cash mode with cost handled by orders: need purchase when no order and base price > 0.
$needs_pay = $state['download_cost'] > 0 || ($pay_modo === '0' && $price > 0 && !$has_paid_order && empty($paid_settings['download_credit']));
if ($pay_modo === '0' && $price > 0 && empty($paid_settings['download_credit'])) {
$state['need_purchase'] = !$has_paid_order && !($has_vip_access && $price <= 0);
$state['has_paid_access'] = $has_paid_order || $price <= 0;
// Download still gated by login/credit path for token; cash unlock is order-based.
$state['can_view'] = true;
$state['can_download'] = ($has_paid_order || $price <= 0) && (!$state['need_login'] || $uid > 0);
return $state;
}
$state['need_purchase'] = !$has_paid_order && $state['download_cost'] > 0 && !$has_free_access;
// VIP with free tier amount already reflected in download_cost.
$state['has_paid_access'] = $has_paid_order || $state['download_cost'] <= 0 || $has_free_access;
$state['can_view'] = true;
$state['can_download'] = !$state['need_login'] || $uid > 0;
$state['can_download'] = (!$state['need_login'] || $uid > 0) && ($has_paid_order || $state['download_cost'] <= 0 || true);
// can_download true only means "may request token"; rest_request still deducts credits.
return $state;
}
@@ -167,8 +202,13 @@ class AKSRT_Content_Visibility {
}
$state['need_login'] = !empty($pay_meta['require_login']);
$state['need_purchase'] = !$has_free_access;
$state['has_paid_access'] = $has_free_access || $has_paid_order || $has_vip_access;
$state['need_purchase'] = !$has_free_access && !$has_paid_order;
$state['has_paid_access'] = $has_free_access || $has_paid_order;
// VIP free tier for reading etc. via amount.
if (!$state['has_paid_access'] && $price <= 0 && $pay_type !== AKSRT_Domain_Model::PAY_TYPE_VIP) {
$state['has_paid_access'] = true;
$state['need_purchase'] = false;
}
$state['can_view'] = $state['has_paid_access'] && (!$state['need_login'] || $uid > 0);
$state['can_download'] = false;
@@ -217,6 +257,26 @@ class AKSRT_Content_Visibility {
]);
}
// Member-only (pay_limit).
if (!empty($state['need_vip']) && empty($state['has_paid_access']) && empty($state['can_download'])) {
$need_level = (int) ($state['pay_limit'] ?? 1);
return new WP_Error('aksrt_need_vip', sprintf(
/* translators: %d: required VIP level */
__('该资源仅限 VIP%s 及以上会员购买/下载。', 'aksrt'),
max(1, $need_level)
), [
'status' => 403,
'pay_limit' => $need_level,
]);
}
// Cash purchase required (order path).
if (!empty($state['need_purchase']) && empty($state['has_paid_access']) && $cost <= 0 && (($state['pay_modo'] ?? '0') === '0')) {
return new WP_Error('aksrt_need_purchase', __('请先购买后再下载。', 'aksrt'), [
'status' => 402,
]);
}
// Zibll daily free-download quota.
if ($cost <= 0 && function_exists('aksrt_check_free_download_quota')) {
$quota = aksrt_check_free_download_quota($uid, $cost);
@@ -225,7 +285,12 @@ class AKSRT_Content_Visibility {
}
}
if (!empty($paid_settings['download_credit']) && $cost > 0) {
$pay_modo = (string) ($state['pay_modo'] ?? '0');
$need_credit_check = $cost > 0 && (
$pay_modo === 'points'
|| !empty($paid_settings['download_credit'])
);
if ($need_credit_check) {
$balance = class_exists('AKSRT_Credits') ? AKSRT_Credits::balance($uid) : 0;
if ($balance < $cost) {
return new WP_Error('aksrt_credits_insufficient', __('积分不足,无法下载。', 'aksrt'), [
+24 -6
View File
@@ -114,6 +114,11 @@ class AKSRT_Download {
$paid_settings = AKSRT_Settings::get_paid_content_settings();
$cost = aksrt_resource_download_cost($post);
$uid = get_current_user_id();
$priced = function_exists('aksrt_get_user_pay_price') ? aksrt_get_user_pay_price($post, $uid) : null;
$pay_modo = is_array($priced)
? ((($priced['modo'] ?? '0') === 'points') ? 'points' : '0')
: ((($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0');
$display_price = is_array($priced) ? (float) ($priced['amount'] ?? 0) : (float) ($meta['price'] ?? 0);
$need_captcha = !empty($paid_settings['download_captcha']) || !empty($meta['require_captcha']);
if ($need_captcha && function_exists('aksrt_is_captcha_enabled_for') && !aksrt_is_captcha_enabled_for('download')) {
@@ -122,7 +127,10 @@ class AKSRT_Download {
return new WP_REST_Response([
'post_id' => $post_id,
'price' => (float) $meta['price'],
'price' => $display_price,
'base_price' => is_array($priced) ? (float) ($priced['base'] ?? $display_price) : (float) ($meta['price'] ?? 0),
'pay_modo' => $pay_modo,
'pay_limit' => (int) ($meta['pay_limit'] ?? 0),
'cost' => $cost,
'require_login' => !empty($paid_settings['download_login']) || !empty($meta['require_login']) || (!empty($paid_settings['free_logged_show']) && $cost <= 0),
'require_captcha' => $need_captcha,
@@ -139,7 +147,7 @@ class AKSRT_Download {
'type' => $row['type'] ?? 'direct',
'has_extract' => $extract_code !== '',
];
}, $meta['downloads'], array_keys($meta['downloads'])),
}, $meta['downloads'] ?? [], array_keys($meta['downloads'] ?? [])),
], 200);
}
@@ -354,14 +362,25 @@ class AKSRT_Download {
header('Content-Length: ' . (string) $size);
$chunk = 1024 * 64; // 64KB
$sleep_us = 0;
if ($speed_kb > 0) {
$chunk = max(1024, min($chunk, $speed_kb * 1024));
// Emit ~speed_kb KB per second using fixed 64KB chunks when possible.
$bytes_per_sec = max(1024, $speed_kb * 1024);
$chunk = min(1024 * 64, $bytes_per_sec);
$chunk = max(1024, $chunk);
// Sleep so chunk_bytes / second ≈ bytes_per_sec.
$sleep_us = (int) max(0, (int) round(($chunk / $bytes_per_sec) * 1000000) - 1000);
}
$fh = fopen($path, 'rb');
if (!$fh) {
$this->fail_410();
}
// Disable output compression for accurate Content-Length / throttle.
if (function_exists('apache_setenv')) {
@apache_setenv('no-gzip', '1');
}
@ini_set('zlib.output_compression', 'Off');
while (!feof($fh)) {
$buf = fread($fh, $chunk);
if ($buf === false) {
@@ -371,9 +390,8 @@ class AKSRT_Download {
if (function_exists('flush')) {
flush();
}
if ($speed_kb > 0) {
// Approximate throttle: sleep 1s per speed_kb window when chunk ~= speed_kb KB.
usleep(200000); // 0.2s per chunk for smoother throttle
if ($sleep_us > 0) {
usleep($sleep_us);
}
}
fclose($fh);
+160 -22
View File
@@ -149,14 +149,26 @@ if (!function_exists('aksrt_get_download_box_meta')) {
$pay_meta = aksrt_get_pay_meta($p);
$download_count = (int) get_post_meta($p->ID, AKSRT_Domain_Model::RESOURCE_DOWNLOAD_COUNT_KEY, true);
$view_count = (int) get_post_meta($p->ID, AKSRT_Domain_Model::POST_VIEW_COUNT_KEY, true);
$virtual_sales = max(0, (int) ($pay_meta['virtual_sales'] ?? 0));
$show_sales = !isset($pay_meta['show_sales']) || !empty($pay_meta['show_sales']);
$pay_modo = (($pay_meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
$pay_limit = (int) ($pay_meta['pay_limit'] ?? 0);
if (!in_array($pay_limit, [0, 1, 2], true)) {
$pay_limit = 0;
}
return [
'version' => (string) ($pay_meta['version'] ?? ''),
'size' => (string) ($pay_meta['size'] ?? ''),
'price' => (float) ($pay_meta['price'] ?? 0),
'points_price' => (int) ($pay_meta['points_price'] ?? 0),
'pay_modo' => $pay_modo,
'pay_limit' => $pay_limit,
'original_price' => (float) ($pay_meta['original_price'] ?? 0),
'vip1_price' => (float) ($pay_meta['vip1_price'] ?? 0),
'vip2_price' => (float) ($pay_meta['vip2_price'] ?? 0),
'vip1_points' => (int) ($pay_meta['vip1_points'] ?? 0),
'vip2_points' => (int) ($pay_meta['vip2_points'] ?? 0),
'pay_type' => (string) ($pay_meta['pay_type'] ?? AKSRT_PAY_TYPE_NO),
'license' => (string) ($pay_meta['license'] ?? ''),
'compat' => (string) ($pay_meta['compat'] ?? ''),
@@ -164,6 +176,9 @@ if (!function_exists('aksrt_get_download_box_meta')) {
'downloads' => array_values(is_array($pay_meta['downloads'] ?? null) ? $pay_meta['downloads'] : []),
'download_count' => max(0, $download_count),
'view_count' => max(0, $view_count),
'virtual_sales' => $virtual_sales,
'sales_count' => $show_sales ? ($virtual_sales + max(0, $download_count)) : 0,
'show_sales' => $show_sales,
'require_login' => !empty($pay_meta['require_login']),
'require_captcha' => !empty($pay_meta['require_captcha']),
'subject_label' => __('内容', 'aksrt'),
@@ -171,6 +186,89 @@ if (!function_exists('aksrt_get_download_box_meta')) {
}
}
/**
* Resolve the amount a given user should pay for a post (Zibll VIP tier min).
*
* VIP tier prices only apply when configured as a positive discount (< base).
* Full free for VIP uses vip_free_download / exempt roles (handled separately).
*
* @param int|WP_Post|null $post
* @param int $user_id
* @return array{amount:float,base:float,vip_amount:float,modo:string,currency:string,is_free:bool,pay_limit:int,vip_level:int,original:float,vip1:float,vip2:float}
*/
if (!function_exists('aksrt_get_user_pay_price')) {
function aksrt_get_user_pay_price($post = null, int $user_id = 0): array {
$meta = function_exists('aksrt_get_pay_meta') ? aksrt_get_pay_meta($post) : AKSRT_Domain_Model::default_pay_meta();
$pay_modo = (($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
$pay_limit = (int) ($meta['pay_limit'] ?? 0);
if (!in_array($pay_limit, [0, 1, 2], true)) {
$pay_limit = 0;
}
$uid = $user_id > 0 ? $user_id : (function_exists('get_current_user_id') ? (int) get_current_user_id() : 0);
$vip_level = 0;
if ($uid > 0 && function_exists('aksrt_get_user_vip_level')) {
$vip_level = (int) aksrt_get_user_vip_level($uid);
}
if ($uid > 0 && function_exists('aksrt_is_vip_exempt') && aksrt_is_vip_exempt($uid)) {
$vip_level = max($vip_level, 2);
}
$currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt');
$cash_symbol = '¥';
if (class_exists('AKSRT_Settings')) {
$paid = AKSRT_Settings::get_paid_content_settings();
$cash_symbol = (string) ($paid['display']['currency_symbol'] ?? '¥');
}
if ($pay_modo === 'points') {
$base = (float) ($meta['points_price'] ?? 0);
$vip1 = (float) ($meta['vip1_points'] ?? 0);
$vip2 = (float) ($meta['vip2_points'] ?? 0);
$currency_label = $currency;
} else {
$base = (float) ($meta['price'] ?? 0);
$vip1 = (float) ($meta['vip1_price'] ?? 0);
$vip2 = (float) ($meta['vip2_price'] ?? 0);
$currency_label = $cash_symbol;
}
// Positive VIP tier prices only (0 defaults mean "not configured").
$vip_amount = -1.0;
if ($vip_level >= 2 && $vip2 > 0) {
$vip_amount = $vip2;
} elseif ($vip_level >= 1 && $vip1 > 0) {
$vip_amount = $vip1;
}
$amount = $base;
if ($vip_amount >= 0 && ($base <= 0 || $vip_amount < $base)) {
$amount = $vip_amount;
}
// Role/VIP free-download exemption (global setting).
if ($amount > 0 && $uid > 0 && function_exists('aksrt_is_download_credit_exempt_user') && aksrt_is_download_credit_exempt_user($uid)) {
$amount = 0.0;
}
$original = (float) ($meta['original_price'] ?? 0);
return [
'amount' => max(0.0, (float) $amount),
'base' => max(0.0, (float) $base),
'vip_amount' => $vip_amount >= 0 ? max(0.0, (float) $vip_amount) : -1.0,
'modo' => $pay_modo,
'currency' => $currency_label,
'is_free' => $amount <= 0,
'pay_limit' => $pay_limit,
'vip_level' => $vip_level,
'original' => $original,
'vip1' => max(0.0, (float) $vip1),
'vip2' => max(0.0, (float) $vip2),
];
}
}
// ============================================================
// 状态判断
// ============================================================
@@ -374,8 +472,15 @@ if (!function_exists('aksrt_is_download_alone_page_enabled')) {
if (!function_exists('aksrt_get_pay_price_label')) {
function aksrt_get_pay_price_label($post = null): array {
$meta = aksrt_get_pay_meta($post);
$pay_modo = (($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
$pay_limit = (int) ($meta['pay_limit'] ?? 0);
$priced = function_exists('aksrt_get_user_pay_price')
? aksrt_get_user_pay_price($post)
: null;
$pay_modo = is_array($priced)
? ((($priced['modo'] ?? '0') === 'points') ? 'points' : '0')
: ((($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0');
$pay_limit = is_array($priced)
? (int) ($priced['pay_limit'] ?? 0)
: (int) ($meta['pay_limit'] ?? 0);
$currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt');
$cash_symbol = '¥';
if (class_exists('AKSRT_Settings')) {
@@ -384,32 +489,48 @@ if (!function_exists('aksrt_get_pay_price_label')) {
}
if ($meta['pay_type'] === AKSRT_PAY_TYPE_VIP || $pay_limit > 0) {
return ['text' => __('会员专属', 'aksrt'), 'free' => false, 'amount' => 0, 'modo' => $pay_modo, 'pay_limit' => $pay_limit];
return [
'text' => __('会员专属', 'aksrt'),
'free' => false,
'amount' => 0,
'base' => is_array($priced) ? (float) ($priced['base'] ?? 0) : 0,
'modo' => $pay_modo,
'pay_limit' => $pay_limit,
];
}
if ($pay_modo === 'points') {
$price = (int) ($meta['points_price'] ?? 0);
if ($price <= 0) {
return ['text' => __('免费', 'aksrt'), 'free' => true, 'amount' => 0, 'modo' => 'points', 'pay_limit' => 0];
}
$price = is_array($priced)
? (float) ($priced['amount'] ?? 0)
: ($pay_modo === 'points' ? (float) ($meta['points_price'] ?? 0) : (float) ($meta['price'] ?? 0));
$base = is_array($priced) ? (float) ($priced['base'] ?? $price) : $price;
if ($price <= 0) {
return [
'text' => sprintf(__('%s %s', 'aksrt'), aksrt_format_price((float) $price), $currency),
'free' => false,
'amount' => (float) $price,
'modo' => 'points',
'text' => __('免费', 'aksrt'),
'free' => true,
'amount' => 0,
'base' => $base,
'modo' => $pay_modo,
'pay_limit' => 0,
];
}
$price = (float) $meta['price'];
if ($price <= 0) {
return ['text' => __('免费', 'aksrt'), 'free' => true, 'amount' => 0, 'modo' => '0', 'pay_limit' => 0];
if ($pay_modo === 'points') {
return [
'text' => sprintf(__('%s %s', 'aksrt'), aksrt_format_price($price), $currency),
'free' => false,
'amount' => $price,
'base' => $base,
'modo' => 'points',
'pay_limit' => 0,
];
}
return [
'text' => $cash_symbol . aksrt_format_price($price),
'free' => false,
'amount' => $price,
'base' => $base,
'modo' => '0',
'pay_limit' => 0,
];
@@ -533,8 +654,18 @@ if (!function_exists('aksrt_get_paywall_html')) {
function aksrt_get_paywall_html(WP_Post $post): string {
$meta = aksrt_get_pay_meta($post);
$pay_type = $meta['pay_type'];
$price = (float) $meta['price'];
$priced = function_exists('aksrt_get_user_pay_price') ? aksrt_get_user_pay_price($post) : null;
$pay_modo = is_array($priced) ? ((($priced['modo'] ?? '0') === 'points') ? 'points' : '0') : ((($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0');
$price = is_array($priced) ? (float) ($priced['amount'] ?? 0) : (float) ($meta['price'] ?? 0);
$currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt');
$cash_symbol = '¥';
if (class_exists('AKSRT_Settings')) {
$paid = AKSRT_Settings::get_paid_content_settings();
$cash_symbol = (string) ($paid['display']['currency_symbol'] ?? '¥');
}
$price_text = $pay_modo === 'points'
? (aksrt_format_price($price) . ' ' . $currency)
: ($cash_symbol . aksrt_format_price($price));
$type_labels = [
AKSRT_PAY_TYPE_READING => ['icon' => 'fa-lock', 'label' => __('付费阅读', 'aksrt'), 'desc' => __('付费后即可查看完整内容', 'aksrt')],
@@ -547,10 +678,11 @@ if (!function_exists('aksrt_get_paywall_html')) {
$is_logged_in = is_user_logged_in();
$original_price = (float) ($meta['original_price'] ?? 0);
$has_original = $original_price > 0 && $original_price > $price;
$pay_limit = (int) ($meta['pay_limit'] ?? 0);
ob_start();
?>
<div class="aksrt-paywall" data-post-id="<?php echo esc_attr((string) $post->ID); ?>" data-pay-type="<?php echo esc_attr($pay_type); ?>">
<div class="aksrt-paywall" data-post-id="<?php echo esc_attr((string) $post->ID); ?>" data-pay-type="<?php echo esc_attr($pay_type); ?>" data-pay-modo="<?php echo esc_attr($pay_modo); ?>">
<div class="aksrt-paywall__overlay">
<div class="aksrt-paywall__blur"></div>
<div class="aksrt-paywall__card">
@@ -560,10 +692,12 @@ if (!function_exists('aksrt_get_paywall_html')) {
<h3 class="aksrt-paywall__title"><?php echo esc_html($type_info['label']); ?></h3>
<p class="aksrt-paywall__desc"><?php echo esc_html($type_info['desc']); ?></p>
<div class="aksrt-paywall__price">
<?php if ($price > 0) : ?>
<span class="aksrt-paywall__price-amount"><?php echo esc_html(aksrt_format_price($price) . ' ' . $currency); ?></span>
<?php if ($pay_limit > 0) : ?>
<span class="aksrt-paywall__price-member"><?php esc_html_e('会员专属', 'aksrt'); ?></span>
<?php elseif ($price > 0) : ?>
<span class="aksrt-paywall__price-amount"><?php echo esc_html($price_text); ?></span>
<?php if ($has_original) : ?>
<span class="aksrt-paywall__price-original"><?php echo esc_html(aksrt_format_price($original_price) . ' ' . $currency); ?></span>
<span class="aksrt-paywall__price-original"><?php echo esc_html(($pay_modo === 'points' ? aksrt_format_price($original_price) . ' ' . $currency : $cash_symbol . aksrt_format_price($original_price))); ?></span>
<?php endif; ?>
<?php else : ?>
<span class="aksrt-paywall__price-free"><?php esc_html_e('免费', 'aksrt'); ?></span>
@@ -573,9 +707,13 @@ if (!function_exists('aksrt_get_paywall_html')) {
<a href="<?php echo esc_url($login_url); ?>" class="but jb-red padding-lg cashier-link aksrt-paywall__btn">
<i class="fa fa-sign-in" aria-hidden="true"></i> <?php esc_html_e('登录后购买', 'aksrt'); ?>
</a>
<?php elseif ($pay_limit > 0) : ?>
<span class="but jb-vip padding-lg aksrt-paywall__btn is-disabled">
<i class="fas fa-crown" aria-hidden="true"></i> <?php esc_html_e('开通会员后可查看', 'aksrt'); ?>
</span>
<?php elseif ($price > 0) : ?>
<button type="button" class="but jb-red padding-lg cashier-link aksrt-paywall__btn" data-aksrt-pay-content="<?php echo esc_attr((string) $post->ID); ?>">
<i class="fa fa-shopping-cart" aria-hidden="true"></i> <?php printf(esc_html__('立即购买(%s)', 'aksrt'), aksrt_format_price($price) . ' ' . $currency); ?>
<button type="button" class="but <?php echo $pay_modo === 'points' ? 'jb-yellow' : 'jb-red'; ?> padding-lg cashier-link aksrt-paywall__btn" data-aksrt-pay-content="<?php echo esc_attr((string) $post->ID); ?>">
<i class="fa fa-shopping-cart" aria-hidden="true"></i> <?php printf(esc_html__('立即购买(%s)', 'aksrt'), $price_text); ?>
</button>
<?php endif; ?>
<p class="aksrt-paywall__hint">
+60 -16
View File
@@ -61,13 +61,21 @@ if (!function_exists('aksrt_get_resource_meta')) {
return $row;
}, $downloads)));
$virtual_sales = max(0, (int) ($pay_meta['virtual_sales'] ?? 0));
$show_sales = !isset($pay_meta['show_sales']) || !empty($pay_meta['show_sales']);
return [
'version' => (string) ($pay_meta['version'] ?? ''),
'size' => (string) ($pay_meta['size'] ?? ''),
'price' => (float) ($pay_meta['price'] ?? 0),
'points_price' => (int) ($pay_meta['points_price'] ?? 0),
'pay_modo' => (($pay_meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0',
'pay_limit' => in_array((int) ($pay_meta['pay_limit'] ?? 0), [0, 1, 2], true) ? (int) $pay_meta['pay_limit'] : 0,
'original_price' => (float) ($pay_meta['original_price'] ?? 0),
'vip1_price' => (float) ($pay_meta['vip1_price'] ?? 0),
'vip2_price' => (float) ($pay_meta['vip2_price'] ?? 0),
'vip1_points' => (int) ($pay_meta['vip1_points'] ?? 0),
'vip2_points' => (int) ($pay_meta['vip2_points'] ?? 0),
'pay_type' => (string) ($pay_meta['pay_type'] ?? AKSRT_Domain_Model::PAY_TYPE_DOWNLOAD),
'license' => (string) ($pay_meta['license'] ?? ''),
'compat' => (string) ($pay_meta['compat'] ?? ''),
@@ -75,6 +83,9 @@ if (!function_exists('aksrt_get_resource_meta')) {
'downloads' => $downloads,
'download_count' => max(0, max($download_count, $legacy_download_count)),
'view_count' => max(0, max($resource_view_count, $common_view_count)),
'virtual_sales' => $virtual_sales,
'sales_count' => $show_sales ? ($virtual_sales + max(0, max($download_count, $legacy_download_count))) : 0,
'show_sales' => $show_sales,
'require_login' => !empty($pay_meta['require_login']),
'require_captcha' => !empty($pay_meta['require_captcha']),
];
@@ -89,9 +100,14 @@ if (!function_exists('aksrt_default_resource_meta')) {
'version' => (string) ($meta['version'] ?? ''),
'size' => (string) ($meta['size'] ?? ''),
'price' => (float) ($meta['price'] ?? 0),
'points_price' => (int) ($meta['points_price'] ?? 0),
'pay_modo' => (($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0',
'pay_limit' => in_array((int) ($meta['pay_limit'] ?? 0), [0, 1, 2], true) ? (int) $meta['pay_limit'] : 0,
'original_price' => (float) ($meta['original_price'] ?? 0),
'vip1_price' => (float) ($meta['vip1_price'] ?? 0),
'vip2_price' => (float) ($meta['vip2_price'] ?? 0),
'vip1_points' => (int) ($meta['vip1_points'] ?? 0),
'vip2_points' => (int) ($meta['vip2_points'] ?? 0),
'pay_type' => AKSRT_Domain_Model::PAY_TYPE_DOWNLOAD,
'license' => (string) ($meta['license'] ?? ''),
'compat' => (string) ($meta['compat'] ?? ''),
@@ -99,6 +115,9 @@ if (!function_exists('aksrt_default_resource_meta')) {
'downloads' => [],
'download_count' => 0,
'view_count' => 0,
'virtual_sales' => 0,
'sales_count' => 0,
'show_sales' => true,
'require_login' => !empty($meta['require_login']),
'require_captcha' => !empty($meta['require_captcha']),
];
@@ -171,9 +190,6 @@ if (!function_exists('aksrt_resource_card_badge_text')) {
$pay_modo = (($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
$pay_limit = (int) ($meta['pay_limit'] ?? 0);
$price = $pay_modo === 'points'
? (float) ($meta['points_price'] ?? 0)
: (float) ($meta['price'] ?? 0);
$type_labels = function_exists('aksrt_get_pay_types') ? aksrt_get_pay_types() : [];
$type_name = $type_labels[$pay_type] ?? __('付费内容', 'aksrt');
@@ -182,6 +198,15 @@ if (!function_exists('aksrt_resource_card_badge_text')) {
return __('会员专属', 'aksrt');
}
$priced = function_exists('aksrt_get_user_pay_price')
? aksrt_get_user_pay_price($p)
: [
'amount' => $pay_modo === 'points' ? (float) ($meta['points_price'] ?? 0) : (float) ($meta['price'] ?? 0),
'modo' => $pay_modo,
];
$price = (float) ($priced['amount'] ?? 0);
$pay_modo = (($priced['modo'] ?? $pay_modo) === 'points') ? 'points' : '0';
// Free paid-type (price 0).
if ($price <= 0) {
if ($pay_type === 'download') {
@@ -430,14 +455,20 @@ if (!function_exists('aksrt_resource_download_cost')) {
* 优先级:单条 _aksrt_res_price > 全局 download_default_cost。
*/
function aksrt_resource_download_cost($post = null): int {
$meta = aksrt_get_resource_meta($post);
// Prefer unified pay meta when available (pay_modo / points_price).
if (function_exists('aksrt_get_pay_meta')) {
$pay = aksrt_get_pay_meta($post);
if (is_array($pay) && (($pay['pay_type'] ?? '') === 'download' || !empty($pay['downloads']))) {
$meta = array_merge($meta, $pay);
$p = get_post($post);
$uid = function_exists('get_current_user_id') ? (int) get_current_user_id() : 0;
// Paid order → no further credit deduct. Avoid has_paid_access() here (recursion via access state).
if ($p instanceof WP_Post && $uid > 0 && class_exists('AKSRT_Order')) {
if (AKSRT_Order::get_instance()->has_paid_access(
$uid,
AKSRT_Domain_Model::ORDER_PRODUCT_RESOURCE,
(int) $p->ID
)) {
return 0;
}
}
$paid_settings = class_exists('AKSRT_Settings')
? AKSRT_Settings::get_paid_content_settings()
: [
@@ -445,25 +476,38 @@ if (!function_exists('aksrt_resource_download_cost')) {
'default_cost' => 0,
];
$pay_modo = (($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
// Cash mode: do not deduct credits for download unlock (order/cash checkout path).
// Points mode or legacy credit gate: use points_price / price.
$priced = function_exists('aksrt_get_user_pay_price')
? aksrt_get_user_pay_price($post, $uid)
: null;
$pay_modo = is_array($priced) && (($priced['modo'] ?? '0') === 'points') ? 'points' : '0';
if (!is_array($priced) && function_exists('aksrt_get_pay_meta')) {
$pay = aksrt_get_pay_meta($post);
$pay_modo = (($pay['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
}
// Cash mode: order/checkout path unless legacy download_credit is on.
if ($pay_modo !== 'points' && empty($paid_settings['download_credit'])) {
return 0;
}
if ($pay_modo === '0' && empty($paid_settings['download_credit'])) {
// Cash purchase path — cost handled by orders, not credit deduct.
if ($uid > 0 && function_exists('aksrt_is_download_credit_exempt_user') && aksrt_is_download_credit_exempt_user($uid)) {
return 0;
}
if (function_exists('get_current_user_id') && aksrt_is_download_credit_exempt_user((int) get_current_user_id())) {
if (is_array($priced)) {
$price = (float) ($priced['amount'] ?? 0);
if ($price > 0) {
return (int) ceil($price);
}
return 0;
}
// Fallback without helper.
$meta = function_exists('aksrt_get_pay_meta') ? aksrt_get_pay_meta($post) : aksrt_get_resource_meta($post);
if ($pay_modo === 'points') {
$price = (float) ($meta['points_price'] ?? $meta['price'] ?? 0);
} else {
// When download_credit is on, treat price as credit cost (legacy AKSRT).
$price = (float) ($meta['price'] ?? 0);
}
if ($price > 0) {
+128 -61
View File
@@ -47,6 +47,15 @@ $paid_settings = class_exists('AKSRT_Settings')
$cost = function_exists('aksrt_get_download_cost') ? aksrt_get_download_cost($post_id) : (int) ceil((float) ($meta['price'] ?? 0));
$credit_active = !empty($paid_settings['download_credit']) && $cost > 0;
$pay_modo = (($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
if (function_exists('aksrt_get_user_pay_price')) {
$priced = aksrt_get_user_pay_price($post_id);
$pay_modo = (($priced['modo'] ?? $pay_modo) === 'points') ? 'points' : '0';
}
// Points mode always uses credit deduct path when cost > 0.
if ($pay_modo === 'points' && $cost > 0) {
$credit_active = true;
}
$captcha_active = !empty($paid_settings['download_captcha']) || !empty($meta['require_captcha']);
if ($captcha_active && function_exists('aksrt_is_captcha_enabled_for') && !aksrt_is_captcha_enabled_for('download')) {
$captcha_active = false;
@@ -55,58 +64,83 @@ $balance = (int) ($gate_data['balance'] ?? 0);
$login_url = (string) ($gate_data['login_url'] ?? wp_login_url(get_permalink($post_id)));
$is_need_login = $gate_blocked && $gate_code === 'aksrt_need_login';
$is_low_credit = $gate_blocked && $gate_code === 'aksrt_credits_insufficient';
$is_low_credit = $gate_blocked && $gate_code === 'aksrt_credits_insufficient';
$is_need_vip = $gate_blocked && $gate_code === 'aksrt_need_vip';
$is_need_purchase = $gate_blocked && $gate_code === 'aksrt_need_purchase';
// Zibll pay_free_logged_show: free downloads still require login.
$free_logged_show = !empty($paid_settings['free_logged_show']);
$price_amount = (float) ($meta['price'] ?? 0);
if ($price_amount <= 0 && $free_logged_show && !is_user_logged_in()) {
$is_need_login = true;
$gate_blocked = true;
}
// Zibll pay_free_logged_show: free downloads still require login.
$free_logged_show = !empty($paid_settings['free_logged_show']);
$price_amount = (float) ($price_label['amount'] ?? $meta['price'] ?? 0);
if ($price_amount <= 0 && $free_logged_show && !is_user_logged_in()) {
$is_need_login = true;
$gate_blocked = true;
}
// Zibll down_alone_page: single entry to independent download page.
$alone_page = !empty($paid_settings['down_alone_page']) || !empty($paid_settings['download']['alone_page']);
$alone_url = '';
if ($alone_page && function_exists('aksrt_get_single_download_page_url')) {
$alone_url = aksrt_get_single_download_page_url($post_id);
}
$use_alone_entry = $alone_page && $alone_url !== '' && !$is_need_login && !$is_low_credit;
if (!empty($GLOBALS['aksrt_on_download_file_page'])) {
$use_alone_entry = false;
}
// Zibll down_alone_page: single entry to independent download page.
$alone_page = !empty($paid_settings['down_alone_page']) || !empty($paid_settings['download']['alone_page']);
$alone_url = '';
if ($alone_page && function_exists('aksrt_get_single_download_page_url')) {
$alone_url = aksrt_get_single_download_page_url($post_id);
}
$use_alone_entry = $alone_page && $alone_url !== '' && !$is_need_login && !$is_low_credit && !$is_need_vip && !$is_need_purchase;
if (!empty($GLOBALS['aksrt_on_download_file_page'])) {
$use_alone_entry = false;
}
// 缩略图
$thumbnail = get_the_post_thumbnail_url($post_id, 'medium') ?: '';
$has_thumbnail = $thumbnail !== '';
// 原价 & VIP 价
// 原价 & VIP 价(按 pay_modo 切换现金/积分档)
$original_price = (float) ($meta['original_price'] ?? 0);
$vip1_price = (float) ($meta['vip1_price'] ?? 0);
$vip2_price = (float) ($meta['vip2_price'] ?? 0);
$has_original = $original_price > 0 && $original_price > (float) ($meta['price'] ?? 0);
$has_vip = $vip1_price > 0 || $vip2_price > 0;
if ($pay_modo === 'points') {
$vip1_price = (float) ($meta['vip1_points'] ?? 0);
$vip2_price = (float) ($meta['vip2_points'] ?? 0);
$base_price = (float) ($meta['points_price'] ?? $meta['price'] ?? 0);
} else {
$vip1_price = (float) ($meta['vip1_price'] ?? 0);
$vip2_price = (float) ($meta['vip2_price'] ?? 0);
$base_price = (float) ($meta['price'] ?? 0);
}
$has_original = $original_price > 0 && $original_price > $base_price;
$has_vip = ($vip1_price > 0 && $vip1_price < $base_price) || ($vip2_price > 0 && $vip2_price < $base_price);
$pay_limit = (int) ($meta['pay_limit'] ?? 0);
// 销量
$download_count = (int) ($meta['download_count'] ?? 0);
$sales_count = (int) ($meta['sales_count'] ?? 0);
$display_count = max($download_count, $sales_count);
$show_sales = !isset($meta['show_sales']) || !empty($meta['show_sales']);
// 付费类型徽章
$pay_type_badge = function_exists('aksrt_get_pay_type_badge') ? aksrt_get_pay_type_badge($pay_type) : '';
// 货币名称
$currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt');
$cash_symbol = '¥';
if (class_exists('AKSRT_Settings')) {
$paid_display = AKSRT_Settings::get_paid_content_settings();
$cash_symbol = (string) ($paid_display['display']['currency_symbol'] ?? '¥');
}
$format_vip = static function (float $amount) use ($pay_modo, $currency, $cash_symbol): string {
if ($amount <= 0) {
return (string) __('免费', 'aksrt');
}
$n = function_exists('aksrt_format_price') ? aksrt_format_price($amount) : (string) $amount;
return $pay_modo === 'points' ? ($n . ' ' . $currency) : ($cash_symbol . $n);
};
?>
<section class="widget resource-download-box resource-download-box--v2<?php echo $gate_blocked ? ' is-blocked' : ''; ?> resource-download-box--<?php echo esc_attr($context_variant); ?>"
data-post-id="<?php echo esc_attr((string) $post_id); ?>"
data-price="<?php echo esc_attr((string) ($meta['price'] ?? 0)); ?>"
data-price="<?php echo esc_attr((string) $base_price); ?>"
data-pay-modo="<?php echo esc_attr($pay_modo); ?>"
data-pay-limit="<?php echo esc_attr((string) $pay_limit); ?>"
data-credit="<?php echo $credit_active ? '1' : '0'; ?>"
data-captcha="<?php echo $captcha_active ? '1' : '0'; ?>"
aria-label="<?php esc_attr_e('下载区', 'aksrt'); ?>">
<?php if ($display_count > 0) : ?>
<?php if ($show_sales && $display_count > 0) : ?>
<span class="resource-download-box__sales-badge">
<i class="fas fa-fire" aria-hidden="true"></i>
<?php
@@ -144,31 +178,37 @@ $currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name()
<span class="resource-download-box__price<?php echo !empty($price_label['free']) ? ' is-free' : ''; ?>">
<?php echo esc_html((string) ($price_label['text'] ?? '')); ?>
</span>
<?php if ($has_original) : ?>
<?php if ($has_original && $pay_limit <= 0) : ?>
<span class="resource-download-box__original-price">
<?php echo esc_html(aksrt_format_price($original_price) . ' ' . $currency); ?>
<?php
echo esc_html(
$pay_modo === 'points'
? (aksrt_format_price($original_price) . ' ' . $currency)
: ($cash_symbol . aksrt_format_price($original_price))
);
?>
</span>
<?php endif; ?>
<?php echo $pay_type_badge && !$has_thumbnail ? $pay_type_badge : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<?php if ($has_vip) : ?>
<?php if ($has_vip && $pay_limit <= 0) : ?>
<div class="resource-download-box__vip-pricing">
<?php if ($vip1_price > 0) : ?>
<?php if ($vip1_price > 0 && $vip1_price < $base_price) : ?>
<span class="resource-download-box__vip-badge resource-download-box__vip-badge--1">
<i class="fas fa-crown" aria-hidden="true"></i>
<?php
/* translators: %s: VIP1 价格 */
printf(esc_html__('VIP1 %s', 'aksrt'), aksrt_format_price($vip1_price));
printf(esc_html__('VIP1 %s', 'aksrt'), $format_vip($vip1_price));
?>
</span>
<?php endif; ?>
<?php if ($vip2_price > 0) : ?>
<?php if ($vip2_price > 0 && $vip2_price < $base_price) : ?>
<span class="resource-download-box__vip-badge resource-download-box__vip-badge--2">
<i class="fas fa-gem" aria-hidden="true"></i>
<?php
/* translators: %s: VIP2 价格 */
printf(esc_html__('VIP2 %s', 'aksrt'), aksrt_format_price($vip2_price));
printf(esc_html__('VIP2 %s', 'aksrt'), $format_vip($vip2_price));
?>
</span>
<?php endif; ?>
@@ -179,7 +219,19 @@ $currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name()
<p class="resource-download-box__catalog-note"><?php echo esc_html((string) $paid_settings['catalog_note']); ?></p>
<?php endif; ?>
<?php if (!empty($use_alone_entry)) : ?>
<?php if ($is_need_vip) : ?>
<div class="mt10 resource-download-box__vip-gate">
<span class="resource-download-box__btn btn-primary resource-download-box__btn--vip is-disabled">
<i class="fas fa-crown" aria-hidden="true"></i>
<span><?php echo esc_html($gate instanceof WP_Error ? $gate->get_error_message() : __('会员专属资源', 'aksrt')); ?></span>
</span>
<?php
if (function_exists('aksrt_get_demo_link_html')) {
echo aksrt_get_demo_link_html($post_id); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
?>
</div>
<?php elseif (!empty($use_alone_entry)) : ?>
<div class="mt10 resource-download-box__alone">
<a target="_blank" rel="nofollow" href="<?php echo esc_url($alone_url); ?>" class="resource-download-box__btn btn-primary resource-download-box__btn--alone">
<i class="fas fa-download" aria-hidden="true"></i>
@@ -220,6 +272,11 @@ $currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name()
$btn_text = __('登录后下载', 'aksrt');
$btn_icon = 'fa-sign-in-alt';
$btn_modifier = ' resource-download-box__btn--login';
} elseif ($is_need_purchase) {
$btn_tag = 'button';
$btn_text = __('购买后下载', 'aksrt');
$btn_icon = 'fa-shopping-cart';
$btn_modifier = ' resource-download-box__btn--purchase';
} elseif ($is_low_credit) {
$btn_tag = 'button';
$btn_text = sprintf(__('解锁下载(%d 积分)', 'aksrt'), $cost);
@@ -256,7 +313,7 @@ $currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name()
<button
type="button"
class="resource-download-box__btn btn-primary resource-download-box__btn--service-<?php echo esc_attr($service['key']); ?><?php echo esc_attr($btn_modifier); ?>"
data-action="<?php echo $is_low_credit ? 'aksrt-need-credits' : 'aksrt-download'; ?>"
data-action="<?php echo $is_low_credit ? 'aksrt-need-credits' : ($is_need_purchase ? 'aksrt-need-purchase' : 'aksrt-download'); ?>"
data-source-index="<?php echo esc_attr((string) $idx); ?>"
data-source-type="<?php echo esc_attr($type); ?>"
data-has-extract="<?php echo $has_extract ? '1' : '0'; ?>"
@@ -282,42 +339,52 @@ $currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name()
</ul>
<?php endif; ?>
<?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>';
}
<?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
if (function_exists('aksrt_get_pay_service_html')) {
echo aksrt_get_pay_service_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} else {
?>
<span class="resource-download-box__guarantee"><i class="fas fa-shield-alt" aria-hidden="true"></i> <?php esc_html_e('安全检测', 'aksrt'); ?></span>
<span class="resource-download-box__guarantee"><i class="fas fa-crown" aria-hidden="true"></i> <?php esc_html_e('支持 VIP 权益', 'aksrt'); ?></span>
<span class="resource-download-box__guarantee"><i class="fas fa-coins" aria-hidden="true"></i> <?php esc_html_e('支持积分结算', 'aksrt'); ?></span>
<?php
}
}
?>
<div class="resource-download-box__guarantees">
<?php
if (function_exists('aksrt_get_pay_service_html')) {
echo aksrt_get_pay_service_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} else {
?>
</div>
<span class="resource-download-box__guarantee"><i class="fas fa-shield-alt" aria-hidden="true"></i> <?php esc_html_e('安全检测', 'aksrt'); ?></span>
<span class="resource-download-box__guarantee"><i class="fas fa-crown" aria-hidden="true"></i> <?php esc_html_e('支持 VIP 权益', 'aksrt'); ?></span>
<span class="resource-download-box__guarantee"><i class="fas fa-coins" aria-hidden="true"></i> <?php esc_html_e('支持积分结算', 'aksrt'); ?></span>
<?php
}
?>
</div>
</div>
</div>
<?php if ($is_need_login) : ?>
<p class="resource-download-box__hint resource-download-box__hint--login">
<i class="fas fa-info-circle" aria-hidden="true"></i>
<?php echo (isset($price_amount) && $price_amount <= 0) ? esc_html__('免费资源,请登录后下载。', 'aksrt') : esc_html__('登录后可解锁并下载该内容。', 'aksrt'); ?>
<?php echo ($price_amount <= 0) ? esc_html__('免费资源,请登录后下载。', 'aksrt') : esc_html__('登录后可解锁并下载该内容。', 'aksrt'); ?>
</p>
<?php elseif ($is_need_vip) : ?>
<p class="resource-download-box__hint resource-download-box__hint--vip">
<i class="fas fa-info-circle" aria-hidden="true"></i>
<?php echo esc_html($gate instanceof WP_Error ? $gate->get_error_message() : __('该资源仅限会员购买/下载。', 'aksrt')); ?>
</p>
<?php elseif ($is_need_purchase) : ?>
<p class="resource-download-box__hint resource-download-box__hint--purchase">
<i class="fas fa-info-circle" aria-hidden="true"></i>
<?php esc_html_e('请先完成购买后再下载该资源。', 'aksrt'); ?>
</p>
<?php elseif ($is_low_credit) : ?>
<p class="resource-download-box__hint resource-download-box__hint--credit">