From e41350a81be24aa5e10513f8241c10cfa98809b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 25 Aug 2026 19:03:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Core/FrontSubmit.php | 2 + src/Core/FrontSubmitPay.php | 40 ++++++--- src/Settings/PostDisplay.php | 2 + templates/parts/submit/context.php | 7 ++ tests/asset-ledger/FrontSubmitPayTest.php | 101 ++++++++++++++++++++++ tests/asset-ledger/bootstrap.php | 15 ++++ 6 files changed, 155 insertions(+), 12 deletions(-) create mode 100644 tests/asset-ledger/FrontSubmitPayTest.php diff --git a/src/Core/FrontSubmit.php b/src/Core/FrontSubmit.php index 9dbe110a..2135127c 100644 --- a/src/Core/FrontSubmit.php +++ b/src/Core/FrontSubmit.php @@ -177,6 +177,8 @@ class FrontSubmit { 'pay_price_min' => 0, 'pay_price_max' => 100, 'pay_vip_price_s' => true, + 'pay_vip_1_enabled' => false, + 'pay_vip_2_enabled' => false, 'pay_vip_1_discount' => 80, 'pay_vip_2_discount' => 50, ]; diff --git a/src/Core/FrontSubmitPay.php b/src/Core/FrontSubmitPay.php index 6ae2d4c0..1582fb70 100644 --- a/src/Core/FrontSubmitPay.php +++ b/src/Core/FrontSubmitPay.php @@ -69,6 +69,8 @@ trait FrontSubmitPay { $allow_free = !empty($settings['pay_free_s']); $vip_manual = !empty($settings['pay_vip_price_s']); + $vip1_enabled = !array_key_exists('pay_vip_1_enabled', $settings) || !empty($settings['pay_vip_1_enabled']); + $vip2_enabled = !array_key_exists('pay_vip_2_enabled', $settings) || !empty($settings['pay_vip_2_enabled']); $vip1_disc = (int) ($settings['pay_vip_1_discount'] ?? 100); $vip2_disc = (int) ($settings['pay_vip_2_discount'] ?? 100); @@ -90,17 +92,27 @@ trait FrontSubmitPay { } if ($vip_manual) { - $vip1 = $this->parse_front_points($raw['vip1_points'] ?? $raw['vip_1_points'] ?? null); - $vip2 = $this->parse_front_points($raw['vip2_points'] ?? $raw['vip_2_points'] ?? null); - if ($vip1 === null || $vip2 === null) { + $vip1 = $vip1_enabled + ? $this->parse_front_points($raw['vip1_points'] ?? $raw['vip_1_points'] ?? null) + : 0; + $vip2 = $vip2_enabled + ? $this->parse_front_points($raw['vip2_points'] ?? $raw['vip_2_points'] ?? null) + : 0; + if (($vip1_enabled && $vip1 === null) || ($vip2_enabled && $vip2 === null)) { return ['success' => false, 'message' => __('请设置正确的会员积分价格', 'aksrt')]; } + if ($vip1_enabled && $vip1 > $points) { + return ['success' => false, 'message' => __('会员积分价格不能高于普通积分价格', 'aksrt')]; + } + if ($vip2_enabled && $vip2 > ($vip1_enabled ? $vip1 : $points)) { + return ['success' => false, 'message' => __('更高等级会员积分价格不能高于较低等级会员积分价格', 'aksrt')]; + } } else { $vip1 = (intdiv($points, 100) * $vip1_disc) + intdiv(($points % 100) * $vip1_disc, 100); $vip2 = (intdiv($points, 100) * $vip2_disc) + intdiv(($points % 100) * $vip2_disc, 100); } - $vip1 = max(0, min($points, $vip1)); - $vip2 = max(0, min($vip1, $vip2)); + $vip1 = max(0, min($points, (int) $vip1)); + $vip2 = max(0, min($vip1_enabled ? $vip1 : $points, (int) $vip2)); $meta['points_price'] = $points; $meta['price'] = '0.00'; @@ -126,23 +138,27 @@ trait FrontSubmitPay { } if ($vip_manual) { - $vip1_minor = $this->parse_front_cash_minor($raw['vip1_price'] ?? $raw['vip_1_price'] ?? null); - $vip2_minor = $this->parse_front_cash_minor($raw['vip2_price'] ?? $raw['vip_2_price'] ?? null); - if ($vip1_minor === null || $vip2_minor === null) { + $vip1_minor = $vip1_enabled + ? $this->parse_front_cash_minor($raw['vip1_price'] ?? $raw['vip_1_price'] ?? null) + : 0; + $vip2_minor = $vip2_enabled + ? $this->parse_front_cash_minor($raw['vip2_price'] ?? $raw['vip_2_price'] ?? null) + : 0; + if (($vip1_enabled && $vip1_minor === null) || ($vip2_enabled && $vip2_minor === null)) { return ['success' => false, 'message' => __('请设置正确的会员价格', 'aksrt')]; } - if ($vip1_minor > $price_minor) { + if ($vip1_enabled && $vip1_minor > $price_minor) { return ['success' => false, 'message' => __('会员价不能高于普通价', 'aksrt')]; } - if ($vip2_minor > $vip1_minor) { + if ($vip2_enabled && $vip2_minor > ($vip1_enabled ? $vip1_minor : $price_minor)) { return ['success' => false, 'message' => __('更高等级会员价不能高于较低等级会员价', 'aksrt')]; } } else { $vip1_minor = \AKSRT\Ledger\AssetAmount::percentage($price_minor, max(0, min(100, $vip1_disc))); $vip2_minor = \AKSRT\Ledger\AssetAmount::percentage($price_minor, max(0, min(100, $vip2_disc))); } - $vip1_minor = max(0, min($price_minor, $vip1_minor)); - $vip2_minor = max(0, min($vip1_minor, $vip2_minor)); + $vip1_minor = max(0, min($price_minor, (int) $vip1_minor)); + $vip2_minor = max(0, min($vip1_enabled ? $vip1_minor : $price_minor, (int) $vip2_minor)); $meta['price'] = \AKSRT\Ledger\AssetAmount::decimal_from_minor($price_minor); $meta['points_price'] = 0; diff --git a/src/Settings/PostDisplay.php b/src/Settings/PostDisplay.php index 93b50042..c47348fd 100644 --- a/src/Settings/PostDisplay.php +++ b/src/Settings/PostDisplay.php @@ -354,6 +354,8 @@ class PostDisplay { 'pay_price_min' => $money_setting($settings['post_article_pay_price_min'] ?? '0.00', '0.00'), 'pay_price_max' => $money_setting($settings['post_article_pay_price_max'] ?? '100.00', '100.00'), 'pay_vip_price_s' => !isset($settings['post_article_pay_vip_price_s']) || !empty($settings['post_article_pay_vip_price_s']), + 'pay_vip_1_enabled' => !empty($settings['pay_user_vip_1_s']), + 'pay_vip_2_enabled' => !empty($settings['pay_user_vip_2_s']), 'pay_vip_1_discount' => max(0, min(100, (int) ($settings['post_article_pay_vip_1_discount'] ?? 80))), 'pay_vip_2_discount' => max(0, min(100, (int) ($settings['post_article_pay_vip_2_discount'] ?? 50))), 'custom_filter_s' => !isset($settings['post_article_custom_filter_s']) || !empty($settings['post_article_custom_filter_s']), diff --git a/templates/parts/submit/context.php b/templates/parts/submit/context.php index 7c810574..373e797c 100644 --- a/templates/parts/submit/context.php +++ b/templates/parts/submit/context.php @@ -149,6 +149,13 @@ if (empty($vip) && class_exists('\AKSRT\Settings\PaymentRuntime')) { 'vip2_name' => (string) ($all['pay_user_vip_2_name'] ?? 'VIP2'), ]; } +$vip_levels = is_array($vip['levels'] ?? null) ? $vip['levels'] : []; +$vip = [ + 'vip1_enabled' => !empty($vip['vip1_enabled']) || !empty($vip_levels[1]['enabled']), + 'vip2_enabled' => !empty($vip['vip2_enabled']) || !empty($vip_levels[2]['enabled']), + 'vip1_name' => (string) ($vip['vip1_name'] ?? $vip_levels[1]['name'] ?? 'VIP1'), + 'vip2_name' => (string) ($vip['vip2_name'] ?? $vip_levels[2]['name'] ?? 'VIP2'), +]; $points_enabled = class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'credits_enabled') ? \AKSRT\Settings\Settings::credits_enabled() : false; diff --git a/tests/asset-ledger/FrontSubmitPayTest.php b/tests/asset-ledger/FrontSubmitPayTest.php new file mode 100644 index 00000000..ea8cc94b --- /dev/null +++ b/tests/asset-ledger/FrontSubmitPayTest.php @@ -0,0 +1,101 @@ +save_pay_meta($post_id, $data, 7, $settings); + } +} + +final class FrontSubmitPayTest extends TestCase { + private FrontSubmitPayHarness $submit; + + protected function setUp(): void { + $GLOBALS['aksrt_test_post_meta'] = []; + $this->submit = new FrontSubmitPayHarness(); + } + + public function test_manual_cash_price_only_requires_enabled_vip_level(): void { + $result = $this->submit->save(101, [ + 'pay_enabled' => '1', + 'aksrt_pay' => [ + 'price' => '10.00', + 'vip1_price' => '8.00', + ], + ], $this->settings(true, false)); + + self::assertTrue($result['success']); + $meta = $GLOBALS['aksrt_test_post_meta'][101][DomainModel::PAY_META_KEY]; + self::assertSame('8.00', $meta['vip1_price']); + self::assertSame('0.00', $meta['vip2_price']); + } + + public function test_manual_points_price_only_requires_enabled_vip_level(): void { + $result = $this->submit->save(102, [ + 'pay_enabled' => '1', + 'aksrt_pay' => [ + 'pay_modo' => 'points', + 'points_price' => '100', + 'vip2_points' => '50', + ], + ], $this->settings(false, true)); + + self::assertTrue($result['success']); + $meta = $GLOBALS['aksrt_test_post_meta'][102][DomainModel::PAY_META_KEY]; + self::assertSame(0, $meta['vip1_points']); + self::assertSame(50, $meta['vip2_points']); + } + + public function test_manual_price_rejects_missing_enabled_vip_level(): void { + $result = $this->submit->save(103, [ + 'pay_enabled' => '1', + 'aksrt_pay' => ['price' => '10.00'], + ], $this->settings(true, false)); + + self::assertFalse($result['success']); + self::assertSame('请设置正确的会员价格', $result['message']); + } + + public function test_manual_price_does_not_require_disabled_vip_levels(): void { + $result = $this->submit->save(104, [ + 'pay_enabled' => '1', + 'aksrt_pay' => ['price' => '10.00'], + ], $this->settings(false, false)); + + self::assertTrue($result['success']); + $meta = $GLOBALS['aksrt_test_post_meta'][104][DomainModel::PAY_META_KEY]; + self::assertSame('0.00', $meta['vip1_price']); + self::assertSame('0.00', $meta['vip2_price']); + } + + private function settings(bool $vip1_enabled, bool $vip2_enabled): array { + return [ + 'pay_free_s' => true, + 'pay_price_min' => '0.00', + 'pay_price_max' => '100.00', + 'pay_vip_price_s' => true, + 'pay_vip_1_enabled' => $vip1_enabled, + 'pay_vip_2_enabled' => $vip2_enabled, + 'pay_vip_1_discount' => 80, + 'pay_vip_2_discount' => 50, + ]; + } +} diff --git a/tests/asset-ledger/bootstrap.php b/tests/asset-ledger/bootstrap.php index d6c1981a..849d3956 100644 --- a/tests/asset-ledger/bootstrap.php +++ b/tests/asset-ledger/bootstrap.php @@ -17,6 +17,21 @@ if (!function_exists('sanitize_text_field')) { return trim(strip_tags((string) $value)); } } +if (!function_exists('sanitize_textarea_field')) { + function sanitize_textarea_field($value): string { + return trim(strip_tags((string) $value)); + } +} +if (!function_exists('esc_url_raw')) { + function esc_url_raw($value): string { + return filter_var((string) $value, FILTER_VALIDATE_URL) ? (string) $value : ''; + } +} +if (!function_exists('wp_kses_post')) { + function wp_kses_post($value): string { + return (string) $value; + } +} if (!function_exists('wp_timezone')) { function wp_timezone(): DateTimeZone { return new DateTimeZone('UTC');