$ticket */ public static function ticket_urged(array $ticket): void { $vars = [ 'username' => (string) ($ticket['user_name'] ?? ''), 'count' => (int) ($ticket['urge_count'] ?? 0), 'ticket_num' => (string) ($ticket['ticket_num'] ?? ''), 'title' => (string) ($ticket['title'] ?? ''), 'url' => admin_url('users.php?page=aksrt_tickets&id=' . (int) ($ticket['id'] ?? 0)), ]; $assignee = get_userdata((int) ($ticket['admin_id'] ?? 0)); if ($assignee instanceof \WP_User && is_email($assignee->user_email)) { self::send('ticket_urge_admin', $assignee->user_email, $vars); return; } self::send_admin('ticket_urge_admin', $vars); } public static function restriction_changed(int $user_id, string $type, string $action, string $reason): void { $user = get_userdata($user_id); if (!$user instanceof \WP_User) return; self::send('user_ban', $user->user_email, [ 'username' => $user->display_name, 'status' => $action === 'removed' ? __('限制已解除', 'aksrt') : $type, 'note' => $reason, ]); } public static function phone_changed(int $user_id, string $phone): void { $user = get_userdata($user_id); if ($user instanceof \WP_User) self::send('phone_changed', $user->user_email, ['username' => $user->display_name, 'site_name' => get_bloginfo('name')]); } public static function withdrawal_submitted(int $user_id, array $row): void { $user = get_userdata($user_id); if (!$user instanceof \WP_User) return; $vars = [ 'username' => $user->display_name, 'withdrawal_number' => (string) ($row['withdrawal_number'] ?? ''), 'amount' => (string) ($row['gross_amount'] ?? $row['amount'] ?? ''), 'method' => (string) ($row['method'] ?? ''), ]; self::send('withdraw_submitted', $user->user_email, $vars); self::send_admin('withdraw_submitted_admin', $vars); } public static function withdrawal_status(int $user_id, array $row, string $status, string $note): void { $user = get_userdata($user_id); if (!$user instanceof \WP_User) return; self::send('withdraw_completed', $user->user_email, [ 'username' => $user->display_name, 'withdrawal_number' => (string) ($row['withdrawal_number'] ?? ''), 'status' => $status, 'amount' => (string) ($row['gross_amount'] ?? $row['amount'] ?? ''), 'note' => $note, ]); } public static function order_paid(string $order_number, array $order): void { $user = get_userdata((int) ($order['user_id'] ?? 0)); if (!$user instanceof \WP_User) return; $vars = self::order_vars($order_number, $order, $user); self::send('order_paid', $user->user_email, $vars); self::send_admin('order_paid_admin', $vars); } public static function order_status(string $order_number, string $status, array $order): void { if ($status === 'paid') return; $user = get_userdata((int) ($order['user_id'] ?? 0)); if (!$user instanceof \WP_User) return; self::send('order_status', $user->user_email, self::order_vars($order_number, $order, $user) + ['status' => $status]); } public static function asset_transaction($result, $command): void { if (!$result instanceof \AKSRT\Ledger\LedgerResult || !$command instanceof \AKSRT\Ledger\LedgerCommand || $result->replayed) return; $reason = $command->reason; if (!in_array($reason, ['affiliate_commission', 'creator_income', 'transfer', 'tip', 'referral'], true)) return; foreach ($result->entries as $entry) { if ((int) ($entry['delta_minor'] ?? 0) <= 0) continue; $user = get_userdata((int) ($entry['user_id'] ?? 0)); if (!$user instanceof \WP_User) continue; $amount = self::minor_amount((string) ($entry['asset'] ?? 'balance'), (int) $entry['delta_minor']); $url = function_exists('aksrt_get_user_center_url') ? aksrt_get_user_center_url('credits') : home_url('/'); if ($reason === 'affiliate_commission') { self::send('affiliate_commission', $user->user_email, ['username' => $user->display_name, 'amount' => $amount, 'order_number' => $command->ref_key, 'url' => $url]); } elseif ($reason === 'creator_income') { self::send('creator_income', $user->user_email, ['username' => $user->display_name, 'amount' => $amount, 'order_number' => $command->ref_key, 'url' => $url]); } elseif ($reason === 'referral') { self::send('referral_reward', $user->user_email, ['username' => $user->display_name, 'amount' => $amount, 'url' => $url]); } elseif ($reason === 'transfer' && (string) ($entry['entry_type'] ?? '') === 'transfer_in') { $sender = get_userdata((int) ($entry['counterparty_user_id'] ?? 0)); self::send('transfer_received', $user->user_email, [ 'username' => $user->display_name, 'sender' => $sender instanceof \WP_User ? $sender->display_name : __('其他用户', 'aksrt'), 'asset' => ((string) ($entry['asset'] ?? '') === 'points') ? __('积分', 'aksrt') : __('余额', 'aksrt'), 'amount' => $amount, 'note' => (string) ($entry['remark'] ?? ''), 'url' => $url, ]); } } } public static function notification(int $user_id, string $type, array $data): void { $user = get_userdata($user_id); if (!$user instanceof \WP_User) return; $url = (string) ($data['target_url'] ?? $data['url'] ?? home_url('/')); $title = (string) ($data['title'] ?? ''); $content = (string) ($data['description'] ?? $data['desc'] ?? ''); $map = [ 'comment_reply' => 'comment_reply', 'comment_approved' => 'comment_approved', ]; if (!isset($map[$type])) return; $event = $map[$type]; $vars = ['username' => $user->display_name, 'site_name' => get_bloginfo('name'), 'title' => $title, 'content' => $content, 'status' => $title, 'note' => $content, 'url' => $url, 'amount' => '', 'withdrawal_number' => '']; self::send($event, $user->user_email, $vars); } public static function auth_submitted(int $user_id, array $application): void { $user = get_userdata($user_id); self::send_admin('auth_apply_admin', [ 'username' => $user instanceof \WP_User ? $user->display_name : (string) ($application['public_name'] ?? __('用户', 'aksrt')), 'url' => admin_url('users.php?page=aksrt_users_verify'), ]); } public static function auth_reviewed(int $user_id, string $status, string $note, int $reviewer_id): void { $user = get_userdata($user_id); if ($user instanceof \WP_User) self::send('auth_apply_result', $user->user_email, ['username' => $user->display_name, 'status' => $status, 'note' => $note, 'url' => function_exists('aksrt_get_user_center_tab_url') ? aksrt_get_user_center_tab_url('auth') : home_url('/')]); } public static function ban_appeal_submitted(int $user_id, array $payload): void { $user = get_userdata($user_id); if ($user instanceof \WP_User) self::send_admin('ban_appeal_admin', ['username' => $user->display_name, 'url' => admin_url('users.php?page=aksrt_user_ban&type=appeal&status=pending')]); } public static function ban_appeal_processed(int $user_id, string $decision, string $note): void { $user = get_userdata($user_id); if ($user instanceof \WP_User) self::send('user_ban', $user->user_email, ['username' => $user->display_name, 'status' => $decision, 'note' => $note]); } public static function post_pending($post): void { if (!$post instanceof \WP_Post) return; $author = get_userdata((int) $post->post_author); if ($author instanceof \WP_User) self::send_admin('post_pending_admin', ['username' => $author->display_name, 'title' => get_the_title($post), 'url' => get_edit_post_link($post->ID, '') ?: admin_url('edit.php')]); } public static function post_status_changed(string $new_status, string $old_status, \WP_Post $post): void { if ($old_status === $new_status || !in_array($new_status, ['publish', 'draft', 'pending'], true)) return; $author = get_userdata((int) $post->post_author); if ($author instanceof \WP_User) { self::send('post_result', $author->user_email, [ 'username' => $author->display_name, 'title' => get_the_title($post), 'status' => $new_status, 'url' => get_permalink($post), ]); } } public static function report_submitted(int $report_id, array $report): void { $reporter = get_userdata((int) ($report['reporter_id'] ?? 0)); self::send_admin('report_admin', ['username' => $reporter instanceof \WP_User ? $reporter->display_name : __('用户', 'aksrt'), 'title' => (string) ($report['target_type'] ?? ''), 'url' => admin_url('users.php?page=aksrt_user_ban')]); } public static function report_status_changed(int $report_id, int $reporter_id, string $status, string $note = ''): void { $reporter = get_userdata($reporter_id); if (!$reporter instanceof \WP_User) { return; } // 状态值中文化后进入邮件;处理说明来自后台“处理说明”输入(钩子第 4 参)。 $labels = [ 'pending' => __('待处理', 'aksrt'), 'reviewing' => __('审核中', 'aksrt'), 'resolved' => __('已解决', 'aksrt'), 'dismissed' => __('已驳回', 'aksrt'), ]; self::send('report_result', $reporter->user_email, [ 'username' => $reporter->display_name, 'status' => $labels[$status] ?? $status, 'note' => $note !== '' ? $note : __('—', 'aksrt'), 'url' => home_url('/'), ]); } public static function friend_link_submitted(array $link): void { self::send_admin('links_submit_admin', ['title' => (string) ($link['name'] ?? ''), 'username' => __('访客', 'aksrt'), 'url' => (string) ($link['url'] ?? '')]); } /** @param array $vars */ private static function send(string $event, string $to, array $vars): void { $placeholders = []; foreach ($vars as $key => $value) $placeholders['{' . $key . '}'] = (string) $value; Mail::send_event_email($event, $to, $placeholders); } /** @param array $vars */ private static function send_admin(string $event, array $vars): void { foreach (self::admin_emails() as $email) self::send($event, $email, $vars); } /** @return list */ private static function admin_emails(): array { $emails = []; foreach (get_users(['role' => 'administrator', 'fields' => ['user_email'], 'number' => 100]) as $user) { $email = sanitize_email((string) ($user->user_email ?? '')); if ($email !== '' && is_email($email)) $emails[$email] = true; } return array_keys($emails); } /** @return array */ private static function order_vars(string $order_number, array $order, \WP_User $user): array { $product = (string) ($order['product_type'] ?? 'order'); return ['username' => $user->display_name, 'order_number' => $order_number, 'product' => $product, 'amount' => (string) ($order['amount'] ?? ''), 'currency' => (string) ($order['currency'] ?? 'CNY'), 'payment_method' => (string) ($order['payment_method'] ?? ''), 'url' => function_exists('aksrt_get_user_center_url') ? aksrt_get_user_center_url('orders') : home_url('/')]; } private static function minor_amount(string $asset, int $minor): string { if ($asset === 'points') return (string) $minor; return number_format($minor / 100, 2, '.', ''); } }