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:
@@ -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'), [
|
||||
|
||||
@@ -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
@@ -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">
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user