全部可用 */ return array_values($cfg['types']); } function kehua_cert_type_by_id($type_id, $cfg = null) { $type_id = trim((string) $type_id); if ($type_id === '') { return null; } if ($cfg === null) { $cfg = kehua_cert_cfg(); } if (empty($cfg['types']) || !is_array($cfg['types'])) { return null; } foreach ($cfg['types'] as $t) { if (isset($t['id']) && (string) $t['id'] === $type_id) { return $t; } } return null; } function kehua_cert_ensure_schema() { global $db; if (empty($db) || empty($db->tablepre)) { return false; } $tp = $db->tablepre; $sql1 = "CREATE TABLE IF NOT EXISTS {$tp}kehua_cert_apply ( id int(11) unsigned NOT NULL AUTO_INCREMENT, uid int(11) NOT NULL DEFAULT 0, type_id varchar(32) NOT NULL DEFAULT '', type_name varchar(64) NOT NULL DEFAULT '', material varchar(1000) NOT NULL DEFAULT '', status tinyint(1) NOT NULL DEFAULT 0, create_date int(10) NOT NULL DEFAULT 0, review_date int(10) NOT NULL DEFAULT 0, review_uid int(11) NOT NULL DEFAULT 0, review_note varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (id), KEY uid_status (uid, status), KEY type_id (type_id), KEY status_date (status, create_date) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"; db_exec($sql1); $sql2 = "CREATE TABLE IF NOT EXISTS {$tp}kehua_cert_user ( id int(11) unsigned NOT NULL AUTO_INCREMENT, uid int(11) NOT NULL DEFAULT 0, type_id varchar(32) NOT NULL DEFAULT '', type_name varchar(64) NOT NULL DEFAULT '', color varchar(16) NOT NULL DEFAULT '#2563eb', create_date int(10) NOT NULL DEFAULT 0, PRIMARY KEY (id), UNIQUE KEY uid_type (uid, type_id), KEY uid (uid) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"; db_exec($sql2); return true; } function kehua_cert_credit_labels() { $l1 = '声望'; $l2 = '金币'; $l3 = '点券'; if (function_exists('kehua_theme_cfg')) { $theme = kehua_theme_cfg(); if (!empty($theme['credits_label_1'])) { $l1 = $theme['credits_label_1']; } if (!empty($theme['credits_label_2'])) { $l2 = $theme['credits_label_2']; } if (!empty($theme['credits_label_3'])) { $l3 = $theme['credits_label_3']; } } return array($l1, $l2, $l3); } /** * 检查用户是否满足申请条件。 * @param array|null $type 认证类型;须传入该类型门槛,否则视为无限制 * @return array{ok:bool,items:array,message:string} */ function kehua_cert_check_conditions($user, $cfg = null, $type = null) { if ($cfg === null) { $cfg = kehua_cert_cfg(); } if (!is_array($user)) { return array('ok' => false, 'items' => array(), 'message' => '用户不存在'); } if (is_array($type) && isset($type['require']) && is_array($type['require'])) { $req = kehua_cert_normalize_require($type['require']); } else { $req = kehua_cert_empty_require(); } list($l1, $l2, $l3) = kehua_cert_credit_labels(); $items = array(); $all_ok = true; $add = function ($key, $label, $need, $have, $pass) use (&$items, &$all_ok) { if ($need <= 0) { return; } $items[] = array( 'key' => $key, 'label' => $label, 'need' => $need, 'have' => $have, 'ok' => $pass ? 1 : 0, ); if (!$pass) { $all_ok = false; } }; $threads = isset($user['threads']) ? intval($user['threads']) : 0; $posts = isset($user['posts']) ? intval($user['posts']) : 0; $credits = isset($user['credits']) ? intval($user['credits']) : 0; $golds = isset($user['golds']) ? intval($user['golds']) : 0; $rmbs = isset($user['rmbs']) ? intval($user['rmbs']) : 0; $followeds = isset($user['followeds']) ? intval($user['followeds']) : 0; $create_date = isset($user['create_date']) ? intval($user['create_date']) : 0; $days = 0; if ($create_date > 0) { $days = max(0, intval(floor((time() - $create_date) / 86400))); } $add('threads', '主题数 ≥ ' . intval($req['threads']), intval($req['threads']), $threads, $threads >= intval($req['threads'])); $add('posts', '回帖数 ≥ ' . intval($req['posts']), intval($req['posts']), $posts, $posts >= intval($req['posts'])); $add('credits', $l1 . ' ≥ ' . intval($req['credits']), intval($req['credits']), $credits, $credits >= intval($req['credits'])); $add('golds', $l2 . ' ≥ ' . intval($req['golds']), intval($req['golds']), $golds, $golds >= intval($req['golds'])); $add('rmbs', $l3 . ' ≥ ' . intval($req['rmbs']), intval($req['rmbs']), $rmbs, $rmbs >= intval($req['rmbs'])); $add('followeds', '粉丝数 ≥ ' . intval($req['followeds']), intval($req['followeds']), $followeds, $followeds >= intval($req['followeds'])); $add('days', '注册天数 ≥ ' . intval($req['days']) . ' 天', intval($req['days']), $days, $days >= intval($req['days'])); $msg = $all_ok ? '' : '暂未满足申请条件'; return array('ok' => $all_ok, 'items' => $items, 'message' => $msg); } /** * 为前台生成各认证类型的门槛校验结果。 * @return array */ function kehua_cert_conditions_by_types($user, $cfg = null) { if ($cfg === null) { $cfg = kehua_cert_cfg(); } $out = array(); $types = kehua_cert_types_enabled($cfg); foreach ($types as $type) { $id = isset($type['id']) ? (string) $type['id'] : ''; if ($id === '') { continue; } $cond = kehua_cert_check_conditions($user, $cfg, $type); $ok_n = 0; $total = !empty($cond['items']) ? count($cond['items']) : 0; if (!empty($cond['items'])) { foreach ($cond['items'] as $it) { if (!empty($it['ok'])) { $ok_n++; } } } $out[$id] = array( 'ok' => !empty($cond['ok']) ? 1 : 0, 'items' => isset($cond['items']) ? $cond['items'] : array(), 'ok_n' => $ok_n, 'total' => $total, 'message' => isset($cond['message']) ? $cond['message'] : '', ); } return $out; } function kehua_cert_user_list($uid) { $uid = intval($uid); if ($uid < 1) { return array(); } kehua_cert_ensure_schema(); $list = db_find('kehua_cert_user', array('uid' => $uid), array('id' => 1), 1, 50); if ($list === false || !is_array($list)) { return array(); } $out = array(); foreach ($list as $row) { if (!is_array($row)) { continue; } $row['color'] = kehua_cert_sanitize_color(isset($row['color']) ? $row['color'] : '#2563eb'); $out[] = $row; } return $out; } function kehua_cert_user_has_type($uid, $type_id) { $uid = intval($uid); $type_id = trim((string) $type_id); if ($uid < 1 || $type_id === '') { return false; } kehua_cert_ensure_schema(); $row = db_find_one('kehua_cert_user', array('uid' => $uid, 'type_id' => $type_id)); return !empty($row); } function kehua_cert_pending_apply($uid, $type_id = '') { $uid = intval($uid); if ($uid < 1) { return null; } kehua_cert_ensure_schema(); $cond = array('uid' => $uid, 'status' => 0); if ($type_id !== '') { $cond['type_id'] = trim((string) $type_id); } return db_find_one('kehua_cert_apply', $cond, array('id' => -1)); } function kehua_cert_user_applies($uid, $limit = 20) { $uid = intval($uid); if ($uid < 1) { return array(); } kehua_cert_ensure_schema(); $list = db_find('kehua_cert_apply', array('uid' => $uid), array('id' => -1), 1, max(1, min(50, intval($limit)))); if ($list === false || !is_array($list)) { return array(); } return $list; } /** * 提交认证申请。 * @return array{ok:bool,message:string,id?:int} */ function kehua_cert_submit_apply($uid, $type_id, $material = '') { $uid = intval($uid); $type_id = trim((string) $type_id); $material = trim((string) $material); if ($uid < 1) { return array('ok' => false, 'message' => '请先登录'); } if (!kehua_cert_enabled()) { return array('ok' => false, 'message' => '达人认证功能未开启'); } $cfg = kehua_cert_cfg(); $type = kehua_cert_type_by_id($type_id, $cfg); if (empty($type)) { return array('ok' => false, 'message' => '认证类型不存在'); } $user = user_read($uid); if (empty($user)) { return array('ok' => false, 'message' => '用户不存在'); } $cond = kehua_cert_check_conditions($user, $cfg, $type); if (empty($cond['ok'])) { return array('ok' => false, 'message' => $cond['message'] !== '' ? $cond['message'] : '暂未满足该认证类型的申请条件'); } if (kehua_cert_user_has_type($uid, $type_id)) { return array('ok' => false, 'message' => '您已拥有该认证'); } $pending = kehua_cert_pending_apply($uid); if (!empty($pending)) { return array('ok' => false, 'message' => '您有待审核的申请,请等待处理后再提交'); } if (function_exists('mb_substr')) { $material = mb_substr($material, 0, 1000, 'UTF-8'); } else { $material = substr($material, 0, 1000); } kehua_cert_ensure_schema(); $id = db_insert('kehua_cert_apply', array( 'uid' => $uid, 'type_id' => $type['id'], 'type_name' => $type['name'], 'material' => $material, 'status' => 0, 'create_date' => time(), 'review_date' => 0, 'review_uid' => 0, 'review_note' => '', )); if ($id === false || !$id) { return array('ok' => false, 'message' => '提交失败,请稍后重试'); } $id = intval($id); return array( 'ok' => true, 'message' => '申请已提交,请等待审核', 'id' => $id, 'type_name' => $type['name'], 'material' => $material, ); } function kehua_cert_admin_can_moderate() { global $gid; return !empty($gid) && intval($gid) == 1; } function kehua_cert_count_pending() { kehua_cert_ensure_schema(); $n = db_count('kehua_cert_apply', array('status' => 0)); return $n === false ? 0 : intval($n); } function kehua_cert_admin_find_list($status_filter, $page, $pagesize) { kehua_cert_ensure_schema(); $page = max(1, intval($page)); $pagesize = max(1, min(100, intval($pagesize))); $cond = array(); if ($status_filter !== '' && $status_filter !== 'all' && $status_filter !== null) { $cond['status'] = intval($status_filter); } $list = db_find('kehua_cert_apply', $cond, array('id' => -1), $page, $pagesize); if ($list === false || !is_array($list)) { return array(); } foreach ($list as &$row) { $u = user_read(isset($row['uid']) ? intval($row['uid']) : 0); $row['username'] = !empty($u['username']) ? $u['username'] : ('UID:' . intval($row['uid'])); $row['avatar_url'] = kehua_cert_admin_avatar_url(!empty($u['avatar_url']) ? $u['avatar_url'] : ''); } unset($row); return $list; } /** * 后台列表头像地址:相对站点路径在 /admin/ 下会 404,需补 ../ */ function kehua_cert_admin_avatar_url($url) { $url = trim((string) $url); if ($url === '') { $url = 'view/img/avatar.png'; } if (preg_match('#^(https?:)?//#i', $url) || strpos($url, '/') === 0 || strpos($url, '../') === 0 || strpos($url, 'data:') === 0) { return $url; } return '../' . ltrim($url, './'); } function kehua_cert_admin_count($status_filter = '') { kehua_cert_ensure_schema(); $cond = array(); if ($status_filter !== '' && $status_filter !== 'all' && $status_filter !== null) { $cond['status'] = intval($status_filter); } $n = db_count('kehua_cert_apply', $cond); return $n === false ? 0 : intval($n); } /** * 审核申请:status 1通过 2拒绝 */ function kehua_cert_review($id, $status, $review_uid, $note = '') { $id = intval($id); $status = intval($status); $review_uid = intval($review_uid); $note = trim((string) $note); if ($id < 1 || !in_array($status, array(1, 2), true)) { return array('ok' => false, 'message' => '参数错误'); } if (!kehua_cert_admin_can_moderate()) { return array('ok' => false, 'message' => '无权限'); } kehua_cert_ensure_schema(); $row = db_find_one('kehua_cert_apply', array('id' => $id)); if (empty($row)) { return array('ok' => false, 'message' => '申请不存在'); } if (intval($row['status']) !== 0) { return array('ok' => false, 'message' => '该申请已处理'); } if (function_exists('mb_substr')) { $note = mb_substr($note, 0, 255, 'UTF-8'); } else { $note = substr($note, 0, 255); } $ok = db_update('kehua_cert_apply', array('id' => $id), array( 'status' => $status, 'review_date' => time(), 'review_uid' => $review_uid, 'review_note' => $note, )); if ($ok === false) { return array('ok' => false, 'message' => '更新失败'); } $uid = intval($row['uid']); $type_id = isset($row['type_id']) ? $row['type_id'] : ''; $type_name = isset($row['type_name']) ? $row['type_name'] : ''; if ($status === 1) { $cfg = kehua_cert_cfg(); $type = kehua_cert_type_by_id($type_id, $cfg); $color = !empty($type['color']) ? $type['color'] : '#2563eb'; $exist = db_find_one('kehua_cert_user', array('uid' => $uid, 'type_id' => $type_id)); if (empty($exist)) { db_insert('kehua_cert_user', array( 'uid' => $uid, 'type_id' => $type_id, 'type_name' => $type_name, 'color' => kehua_cert_sanitize_color($color), 'create_date' => time(), )); } else { db_update('kehua_cert_user', array('id' => intval($exist['id'])), array( 'type_name' => $type_name, 'color' => kehua_cert_sanitize_color($color), )); } kehua_cert_notify_user($uid, $type_name, 'pass', $note, $review_uid); return array('ok' => true, 'message' => '已通过认证'); } kehua_cert_notify_user($uid, $type_name, 'reject', $note, $review_uid); return array('ok' => true, 'message' => '已拒绝申请'); } function kehua_cert_revoke($uid, $type_id, $admin_uid = 0) { $uid = intval($uid); $type_id = trim((string) $type_id); if ($uid < 1 || $type_id === '') { return array('ok' => false, 'message' => '参数错误'); } if (!kehua_cert_admin_can_moderate()) { return array('ok' => false, 'message' => '无权限'); } kehua_cert_ensure_schema(); $row = db_find_one('kehua_cert_user', array('uid' => $uid, 'type_id' => $type_id)); $apply = db_find_one('kehua_cert_apply', array('uid' => $uid, 'type_id' => $type_id, 'status' => 1), array('id' => -1)); if (empty($row) && empty($apply)) { return array('ok' => false, 'message' => '该用户无此认证'); } if (!empty($row)) { db_delete('kehua_cert_user', array('id' => intval($row['id']))); } /* 同步更新申请记录,否则后台列表仍显示「已通过」+「撤销认证」 */ db_update('kehua_cert_apply', array( 'uid' => $uid, 'type_id' => $type_id, 'status' => 1, ), array( 'status' => 3, 'review_date' => time(), 'review_uid' => intval($admin_uid), 'review_note' => '管理员撤销认证', )); $type_name = !empty($row['type_name']) ? $row['type_name'] : (!empty($apply['type_name']) ? $apply['type_name'] : $type_id); kehua_cert_notify_user($uid, $type_name, 'revoke', '', intval($admin_uid)); return array('ok' => true, 'message' => '已撤销认证'); } /** * 前台个人中心认证页链接(后台审核时 url() 可能带 admin 路径,需纠正) */ function kehua_cert_front_url($route = 'my-cert') { global $conf; $route = trim((string) $route); if ($route === '') { $route = 'my-cert'; } if (function_exists('kehua_store_front_url')) { return kehua_store_front_url($route); } $rel = function_exists('url') ? url($route) : ('?'.$route.'.htm'); if (preg_match('#^https?://#i', $rel)) { return $rel; } if (!empty($conf['url'])) { $base = rtrim((string) $conf['url'], '/') . '/'; } elseif (function_exists('http_url_path')) { $base = preg_replace('#/admin/?$#i', '/', http_url_path()); } else { return $rel; } $path = ltrim($rel, './'); return $path === '' ? rtrim($base, '/') . '/' : $base . $path; } /** * 确保站内通知能力可用 */ function kehua_cert_notice_ready() { if (!function_exists('notice_send') && is_file(APP_PATH . 'plugin/kehua_theme/model/kehua_notice.func.php')) { include_once _include(APP_PATH . 'plugin/kehua_theme/model/kehua_notice.func.php'); } return function_exists('notice_send'); } /** * 向用户发送达人认证系统通知(type=3) * @param string $result pass|reject|revoke */ function kehua_cert_notify_user($recv_uid, $type_name, $result = 'pass', $note = '', $from_uid = 0) { $recv_uid = intval($recv_uid); if ($recv_uid < 1 || !kehua_cert_notice_ready()) { return false; } /* 兼容旧布尔调用:true=通过 false=拒绝 */ if ($result === true || $result === 1 || $result === '1') { $result = 'pass'; } elseif ($result === false || $result === 0 || $result === '0') { $result = 'reject'; } $result = (string) $result; if (!in_array($result, array('pass', 'reject', 'revoke'), true)) { $result = 'pass'; } global $user; $from = intval($from_uid); if ($from < 1 && is_array($user) && !empty($user['uid'])) { $from = intval($user['uid']); } if ($from < 1 && !empty($GLOBALS['uid'])) { $from = intval($GLOBALS['uid']); } if ($from < 1 || $from === $recv_uid) { $from = 1; } if ($from === $recv_uid) { /* 接收人是 uid=1 时无法用系统号自投(极罕见) */ return false; } $type_name = htmlspecialchars(trim((string) $type_name), ENT_QUOTES, 'UTF-8'); if ($type_name === '') { $type_name = '达人认证'; } $note = trim((string) $note); $admin_l = function_exists('lang') ? lang('notice_admin') : '管理员'; $cert_url = kehua_cert_front_url('my-cert'); $cert_link = '查看认证'; if ($result === 'pass') { $msg = $admin_l . '已通过你的达人认证「' . $type_name . '」 ' . '认证标识已生效,可在个人资料中查看。' . $cert_link; } elseif ($result === 'reject') { $msg = $admin_l . '未通过你的达人认证「' . $type_name . '」'; if ($note !== '') { $msg .= ' 原因:' . htmlspecialchars($note, ENT_QUOTES, 'UTF-8'); } else { $msg .= ' 如有疑问请联系管理员。'; } $msg .= ' ' . $cert_link; } else { $msg = $admin_l . '已撤销你的达人认证「' . $type_name . '」 ' . '前台认证标识已失效。' . $cert_link; } $nid = notice_send($from, $recv_uid, $msg, 3); return $nid ? true : false; } /** * 用户名旁认证徽章 HTML */ function kehua_cert_badges_html($uid, $style = 'inline') { $uid = intval($uid); if ($uid < 1 || !kehua_cert_enabled()) { return ''; } $list = kehua_cert_user_list($uid); if (empty($list)) { return ''; } $html = ''; foreach ($list as $c) { $name = isset($c['type_name']) ? $c['type_name'] : ''; $color = kehua_cert_sanitize_color(isset($c['color']) ? $c['color'] : '#2563eb'); $name_esc = htmlspecialchars($name, ENT_QUOTES, 'UTF-8'); $color_esc = htmlspecialchars($color, ENT_QUOTES, 'UTF-8'); $icon = ''; if ($style === 'tag') { $html .= '' . $icon . '' . $name_esc . ''; } else { $html .= '' . $icon . ''; } } return $html; } function kehua_cert_apply_info_text($cfg = null) { if ($cfg === null) { $cfg = kehua_cert_cfg(); } $raw = isset($cfg['apply_info']) ? trim((string) $cfg['apply_info']) : ''; if ($raw === '') { return "欢迎申请达人认证。\n请选择符合您身份的认证类型,填写相关说明后提交,管理员审核通过后将在个人资料展示认证标识。"; } return $raw; } function kehua_cert_status_text($status) { $status = intval($status); if ($status === 1) { return '已通过'; } if ($status === 2) { return '已拒绝'; } if ($status === 3) { return '已撤销'; } return '待审核'; } function kehua_cert_mail_smtp_ready() { return is_file(APP_PATH . 'conf/smtp.conf.php'); } /** * 解析达人认证通知邮箱(仅使用本模块配置)。 */ function kehua_cert_mail_resolve_notify_email() { $cfg = kehua_cert_cfg(); $email = isset($cfg['mail_email']) ? trim((string) $cfg['mail_email']) : ''; if ($email !== '' && filter_var($email, FILTER_VALIDATE_EMAIL)) { return $email; } return ''; } function kehua_cert_mail_should_send() { $cfg = kehua_cert_cfg(); if (empty($cfg['mail_enable'])) { return false; } if (!kehua_cert_mail_smtp_ready()) { return false; } return kehua_cert_mail_resolve_notify_email() !== ''; } function kehua_cert_mail_do_send($mail_data) { if (function_exists('kehua_report_mail_do_send')) { return kehua_report_mail_do_send($mail_data); } try { $smtp_conf_file = isset($mail_data['smtp_conf_file']) ? $mail_data['smtp_conf_file'] : ''; if ($smtp_conf_file === '' || !is_file($smtp_conf_file)) { return false; } $smtplist = @include $smtp_conf_file; if (empty($smtplist) || !is_array($smtplist)) { return false; } if (!function_exists('xn_send_mail')) { $_xf = XIUNOPHP_PATH . 'xn_send_mail.func.php'; if (is_file($_xf)) { include_once _include($_xf); } } if (!function_exists('xn_send_mail')) { return false; } $n = array_rand($smtplist); $smtp = $smtplist[$n]; @xn_send_mail($smtp, $mail_data['sitename'], $mail_data['email'], $mail_data['subject'], $mail_data['body']); return true; } catch (Exception $e) { return false; } } function kehua_cert_mail_build_payload($apply_id, $uid, $type_name, $material) { if (!kehua_cert_mail_should_send()) { return null; } $notify_email = kehua_cert_mail_resolve_notify_email(); if ($notify_email === '') { return null; } global $conf; $sitename = !empty($conf['sitename']) ? $conf['sitename'] : '论坛'; $user = user_read(intval($uid)); $uname = !empty($user['username']) ? $user['username'] : ('UID ' . intval($uid)); $type_name = trim((string) $type_name); if ($type_name === '') { $type_name = '未知类型'; } $material = trim(strip_tags((string) $material)); $material = preg_replace('/\s+/u', ' ', $material); if (function_exists('mb_substr')) { $material_show = mb_substr($material, 0, 500, 'UTF-8'); } else { $material_show = substr($material, 0, 500); } if ($material_show === '') { $material_show = '(未填写)'; } $admin_url = ''; if (function_exists('http_url_path') && function_exists('url')) { $admin_url = http_url_path() . url('admin-cert-list'); } if (!function_exists('kehua_audit_mail_table_row')) { include_once _include(APP_PATH . 'plugin/kehua_theme/model/kehua_audit_mail.func.php'); } $rows = ''; $rows .= kehua_audit_mail_table_row('申请编号', '#' . intval($apply_id), false); $rows .= kehua_audit_mail_table_row('用户', htmlspecialchars($uname, ENT_QUOTES, 'UTF-8') . ' (UID: ' . intval($uid) . ')', true); $rows .= kehua_audit_mail_table_row('认证类型', htmlspecialchars($type_name, ENT_QUOTES, 'UTF-8'), false); $rows .= kehua_audit_mail_table_row('申请理由', htmlspecialchars($material_show, ENT_QUOTES, 'UTF-8'), true); $rows .= kehua_audit_mail_table_row('时间', htmlspecialchars(date('Y-m-d H:i:s'), ENT_QUOTES, 'UTF-8'), false); $subject = '【' . $sitename . '】新的达人认证申请:' . $type_name; $intro = '有用户提交了达人认证申请,请及时登录后台查看并审核。'; $body = kehua_audit_mail_build_wrapper('达人认证申请通知', $intro, $rows, '进入后台审核', $admin_url, '认证通知', '#2563eb'); return array( 'smtp_conf_file' => APP_PATH . 'conf/smtp.conf.php', 'sitename' => $sitename, 'email' => $notify_email, 'subject' => $subject, 'body' => $body, ); } /** * 断开客户端后再执行慢操作(SMTP),避免前台一直转圈等待发信。 */ function kehua_cert_mail_detach_client() { if (function_exists('kehua_report_mail_detach_client')) { kehua_report_mail_detach_client(); return; } if (function_exists('ob_get_level')) { while (ob_get_level() > 0) { @ob_end_flush(); } } @flush(); if (function_exists('fastcgi_finish_request')) { @fastcgi_finish_request(); } @ignore_user_abort(true); if (function_exists('set_time_limit')) { @set_time_limit(120); } } /** * 申请提交成功:先返回 JSON 给浏览器,再异步发管理员邮件。 */ function kehua_cert_submit_success($apply_id, $uid, $type_name, $material, $message = '') { $message = trim((string) $message); if ($message === '') { $message = '申请已提交,请等待审核'; } $payload = null; if (kehua_cert_mail_should_send()) { $payload = kehua_cert_mail_build_payload($apply_id, $uid, $type_name, $material); } kehua_cert_submit_success_finish($message, $payload); } function kehua_cert_submit_success_finish($message, $mail_payload = null) { $arr = array( 'code' => '0', 'message' => (string) $message, ); $json = function_exists('xn_json_encode') ? xn_json_encode($arr) : json_encode($arr, JSON_UNESCAPED_UNICODE); if (!headers_sent()) { header('Content-Type: application/json; charset=utf-8'); header('Connection: close'); header('Content-Length: ' . strlen($json)); } echo $json; kehua_cert_mail_detach_client(); if (!empty($mail_payload)) { kehua_cert_mail_do_send($mail_payload); } exit; } /** * 有新申请时邮件通知管理员(兼容旧调用:延后到 shutdown 再发)。 * 前台提交请改用 kehua_cert_submit_success(),避免卡住。 */ function kehua_cert_mail_notify_admin($apply_id, $uid, $type_name, $material) { if (!kehua_cert_mail_should_send()) { return false; } $payload = kehua_cert_mail_build_payload($apply_id, $uid, $type_name, $material); if (empty($payload)) { return false; } register_shutdown_function(function () use ($payload) { kehua_cert_mail_detach_client(); kehua_cert_mail_do_send($payload); }); return true; }