积分与余额账务系统硬切重构
This commit is contained in:
1 parent
ca12226b39
commit
5cae5b5c93
159 files changed
+7275
-4718
No files matched your search
+131
-57
@@ -35,6 +35,30 @@ if (!defined('AKSRT_PAY_TYPE_VIP')) {
|
||||
define('AKSRT_PAY_TYPE_VIP', \AKSRT\Core\DomainModel::PAY_TYPE_VIP);
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_asset_price_minor')) {
|
||||
function aksrt_asset_price_minor($value, string $pay_modo): int {
|
||||
if ($pay_modo === 'points') {
|
||||
return is_int($value) ? max(0, $value) : 0;
|
||||
}
|
||||
if (!is_string($value)) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
return \AKSRT\Ledger\AssetAmount::balance_minor($value);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_asset_price_value')) {
|
||||
function aksrt_asset_price_value(int $minor, string $pay_modo) {
|
||||
return $pay_modo === 'points'
|
||||
? max(0, $minor)
|
||||
: \AKSRT\Ledger\AssetAmount::decimal_from_minor(max(0, $minor));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否为 VIP 豁免用户(免扣积分下载)。
|
||||
*
|
||||
@@ -195,18 +219,18 @@ if (!function_exists('aksrt_get_download_box_meta')) {
|
||||
if (!in_array($pay_limit, [0, 1, 2], true)) {
|
||||
$pay_limit = 0;
|
||||
}
|
||||
$over_price = max(0.0, (float) ($pay_meta['download_limit_over_price'] ?? 0));
|
||||
$over_price = $pay_meta['download_limit_over_price'] ?? ($pay_modo === 'points' ? 0 : '0.00');
|
||||
|
||||
return [
|
||||
'version' => (string) ($pay_meta['version'] ?? ''),
|
||||
'size' => (string) ($pay_meta['size'] ?? ''),
|
||||
'price' => (float) ($pay_meta['price'] ?? 0),
|
||||
'price' => (string) ($pay_meta['price'] ?? '0.00'),
|
||||
'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),
|
||||
'original_price' => (string) ($pay_meta['original_price'] ?? '0.00'),
|
||||
'vip1_price' => (string) ($pay_meta['vip1_price'] ?? '0.00'),
|
||||
'vip2_price' => (string) ($pay_meta['vip2_price'] ?? '0.00'),
|
||||
'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),
|
||||
@@ -349,8 +373,8 @@ if (!function_exists('aksrt_content_order_cookie_token_key')) {
|
||||
$post_id = (int) ($order['product_id'] ?? $meta['post_id'] ?? 0);
|
||||
$num = (string) ($order['order_number'] ?? '');
|
||||
$amount = function_exists('aksrt_format_price')
|
||||
? aksrt_format_price((float) ($order['amount'] ?? 0))
|
||||
: (string) round((float) ($order['amount'] ?? 0), 2);
|
||||
? aksrt_format_price((string) ($order['amount'] ?? '0.00'))
|
||||
: (string) ($order['amount'] ?? '0.00');
|
||||
return $id . '_' . $post_id . '_' . trim($num) . '_' . $amount . '_' . trim($ip);
|
||||
}
|
||||
}
|
||||
@@ -484,7 +508,7 @@ if (!function_exists('aksrt_guest_has_paid_access')) {
|
||||
*
|
||||
* @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}
|
||||
* @return array{amount:int|string,base:int|string,vip_amount:int|string|null,modo:string,currency:string,is_free:bool,pay_limit:int,vip_level:int,original:int|string,vip1:int|string,vip2:int|string}
|
||||
*/
|
||||
if (!function_exists('aksrt_get_user_pay_price')) {
|
||||
function aksrt_get_user_pay_price($post = null, int $user_id = 0): array {
|
||||
@@ -512,49 +536,74 @@ if (!function_exists('aksrt_get_user_pay_price')) {
|
||||
}
|
||||
|
||||
if ($pay_modo === 'points') {
|
||||
$base = (float) ($meta['points_price'] ?? 0);
|
||||
$vip1 = (float) ($meta['vip1_points'] ?? 0);
|
||||
$vip2 = (float) ($meta['vip2_points'] ?? 0);
|
||||
$base_minor = max(0, (int) ($meta['points_price'] ?? 0));
|
||||
$vip1_minor = max(0, (int) ($meta['vip1_points'] ?? 0));
|
||||
$vip2_minor = max(0, (int) ($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);
|
||||
$parse_cash = static function ($value): int {
|
||||
if (!is_string($value)) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
return \AKSRT\Ledger\AssetAmount::balance_minor($value);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
$base_minor = $parse_cash($meta['price'] ?? '0');
|
||||
$vip1_minor = $parse_cash($meta['vip1_price'] ?? '0');
|
||||
$vip2_minor = $parse_cash($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;
|
||||
$vip_minor = null;
|
||||
if ($vip_level >= 2 && $vip2_minor > 0) {
|
||||
$vip_minor = $vip2_minor;
|
||||
} elseif ($vip_level >= 1 && $vip1_minor > 0) {
|
||||
$vip_minor = $vip1_minor;
|
||||
}
|
||||
|
||||
$amount = $base;
|
||||
if ($vip_amount >= 0 && ($base <= 0 || $vip_amount < $base)) {
|
||||
$amount = $vip_amount;
|
||||
$amount_minor = $base_minor;
|
||||
if ($vip_minor !== null && ($base_minor <= 0 || $vip_minor < $base_minor)) {
|
||||
$amount_minor = $vip_minor;
|
||||
}
|
||||
|
||||
// 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;
|
||||
if ($amount_minor > 0 && $uid > 0 && function_exists('aksrt_is_download_credit_exempt_user') && aksrt_is_download_credit_exempt_user($uid)) {
|
||||
$amount_minor = 0;
|
||||
}
|
||||
|
||||
$original = (float) ($meta['original_price'] ?? 0);
|
||||
if ($pay_modo === 'points') {
|
||||
$original = max(0, (int) ($meta['original_price'] ?? 0));
|
||||
$amount = $amount_minor;
|
||||
$base = $base_minor;
|
||||
$vip1 = $vip1_minor;
|
||||
$vip2 = $vip2_minor;
|
||||
$vip_amount = $vip_minor;
|
||||
} else {
|
||||
$original_minor = $parse_cash($meta['original_price'] ?? '0');
|
||||
$amount = \AKSRT\Ledger\AssetAmount::decimal_from_minor($amount_minor);
|
||||
$base = \AKSRT\Ledger\AssetAmount::decimal_from_minor($base_minor);
|
||||
$vip1 = \AKSRT\Ledger\AssetAmount::decimal_from_minor($vip1_minor);
|
||||
$vip2 = \AKSRT\Ledger\AssetAmount::decimal_from_minor($vip2_minor);
|
||||
$vip_amount = $vip_minor === null ? null : \AKSRT\Ledger\AssetAmount::decimal_from_minor($vip_minor);
|
||||
$original = \AKSRT\Ledger\AssetAmount::decimal_from_minor($original_minor);
|
||||
}
|
||||
|
||||
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,
|
||||
'amount' => $amount,
|
||||
'base' => $base,
|
||||
'vip_amount' => $vip_amount,
|
||||
'modo' => $pay_modo,
|
||||
'currency' => $currency_label,
|
||||
'is_free' => $amount <= 0,
|
||||
'is_free' => $amount_minor <= 0,
|
||||
'pay_limit' => $pay_limit,
|
||||
'vip_level' => $vip_level,
|
||||
'original' => $original,
|
||||
'vip1' => max(0.0, (float) $vip1),
|
||||
'vip2' => max(0.0, (float) $vip2),
|
||||
'vip1' => $vip1,
|
||||
'vip2' => $vip2,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -585,32 +634,33 @@ if (!function_exists('aksrt_is_content_coupon_allowed')) {
|
||||
* Cash only; mirrors aksrtpay_get_post_rebate_discount.
|
||||
*/
|
||||
if (!function_exists('aksrt_get_post_rebate_discount')) {
|
||||
function aksrt_get_post_rebate_discount($post = null, int $user_id = 0): float {
|
||||
function aksrt_get_post_rebate_discount($post = null, int $user_id = 0): string {
|
||||
$meta = function_exists('aksrt_get_pay_meta') ? aksrt_get_pay_meta($post) : [];
|
||||
$fixed = max(0.0, (float) ($meta['pay_rebate_discount'] ?? 0));
|
||||
if ($fixed <= 0) {
|
||||
return 0.0;
|
||||
$fixed = is_string($meta['pay_rebate_discount'] ?? null) ? (string) $meta['pay_rebate_discount'] : '0.00';
|
||||
$fixed_minor = aksrt_asset_price_minor($fixed, '0');
|
||||
if ($fixed_minor <= 0) {
|
||||
return '0.00';
|
||||
}
|
||||
if (!class_exists('\AKSRT\Settings\Settings') || !method_exists('\AKSRT\Settings\Settings', 'get_payment_affiliate_settings')) {
|
||||
return 0.0;
|
||||
return '0.00';
|
||||
}
|
||||
$aff = \AKSRT\Settings\Settings::get_payment_affiliate_settings();
|
||||
if (empty($aff['enabled'])) {
|
||||
return 0.0;
|
||||
return '0.00';
|
||||
}
|
||||
$uid = $user_id > 0 ? $user_id : (function_exists('get_current_user_id') ? (int) get_current_user_id() : 0);
|
||||
$referrer_id = class_exists('\AKSRT\Payment\ReferralAttribution')
|
||||
? \AKSRT\Payment\ReferralAttribution::get_instance()->resolve($uid)
|
||||
: 0;
|
||||
if ($referrer_id <= 0) {
|
||||
return 0.0;
|
||||
return '0.00';
|
||||
}
|
||||
// Need a positive ratio for referrer (VIP tier of referrer preferred).
|
||||
$ratio = (int) round(\AKSRT\Settings\Settings::affiliate_ratio_for_user($referrer_id));
|
||||
$ratio = (int) \AKSRT\Settings\Settings::affiliate_ratio_for_user($referrer_id);
|
||||
if ($ratio <= 0) {
|
||||
return 0.0;
|
||||
return '0.00';
|
||||
}
|
||||
return round($fixed, 2);
|
||||
return \AKSRT\Ledger\AssetAmount::decimal_from_minor($fixed_minor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,10 +752,10 @@ if (!function_exists('aksrt_is_payshow_purchase_enabled')) {
|
||||
|
||||
$pay_modo = ($meta['pay_modo'] ?? '0') === 'points' ? 'points' : '0';
|
||||
$price = $pay_modo === 'points'
|
||||
? (float) ($meta['points_price'] ?? 0)
|
||||
: (float) ($meta['price'] ?? 0);
|
||||
? (int) ($meta['points_price'] ?? 0)
|
||||
: (string) ($meta['price'] ?? '0.00');
|
||||
|
||||
return $price > 0;
|
||||
return aksrt_asset_price_minor($price, $pay_modo) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,7 +801,9 @@ if (!function_exists('aksrt_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;
|
||||
$pay_modo = ($meta['pay_modo'] ?? '0') === 'points' ? 'points' : '0';
|
||||
$price = $pay_modo === 'points' ? (int) ($meta['points_price'] ?? 0) : (string) ($meta['price'] ?? '0.00');
|
||||
if (aksrt_asset_price_minor($price, $pay_modo) <= 0 && $meta['pay_type'] !== AKSRT_PAY_TYPE_VIP) return true;
|
||||
|
||||
$uid = $user_id > 0 ? $user_id : get_current_user_id();
|
||||
|
||||
@@ -843,7 +895,10 @@ if (!function_exists('aksrt_get_download_cost')) {
|
||||
}
|
||||
|
||||
$meta = aksrt_get_pay_meta($post);
|
||||
return (int) ceil((float) $meta['price']);
|
||||
if (($meta['pay_modo'] ?? '0') !== 'points') {
|
||||
return 0;
|
||||
}
|
||||
return max(0, (int) ($meta['points_price'] ?? 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -918,18 +973,19 @@ if (!function_exists('aksrt_get_pay_price_label')) {
|
||||
'text' => __('会员专属', 'aksrt'),
|
||||
'free' => false,
|
||||
'amount' => 0,
|
||||
'base' => is_array($priced) ? (float) ($priced['base'] ?? 0) : 0,
|
||||
'base' => is_array($priced) ? ($priced['base'] ?? ($pay_modo === 'points' ? 0 : '0.00')) : ($pay_modo === 'points' ? 0 : '0.00'),
|
||||
'modo' => $pay_modo,
|
||||
'pay_limit' => $pay_limit,
|
||||
];
|
||||
}
|
||||
|
||||
$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;
|
||||
? ($priced['amount'] ?? ($pay_modo === 'points' ? 0 : '0.00'))
|
||||
: ($pay_modo === 'points' ? (int) ($meta['points_price'] ?? 0) : (string) ($meta['price'] ?? '0.00'));
|
||||
$base = is_array($priced) ? ($priced['base'] ?? $price) : $price;
|
||||
$price_minor = aksrt_asset_price_minor($price, $pay_modo);
|
||||
|
||||
if ($price <= 0) {
|
||||
if ($price_minor <= 0) {
|
||||
return [
|
||||
'text' => __('免费', 'aksrt'),
|
||||
'free' => true,
|
||||
@@ -963,9 +1019,21 @@ if (!function_exists('aksrt_get_pay_price_label')) {
|
||||
}
|
||||
|
||||
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'), '.');
|
||||
function aksrt_format_price($price): string {
|
||||
if (is_int($price)) {
|
||||
return (string) max(0, $price);
|
||||
}
|
||||
if (!is_string($price)) {
|
||||
return '0';
|
||||
}
|
||||
try {
|
||||
$decimal = \AKSRT\Ledger\AssetAmount::balance($price)->decimal();
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return '0';
|
||||
}
|
||||
return str_ends_with($decimal, '.00')
|
||||
? substr($decimal, 0, -3)
|
||||
: rtrim($decimal, '0');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1132,7 +1200,10 @@ if (!function_exists('aksrt_get_paywall_html')) {
|
||||
$pay_type = $meta['pay_type'];
|
||||
$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);
|
||||
$price = is_array($priced)
|
||||
? ($priced['amount'] ?? ($pay_modo === 'points' ? 0 : '0.00'))
|
||||
: ($pay_modo === 'points' ? (int) ($meta['points_price'] ?? 0) : (string) ($meta['price'] ?? '0.00'));
|
||||
$price_minor = aksrt_asset_price_minor($price, $pay_modo);
|
||||
$vip_level = is_array($priced) ? (int) ($priced['vip_level'] ?? 0) : 0;
|
||||
$currency = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_currency_name() : __('积分', 'aksrt');
|
||||
$cash_symbol = '¥';
|
||||
@@ -1156,8 +1227,11 @@ if (!function_exists('aksrt_get_paywall_html')) {
|
||||
}
|
||||
$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;
|
||||
$original_price = $pay_modo === 'points'
|
||||
? max(0, (int) ($meta['original_price'] ?? 0))
|
||||
: (string) ($meta['original_price'] ?? '0.00');
|
||||
$original_minor = aksrt_asset_price_minor($original_price, $pay_modo);
|
||||
$has_original = $original_minor > 0 && $original_minor > $price_minor;
|
||||
$pay_limit = (int) ($meta['pay_limit'] ?? 0);
|
||||
$member_blocked = $pay_limit > 0 && $vip_level < $pay_limit;
|
||||
$vip_url = function_exists('aksrt_get_user_center_tab_url')
|
||||
|
||||
Reference in new issue
Block a user