From b98faa965a3ec1a7a89cb56da9dbc48b8a88f7fe Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 4 Jul 2026 19:24:04 +0800 Subject: [PATCH] Restore unified paid download model --- .../class-aksrt-admin-schema-payment.php | 12 +- .../class-aksrt-content-visibility.php | 6 +- inc/classes/class-aksrt-download.php | 16 +- inc/core-hooks/part-2.php | 3 + inc/helpers/aksrt-pay.php | 54 ++++ single-aksrt_resource.php | 5 + single.php | 20 ++ templates/pages/page-download.php | 45 ++-- templates/parts/resource-download-box.php | 239 +++++++++--------- 9 files changed, 246 insertions(+), 154 deletions(-) diff --git a/inc/classes/admin/schema/class-aksrt-admin-schema-payment.php b/inc/classes/admin/schema/class-aksrt-admin-schema-payment.php index 462a5bbd..a66f425b 100644 --- a/inc/classes/admin/schema/class-aksrt-admin-schema-payment.php +++ b/inc/classes/admin/schema/class-aksrt-admin-schema-payment.php @@ -16,13 +16,13 @@ class AKSRT_Admin_Schema_Payment { 'sections' => [ 'paid' => [ 'key' => 'paid', - 'title' => '下载/付费内容中心', + 'title' => '内容付费 / 下载', 'version' => '1.0.0', 'option_key' => 'aksrt_settings', 'groups' => [ - ['key' => 'strategy', 'title' => '付费内容策略', 'fields' => [ + ['key' => 'strategy', 'title' => '内容付费策略', 'fields' => [ ['key' => 'payment_paid_post_types', 'label' => '受管内容类型', 'type' => 'input', 'default' => 'post'], - ['key' => 'payment_vip_free_download', 'label' => '角色白名单免扣下载', 'type' => 'switch', 'default' => false], + ['key' => 'payment_vip_free_download', 'label' => 'VIP / 角色白名单免扣下载', 'type' => 'switch', 'default' => false], ['key' => 'payment_vip_exempt_roles', 'label' => '免扣角色列表', 'type' => 'input', 'default' => ''], ]], ['key' => 'delivery', 'title' => '交付说明', 'fields' => [ @@ -41,12 +41,12 @@ class AKSRT_Admin_Schema_Payment { ['label' => '模块下', 'value' => 'box_bottom'], ]], ]], - ['key' => 'download', 'title' => '下载设置', 'fields' => [ - ['key' => 'payment_download_enable', 'label' => '启用下载功能', 'type' => 'switch', 'default' => false], + ['key' => 'download', 'title' => '下载能力', 'fields' => [ + ['key' => 'payment_download_enable', 'label' => '启用下载能力', 'type' => 'switch', 'default' => false], ['key' => 'payment_download_remote_s', 'label' => '远程文件下载', 'type' => 'switch', 'default' => true], ['key' => 'payment_download_verify_nonce', 'label' => '下载鉴权', 'type' => 'switch', 'default' => true], ['key' => 'payment_download_user_log', 'label' => '用户下载记录条数', 'type' => 'number', 'default' => 50, 'min' => 0, 'max' => 9999], - ['key' => 'payment_download_post_log', 'label' => '文章下载记录条数', 'type' => 'number', 'default' => 50, 'min' => 0, 'max' => 9999], + ['key' => 'payment_download_post_log', 'label' => '内容下载记录条数', 'type' => 'number', 'default' => 50, 'min' => 0, 'max' => 9999], ['key' => 'payment_download_remote_size', 'label' => '远程文件大小限制(KB)', 'type' => 'number', 'default' => 2048, 'min' => 1, 'max' => 999999], ['key' => 'payment_download_remote_ext', 'label' => '远程文件格式限制', 'type' => 'input', 'default' => 'zip,rar,7z'], ]], diff --git a/inc/classes/class-aksrt-content-visibility.php b/inc/classes/class-aksrt-content-visibility.php index 0531b0b8..7a7e4809 100644 --- a/inc/classes/class-aksrt-content-visibility.php +++ b/inc/classes/class-aksrt-content-visibility.php @@ -136,15 +136,15 @@ class AKSRT_Content_Visibility { */ public static function can_download_resource($post = null, int $user_id = 0) { $resource_post = get_post($post); - if (!($resource_post instanceof WP_Post) || !function_exists('aksrt_is_resource_post') || !aksrt_is_resource_post($resource_post)) { - return new WP_Error('aksrt_not_resource', __('该内容不是可下载资源。', 'aksrt')); + if (!($resource_post instanceof WP_Post) || !function_exists('aksrt_is_downloadable_content') || !aksrt_is_downloadable_content($resource_post)) { + return new WP_Error('aksrt_not_downloadable', __('该内容未启用下载能力。', 'aksrt')); } $state = self::get_post_access_state($resource_post, $user_id); $uid = $user_id > 0 ? $user_id : get_current_user_id(); if (($state['pay_type'] ?? '') !== AKSRT_Domain_Model::PAY_TYPE_DOWNLOAD) { - return new WP_Error('aksrt_not_downloadable', __('该内容不是可下载资源。', 'aksrt')); + return new WP_Error('aksrt_not_downloadable', __('该内容未启用下载能力。', 'aksrt')); } if (!empty($state['need_login']) && $uid <= 0) { diff --git a/inc/classes/class-aksrt-download.php b/inc/classes/class-aksrt-download.php index 163677de..ce19aec8 100644 --- a/inc/classes/class-aksrt-download.php +++ b/inc/classes/class-aksrt-download.php @@ -106,11 +106,11 @@ class AKSRT_Download { public function rest_policy(WP_REST_Request $request) { $post_id = (int) $request['id']; $post = get_post($post_id); - if (!$post || !aksrt_is_resource_post($post)) { - return new WP_Error('aksrt_invalid', __('资源不存在', 'aksrt'), ['status' => 404]); + if (!$post || !function_exists('aksrt_is_downloadable_content') || !aksrt_is_downloadable_content($post)) { + return new WP_Error('aksrt_invalid', __('内容不存在或未启用下载能力', 'aksrt'), ['status' => 404]); } - $meta = aksrt_get_resource_meta($post); + $meta = function_exists('aksrt_get_download_box_meta') ? aksrt_get_download_box_meta($post) : []; $paid_settings = AKSRT_Settings::get_paid_content_settings(); $cost = aksrt_resource_download_cost($post); $uid = get_current_user_id(); @@ -148,11 +148,11 @@ class AKSRT_Download { $source_index = isset($params['source_index']) ? (int) $params['source_index'] : 0; $post = get_post($post_id); - if (!$post || !aksrt_is_resource_post($post)) { - return new WP_Error('aksrt_invalid', __('资源不存在', 'aksrt'), ['status' => 404]); + if (!$post || !function_exists('aksrt_is_downloadable_content') || !aksrt_is_downloadable_content($post)) { + return new WP_Error('aksrt_invalid', __('内容不存在或未启用下载能力', 'aksrt'), ['status' => 404]); } - $meta = aksrt_get_resource_meta($post); + $meta = function_exists('aksrt_get_download_box_meta') ? aksrt_get_download_box_meta($post) : []; if (empty($meta['downloads'][$source_index])) { return new WP_Error('aksrt_no_source', __('下载源不存在', 'aksrt'), ['status' => 404]); } @@ -245,8 +245,8 @@ class AKSRT_Download { if (!empty($row['ua_hash']) && $row['ua_hash'] !== $ua_hash) $this->fail_410(); $post = get_post((int) $row['post_id']); - if (!$post || !aksrt_is_resource_post($post)) $this->fail_410(); - $meta = aksrt_get_resource_meta($post); + if (!$post || !function_exists('aksrt_is_downloadable_content') || !aksrt_is_downloadable_content($post)) $this->fail_410(); + $meta = function_exists('aksrt_get_download_box_meta') ? aksrt_get_download_box_meta($post) : []; $idx = (int) $row['source_index']; if (empty($meta['downloads'][$idx]['url'])) $this->fail_410(); diff --git a/inc/core-hooks/part-2.php b/inc/core-hooks/part-2.php index a08ecd46..f83171d5 100644 --- a/inc/core-hooks/part-2.php +++ b/inc/core-hooks/part-2.php @@ -476,6 +476,9 @@ add_filter('single_template', function ($template) { if (!($post instanceof WP_Post)) return $template; if (!function_exists('aksrt_is_resource_post')) return $template; if (!aksrt_is_resource_post($post)) return $template; + if (function_exists('aksrt_is_downloadable_content') && !aksrt_is_downloadable_content($post)) { + return $template; + } $candidate = locate_template(['single-aksrt_resource.php']); return $candidate ?: $template; }); diff --git a/inc/helpers/aksrt-pay.php b/inc/helpers/aksrt-pay.php index 710a447e..0347c323 100644 --- a/inc/helpers/aksrt-pay.php +++ b/inc/helpers/aksrt-pay.php @@ -117,6 +117,60 @@ if (!function_exists('aksrt_default_pay_meta')) { } } +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'), + ]; + } +} + // ============================================================ // 状态判断 // ============================================================ diff --git a/single-aksrt_resource.php b/single-aksrt_resource.php index 6b3c10cd..103d3abd 100644 --- a/single-aksrt_resource.php +++ b/single-aksrt_resource.php @@ -75,6 +75,7 @@ while (have_posts()) : } set_query_var('aksrt_resource_meta', $resource_meta); + $is_legacy_resource_shell = true; ?> @@ -259,6 +260,10 @@ while (have_posts()) :