积分与余额账务系统硬切重构
This commit is contained in:
@@ -154,8 +154,8 @@ trait CreditsPaymentGroups {
|
||||
}
|
||||
|
||||
public static function affiliate_enabled(): bool { return PaymentRuntime::affiliate_enabled(); }
|
||||
public static function affiliate_ratio_for_user(int $user_id = 0): float { return PaymentRuntime::affiliate_ratio_for_user($user_id > 0 ? $user_id : get_current_user_id()); }
|
||||
public static function affiliate_ratio_for_level(int $level): float { return PaymentRuntime::affiliate_ratio_for_level($level); }
|
||||
public static function affiliate_ratio_for_user(int $user_id = 0): int { return PaymentRuntime::affiliate_ratio_for_user($user_id > 0 ? $user_id : get_current_user_id()); }
|
||||
public static function affiliate_ratio_for_level(int $level): int { return PaymentRuntime::affiliate_ratio_for_level($level); }
|
||||
public static function get_affiliate_settings(): array { return PaymentRuntime::get_affiliate_settings(); }
|
||||
public static function get_settlement_settings(): array { return PaymentRuntime::get_settlement_settings(); }
|
||||
|
||||
@@ -178,7 +178,7 @@ trait CreditsPaymentGroups {
|
||||
/**
|
||||
* 获取充值卡设置
|
||||
*
|
||||
* @return array{enabled:bool,desc:string,type:string,prefix:string,length:int,batch_size:int,max_redeem:int,expiry_days:int,amount:int,vip_days:int,credits:int,redeem_page:string,success_msg:string,fail_msg:string}
|
||||
* @return array{enabled:bool,desc:string,type:string,prefix:string,length:int,batch_size:int,max_redeem:int,expiry_days:int,amount:string,vip_days:int,credits:int,redeem_page:string,success_msg:string,fail_msg:string}
|
||||
*/
|
||||
public static function get_card_pass_settings(): array {
|
||||
return PaymentRuntime::get_card_pass_settings();
|
||||
|
||||
@@ -286,8 +286,10 @@ class Integration {
|
||||
'comment_reply' => true,
|
||||
'comment_approved' => true,
|
||||
'download_ready' => true,
|
||||
'credits_added' => true,
|
||||
'credits_deducted' => true,
|
||||
'asset_points_increase' => true,
|
||||
'asset_points_decrease' => true,
|
||||
'asset_balance_increase' => true,
|
||||
'asset_balance_decrease' => true,
|
||||
'pending_comments' => true,
|
||||
'upload_moderation' => true,
|
||||
],
|
||||
@@ -301,7 +303,11 @@ class Integration {
|
||||
if (!is_array($saved)) {
|
||||
$saved = [];
|
||||
}
|
||||
if (isset($saved['enabled_types']) && is_array($saved['enabled_types'])) {
|
||||
$saved['enabled_types'] = array_intersect_key($saved['enabled_types'], $defaults['enabled_types']);
|
||||
}
|
||||
$merged = array_merge($defaults, $saved);
|
||||
$merged['enabled_types'] = array_replace($defaults['enabled_types'], (array) ($saved['enabled_types'] ?? []));
|
||||
$merged['read_retention_days'] = max(1, min(365, (int) $merged['read_retention_days']));
|
||||
$merged['unread_retention_days'] = max(7, min(3650, (int) $merged['unread_retention_days']));
|
||||
$merged['max_per_user'] = max(20, min(5000, (int) $merged['max_per_user']));
|
||||
|
||||
@@ -88,13 +88,12 @@ class PaymentRuntime {
|
||||
return [
|
||||
'enabled' => !empty($settings['pay_balance_s']),
|
||||
'desc' => $desc,
|
||||
'auto_to_balance' => !isset($settings['pay_auto_to_balance']) || !empty($settings['pay_auto_to_balance']),
|
||||
'packages_raw' => $packages,
|
||||
'package_count' => self::count_structured_lines($packages),
|
||||
'help_text' => $desc !== '' ? $desc : __('当前支持人工确认与测试联调;接入真实网关时复用同一组字段。', 'aksrt'),
|
||||
'product' => [
|
||||
'name' => sanitize_text_field((string) ($settings['pay_balance_product_name'] ?? '')),
|
||||
'price' => max(0, (float) ($settings['pay_balance_price'] ?? 0)),
|
||||
'price' => self::money_decimal($settings['pay_balance_price'] ?? '0.00', '0.00'),
|
||||
'tag' => sanitize_text_field((string) ($settings['pay_balance_tag'] ?? '元')),
|
||||
'tag_class' => sanitize_text_field((string) ($settings['pay_balance_tag_class'] ?? '')),
|
||||
'custom_s' => !isset($settings['pay_balance_product_custom_s']) || !empty($settings['pay_balance_product_custom_s']),
|
||||
@@ -234,7 +233,7 @@ class PaymentRuntime {
|
||||
'desc' => sanitize_textarea_field((string) ($settings['vip_renew_desc'] ?? '')),
|
||||
'price_type' => $renew_price_type,
|
||||
'discount' => max(1, min(100, (int) ($settings['vip_renew_discount'] ?? 8))),
|
||||
'reduce' => max(0, min(9999, (int) ($settings['vip_renew_reduce'] ?? 20))),
|
||||
'reduce' => self::money_decimal($settings['vip_renew_reduce'] ?? '20.00', '20.00', 999900),
|
||||
],
|
||||
'upgrade' => [
|
||||
'enabled' => !isset($settings['vip_upgrade']) || !empty($settings['vip_upgrade']),
|
||||
@@ -284,7 +283,7 @@ class PaymentRuntime {
|
||||
*/
|
||||
public static function get_payment_affiliate_settings(): array {
|
||||
$settings = Settings::get_all();
|
||||
$clamp_ratio = static fn ($value): float => max(0, min(100, (float) $value));
|
||||
$clamp_ratio = static fn($value): int => max(0, min(100, (int) $value));
|
||||
$types = (array) ($settings['affiliate_order_types'] ?? ['membership', 'content']);
|
||||
$types = array_values(array_intersect(['membership', 'content', 'credits'], array_map('sanitize_key', $types)));
|
||||
if (!$types) { $types = ['membership', 'content']; }
|
||||
@@ -303,14 +302,14 @@ class PaymentRuntime {
|
||||
}
|
||||
|
||||
public static function affiliate_enabled(): bool { return !empty(self::get_payment_affiliate_settings()['enabled']); }
|
||||
public static function affiliate_ratio_for_user(int $user_id): float {
|
||||
public static function affiliate_ratio_for_user(int $user_id): int {
|
||||
$level = function_exists('aksrt_get_user_vip_level') ? (int) aksrt_get_user_vip_level($user_id) : 0;
|
||||
return self::affiliate_ratio_for_level($level);
|
||||
}
|
||||
public static function affiliate_ratio_for_level(int $level): float {
|
||||
public static function affiliate_ratio_for_level(int $level): int {
|
||||
$settings = self::get_payment_affiliate_settings();
|
||||
$key = $level >= 2 ? 'vip_2' : ($level >= 1 ? 'vip_1' : 'user');
|
||||
return (float) ($settings['ratios'][$key] ?? 0);
|
||||
return (int) ($settings['ratios'][$key] ?? 0);
|
||||
}
|
||||
public static function get_affiliate_settings(): array { return self::get_payment_affiliate_settings(); }
|
||||
public static function get_settlement_settings(): array {
|
||||
@@ -433,7 +432,7 @@ class PaymentRuntime {
|
||||
'batch_size' => max(1, min(500, (int) ($s['card_pass_batch_size'] ?? 50))),
|
||||
'max_redeem' => max(1, min(100, (int) ($s['card_pass_max_redeem'] ?? 1))),
|
||||
'expiry_days' => max(0, (int) ($s['card_pass_expiry'] ?? 0)),
|
||||
'amount' => max(1, min(9999, (int) ($s['card_pass_amount'] ?? 10))),
|
||||
'amount' => self::money_decimal($s['card_pass_amount'] ?? '10.00', '10.00', 999900),
|
||||
'vip_days' => max(1, min(3650, (int) ($s['card_pass_vip_days'] ?? 30))),
|
||||
'credits' => max(0, min(99999, (int) ($s['card_pass_credits'] ?? 0))),
|
||||
'redeem_page' => esc_url_raw((string) ($s['card_pass_redeem_page'] ?? '')),
|
||||
@@ -442,16 +441,16 @@ class PaymentRuntime {
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array{min_amount:float,service_charge_rate:int,daily_count:int,daily_limit:float,reset_time:string,payout_channels:string[]} */
|
||||
/** @return array{min_amount:string,service_charge_rate:int,daily_count:int,daily_limit:string,reset_time:string,payout_channels:string[]} */
|
||||
public static function get_withdrawal_settings(): array {
|
||||
$s = Settings::get_all();
|
||||
$channels = array_values(array_intersect(['alipay', 'wechat'], array_map('sanitize_key', (array) ($s['affiliate_payout_channels'] ?? ['alipay', 'wechat']))));
|
||||
if (!$channels) { $channels = ['alipay', 'wechat']; }
|
||||
return [
|
||||
'min_amount' => max(0, min(999999, (float) ($s['affiliate_min_withdrawal'] ?? 50))),
|
||||
'service_charge_rate' => (int) round(max(0, min(100, (float) ($s['affiliate_withdrawal_fee'] ?? 5)))),
|
||||
'min_amount' => self::money_decimal($s['affiliate_min_withdrawal'] ?? '50.00', '50.00', 99999900),
|
||||
'service_charge_rate' => max(0, min(100, (int) ($s['affiliate_withdrawal_fee'] ?? 5))),
|
||||
'daily_count' => max(0, min(99999, (int) ($s['affiliate_daily_withdrawal_count'] ?? 3))),
|
||||
'daily_limit' => max(0, min(999999, (float) ($s['affiliate_daily_withdrawal_limit'] ?? 500))),
|
||||
'daily_limit' => self::money_decimal($s['affiliate_daily_withdrawal_limit'] ?? '500.00', '500.00', 99999900),
|
||||
'reset_time' => preg_match('/^(?:[01]\\d|2[0-3]):[0-5]\\d$/', (string) ($s['affiliate_withdrawal_reset_time'] ?? '00:00'))
|
||||
? (string) $s['affiliate_withdrawal_reset_time']
|
||||
: '00:00',
|
||||
@@ -516,6 +515,18 @@ class PaymentRuntime {
|
||||
return $count;
|
||||
}
|
||||
|
||||
private static function money_decimal(mixed $value, string $default, int $max_minor = PHP_INT_MAX): string {
|
||||
try {
|
||||
if (!is_string($value)) {
|
||||
throw new \InvalidArgumentException('money_decimal_must_be_string');
|
||||
}
|
||||
$amount = \AKSRT\Ledger\AssetAmount::balance(trim($value));
|
||||
return $amount->minor() <= $max_minor ? $amount->decimal() : $default;
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int,mixed> $products
|
||||
*/
|
||||
|
||||
@@ -152,14 +152,37 @@ class PostDisplay {
|
||||
if ($rewards_text === '') {
|
||||
$rewards_text = '赞赏';
|
||||
}
|
||||
$rewards_amounts = array_values(array_filter(array_map(static function ($value): float {
|
||||
return round((float) $value, 2);
|
||||
}, explode(',', (string) ($settings['post_rewards_amounts'] ?? '5,10,20,50,100'))), static fn(float $value): bool => $value > 0));
|
||||
if ($rewards_amounts === []) {
|
||||
$rewards_amounts = [5, 10, 20, 50, 100];
|
||||
}
|
||||
$rewards_min = max(0.01, round((float) ($settings['post_rewards_min'] ?? 1), 2));
|
||||
$rewards_max = max($rewards_min, round((float) ($settings['post_rewards_max'] ?? 1000), 2));
|
||||
$reward_amount = static function ($value, string $default): \AKSRT\Ledger\AssetAmount {
|
||||
try {
|
||||
return \AKSRT\Ledger\AssetAmount::balance(is_string($value) ? trim($value) : '');
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return \AKSRT\Ledger\AssetAmount::balance($default);
|
||||
}
|
||||
};
|
||||
$rewards_amounts = [];
|
||||
foreach (explode(',', (string) ($settings['post_rewards_amounts'] ?? '5.00,10.00,20.00,50.00,100.00')) as $value) {
|
||||
try {
|
||||
$parsed = \AKSRT\Ledger\AssetAmount::balance(trim($value));
|
||||
if ($parsed->minor() > 0) {
|
||||
$rewards_amounts[] = $parsed->decimal();
|
||||
}
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($rewards_amounts === []) {
|
||||
$rewards_amounts = ['5.00', '10.00', '20.00', '50.00', '100.00'];
|
||||
}
|
||||
$rewards_min_amount = $reward_amount($settings['post_rewards_min'] ?? '1.00', '1.00');
|
||||
if ($rewards_min_amount->minor() <= 0) {
|
||||
$rewards_min_amount = \AKSRT\Ledger\AssetAmount::balance('0.01');
|
||||
}
|
||||
$rewards_max_amount = $reward_amount($settings['post_rewards_max'] ?? '1000.00', '1000.00');
|
||||
if ($rewards_max_amount->minor() < $rewards_min_amount->minor()) {
|
||||
$rewards_max_amount = $rewards_min_amount;
|
||||
}
|
||||
$rewards_min = $rewards_min_amount->decimal();
|
||||
$rewards_max = $rewards_max_amount->decimal();
|
||||
$author_card_limit = max(0, min(12, (int) ($settings['post_author_card_limit'] ?? 6)));
|
||||
$author_card_orderby = sanitize_key((string) ($settings['post_author_card_orderby'] ?? 'views'));
|
||||
if (!in_array($author_card_orderby, ['views', 'date', 'modified', 'comment_count'], true)) {
|
||||
@@ -277,6 +300,17 @@ class PostDisplay {
|
||||
public static function get_submit_settings(): array {
|
||||
$settings = Settings::get_all();
|
||||
|
||||
$money_setting = static function ($value, string $default): string {
|
||||
if (!is_string($value)) {
|
||||
return $default;
|
||||
}
|
||||
try {
|
||||
return \AKSRT\Ledger\AssetAmount::balance($value)->decimal();
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return $default;
|
||||
}
|
||||
};
|
||||
|
||||
$title_min = max(1, min(100, (int) ($settings['post_article_title_strlen_limit_min'] ?? 5)));
|
||||
$title_max = max(5, min(200, (int) ($settings['post_article_title_strlen_limit_max'] ?? 30)));
|
||||
if ($title_max < $title_min) {
|
||||
@@ -317,8 +351,8 @@ class PostDisplay {
|
||||
'draft_save' => !isset($settings['front_submit_draft_save']) || !empty($settings['front_submit_draft_save']),
|
||||
'leave_warning' => !isset($settings['front_submit_leave_warning']) || !empty($settings['front_submit_leave_warning']),
|
||||
'pay_free_s' => !isset($settings['post_article_pay_free_s']) || !empty($settings['post_article_pay_free_s']),
|
||||
'pay_price_min' => max(0, (float) ($settings['post_article_pay_price_min'] ?? 0)),
|
||||
'pay_price_max' => max(0, (float) ($settings['post_article_pay_price_max'] ?? 100)),
|
||||
'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_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))),
|
||||
|
||||
@@ -105,7 +105,7 @@ class UserRuntime {
|
||||
* User identity, level, medal, and report governance settings.
|
||||
*
|
||||
* @return array{
|
||||
* verify:array{enabled:bool,public_display:bool,allow_apply:bool,disable_desc:string,desc:string,types:array<string,array{slug:string,label:string,badge_text:string,fee:float,free_applications:int,require_real_name:bool}>},
|
||||
* verify:array{enabled:bool,public_display:bool,allow_apply:bool,disable_desc:string,desc:string,types:array<string,array{slug:string,label:string,badge_text:string,fee:string,free_applications:int,require_real_name:bool}>},
|
||||
* level:array{enabled:bool,public_display:bool,source:string,label_prefix:string,thresholds:array<int,int>},
|
||||
* medal:array{enabled:bool,public_display:bool,limit:int,categories:array<int,array{cat_name:string,items:array<int,array{slug:string,name:string,desc:string,icon:string,get_type:string,get_val:int}>}>,items_by_slug:array<string,array{slug:string,name:string,desc:string,icon:string,get_type:string,get_val:int,cat_name:string}>},
|
||||
* badge:array{enabled:bool,public_display:bool,limit:int,dictionary:array<int,array{slug:string,label:string,tone:string,desc:string,icon_url?:string}>},
|
||||
@@ -120,7 +120,7 @@ class UserRuntime {
|
||||
'slug' => 'personal',
|
||||
'label' => __('个人认证', 'aksrt'),
|
||||
'badge_text' => trim((string) ($settings['user_verify_personal_badge_text'] ?? '')) ?: __('个人认证', 'aksrt'),
|
||||
'fee' => max(0, round((float) ($settings['user_verify_personal_fee'] ?? 0), 2)),
|
||||
'fee' => self::identity_fee_setting($settings, 'user_verify_personal_fee'),
|
||||
'free_applications' => max(0, (int) ($settings['user_verify_personal_free_applications'] ?? 0)),
|
||||
'require_real_name' => true,
|
||||
],
|
||||
@@ -128,7 +128,7 @@ class UserRuntime {
|
||||
'slug' => 'enterprise',
|
||||
'label' => __('企业认证', 'aksrt'),
|
||||
'badge_text' => trim((string) ($settings['user_verify_enterprise_badge_text'] ?? '')) ?: __('企业认证', 'aksrt'),
|
||||
'fee' => max(0, round((float) ($settings['user_verify_enterprise_fee'] ?? 0), 2)),
|
||||
'fee' => self::identity_fee_setting($settings, 'user_verify_enterprise_fee'),
|
||||
'free_applications' => max(0, (int) ($settings['user_verify_enterprise_free_applications'] ?? 0)),
|
||||
'require_real_name' => true,
|
||||
],
|
||||
@@ -182,6 +182,19 @@ class UserRuntime {
|
||||
];
|
||||
}
|
||||
|
||||
/** @param array<string,mixed> $settings */
|
||||
private static function identity_fee_setting(array $settings, string $key): string {
|
||||
$value = array_key_exists($key, $settings) ? $settings[$key] : '0.00';
|
||||
if (!is_string($value)) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
return \AKSRT\Ledger\AssetAmount::balance(trim($value))->decimal();
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁封设置
|
||||
*/
|
||||
@@ -245,8 +258,8 @@ class UserRuntime {
|
||||
'like',
|
||||
'comment_like',
|
||||
'views',
|
||||
'pay_income',
|
||||
'pay_rebate',
|
||||
'creator_income',
|
||||
'affiliate_commission',
|
||||
'manually_add',
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user