积分与余额账务系统硬切重构
This commit is contained in:
1 parent
ca12226b39
commit
5cae5b5c93
159 files changed
+7275
-4718
No files matched your search
@@ -14,7 +14,7 @@ class DBMigrator {
|
||||
use DBMigratorVip;
|
||||
|
||||
/** Current schema version; changing it re-runs dbDelta. */
|
||||
const SCHEMA_VERSION = '1.24.0';
|
||||
const SCHEMA_VERSION = '2.0.0';
|
||||
|
||||
const OPT_KEY = 'aksrt_db_schema_version';
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ trait DBMigratorIdentity {
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
application_uuid CHAR(36) NOT NULL,
|
||||
client_request_id CHAR(36) NOT NULL,
|
||||
request_payload_hash CHAR(64) NOT NULL,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
type VARCHAR(20) NOT NULL,
|
||||
channel VARCHAR(20) NOT NULL DEFAULT 'cloud',
|
||||
@@ -59,7 +60,7 @@ trait DBMigratorIdentity {
|
||||
KEY idx_status_updated (status, updated_at),
|
||||
KEY idx_id_number_hash (id_number_hash),
|
||||
KEY idx_company_code_hash (company_code_hash)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($application);
|
||||
|
||||
$event = "CREATE TABLE {$prefix}aksrt_identity_event (
|
||||
@@ -81,7 +82,7 @@ trait DBMigratorIdentity {
|
||||
UNIQUE KEY uniq_dedupe_key (dedupe_key),
|
||||
KEY idx_application_created (application_id, created_at),
|
||||
KEY idx_source_external (source, external_event_id)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($event);
|
||||
}
|
||||
}
|
||||
@@ -20,43 +20,55 @@ trait DBMigratorPart2 {
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
$prefix = $wpdb->prefix;
|
||||
|
||||
// ---------- 1. 积分流水 ----------
|
||||
$sql_credit_log = "CREATE TABLE {$prefix}aksrt_credit_log (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
// ---------- 1. 统一资产账户与不可变账本 ----------
|
||||
$sql_asset_account = "CREATE TABLE {$prefix}aksrt_asset_account (
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
delta INT NOT NULL,
|
||||
balance_after INT NOT NULL,
|
||||
reason VARCHAR(64) NOT NULL,
|
||||
remark VARCHAR(255) DEFAULT NULL,
|
||||
ref_type VARCHAR(32) DEFAULT NULL,
|
||||
ref_id BIGINT UNSIGNED DEFAULT NULL,
|
||||
ip VARCHAR(64) DEFAULT NULL,
|
||||
ua VARCHAR(255) DEFAULT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_user_time (user_id, created_at),
|
||||
KEY idx_reason (reason)
|
||||
) {$charset_collate};";
|
||||
dbDelta($sql_credit_log);
|
||||
asset VARCHAR(16) NOT NULL,
|
||||
balance_minor BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
version BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
updated_at DATETIME(6) NOT NULL,
|
||||
PRIMARY KEY (user_id, asset),
|
||||
KEY idx_asset_balance (asset, balance_minor)
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_asset_account);
|
||||
|
||||
// ---------- 1b. 现金余额流水(站内钱包,与积分分离) ----------
|
||||
$sql_balance_log = "CREATE TABLE {$prefix}aksrt_balance_log (
|
||||
$sql_asset_transaction = "CREATE TABLE {$prefix}aksrt_asset_transaction (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
delta DECIMAL(18,2) NOT NULL,
|
||||
balance_after DECIMAL(18,2) NOT NULL,
|
||||
operation_key VARCHAR(191) NOT NULL,
|
||||
payload_hash CHAR(64) NOT NULL,
|
||||
reason VARCHAR(64) NOT NULL,
|
||||
remark VARCHAR(255) DEFAULT NULL,
|
||||
ref_type VARCHAR(32) DEFAULT NULL,
|
||||
ref_id BIGINT UNSIGNED DEFAULT NULL,
|
||||
ref_key VARCHAR(191) DEFAULT NULL,
|
||||
actor_user_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
metadata LONGTEXT DEFAULT NULL,
|
||||
ip VARCHAR(64) DEFAULT NULL,
|
||||
ua VARCHAR(255) DEFAULT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
created_at DATETIME(6) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_user_time (user_id, created_at),
|
||||
KEY idx_reason (reason)
|
||||
) {$charset_collate};";
|
||||
dbDelta($sql_balance_log);
|
||||
UNIQUE KEY uniq_operation_key (operation_key),
|
||||
KEY idx_reason_time (reason, created_at),
|
||||
KEY idx_reference (ref_type, ref_key)
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_asset_transaction);
|
||||
|
||||
$sql_asset_entry = "CREATE TABLE {$prefix}aksrt_asset_entry (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
transaction_id BIGINT UNSIGNED NOT NULL,
|
||||
line_no SMALLINT UNSIGNED NOT NULL,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
asset VARCHAR(16) NOT NULL,
|
||||
entry_type VARCHAR(32) NOT NULL,
|
||||
delta_minor BIGINT NOT NULL,
|
||||
balance_after_minor BIGINT UNSIGNED NOT NULL,
|
||||
counterparty_user_id BIGINT UNSIGNED DEFAULT NULL,
|
||||
remark VARCHAR(255) DEFAULT NULL,
|
||||
created_at DATETIME(6) NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uniq_transaction_line (transaction_id, line_no),
|
||||
KEY idx_user_asset_time (user_id, asset, created_at, id),
|
||||
KEY idx_transaction (transaction_id)
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_asset_entry);
|
||||
|
||||
// ---------- 2. 签到 ----------
|
||||
$sql_signin = "CREATE TABLE {$prefix}aksrt_signin_log (
|
||||
@@ -68,7 +80,7 @@ trait DBMigratorPart2 {
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uniq_user_date (user_id, signin_date),
|
||||
KEY idx_user (user_id)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_signin);
|
||||
|
||||
// ---------- 3. 下载 token ----------
|
||||
@@ -88,7 +100,7 @@ trait DBMigratorPart2 {
|
||||
KEY idx_expires (expires_at),
|
||||
KEY idx_user (user_id),
|
||||
KEY idx_post (post_id)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_dl_token);
|
||||
|
||||
// ---------- 5. 用户通知收件箱 ----------
|
||||
@@ -105,13 +117,14 @@ trait DBMigratorPart2 {
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_user_created (user_id, created_at),
|
||||
KEY idx_user_read (user_id, is_read)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_notification);
|
||||
|
||||
// ---------- 8. 订单表 ----------
|
||||
$sql_order = "CREATE TABLE {$prefix}aksrt_order (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
order_number VARCHAR(32) NOT NULL,
|
||||
request_key VARCHAR(191) DEFAULT NULL,
|
||||
user_id BIGINT UNSIGNED NOT NULL,
|
||||
product_type VARCHAR(32) NOT NULL DEFAULT '',
|
||||
product_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
@@ -131,12 +144,13 @@ trait DBMigratorPart2 {
|
||||
note TEXT DEFAULT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uniq_order_number (order_number),
|
||||
UNIQUE KEY uniq_request_key (request_key),
|
||||
KEY idx_user (user_id),
|
||||
KEY idx_user_status_created (user_id, status, created_at),
|
||||
KEY idx_status (status),
|
||||
KEY idx_created (created_at),
|
||||
KEY idx_product (product_type, product_id)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_order);
|
||||
|
||||
// ---------- 9. 作者收益台账 ----------
|
||||
@@ -168,7 +182,7 @@ trait DBMigratorPart2 {
|
||||
KEY idx_currency (currency),
|
||||
KEY idx_status (status),
|
||||
KEY idx_created (created_at)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_revenue);
|
||||
|
||||
// ---------- 10. 提现台账 ----------
|
||||
@@ -180,15 +194,17 @@ trait DBMigratorPart2 {
|
||||
method VARCHAR(32) NOT NULL DEFAULT '',
|
||||
account_info TEXT DEFAULT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
ledger_transaction_id BIGINT UNSIGNED DEFAULT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
processed_at DATETIME DEFAULT NULL,
|
||||
note TEXT DEFAULT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uniq_ledger_transaction (ledger_transaction_id),
|
||||
KEY idx_user (user_id),
|
||||
KEY idx_user_created (user_id, created_at),
|
||||
KEY idx_status (status),
|
||||
KEY idx_created (created_at)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_withdrawal);
|
||||
|
||||
// ---------- 11. 举报工单 ----------
|
||||
@@ -208,7 +224,7 @@ trait DBMigratorPart2 {
|
||||
KEY idx_target (target_type, target_id),
|
||||
KEY idx_reporter (reporter_id),
|
||||
KEY idx_created (created_at)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_report);
|
||||
|
||||
// ---------- 12. 用户限制/封禁 ----------
|
||||
@@ -227,7 +243,7 @@ trait DBMigratorPart2 {
|
||||
KEY idx_scope (scope),
|
||||
KEY idx_expires (expires_at),
|
||||
KEY idx_created (created_at)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_restriction);
|
||||
|
||||
// ── follow ──
|
||||
@@ -240,7 +256,7 @@ trait DBMigratorPart2 {
|
||||
UNIQUE KEY idx_pair (follower_id, following_id),
|
||||
KEY idx_following (following_id),
|
||||
KEY idx_created (created_at)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_follow);
|
||||
|
||||
// ── coupon ──
|
||||
@@ -262,7 +278,7 @@ trait DBMigratorPart2 {
|
||||
UNIQUE KEY idx_code (code),
|
||||
KEY idx_status (status),
|
||||
KEY idx_expires (expires_at)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_coupon);
|
||||
|
||||
// ── coupon_usage (R68) ──
|
||||
@@ -276,11 +292,11 @@ trait DBMigratorPart2 {
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_coupon (coupon_id),
|
||||
KEY idx_user (user_id),
|
||||
KEY idx_order (order_number)
|
||||
) {$charset_collate};";
|
||||
UNIQUE KEY uniq_coupon_usage_order (order_number)
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_coupon_usage);
|
||||
|
||||
// ── charge_card (legacy-style typed card_pass) ──
|
||||
// ── typed charge cards ──
|
||||
$sql_charge_card = "CREATE TABLE {$prefix}aksrt_charge_card (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
card VARCHAR(60) NOT NULL DEFAULT '',
|
||||
@@ -304,31 +320,9 @@ trait DBMigratorPart2 {
|
||||
KEY idx_used_by (used_by),
|
||||
KEY idx_order_number (order_number),
|
||||
KEY idx_expires (expires_at)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_charge_card);
|
||||
|
||||
// ── rebate_log ──
|
||||
$sql_rebate_log = "CREATE TABLE {$prefix}aksrt_rebate_log (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
user_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
||||
order_number VARCHAR(32) NOT NULL DEFAULT '',
|
||||
source_user_id BIGINT UNSIGNED DEFAULT NULL,
|
||||
amount DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||
type VARCHAR(32) NOT NULL DEFAULT 'order',
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
created_at DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
settled_at DATETIME DEFAULT NULL,
|
||||
note TEXT DEFAULT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_user (user_id),
|
||||
KEY idx_order (order_number),
|
||||
KEY idx_source (source_user_id),
|
||||
KEY idx_status (status),
|
||||
KEY idx_type (type),
|
||||
KEY idx_created (created_at)
|
||||
) {$charset_collate};";
|
||||
dbDelta($sql_rebate_log);
|
||||
|
||||
// ── canonical Ref attribution and permanent user binding ──
|
||||
$sql_affiliate_relation = "CREATE TABLE {$prefix}aksrt_affiliate_relation (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
@@ -349,7 +343,7 @@ trait DBMigratorPart2 {
|
||||
KEY idx_status_touch (status, first_touch_at),
|
||||
KEY idx_reward_status (reward_status),
|
||||
KEY idx_reward_ip (registration_ip, rewarded_at)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_affiliate_relation);
|
||||
|
||||
// ── immutable commission ledger ──
|
||||
@@ -365,17 +359,20 @@ trait DBMigratorPart2 {
|
||||
adjustment_total DECIMAL(18,2) NOT NULL DEFAULT 0,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending',
|
||||
idempotency_key VARCHAR(128) NOT NULL,
|
||||
cancel_operation_key VARCHAR(191) DEFAULT NULL,
|
||||
cancel_payload_hash CHAR(64) DEFAULT NULL,
|
||||
available_at DATETIME NOT NULL,
|
||||
settled_at DATETIME DEFAULT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
note TEXT DEFAULT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uniq_commission_idempotency (idempotency_key),
|
||||
UNIQUE KEY uniq_commission_cancel_operation (cancel_operation_key),
|
||||
KEY idx_promoter_status (promoter_id, status),
|
||||
KEY idx_order_type (order_number, order_type),
|
||||
KEY idx_available (status, available_at),
|
||||
KEY idx_created (created_at)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_commission_ledger);
|
||||
|
||||
// ── immutable commission adjustments (refund/debt/manual) ──
|
||||
@@ -393,7 +390,7 @@ trait DBMigratorPart2 {
|
||||
UNIQUE KEY uniq_adjustment_source (source_key),
|
||||
KEY idx_ledger (ledger_id),
|
||||
KEY idx_promoter (promoter_id)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_commission_adjustment);
|
||||
|
||||
// ── payout account snapshots ──
|
||||
@@ -409,7 +406,7 @@ trait DBMigratorPart2 {
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uniq_user_channel (user_id, channel),
|
||||
KEY idx_user_status (user_id, status)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_payout_account);
|
||||
|
||||
// ── order_items (§6.5 多商品多商家) ──
|
||||
@@ -434,7 +431,7 @@ trait DBMigratorPart2 {
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_order (order_number),
|
||||
KEY idx_product (product_id)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($sql_order_items);
|
||||
|
||||
self::migrate_identity_tables($prefix, $charset_collate);
|
||||
|
||||
@@ -16,8 +16,9 @@ trait DBMigratorPart3 {
|
||||
public static function table(string $name): string {
|
||||
global $wpdb;
|
||||
$allowed = [
|
||||
'credit_log' => 'aksrt_credit_log',
|
||||
'balance_log' => 'aksrt_balance_log',
|
||||
'asset_account' => 'aksrt_asset_account',
|
||||
'asset_transaction' => 'aksrt_asset_transaction',
|
||||
'asset_entry' => 'aksrt_asset_entry',
|
||||
'signin_log' => 'aksrt_signin_log',
|
||||
'dl_token' => 'aksrt_dl_token',
|
||||
'notification' => 'aksrt_notification',
|
||||
@@ -29,7 +30,6 @@ trait DBMigratorPart3 {
|
||||
'follow' => 'aksrt_follow',
|
||||
'coupon' => 'aksrt_coupon',
|
||||
'charge_card' => 'aksrt_charge_card',
|
||||
'rebate_log' => 'aksrt_rebate_log',
|
||||
'affiliate_relation' => 'aksrt_affiliate_relation',
|
||||
'commission_ledger' => 'aksrt_commission_ledger',
|
||||
'commission_adjustment' => 'aksrt_commission_adjustment',
|
||||
|
||||
@@ -36,7 +36,7 @@ trait DBMigratorVip {
|
||||
KEY idx_batch (batch_uuid),
|
||||
KEY idx_status_created (status, created_at),
|
||||
KEY idx_operation_created (operation, created_at)
|
||||
) {$charset_collate};";
|
||||
) ENGINE=InnoDB {$charset_collate};";
|
||||
dbDelta($event);
|
||||
}
|
||||
}
|
||||
+44
-16
@@ -22,7 +22,6 @@ class DomainModel {
|
||||
public const RESOURCE_SALES_VOLUME_KEY = '_aksrt_sales_volume';
|
||||
public const POST_VIEW_COUNT_KEY = 'aksrt_post_views';
|
||||
|
||||
public const ORDER_MIGRATED_OPTION = 'aksrt_order_migrated_to_table';
|
||||
public const RESOURCE_PAY_META_MIGRATED = 'aksrt_resource_pay_meta_migrated';
|
||||
|
||||
public const ORDER_PRODUCT_RESOURCE = 'resource';
|
||||
@@ -116,11 +115,11 @@ class DomainModel {
|
||||
return [
|
||||
'pay_type' => self::PAY_TYPE_NO,
|
||||
'pay_modo' => '0', // '0' cash | 'points' credits (legacy)
|
||||
'price' => 0.0,
|
||||
'price' => '0.00',
|
||||
'points_price' => 0,
|
||||
'original_price' => 0.0,
|
||||
'vip1_price' => 0.0,
|
||||
'vip2_price' => 0.0,
|
||||
'original_price' => '0.00',
|
||||
'vip1_price' => '0.00',
|
||||
'vip2_price' => '0.00',
|
||||
'vip1_points' => 0,
|
||||
'vip2_points' => 0,
|
||||
'pay_limit' => 0, // 0 all | 1 VIP1+ | 2 VIP2 only (legacy)
|
||||
@@ -143,11 +142,11 @@ class DomainModel {
|
||||
'free_preview' => '',
|
||||
'show_sales' => true,
|
||||
// legacy: free daily quota overbuy price (cash or points by pay_modo).
|
||||
'download_limit_over_price' => 0.0,
|
||||
'download_limit_over_price' => '0.00',
|
||||
// Content cashier: coupon + buyer-facing 推广折扣 (legacy posts_aksrtpay).
|
||||
'coupon_s' => false,
|
||||
'coupon_desc' => '',
|
||||
'pay_rebate_discount' => 0.0,
|
||||
'pay_rebate_discount' => '0.00',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -319,13 +318,13 @@ class DomainModel {
|
||||
$meta['pay_type'] = self::normalize_pay_type((string) ($raw['pay_type'] ?? $meta['pay_type']));
|
||||
$pay_modo = sanitize_key((string) ($raw['pay_modo'] ?? '0'));
|
||||
$meta['pay_modo'] = $pay_modo === 'points' ? 'points' : '0';
|
||||
$meta['price'] = max(0, (float) ($raw['price'] ?? 0));
|
||||
$meta['points_price'] = max(0, (int) ($raw['points_price'] ?? $raw['price'] ?? 0));
|
||||
$meta['original_price'] = max(0, (float) ($raw['original_price'] ?? 0));
|
||||
$meta['vip1_price'] = max(0, (float) ($raw['vip1_price'] ?? 0));
|
||||
$meta['vip2_price'] = max(0, (float) ($raw['vip2_price'] ?? 0));
|
||||
$meta['vip1_points'] = max(0, (int) ($raw['vip1_points'] ?? $raw['vip1_price'] ?? 0));
|
||||
$meta['vip2_points'] = max(0, (int) ($raw['vip2_points'] ?? $raw['vip2_price'] ?? 0));
|
||||
$meta['price'] = self::sanitize_balance_decimal($raw['price'] ?? '0');
|
||||
$meta['points_price'] = self::sanitize_points($raw['points_price'] ?? 0);
|
||||
$meta['original_price'] = self::sanitize_balance_decimal($raw['original_price'] ?? '0');
|
||||
$meta['vip1_price'] = self::sanitize_balance_decimal($raw['vip1_price'] ?? '0');
|
||||
$meta['vip2_price'] = self::sanitize_balance_decimal($raw['vip2_price'] ?? '0');
|
||||
$meta['vip1_points'] = self::sanitize_points($raw['vip1_points'] ?? 0);
|
||||
$meta['vip2_points'] = self::sanitize_points($raw['vip2_points'] ?? 0);
|
||||
$pay_limit = (int) ($raw['pay_limit'] ?? 0);
|
||||
$meta['pay_limit'] = in_array($pay_limit, [0, 1, 2], true) ? $pay_limit : 0;
|
||||
$meta['version'] = sanitize_text_field((string) ($raw['version'] ?? ''));
|
||||
@@ -347,14 +346,43 @@ class DomainModel {
|
||||
$meta['purchase_limit'] = max(0, (int) ($raw['purchase_limit'] ?? 0));
|
||||
$meta['free_preview'] = wp_kses_post((string) ($raw['free_preview'] ?? ''));
|
||||
$meta['show_sales'] = !isset($raw['show_sales']) || !empty($raw['show_sales']);
|
||||
$meta['download_limit_over_price'] = max(0, (float) ($raw['download_limit_over_price'] ?? 0));
|
||||
$meta['download_limit_over_price'] = $meta['pay_modo'] === 'points'
|
||||
? self::sanitize_points($raw['download_limit_over_price'] ?? 0)
|
||||
: self::sanitize_balance_decimal($raw['download_limit_over_price'] ?? '0');
|
||||
$meta['coupon_s'] = !empty($raw['coupon_s']);
|
||||
$meta['coupon_desc'] = sanitize_textarea_field((string) ($raw['coupon_desc'] ?? ''));
|
||||
$meta['pay_rebate_discount'] = max(0, (float) ($raw['pay_rebate_discount'] ?? 0));
|
||||
$meta['pay_rebate_discount'] = self::sanitize_balance_decimal($raw['pay_rebate_discount'] ?? '0');
|
||||
|
||||
return $meta;
|
||||
}
|
||||
|
||||
private static function sanitize_balance_decimal($value): string {
|
||||
if (!is_string($value)) {
|
||||
return '0.00';
|
||||
}
|
||||
try {
|
||||
return \AKSRT\Ledger\AssetAmount::balance($value)->decimal();
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return '0.00';
|
||||
}
|
||||
}
|
||||
|
||||
private static function sanitize_points($value): int {
|
||||
if (is_int($value)) {
|
||||
return max(0, $value);
|
||||
}
|
||||
if (!is_string($value) || !preg_match('/^(0|[1-9]\d*)$/', trim($value))) {
|
||||
return 0;
|
||||
}
|
||||
$value = trim($value);
|
||||
if (strlen($value) > strlen((string) PHP_INT_MAX)
|
||||
|| (strlen($value) === strlen((string) PHP_INT_MAX) && strcmp($value, (string) PHP_INT_MAX) > 0)
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
|
||||
+78
-33
@@ -67,16 +67,16 @@ trait FrontSubmitPay {
|
||||
$meta['pay_type'] = $pay_type;
|
||||
$meta['pay_modo'] = $pay_modo;
|
||||
|
||||
$min = (float) ($settings['pay_price_min'] ?? 0);
|
||||
$max = (float) ($settings['pay_price_max'] ?? 0);
|
||||
$allow_free = !empty($settings['pay_free_s']);
|
||||
$vip_manual = !empty($settings['pay_vip_price_s']);
|
||||
$vip1_disc = (int) ($settings['pay_vip_1_discount'] ?? 100);
|
||||
$vip2_disc = (int) ($settings['pay_vip_2_discount'] ?? 100);
|
||||
|
||||
if ($pay_modo === 'points') {
|
||||
$points = isset($raw['points_price']) ? (int) $raw['points_price'] : (int) ($data['points_price'] ?? 0);
|
||||
if ($points < 0) {
|
||||
$points = $this->parse_front_points($raw['points_price'] ?? $data['points_price'] ?? null);
|
||||
$min = $this->parse_front_points_limit($settings['pay_price_min'] ?? '0.00');
|
||||
$max = $this->parse_front_points_limit($settings['pay_price_max'] ?? '0.00');
|
||||
if ($points === null) {
|
||||
return ['success' => false, 'message' => __('请设置正确的积分价格', 'aksrt')];
|
||||
}
|
||||
if (!$allow_free && $points <= 0) {
|
||||
@@ -90,59 +90,64 @@ trait FrontSubmitPay {
|
||||
}
|
||||
|
||||
if ($vip_manual) {
|
||||
$vip1 = isset($raw['vip1_points']) ? (int) $raw['vip1_points'] : (int) ($raw['vip_1_points'] ?? 0);
|
||||
$vip2 = isset($raw['vip2_points']) ? (int) $raw['vip2_points'] : (int) ($raw['vip_2_points'] ?? 0);
|
||||
$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) {
|
||||
return ['success' => false, 'message' => __('请设置正确的会员积分价格', 'aksrt')];
|
||||
}
|
||||
} else {
|
||||
$vip1 = (int) floor($points * $vip1_disc / 100);
|
||||
$vip2 = (int) floor($points * $vip2_disc / 100);
|
||||
$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));
|
||||
|
||||
$meta['points_price'] = $points;
|
||||
$meta['price'] = 0.0;
|
||||
$meta['price'] = '0.00';
|
||||
$meta['vip1_points'] = $vip1;
|
||||
$meta['vip2_points'] = $vip2;
|
||||
$meta['vip1_price'] = 0.0;
|
||||
$meta['vip2_price'] = 0.0;
|
||||
$meta['vip1_price'] = '0.00';
|
||||
$meta['vip2_price'] = '0.00';
|
||||
} else {
|
||||
$price = isset($raw['price']) ? (float) $raw['price'] : (float) ($raw['pay_price'] ?? $data['pay_price'] ?? 0);
|
||||
$price = round($price, 2);
|
||||
if ($price < 0) {
|
||||
$price_minor = $this->parse_front_cash_minor($raw['price'] ?? $raw['pay_price'] ?? $data['pay_price'] ?? null);
|
||||
$min_minor = $this->parse_front_cash_minor($settings['pay_price_min'] ?? '0') ?? 0;
|
||||
$max_minor = $this->parse_front_cash_minor($settings['pay_price_max'] ?? '0') ?? 0;
|
||||
if ($price_minor === null) {
|
||||
return ['success' => false, 'message' => __('请设置正确的价格', 'aksrt')];
|
||||
}
|
||||
if (!$allow_free && $price <= 0) {
|
||||
if (!$allow_free && $price_minor <= 0) {
|
||||
return ['success' => false, 'message' => __('请设置付费内容的价格', 'aksrt')];
|
||||
}
|
||||
if ($min > 0 && $price < $min) {
|
||||
return ['success' => false, 'message' => sprintf(__('价格不能低于:%s', 'aksrt'), (string) $min)];
|
||||
if ($min_minor > 0 && $price_minor < $min_minor) {
|
||||
return ['success' => false, 'message' => sprintf(__('价格不能低于:%s', 'aksrt'), \AKSRT\Ledger\AssetAmount::decimal_from_minor($min_minor))];
|
||||
}
|
||||
if ($max > 0 && $price > $max) {
|
||||
return ['success' => false, 'message' => sprintf(__('价格不能高于:%s', 'aksrt'), (string) $max)];
|
||||
if ($max_minor > 0 && $price_minor > $max_minor) {
|
||||
return ['success' => false, 'message' => sprintf(__('价格不能高于:%s', 'aksrt'), \AKSRT\Ledger\AssetAmount::decimal_from_minor($max_minor))];
|
||||
}
|
||||
|
||||
if ($vip_manual) {
|
||||
$vip1 = isset($raw['vip1_price']) ? (float) $raw['vip1_price'] : (float) ($raw['vip_1_price'] ?? 0);
|
||||
$vip2 = isset($raw['vip2_price']) ? (float) $raw['vip2_price'] : (float) ($raw['vip_2_price'] ?? 0);
|
||||
$vip1 = round($vip1, 2);
|
||||
$vip2 = round($vip2, 2);
|
||||
if ($vip1 > $price) {
|
||||
$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) {
|
||||
return ['success' => false, 'message' => __('请设置正确的会员价格', 'aksrt')];
|
||||
}
|
||||
if ($vip1_minor > $price_minor) {
|
||||
return ['success' => false, 'message' => __('会员价不能高于普通价', 'aksrt')];
|
||||
}
|
||||
if ($vip2 > $vip1) {
|
||||
if ($vip2_minor > $vip1_minor) {
|
||||
return ['success' => false, 'message' => __('更高等级会员价不能高于较低等级会员价', 'aksrt')];
|
||||
}
|
||||
} else {
|
||||
$vip1 = round($price * $vip1_disc / 100, 2);
|
||||
$vip2 = round($price * $vip2_disc / 100, 2);
|
||||
$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 = max(0, min($price, $vip1));
|
||||
$vip2 = max(0, min($vip1, $vip2));
|
||||
$vip1_minor = max(0, min($price_minor, $vip1_minor));
|
||||
$vip2_minor = max(0, min($vip1_minor, $vip2_minor));
|
||||
|
||||
$meta['price'] = $price;
|
||||
$meta['price'] = \AKSRT\Ledger\AssetAmount::decimal_from_minor($price_minor);
|
||||
$meta['points_price'] = 0;
|
||||
$meta['vip1_price'] = $vip1;
|
||||
$meta['vip2_price'] = $vip2;
|
||||
$meta['vip1_price'] = \AKSRT\Ledger\AssetAmount::decimal_from_minor($vip1_minor);
|
||||
$meta['vip2_price'] = \AKSRT\Ledger\AssetAmount::decimal_from_minor($vip2_minor);
|
||||
$meta['vip1_points'] = 0;
|
||||
$meta['vip2_points'] = 0;
|
||||
}
|
||||
@@ -159,6 +164,40 @@ trait FrontSubmitPay {
|
||||
return ['success' => true];
|
||||
}
|
||||
|
||||
private function parse_front_points($value): ?int {
|
||||
if (is_int($value)) {
|
||||
return $value >= 0 ? $value : null;
|
||||
}
|
||||
if (!is_string($value) || !preg_match('/^(0|[1-9]\d*)$/', trim($value))) {
|
||||
return null;
|
||||
}
|
||||
$value = trim($value);
|
||||
if (strlen($value) > strlen((string) PHP_INT_MAX)
|
||||
|| (strlen($value) === strlen((string) PHP_INT_MAX) && strcmp($value, (string) PHP_INT_MAX) > 0)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
private function parse_front_cash_minor($value): ?int {
|
||||
if (!is_string($value)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return \AKSRT\Ledger\AssetAmount::balance_minor($value);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function parse_front_points_limit($value): int {
|
||||
if (!is_string($value) || !preg_match('/^(0|[1-9]\d*)(?:\.00)?$/', trim($value), $matches)) {
|
||||
return 0;
|
||||
}
|
||||
return $this->parse_front_points((string) $matches[1]) ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $raw
|
||||
* @return array<int, array<string, string>>
|
||||
@@ -210,7 +249,13 @@ trait FrontSubmitPay {
|
||||
$meta = DomainModel::sanitize_pay_meta($meta);
|
||||
update_post_meta($post_id, DomainModel::PAY_META_KEY, $meta);
|
||||
update_post_meta($post_id, DomainModel::PAY_TYPE_KEY, (string) ($meta['pay_type'] ?? DomainModel::PAY_TYPE_NO));
|
||||
update_post_meta($post_id, DomainModel::PAY_PRICE_KEY, (float) ($meta['price'] ?? 0));
|
||||
update_post_meta(
|
||||
$post_id,
|
||||
DomainModel::PAY_PRICE_KEY,
|
||||
($meta['pay_modo'] ?? '0') === 'points'
|
||||
? (int) ($meta['points_price'] ?? 0)
|
||||
: (string) ($meta['price'] ?? '0.00')
|
||||
);
|
||||
update_post_meta(
|
||||
$post_id,
|
||||
DomainModel::RESOURCE_MARKER_KEY,
|
||||
|
||||
+23
-10
@@ -473,13 +473,13 @@ class PostMetaBox {
|
||||
$type_label = $labels[$pay_type] ?? $pay_type;
|
||||
$modo = (($pay['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
|
||||
if ($modo === 'points') {
|
||||
$price_text = sprintf(__('%d 积分', 'aksrt'), (int) ceil((float) ($pay['points_price'] ?? $pay['price'] ?? 0)));
|
||||
$price_text = sprintf(__('%d 积分', 'aksrt'), max(0, (int) ($pay['points_price'] ?? 0)));
|
||||
} else {
|
||||
$price_text = '¥' . number_format((float) ($pay['price'] ?? 0), 2);
|
||||
$price_text = '¥' . (string) ($pay['price'] ?? '0.00');
|
||||
}
|
||||
$meta_sales = (int) get_post_meta($post_id, DomainModel::RESOURCE_SALES_VOLUME_KEY, true);
|
||||
$db_sales = 0;
|
||||
$revenue = 0.0;
|
||||
$revenue = '0.00';
|
||||
if (class_exists('\AKSRT\Payment\OrderRepository')) {
|
||||
$map = \AKSRT\Payment\OrderRepository::get_instance()->get_content_sales_map(
|
||||
[$post_id],
|
||||
@@ -487,7 +487,7 @@ class PostMetaBox {
|
||||
);
|
||||
if (isset($map[$post_id])) {
|
||||
$db_sales = (int) ($map[$post_id]['sales_count'] ?? 0);
|
||||
$revenue = (float) ($map[$post_id]['revenue'] ?? 0);
|
||||
$revenue = (string) ($map[$post_id]['revenue'] ?? '0.00');
|
||||
}
|
||||
}
|
||||
$orders_url = admin_url('admin.php?page=aksrt_orders&product_type=resource&product_id=' . $post_id);
|
||||
@@ -502,7 +502,7 @@ class PostMetaBox {
|
||||
'<br><a href="%s" title="%s">%s</a>',
|
||||
esc_url($orders_url),
|
||||
esc_attr__('查看销售明细', 'aksrt'),
|
||||
esc_html(sprintf(__('真实销量 %d · ¥%s', 'aksrt'), $db_sales, number_format($revenue, 2)))
|
||||
esc_html(sprintf(__('真实销量 %d · ¥%s', 'aksrt'), $db_sales, $revenue))
|
||||
);
|
||||
} else {
|
||||
echo '<br><span class="description">' . esc_html__('暂无订单', 'aksrt') . '</span>';
|
||||
@@ -682,11 +682,18 @@ class PostMetaBox {
|
||||
$modo = sanitize_key($modo_raw);
|
||||
$meta['pay_modo'] = ($modo === 'points') ? 'points' : '0';
|
||||
}
|
||||
if ($price_raw !== '' && is_numeric($price_raw)) {
|
||||
$meta['price'] = max(0, (float) $price_raw);
|
||||
if ($price_raw !== '') {
|
||||
try {
|
||||
$meta['price'] = \AKSRT\Ledger\AssetAmount::balance($price_raw)->decimal();
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ($points_raw !== '' && is_numeric($points_raw)) {
|
||||
$meta['points_price'] = max(0, (int) $points_raw);
|
||||
if ($points_raw !== '') {
|
||||
if (!preg_match('/^(0|[1-9]\d*)$/', $points_raw)) {
|
||||
return;
|
||||
}
|
||||
$meta['points_price'] = (int) $points_raw;
|
||||
}
|
||||
if ($virtual_raw !== '' && is_numeric($virtual_raw)) {
|
||||
$meta['virtual_sales'] = max(0, (int) $virtual_raw);
|
||||
@@ -695,7 +702,13 @@ class PostMetaBox {
|
||||
$meta = DomainModel::sanitize_pay_meta($meta);
|
||||
update_post_meta($post_id, DomainModel::PAY_META_KEY, $meta);
|
||||
update_post_meta($post_id, DomainModel::PAY_TYPE_KEY, (string) ($meta['pay_type'] ?? DomainModel::PAY_TYPE_NO));
|
||||
update_post_meta($post_id, DomainModel::PAY_PRICE_KEY, (float) ($meta['price'] ?? 0));
|
||||
update_post_meta(
|
||||
$post_id,
|
||||
DomainModel::PAY_PRICE_KEY,
|
||||
($meta['pay_modo'] ?? '0') === 'points'
|
||||
? (int) ($meta['points_price'] ?? 0)
|
||||
: (string) ($meta['price'] ?? '0.00')
|
||||
);
|
||||
if (class_exists('AKSRT\\Core\\DomainModel') && method_exists('AKSRT\\Core\\DomainModel', 'is_resource_pay_type')) {
|
||||
update_post_meta(
|
||||
$post_id,
|
||||
|
||||
@@ -456,18 +456,11 @@ class ResourceMetaBox {
|
||||
if ($pay_modo !== 'points') {
|
||||
$pay_modo = '0';
|
||||
}
|
||||
$price = max(0, (float) ($_POST['aksrt_pay_price'] ?? 0));
|
||||
$price = trim((string) wp_unslash($_POST['aksrt_pay_price'] ?? '0'));
|
||||
$points_price = max(0, (int) ($_POST['aksrt_pay_points_price'] ?? 0));
|
||||
// Keep legacy single-price editors usable: if points field empty and modo points, mirror price.
|
||||
if ($pay_modo === 'points' && $points_price <= 0 && $price > 0) {
|
||||
$points_price = (int) ceil($price);
|
||||
}
|
||||
if ($pay_modo !== 'points' && $price <= 0 && $points_price > 0) {
|
||||
$price = (float) $points_price;
|
||||
}
|
||||
$original_price = max(0, (float) ($_POST['aksrt_pay_original_price'] ?? 0));
|
||||
$vip1_price = max(0, (float) ($_POST['aksrt_pay_vip1_price'] ?? 0));
|
||||
$vip2_price = max(0, (float) ($_POST['aksrt_pay_vip2_price'] ?? 0));
|
||||
$original_price = trim((string) wp_unslash($_POST['aksrt_pay_original_price'] ?? '0'));
|
||||
$vip1_price = trim((string) wp_unslash($_POST['aksrt_pay_vip1_price'] ?? '0'));
|
||||
$vip2_price = trim((string) wp_unslash($_POST['aksrt_pay_vip2_price'] ?? '0'));
|
||||
$vip1_points = max(0, (int) ($_POST['aksrt_pay_vip1_points'] ?? 0));
|
||||
$vip2_points = max(0, (int) ($_POST['aksrt_pay_vip2_points'] ?? 0));
|
||||
$pay_limit = (int) ($_POST['aksrt_pay_limit'] ?? 0);
|
||||
@@ -527,10 +520,10 @@ class ResourceMetaBox {
|
||||
'card_keys' => isset($_POST['aksrt_pay_card_keys']) ? array_filter(array_map('trim', explode("\n", (string) $_POST['aksrt_pay_card_keys']))) : [],
|
||||
'free_preview' => $_POST['aksrt_pay_free_preview'] ?? '',
|
||||
'show_sales' => !empty($_POST['aksrt_pay_show_sales']),
|
||||
'download_limit_over_price' => max(0, (float) ($_POST['aksrt_pay_limit_over_price'] ?? 0)),
|
||||
'download_limit_over_price' => trim((string) wp_unslash($_POST['aksrt_pay_limit_over_price'] ?? '0')),
|
||||
'coupon_s' => !empty($_POST['aksrt_pay_coupon_s']),
|
||||
'coupon_desc' => (string) ($_POST['aksrt_pay_coupon_desc'] ?? ''),
|
||||
'pay_rebate_discount' => max(0, (float) ($_POST['aksrt_pay_rebate_discount'] ?? 0)),
|
||||
'pay_rebate_discount' => trim((string) wp_unslash($_POST['aksrt_pay_rebate_discount'] ?? '0')),
|
||||
]);
|
||||
|
||||
update_post_meta($post_id, DomainModel::PAY_META_KEY, $pay_meta);
|
||||
@@ -538,8 +531,8 @@ class ResourceMetaBox {
|
||||
// 同步标量字段用于查询(模仿 legacy 的 aksrtpay_type 同步)
|
||||
update_post_meta($post_id, DomainModel::PAY_TYPE_KEY, (string) $pay_meta['pay_type']);
|
||||
$query_price = ($pay_meta['pay_modo'] === 'points')
|
||||
? (float) $pay_meta['points_price']
|
||||
: (float) $pay_meta['price'];
|
||||
? (int) $pay_meta['points_price']
|
||||
: (string) $pay_meta['price'];
|
||||
update_post_meta($post_id, DomainModel::PAY_PRICE_KEY, $query_price);
|
||||
update_post_meta($post_id, '_aksrt_pay_modo', (string) $pay_meta['pay_modo']);
|
||||
update_post_meta($post_id, '_aksrt_pay_limit', (int) $pay_meta['pay_limit']);
|
||||
|
||||
@@ -143,8 +143,7 @@ trait ScriptsPart1b {
|
||||
&& class_exists('\AKSRT\Settings\Settings')
|
||||
&& \AKSRT\Settings\Settings::credits_enabled();
|
||||
$balance_on = is_user_logged_in()
|
||||
&& class_exists('\AKSRT\Credits\Balance')
|
||||
&& \AKSRT\Credits\Balance::enabled();
|
||||
&& !empty(\AKSRT\Settings\Settings::get_payment_recharge_settings()['enabled']);
|
||||
$affiliate_on = is_user_logged_in()
|
||||
&& class_exists('\\AKSRT\\Settings\\Settings')
|
||||
&& !empty(\AKSRT\Settings\Settings::get_affiliate_settings()['enabled']);
|
||||
@@ -656,7 +655,7 @@ trait ScriptsPart1b {
|
||||
wp_enqueue_script(
|
||||
'aksrt-cms-download',
|
||||
$base_uri . '/assets/js/cms-download.js',
|
||||
['loader_js', 'aksrt-runtime'],
|
||||
['loader_js', 'aksrt-runtime', 'aksrt-core-request'],
|
||||
file_exists($cms_download_js_path) ? (string) filemtime($cms_download_js_path) : $version,
|
||||
true
|
||||
);
|
||||
@@ -709,7 +708,7 @@ trait ScriptsPart1b {
|
||||
wp_enqueue_script(
|
||||
'aksrt-credits',
|
||||
$base_uri . '/assets/js/credits.js',
|
||||
['loader_js', 'aksrt-lazy-image-attr', 'aksrt-core-modal-runtime', 'aksrt-vip-coordinator', 'aksrt-notyf'],
|
||||
['loader_js', 'aksrt-lazy-image-attr', 'aksrt-core-request', 'aksrt-core-modal-runtime', 'aksrt-vip-coordinator', 'aksrt-notyf'],
|
||||
file_exists($credits_js_path) ? (string) filemtime($credits_js_path) : $version,
|
||||
true
|
||||
);
|
||||
|
||||
@@ -334,7 +334,7 @@ trait ScriptsPart1c {
|
||||
wp_enqueue_script(
|
||||
'aksrt-reward',
|
||||
$base_uri . '/assets/js/reward.js',
|
||||
['loader_js'],
|
||||
['loader_js', 'aksrt-core-request'],
|
||||
(string) filemtime($reward_js),
|
||||
true
|
||||
);
|
||||
|
||||
+18
-8
@@ -161,11 +161,11 @@ class Setup {
|
||||
'enum' => array_keys(DomainModel::pay_type_labels()),
|
||||
],
|
||||
'pay_modo' => ['type' => 'string', 'enum' => ['0', 'points']],
|
||||
'price' => ['type' => 'number'],
|
||||
'price' => ['type' => 'string', 'pattern' => '^(0|[1-9]\\d*)(?:\\.\\d{1,2})?$'],
|
||||
'points_price' => ['type' => 'integer'],
|
||||
'original_price' => ['type' => 'number'],
|
||||
'vip1_price' => ['type' => 'number'],
|
||||
'vip2_price' => ['type' => 'number'],
|
||||
'original_price' => ['type' => 'string', 'pattern' => '^(0|[1-9]\\d*)(?:\\.\\d{1,2})?$'],
|
||||
'vip1_price' => ['type' => 'string', 'pattern' => '^(0|[1-9]\\d*)(?:\\.\\d{1,2})?$'],
|
||||
'vip2_price' => ['type' => 'string', 'pattern' => '^(0|[1-9]\\d*)(?:\\.\\d{1,2})?$'],
|
||||
'vip1_points' => ['type' => 'integer'],
|
||||
'vip2_points' => ['type' => 'integer'],
|
||||
'pay_limit' => ['type' => 'integer', 'enum' => [0, 1, 2]],
|
||||
@@ -221,13 +221,23 @@ class Setup {
|
||||
]);
|
||||
|
||||
register_post_meta('post', DomainModel::PAY_PRICE_KEY, [
|
||||
'type' => 'number',
|
||||
'type' => 'string',
|
||||
'description' => 'Query-friendly paid content price.',
|
||||
'single' => true,
|
||||
'default' => 0,
|
||||
'default' => '0.00',
|
||||
'show_in_rest' => true,
|
||||
'sanitize_callback' => static function ($value) {
|
||||
return max(0, (float) $value);
|
||||
'sanitize_callback' => static function ($value): string {
|
||||
if (is_int($value)) {
|
||||
return (string) max(0, $value);
|
||||
}
|
||||
if (!is_string($value)) {
|
||||
return '0.00';
|
||||
}
|
||||
try {
|
||||
return \AKSRT\Ledger\AssetAmount::balance($value)->decimal();
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return '0.00';
|
||||
}
|
||||
},
|
||||
'auth_callback' => $post_edit_auth,
|
||||
]);
|
||||
|
||||
Reference in new issue
Block a user