__('不付费', 'aksrt'), AKSRT_PAY_TYPE_READING => __('付费阅读', 'aksrt'), AKSRT_PAY_TYPE_DOWNLOAD => __('付费下载', 'aksrt'), AKSRT_PAY_TYPE_GALLERY => __('付费图库', 'aksrt'), AKSRT_PAY_TYPE_VIDEO => __('付费视频', 'aksrt'), AKSRT_PAY_TYPE_VIP => __('VIP 专属', 'aksrt'), ]; } // ============================================================ // 元数据读取 // ============================================================ if (!function_exists('aksrt_get_pay_meta')) { function aksrt_get_pay_meta($post = null): array { $p = get_post($post); if (!($p instanceof WP_Post)) return aksrt_default_pay_meta(); $meta = get_post_meta($p->ID, AKSRT_Domain_Model::PAY_META_KEY, true); if (is_array($meta) && isset($meta['pay_type'])) { return wp_parse_args(AKSRT_Domain_Model::sanitize_pay_meta($meta), aksrt_default_pay_meta()); } return aksrt_default_pay_meta(); } } if (!function_exists('aksrt_default_pay_meta')) { function aksrt_default_pay_meta(): array { return AKSRT_Domain_Model::default_pay_meta(); return [ 'pay_type' => AKSRT_PAY_TYPE_NO, 'price' => 0.0, 'original_price' => 0.0, 'vip1_price' => 0.0, 'vip2_price' => 0.0, 'version' => '', 'size' => '', 'license' => '', 'compat' => '', 'demo_url' => '', 'downloads' => [], 'require_login' => false, 'require_captcha' => false, 'attributes' => [], 'gallery' => [], 'video_url' => '', ]; } } if (!function_exists('aksrt_is_downloadable_content')) { function aksrt_is_downloadable_content($post = null): bool { $p = get_post($post); if (!($p instanceof WP_Post)) { return false; } $meta = aksrt_get_pay_meta($p); if (($meta['pay_type'] ?? AKSRT_PAY_TYPE_NO) !== AKSRT_PAY_TYPE_DOWNLOAD) { return false; } return !empty($meta['downloads']) && is_array($meta['downloads']); } } if (!function_exists('aksrt_get_download_box_meta')) { function aksrt_get_download_box_meta($post = null): array { $p = get_post($post); if (!($p instanceof WP_Post)) { return []; } if (function_exists('aksrt_get_resource_meta') && function_exists('aksrt_is_resource_post') && aksrt_is_resource_post($p)) { $meta = aksrt_get_resource_meta($p); $meta['subject_label'] = __('资源', 'aksrt'); return $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); return [ 'version' => (string) ($pay_meta['version'] ?? ''), 'size' => (string) ($pay_meta['size'] ?? ''), 'price' => (float) ($pay_meta['price'] ?? 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), 'pay_type' => (string) ($pay_meta['pay_type'] ?? AKSRT_PAY_TYPE_NO), 'license' => (string) ($pay_meta['license'] ?? ''), 'compat' => (string) ($pay_meta['compat'] ?? ''), 'demo_url' => (string) ($pay_meta['demo_url'] ?? ''), 'downloads' => array_values(is_array($pay_meta['downloads'] ?? null) ? $pay_meta['downloads'] : []), 'download_count' => max(0, $download_count), 'view_count' => max(0, $view_count), 'require_login' => !empty($pay_meta['require_login']), 'require_captcha' => !empty($pay_meta['require_captcha']), 'subject_label' => __('内容', 'aksrt'), ]; } } // ============================================================ // 状态判断 // ============================================================ if (!function_exists('aksrt_is_paid_post')) { function aksrt_is_paid_post($post = null): bool { return aksrt_get_pay_meta($post)['pay_type'] !== AKSRT_PAY_TYPE_NO; } } if (!function_exists('aksrt_is_paid_reading')) { function aksrt_is_paid_reading($post = null): bool { return aksrt_get_pay_meta($post)['pay_type'] === AKSRT_PAY_TYPE_READING; } } if (!function_exists('aksrt_is_paid_download')) { function aksrt_is_paid_download($post = null): bool { return aksrt_get_pay_meta($post)['pay_type'] === AKSRT_PAY_TYPE_DOWNLOAD; } } if (!function_exists('aksrt_is_paid_gallery')) { function aksrt_is_paid_gallery($post = null): bool { return aksrt_get_pay_meta($post)['pay_type'] === AKSRT_PAY_TYPE_GALLERY; } } if (!function_exists('aksrt_is_paid_video')) { function aksrt_is_paid_video($post = null): bool { return aksrt_get_pay_meta($post)['pay_type'] === AKSRT_PAY_TYPE_VIDEO; } } if (!function_exists('aksrt_is_vip_only')) { function aksrt_is_vip_only($post = null): bool { return aksrt_get_pay_meta($post)['pay_type'] === AKSRT_PAY_TYPE_VIP; } } // ============================================================ // 付费状态检查 // ============================================================ if (!function_exists('aksrt_has_paid_access')) { function aksrt_has_paid_access($post = null, int $user_id = 0): bool { $p = get_post($post); if (!($p instanceof WP_Post)) return true; // 单一真相:付费访问由 AKSRT_Content_Visibility(基于订单 + VIP)裁决。 if (class_exists('AKSRT_Content_Visibility')) { $state = AKSRT_Content_Visibility::get_post_access_state($p, $user_id); return !empty($state['has_paid_access']); } // 兜底:仅在 service 不可用时使用,避免离线环境直接拒绝。 $meta = aksrt_get_pay_meta($p); if ($meta['pay_type'] === AKSRT_PAY_TYPE_NO) return true; if ((float) $meta['price'] <= 0 && $meta['pay_type'] !== AKSRT_PAY_TYPE_VIP) return true; $uid = $user_id > 0 ? $user_id : get_current_user_id(); if ($uid > 0 && function_exists('aksrt_is_vip_exempt') && aksrt_is_vip_exempt($uid)) return true; if ($uid > 0 && get_user_meta($uid, '_aksrt_paid_' . $p->ID, true)) return true; return false; } } if (!function_exists('aksrt_can_access_content')) { function aksrt_can_access_content($post = null): bool { $p = get_post($post); if (!($p instanceof WP_Post)) return true; if (class_exists('AKSRT_Content_Visibility')) { return AKSRT_Content_Visibility::can_view_paid_content($p); } $pay_type = aksrt_get_pay_meta($p)['pay_type']; if ($pay_type === AKSRT_PAY_TYPE_NO) return true; // 只有 reading/gallery/video 需要隐藏内容 if (!in_array($pay_type, [AKSRT_PAY_TYPE_READING, AKSRT_PAY_TYPE_GALLERY, AKSRT_PAY_TYPE_VIDEO], true)) { return true; } return aksrt_has_paid_access($p); } } if (!function_exists('aksrt_can_download')) { /** * 下载授权门禁 —— 单一合同。 * * 实际判定全部交给 AKSRT_Content_Visibility::can_download_resource() * (由 inc/helpers/aksrt-resource.php 的同名 helper 在更早加载时定义)。 * 此处仅作为该 helper 不可用时的兜底,避免出现第二套下载真相。 * * @param int|WP_Post|null $post * @param int $user_id 0 表示当前用户 * @return true|WP_Error */ function aksrt_can_download($post = null, int $user_id = 0) { if (class_exists('AKSRT_Content_Visibility')) { return AKSRT_Content_Visibility::can_download_resource($post, $user_id); } $p = get_post($post); if (!($p instanceof WP_Post)) { return new WP_Error('aksrt_invalid', __('无效内容。', 'aksrt')); } $meta = aksrt_get_pay_meta($p); if ($meta['pay_type'] !== AKSRT_PAY_TYPE_DOWNLOAD) { return new WP_Error('aksrt_not_downloadable', __('该内容不是可下载资源。', 'aksrt')); } $paid_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_paid_content_settings() : ['download_login' => true, 'download_credit' => true]; $uid = $user_id > 0 ? $user_id : get_current_user_id(); if (!empty($paid_settings['download_login']) && $uid <= 0) { $login_url = wp_login_url(get_permalink($p)); return new WP_Error('aksrt_need_login', __('请先登录。', 'aksrt'), ['login_url' => $login_url]); } if ($uid > 0 && aksrt_has_paid_access($p, $uid)) return true; if ($uid > 0 && function_exists('aksrt_is_vip_exempt') && aksrt_is_vip_exempt($uid)) return true; $cost = aksrt_get_download_cost($p); if ($cost > 0 && !empty($paid_settings['download_credit'])) { $balance = function_exists('aksrt_user_credits') ? aksrt_user_credits($uid) : 0; if ($balance < $cost) { return new WP_Error('aksrt_credits_insufficient', __('积分不足。', 'aksrt'), [ 'balance' => $balance, 'cost' => $cost, ]); } } return true; } } if (!function_exists('aksrt_get_download_cost')) { function aksrt_get_download_cost($post = null): int { if (function_exists('aksrt_resource_download_cost')) { return (int) aksrt_resource_download_cost($post); } $meta = aksrt_get_pay_meta($post); return (int) ceil((float) $meta['price']); } } /** * URL of the Zibll-style single-post download page (page template + ?post=ID). */ if (!function_exists('aksrt_get_single_download_page_url')) { function aksrt_get_single_download_page_url($post = null): string { $p = get_post($post); if (!($p instanceof WP_Post)) { return ''; } $page_url = ''; if (function_exists('aksrt_find_template_page')) { $page = aksrt_find_template_page('templates/pages/page-download-file.php'); if ($page instanceof WP_Post) { $page_url = get_permalink($page); } } if ($page_url === '') { // Fallback: look for any page using the template via slug convention. $page_url = home_url('/download-file/'); } return add_query_arg('post', (int) $p->ID, $page_url); } } /** * Whether independent download page mode is enabled (Zibll down_alone_page). */ if (!function_exists('aksrt_is_download_alone_page_enabled')) { function aksrt_is_download_alone_page_enabled(): bool { if (!class_exists('AKSRT_Settings')) { return false; } $paid = AKSRT_Settings::get_paid_content_settings(); return !empty($paid['down_alone_page']) || !empty($paid['download']['alone_page']); } } // ============================================================ // 价格显示 // ============================================================ if (!function_exists('aksrt_get_pay_price_label')) { function aksrt_get_pay_price_label($post = null): array { $meta = aksrt_get_pay_meta($post); $price = (float) $meta['price']; $currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt'); if ($meta['pay_type'] === AKSRT_PAY_TYPE_VIP) { return ['text' => __('VIP 专属', 'aksrt'), 'free' => false, 'amount' => 0]; } if ($price <= 0) { return ['text' => __('免费', 'aksrt'), 'free' => true, 'amount' => 0]; } $amount = aksrt_format_price($price); return ['text' => sprintf(__('%s %s', 'aksrt'), $amount, $currency), 'free' => false, 'amount' => $price]; } } if (!function_exists('aksrt_format_price')) { function aksrt_format_price(float $price): string { if (fmod($price, 1.0) === 0.0) return (string) (int) $price; return rtrim(rtrim(number_format($price, 2, '.', ''), '0'), '.'); } } // ============================================================ // 付费类型徽章 // ============================================================ if (!function_exists('aksrt_get_pay_type_badge')) { function aksrt_get_pay_type_badge(string $pay_type): string { $badges = [ AKSRT_PAY_TYPE_READING => ['label' => __('付费阅读', 'aksrt'), 'color' => '#EF4444', 'icon' => 'fa-lock'], AKSRT_PAY_TYPE_DOWNLOAD => ['label' => __('付费下载', 'aksrt'), 'color' => '#F97316', 'icon' => 'fa-download'], AKSRT_PAY_TYPE_GALLERY => ['label' => __('付费图库', 'aksrt'), 'color' => '#10B981', 'icon' => 'fa-images'], AKSRT_PAY_TYPE_VIDEO => ['label' => __('付费视频', 'aksrt'), 'color' => '#8B5CF6', 'icon' => 'fa-play-circle'], AKSRT_PAY_TYPE_VIP => ['label' => __('VIP 专属', 'aksrt'), 'color' => '#3B82F6', 'icon' => 'fa-crown'], ]; if (!isset($badges[$pay_type])) return ''; $b = $badges[$pay_type]; return sprintf( ' %s', esc_attr($b['color']), esc_attr($b['icon']), esc_html($b['label']) ); } } // ============================================================ // 付费墙 HTML // ============================================================ 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']; $currency = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt'); $type_labels = [ AKSRT_PAY_TYPE_READING => ['icon' => 'fa-lock', 'label' => __('付费阅读', 'aksrt'), 'desc' => __('付费后即可查看完整内容', 'aksrt')], AKSRT_PAY_TYPE_GALLERY => ['icon' => 'fa-images', 'label' => __('付费图库', 'aksrt'), 'desc' => __('付费后即可查看全部图片', 'aksrt')], AKSRT_PAY_TYPE_VIDEO => ['icon' => 'fa-play-circle', 'label' => __('付费视频', 'aksrt'), 'desc' => __('付费后即可观看完整视频', 'aksrt')], ]; $type_info = $type_labels[$pay_type] ?? $type_labels[AKSRT_PAY_TYPE_READING]; $login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink($post)); $is_logged_in = is_user_logged_in(); $original_price = (float) ($meta['original_price'] ?? 0); $has_original = $original_price > 0 && $original_price > $price; ob_start(); ?>