Files
wordpress-theme-aksrt/inc/classes/admin/class-aksrt-admin-user-controller-verify-integrations.php
T

380 lines
14 KiB
PHP

<?php
/**
* AKSRT admin verify and messaging integrations support.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
trait AKSRT_Admin_User_Controller_Verify_Integrations {
public function get_verify_pending(): WP_REST_Response {
$response = $this->get_verify_requests(new WP_REST_Request('GET', '/'));
$data = $response->get_data();
$items = isset($data['data']['items']) && is_array($data['data']['items']) ? $data['data']['items'] : [];
$pending = array_values(array_filter($items, static function ($item) {
return ($item['status'] ?? '') === 'pending';
}));
return $this->success([
'data' => [
'requests' => array_slice($pending, 0, 50),
'total' => count($pending),
],
]);
}
public function get_verify_requests(WP_REST_Request $request): WP_REST_Response {
global $wpdb;
$page = max(1, (int) ($request->get_param('page') ?: 1));
$per_page = max(1, min(100, (int) ($request->get_param('per_page') ?: 20)));
$keyword = trim(sanitize_text_field((string) $request->get_param('keyword')));
$status = sanitize_key((string) $request->get_param('status'));
$date_from = sanitize_text_field((string) $request->get_param('date_from'));
$date_to = sanitize_text_field((string) $request->get_param('date_to'));
$sql = "
SELECT u.ID, u.display_name, u.user_email, u.user_registered,
status.meta_value AS verify_status,
reason.meta_value AS verify_reason,
reviewed_at.meta_value AS reviewed_at,
reviewer.meta_value AS reviewer_id
FROM {$wpdb->users} u
INNER JOIN {$wpdb->usermeta} status
ON status.user_id = u.ID AND status.meta_key = 'aksrt_user_verify_status'
LEFT JOIN {$wpdb->usermeta} reason
ON reason.user_id = u.ID AND reason.meta_key = 'aksrt_user_verify_reason'
LEFT JOIN {$wpdb->usermeta} reviewed_at
ON reviewed_at.user_id = u.ID AND reviewed_at.meta_key = 'aksrt_user_verify_reviewed_at'
LEFT JOIN {$wpdb->usermeta} reviewer
ON reviewer.user_id = u.ID AND reviewer.meta_key = 'aksrt_user_verify_reviewer'
ORDER BY u.user_registered DESC
LIMIT 500
";
$rows = $wpdb->get_results($sql, ARRAY_A);
$items = [];
$counts = ['pending' => 0, 'verified' => 0, 'rejected' => 0, 'total' => 0];
foreach ((array) $rows as $row) {
$item = $this->build_verify_request_item($row);
$item_status = $item['status'];
if (isset($counts[$item_status])) {
$counts[$item_status]++;
}
$counts['total']++;
if ($status !== '' && $item_status !== $status) {
continue;
}
if ($date_from !== '' && strcmp((string) $item['requested_at'], $date_from . ' 00:00:00') < 0) {
continue;
}
if ($date_to !== '' && strcmp((string) $item['requested_at'], $date_to . ' 23:59:59') > 0) {
continue;
}
if ($keyword !== '' && mb_stripos(implode(' ', [
(string) ($item['display_name'] ?? ''),
(string) ($item['email'] ?? ''),
(string) ($item['reason'] ?? ''),
]), $keyword) === false) {
continue;
}
$items[] = $item;
}
$total = count($items);
$offset = ($page - 1) * $per_page;
return $this->success([
'data' => [
'items' => array_values(array_slice($items, $offset, $per_page)),
'total' => $total,
'page' => $page,
'per_page' => $per_page,
'counts' => $counts,
'options' => [
'statuses' => [
['label' => __('待审核', 'aksrt'), 'value' => 'pending'],
['label' => __('已通过', 'aksrt'), 'value' => 'verified'],
['label' => __('已驳回', 'aksrt'), 'value' => 'rejected'],
],
],
],
]);
}
public function get_verify_request_detail(WP_REST_Request $request): WP_REST_Response {
$user_id = (int) $request->get_param('id');
if ($user_id <= 0) {
return $this->error(__('认证申请不存在', 'aksrt'), 404);
}
$user = get_userdata($user_id);
if (!$user) {
return $this->error(__('用户不存在', 'aksrt'), 404);
}
$detail = $this->build_verify_request_item([
'ID' => $user->ID,
'display_name' => $user->display_name,
'user_email' => $user->user_email,
'user_registered' => $user->user_registered,
'verify_status' => get_user_meta($user_id, 'aksrt_user_verify_status', true),
'verify_reason' => get_user_meta($user_id, 'aksrt_user_verify_reason', true),
'reviewed_at' => get_user_meta($user_id, 'aksrt_user_verify_reviewed_at', true),
'reviewer_id' => get_user_meta($user_id, 'aksrt_user_verify_reviewer', true),
]);
return $this->success([
'data' => [
'request' => $detail,
'history' => $this->get_verify_history_for_user($user_id),
'options' => [
'statuses' => [
['label' => __('通过认证', 'aksrt'), 'value' => 'verified'],
['label' => __('驳回申请', 'aksrt'), 'value' => 'rejected'],
],
],
],
]);
}
/**
* POST /verify/review — approve or reject a verification request.
*/
public function review_verify_request(WP_REST_Request $request): WP_REST_Response {
$params = $this->get_json_params($request);
$user_id = (int) ($params['user_id'] ?? 0);
if ($user_id <= 0) {
return $this->error(__('参数无效', 'aksrt'));
}
return $this->perform_verify_review($user_id, $params);
}
public function review_verify_request_by_id(WP_REST_Request $request): WP_REST_Response {
$user_id = (int) $request->get_param('id');
if ($user_id <= 0) {
return $this->error(__('参数无效', 'aksrt'));
}
return $this->perform_verify_review($user_id, $this->get_json_params($request));
}
private function perform_verify_review(int $user_id, array $payload): WP_REST_Response {
$status = sanitize_key((string) ($payload['status'] ?? ''));
$note = sanitize_textarea_field((string) ($payload['note'] ?? ($payload['reason'] ?? '')));
if (!in_array($status, ['verified', 'rejected'], true)) {
return $this->error(__('审核状态无效', 'aksrt'));
}
$user = get_userdata($user_id);
if (!$user) {
return $this->error(__('用户不存在', 'aksrt'), 404);
}
update_user_meta($user_id, 'aksrt_user_verify_status', $status);
update_user_meta($user_id, 'aksrt_user_verify_reviewed_at', current_time('mysql'));
update_user_meta($user_id, 'aksrt_user_verify_reviewer', get_current_user_id());
if ($note !== '') {
update_user_meta($user_id, 'aksrt_user_verify_reason', $note);
} elseif ($status === 'verified') {
delete_user_meta($user_id, 'aksrt_user_verify_reason');
}
$log = get_option('aksrt_verify_review_log', []);
if (!is_array($log)) {
$log = [];
}
$log[] = [
'user_id' => $user_id,
'reviewer' => get_current_user_id(),
'status' => $status,
'reason' => $note,
'time' => current_time('mysql'),
];
if (count($log) > 500) {
$log = array_slice($log, -500);
}
update_option('aksrt_verify_review_log', $log, false);
return $this->success([
'message' => $status === 'verified'
? __('已通过认证', 'aksrt')
: __('已驳回申请', 'aksrt'),
]);
}
private function build_verify_request_item(array $row): array {
$user_id = (int) ($row['ID'] ?? 0);
$reviewer_id = (int) ($row['reviewer_id'] ?? 0);
$reviewer = $reviewer_id > 0 ? get_userdata($reviewer_id) : null;
$status = sanitize_key((string) ($row['verify_status'] ?? 'pending'));
$email_verified = (bool) get_user_meta($user_id, 'aksrt_email_verified', true);
return [
'user_id' => $user_id,
'display_name' => (string) ($row['display_name'] ?? ''),
'email' => (string) ($row['user_email'] ?? ''),
'status' => $status,
'reason' => (string) ($row['verify_reason'] ?? ''),
'requested_at' => (string) ($row['user_registered'] ?? ''),
'reviewed_at' => (string) ($row['reviewed_at'] ?? ''),
'email_verified' => $email_verified,
'reviewer' => $this->build_admin_user_summary($reviewer_id, $reviewer),
'history_count' => count($this->get_verify_history_for_user($user_id)),
];
}
private function get_verify_history_for_user(int $user_id): array {
$log = get_option('aksrt_verify_review_log', []);
if (!is_array($log)) {
return [];
}
$history = [];
foreach ($log as $entry) {
if ((int) ($entry['user_id'] ?? 0) !== $user_id) {
continue;
}
$reviewer_id = (int) ($entry['reviewer'] ?? 0);
$history[] = [
'status' => sanitize_key((string) ($entry['status'] ?? '')),
'reason' => (string) ($entry['reason'] ?? ''),
'time' => (string) ($entry['time'] ?? ''),
'reviewer' => $reviewer_id,
'reviewer_name' => $reviewer_id > 0 && ($user = get_userdata($reviewer_id)) ? $user->display_name : '',
];
}
usort($history, static function ($left, $right) {
return strcmp((string) ($right['time'] ?? ''), (string) ($left['time'] ?? ''));
});
return $history;
}
private function build_admin_user_summary(int $user_id, $user = null): ?array {
if ($user_id <= 0 && !$user instanceof WP_User) {
return null;
}
if (!$user instanceof WP_User) {
$user = get_userdata($user_id);
}
if (!$user instanceof WP_User) {
return null;
}
return [
'id' => (int) $user->ID,
'display_name' => (string) $user->display_name,
'email' => (string) $user->user_email,
'avatar_url' => get_avatar_url((int) $user->ID, ['size' => 64]),
];
}
/**
* GET /sms/status — SMS provider connection status.
*/
public function get_sms_status(): WP_REST_Response {
if (class_exists('AKSRT_SMS')) {
return $this->success(['data' => AKSRT_SMS::get_instance()->get_provider_status()]);
}
return $this->success([
'data' => [
'enabled' => false,
'provider' => 'none',
'configured' => false,
'available' => false,
'verified' => false,
'transport' => '',
'missing_fields' => [],
'code_length' => 6,
'code_expire' => 300,
'rate_limit' => 60,
'daily_limit' => 10,
'notify_bind' => true,
'notify_login' => false,
],
]);
}
/**
* POST /sms/test — Send a test SMS to verify provider configuration.
*/
public function test_sms_send(WP_REST_Request $request): WP_REST_Response {
if (!class_exists('AKSRT_SMS')) {
return $this->error('短信服务不可用');
}
$params = $this->get_json_params($request);
$phone = sanitize_text_field((string) ($params['phone'] ?? ''));
if (!preg_match('/^1[3-9]\d{9}$/', $phone)) {
return $this->error('手机号格式不正确');
}
$result = AKSRT_SMS::get_instance()->test_provider($phone);
if (!empty($result['success'])) {
return $this->success(['message' => $result['message'] ?? '发送成功']);
}
return $this->error($result['message'] ?? '发送失败');
}
/**
* GET /wechat/status — WeChat notification service status.
*/
public function get_wechat_status(): WP_REST_Response {
if (class_exists('AKSRT_WeChat_Notify')) {
return $this->success(['data' => AKSRT_WeChat_Notify::get_instance()->get_status()]);
}
return $this->success([
'data' => [
'appid' => '',
'configured' => false,
'has_token' => false,
'available' => false,
],
]);
}
/**
* POST /wechat/settings — 更新微信通知设置
*/
public function update_wechat_settings(WP_REST_Request $request): WP_REST_Response {
$params = $this->get_json_params($request);
$settings = [
'enabled' => !empty($params['enabled']),
'app_id' => sanitize_text_field((string) ($params['app_id'] ?? '')),
'app_secret' => sanitize_text_field((string) ($params['app_secret'] ?? '')),
'template_id' => sanitize_text_field((string) ($params['template_id'] ?? '')),
];
$existing = AKSRT_Settings::get_wechat_settings();
if ($settings['app_secret'] === '***') {
$settings['app_secret'] = $existing['app_secret'] ?? '';
}
$merged = array_merge($existing, $settings);
AKSRT_Settings::update_wechat_settings($merged);
delete_transient('aksrt_wechat_token');
return $this->success(['message' => __('微信设置已保存', 'aksrt')]);
}
}