feat(pay): sales volume, paid order meta, pending resume, limit-over buy

Bump content sales on resource order paid; show order number/time in download
box; poll pending gateway payments; support download_limit_over_price overbuy.
This commit is contained in:
2026-07-14 12:04:59 +08:00
parent 770205623d
commit 8f15d16d35
8 changed files with 397 additions and 72 deletions
+4
View File
@@ -21,6 +21,7 @@ class AKSRT_Domain_Model {
public const RESOURCE_MARKER_KEY = '_aksrt_is_resource';
public const RESOURCE_DOWNLOAD_COUNT_KEY = '_aksrt_res_download_count';
public const RESOURCE_VIEW_COUNT_KEY = '_aksrt_res_view_count';
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';
@@ -134,6 +135,8 @@ class AKSRT_Domain_Model {
'purchase_limit' => 0,
'free_preview' => '',
'show_sales' => true,
// Zibll: free daily quota overbuy price (cash or points by pay_modo).
'download_limit_over_price' => 0.0,
];
}
@@ -333,6 +336,7 @@ class AKSRT_Domain_Model {
$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));
return $meta;
}
+52 -1
View File
@@ -150,12 +150,14 @@ if (!function_exists('aksrt_get_download_box_meta')) {
$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);
$virtual_sales = max(0, (int) ($pay_meta['virtual_sales'] ?? 0));
$sales_volume = (int) get_post_meta($p->ID, AKSRT_Domain_Model::RESOURCE_SALES_VOLUME_KEY, true);
$show_sales = !isset($pay_meta['show_sales']) || !empty($pay_meta['show_sales']);
$pay_modo = (($pay_meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
$pay_limit = (int) ($pay_meta['pay_limit'] ?? 0);
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));
return [
'version' => (string) ($pay_meta['version'] ?? ''),
@@ -177,8 +179,11 @@ if (!function_exists('aksrt_get_download_box_meta')) {
'download_count' => max(0, $download_count),
'view_count' => max(0, $view_count),
'virtual_sales' => $virtual_sales,
'sales_count' => $show_sales ? ($virtual_sales + max(0, $download_count)) : 0,
'sales_volume' => max(0, $sales_volume),
// Zibll: virtual (pay_cuont) + real sales_volume; fall back to downloads when no sales yet.
'sales_count' => $show_sales ? ($virtual_sales + max(0, $sales_volume, $download_count)) : 0,
'show_sales' => $show_sales,
'download_limit_over_price' => $over_price,
'require_login' => !empty($pay_meta['require_login']),
'require_captcha' => !empty($pay_meta['require_captcha']),
'subject_label' => __('内容', 'aksrt'),
@@ -186,6 +191,52 @@ if (!function_exists('aksrt_get_download_box_meta')) {
}
}
/**
* Latest paid content order for a user/post (resource product_type).
*
* @return array<string,mixed>|null
*/
if (!function_exists('aksrt_get_user_content_paid_order')) {
function aksrt_get_user_content_paid_order(int $post_id, int $user_id = 0): ?array {
$uid = $user_id > 0 ? $user_id : get_current_user_id();
if ($uid <= 0 || $post_id <= 0 || !class_exists('AKSRT_Order_Repository')) {
return null;
}
$orders = AKSRT_Order_Repository::get_instance()->get_user_orders($uid, [
'product_type' => AKSRT_Domain_Model::ORDER_PRODUCT_RESOURCE,
'status' => '',
'limit' => 20,
'offset' => 0,
]);
foreach ($orders as $order) {
if ((int) ($order['product_id'] ?? 0) !== $post_id) {
continue;
}
$status = (string) ($order['status'] ?? '');
if (AKSRT_Domain_Model::is_paid_order_status($status)) {
return $order;
}
}
return null;
}
}
/**
* Increment real sales volume for a paid content post (idempotent per order via order meta note flag optional).
*/
if (!function_exists('aksrt_bump_content_sales_volume')) {
function aksrt_bump_content_sales_volume(int $post_id, int $delta = 1): int {
if ($post_id <= 0 || $delta === 0) {
return 0;
}
$key = AKSRT_Domain_Model::RESOURCE_SALES_VOLUME_KEY;
$cur = (int) get_post_meta($post_id, $key, true);
$next = max(0, $cur + $delta);
update_post_meta($post_id, $key, $next);
return $next;
}
}
/**
* Resolve the amount a given user should pay for a post (Zibll VIP tier min).
*
+13 -5
View File
@@ -270,14 +270,22 @@ if (!function_exists('aksrt_check_free_download_quota')) {
$used = aksrt_get_user_free_downloaded_number($user_id);
if ($used >= $limit) {
$data = [
'status' => 429,
'limit' => $limit,
'used' => $used,
];
// Optional overbuy price for free-quota exhausted (Zibll download_limit_over_price).
// Callers may pass post context via filter.
$over = apply_filters('aksrt_download_limit_over_price', 0.0, $user_id);
if ($over > 0) {
$data['download_limit_over_price'] = $over;
$data['allow_limit_over'] = true;
}
return new WP_Error(
'aksrt_download_limit',
__('您今日下载免费资源个数已超限,请明日再下载。', 'aksrt'),
[
'status' => 429,
'limit' => $limit,
'used' => $used,
]
$data
);
}