register_section_routes('payment', 'payment'); register_rest_route(self::API_NAMESPACE, '/payment/withdrawals', [ 'methods' => 'GET', 'callback' => [$this, 'get_withdrawals'], 'permission_callback' => [$this, 'check_permission'], 'args' => [ 'page' => ['type' => 'integer', 'minimum' => 1, 'default' => 1], 'per_page' => ['type' => 'integer', 'minimum' => 1, 'maximum' => 50, 'default' => 20], 'status' => ['type' => 'string', 'enum' => ['', 'pending', 'processing', 'completed', 'rejected']], ], ]); // Withdrawal status update register_rest_route(self::API_NAMESPACE, '/payment/withdrawals/(?P\d+)', [ 'methods' => 'POST', 'callback' => [$this, 'update_withdrawal_status'], 'permission_callback' => [$this, 'check_permission'], 'args' => [ 'id' => ['type' => 'integer', 'minimum' => 1, 'required' => true], 'status' => ['type' => 'string', 'required' => true, 'enum' => ['processing', 'completed', 'rejected']], 'note' => ['type' => 'string', 'default' => '', 'maxLength' => 1000, 'sanitize_callback' => 'sanitize_textarea_field'], ], ]); } public function get_withdrawals(\WP_REST_Request $request): \WP_REST_Response { if (!class_exists('\AKSRT\Payment\Withdrawal')) { return $this->success(['data' => ['items' => [], 'total' => 0, 'page' => 1, 'total_pages' => 1, 'stats' => []]]); } $status = sanitize_key((string) $request->get_param('status')); $page = max(1, (int) $request->get_param('page')); $per_page = max(1, min(50, (int) $request->get_param('per_page'))) ?: 20; $items = \AKSRT\Payment\Withdrawal::get_instance()->get_all([ 'status' => $status, 'limit' => $per_page, 'offset' => ($page - 1) * $per_page, ]); $total = \AKSRT\Payment\Withdrawal::get_instance()->get_count(['status' => $status]); $stats = \AKSRT\Payment\Withdrawal::get_instance()->get_stats(); return $this->success([ 'data' => [ 'items' => $items, 'total' => $total, 'page' => $page, 'total_pages' => max(1, (int) ceil($total / $per_page)), 'stats' => $stats, ], ]); } /** * POST /payment/withdrawals/{id} — 更新提现状态 */ public function update_withdrawal_status(\WP_REST_Request $request): \WP_REST_Response { if (!class_exists('\AKSRT\Payment\Withdrawal')) { return $this->error('提现模块未初始化', 500); } $id = (int) $request->get_param('id'); $params = $this->get_json_params($request); $new_status = sanitize_key((string) ($params['status'] ?? '')); $note = sanitize_textarea_field((string) ($params['note'] ?? '')); $valid_statuses = ['processing', 'completed', 'rejected']; if (!in_array($new_status, $valid_statuses, true)) { return $this->error('无效的提现状态'); } if ($id <= 0) { return $this->error('无效的提现 ID'); } $operation_key = \AKSRT\Ledger\OperationKey::from_request($request, 'admin-withdraw-transition', get_current_user_id()); if (is_wp_error($operation_key)) { return $this->error($operation_key->get_error_message(), (int) ($operation_key->get_error_data()['status'] ?? 400)); } $result = \AKSRT\Payment\Withdrawal::get_instance()->process_status_change($id, $new_status, $note, $operation_key); if (is_wp_error($result)) { $data = $result->get_error_data(); return $this->error($result->get_error_message(), is_array($data) ? (int) ($data['status'] ?? 400) : 400); } if (is_array($result)) { return $this->success(array_merge(['message' => __('提现状态已更新', 'aksrt')], $result)); } return $this->error(__('更新失败', 'aksrt')); } }