140 lines
4.8 KiB
PHP
140 lines
4.8 KiB
PHP
<?php
|
|
/**
|
|
* @package AKSRT
|
|
*/
|
|
|
|
namespace AKSRT\Payment;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
class Order {
|
|
|
|
public const STATUS_PENDING = \AKSRT\Core\DomainModel::ORDER_STATUS_PENDING;
|
|
public const STATUS_PAID = \AKSRT\Core\DomainModel::ORDER_STATUS_PAID;
|
|
public const STATUS_REFUNDING = \AKSRT\Core\DomainModel::ORDER_STATUS_REFUNDING;
|
|
public const STATUS_REFUNDED = \AKSRT\Core\DomainModel::ORDER_STATUS_REFUNDED;
|
|
public const STATUS_CLOSED = \AKSRT\Core\DomainModel::ORDER_STATUS_CLOSED;
|
|
|
|
private static $instance = null;
|
|
|
|
public static function get_instance(): self {
|
|
if (null === self::$instance) {
|
|
self::$instance = new self();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
public static function get_valid_statuses(): array {
|
|
return \AKSRT\Core\DomainModel::order_status_labels();
|
|
}
|
|
|
|
public static function can_transition(string $from, string $to): bool {
|
|
return \AKSRT\Core\DomainModel::can_transition_order_status($from, $to);
|
|
}
|
|
|
|
public function init(): void {
|
|
add_action('wp_ajax_aksrt_order_list', [$this, 'ajax_list']);
|
|
add_action('wp_ajax_aksrt_order_update_status', [$this, 'ajax_update_status']);
|
|
add_action('wp_ajax_aksrt_order_stats', [$this, 'ajax_stats']);
|
|
}
|
|
|
|
public function create(int $user_id, string $product_type, int $product_id, string $amount, string $currency = 'CNY'): string {
|
|
// Guest content orders may use user_id=0 (legacy pay_no_logged_in).
|
|
if ($user_id < 0 || $product_id < 0) {
|
|
return '';
|
|
}
|
|
|
|
return $this->repo()->create([
|
|
'user_id' => $user_id,
|
|
'product_type' => sanitize_key($product_type),
|
|
'product_id' => $product_id,
|
|
'amount' => $amount,
|
|
'currency' => sanitize_key($currency),
|
|
'status' => self::STATUS_PENDING,
|
|
]);
|
|
}
|
|
|
|
public function get(string $order_number): ?array {
|
|
return $this->repo()->get($order_number);
|
|
}
|
|
|
|
public function get_user_orders(int $user_id, array $args = []): array {
|
|
return $this->repo()->get_user_orders($user_id, $args);
|
|
}
|
|
|
|
public function update_status(string $order_number, string $new_status, array $extra = []): bool {
|
|
return $this->repo()->update_status($order_number, $new_status, $extra);
|
|
}
|
|
|
|
public function get_stats(int $user_id = 0): array {
|
|
return $this->repo()->get_stats($user_id);
|
|
}
|
|
|
|
public function has_paid_access(int $user_id, string $product_type, int $product_id): bool {
|
|
return $this->repo()->has_paid_access($user_id, $product_type, $product_id);
|
|
}
|
|
|
|
public function get_valid_vip_order(int $user_id): ?array {
|
|
return $this->repo()->get_valid_vip_order($user_id);
|
|
}
|
|
|
|
public function ajax_list(): void {
|
|
check_ajax_referer('aksrt_public_nonce', 'nonce');
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(['message' => __('权限不足', 'aksrt')]);
|
|
}
|
|
|
|
$status = sanitize_key((string) ($_GET['status'] ?? ''));
|
|
$search = sanitize_text_field((string) ($_GET['search'] ?? ''));
|
|
$limit = max(1, min(100, (int) ($_GET['limit'] ?? 20)));
|
|
$offset = max(0, (int) ($_GET['offset'] ?? 0));
|
|
|
|
$orders = $this->repo()->get_orders_admin([
|
|
'status' => $status,
|
|
'limit' => $limit,
|
|
'offset' => $offset,
|
|
], $search);
|
|
|
|
wp_send_json_success([
|
|
'orders' => $orders,
|
|
'stats' => $this->get_stats(),
|
|
'total' => $this->repo()->get_orders_count(['status' => $status], $search),
|
|
]);
|
|
}
|
|
|
|
public function ajax_update_status(): void {
|
|
check_ajax_referer('aksrt_public_nonce', 'nonce');
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(['message' => __('权限不足', 'aksrt')]);
|
|
}
|
|
|
|
$order_number = sanitize_text_field((string) ($_POST['order_number'] ?? ''));
|
|
$new_status = sanitize_key((string) ($_POST['status'] ?? ''));
|
|
$note = sanitize_textarea_field((string) ($_POST['note'] ?? ''));
|
|
|
|
if ($order_number === '' || $new_status === '') {
|
|
wp_send_json_error(['message' => __('参数无效', 'aksrt')]);
|
|
}
|
|
|
|
if ($this->update_status($order_number, $new_status, ['note' => $note])) {
|
|
wp_send_json_success(['message' => __('订单状态已更新', 'aksrt')]);
|
|
}
|
|
|
|
wp_send_json_error(['message' => __('更新失败', 'aksrt')]);
|
|
}
|
|
|
|
public function ajax_stats(): void {
|
|
check_ajax_referer('aksrt_public_nonce', 'nonce');
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(['message' => __('权限不足', 'aksrt')]);
|
|
}
|
|
|
|
wp_send_json_success($this->get_stats());
|
|
}
|
|
|
|
private function repo(): OrderRepository {
|
|
return OrderRepository::get_instance();
|
|
}
|
|
}
|