Files
wordpress-theme-aksrt/src/Settings/MailTemplates.php
T
kate522 aad83072a8 refactor(pay): 统一流水号,移除订单/流水/提现三类号码前缀
订单号、资金流水号、提现单号此前各自带前缀配置,同一笔业务在不同界面会
呈现多个号码口径,对账与客诉排查都要先做一次前缀换算。现收敛为单一流水号
分配器,不再按业务类型区分号码形态。

- 删除 payment_order_prefix / payment_flow_prefix /
  payment_withdrawal_prefix 三项配置项及其生成、校验链路
- BusinessNumber::allocate() 成为唯一入口,输出 {YmdHis}{6 位随机},
  共 20 位无前缀,满足 VARCHAR(32) 与网关 out_trade_no ≤ 32 的限制
- 订单、资金流水、提现、卡密渠道交易号四处生成点全部改走该分配器
- 后台支付中心表头「订单号 / 提现单号」统一为「流水号」
- 前台用户中心与订单卡片文案同步统一;前台订单详情合并为单行流水号,
  账本流水号不再下发到前台,避免同一单据出现两个对外号码
- 同步更新 financial-flow / pay-card / card-pass-order-numbers 契约测试
  与 BusinessNumberTest 断言

按用户要求不做双路逻辑与数据迁移,直接替换为统一方案,历史行不做转换。

验证:node --test tests/**/*.test.cjs 362/364 通过,新增 37 项契约;失败的
2 项在改动前的干净 HEAD 基线上同样失败(基线 327 项 / 失败 2 项),分别命中
遗留的 fa fa- 标记与 FA 版本号断言,与本次改动无关。phpunit 44 项 / 103
断言全部通过;php -l 全部改动的 PHP 文件通过。
2026-09-18 22:14:27 +08:00

119 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Canonical email event catalog and admin schema.
*
* @package AKSRT
*/
namespace AKSRT\Settings;
defined('ABSPATH') || exit;
final class MailTemplates {
/** @return array<string, array<string, mixed>> */
public static function definitions(): array {
return [
'links_submit_admin' => self::event('友情链接提交通知', '新友情链接提交:{title}\n提交人:{username}\n链接:{url}\n请登录后台审核。', ['title', 'username', 'url']),
'order_paid_admin' => self::event('新订单通知(管理员)', '收到一笔新订单。\n流水号:{order_number}\n用户:{username}\n商品:{product}\n金额:{amount} {currency}\n支付方式:{payment_method}', ['order_number', 'username', 'product', 'amount', 'currency', 'payment_method']),
'withdraw_submitted_admin' => self::event('提现申请通知(管理员)', '用户 {username} 提交了提现申请。\n流水号:{withdrawal_number}\n金额:{amount}\n方式:{method}', ['username', 'withdrawal_number', 'amount', 'method']),
'post_pending_admin' => self::event('投稿待审核通知', '用户 {username} 提交了待审核内容:{title}\n查看地址:{url}', ['username', 'title', 'url']),
'auth_apply_admin' => self::event('身份认证申请通知', '用户 {username} 提交了身份认证申请,请登录后台审核。\n查看地址:{url}', ['username', 'url']),
'ban_appeal_admin' => self::event('账号申诉通知', '用户 {username} 提交了账号申诉。\n查看地址:{url}', ['username', 'url']),
'report_admin' => self::event('举报提交通知', '收到新的举报。\n举报人:{username}\n对象:{title}\n查看地址:{url}', ['username', 'title', 'url']),
'reg_verify_code' => self::event('注册验证码', '您好 {username},\n\n您正在注册 {site_name},验证码为:\n\n【{code}】\n\n验证码 10 分钟内有效。如非本人操作,请忽略此邮件。', ['username', 'site_name', 'code']),
'reg_success' => self::event('注册成功', '您好 {username},\n\n欢迎加入 {site_name}!您的账号已注册成功。\n\n登录地址:{url}', ['username', 'site_name', 'url']),
'login_code' => self::event('登录验证码', '您好 {username},\n\n您正在登录 {site_name},验证码为:\n\n【{code}】\n\n验证码 10 分钟内有效。如非本人操作,请立即修改密码。', ['username', 'site_name', 'code']),
'password_reset' => self::event('密码重置验证码', '您好 {username},\n\n您正在重置 {site_name} 的账号密码,验证码为:\n\n【{code}】\n\n验证码 10 分钟内有效。如非本人操作,请忽略此邮件。', ['username', 'site_name', 'code']),
'change_code' => self::event('敏感操作验证码', '您好 {username},\n\n您正在进行敏感操作,验证码为:\n\n【{code}】\n\n验证码 5 分钟内有效。如非本人操作,请忽略此邮件。', ['username', 'site_name', 'code']),
'change_notice' => self::event('账号邮箱已变更', '您好 {username},\n\n您的账号邮箱已成功修改为:{new_email}\n\n如果这不是您的操作,请立即联系站点管理员。', ['username', 'site_name', 'new_email']),
'order_paid' => self::event('订单支付成功', '您好 {username},\n\n您的订单已支付成功。\n流水号:{order_number}\n商品:{product}\n金额:{amount} {currency}\n\n查看订单:{url}', ['username', 'order_number', 'product', 'amount', 'currency', 'url']),
'order_status' => self::event('订单状态更新', '您好 {username},\n\n您的订单 {order_number} 状态已更新为:{status}。\n商品:{product}\n查看详情:{url}', ['username', 'order_number', 'status', 'product', 'url']),
'withdraw_submitted' => self::event('提现申请已提交', '您好 {username},\n\n您的提现申请已提交。\n流水号:{withdrawal_number}\n金额:{amount}\n方式:{method}', ['username', 'withdrawal_number', 'amount', 'method']),
'withdraw_completed' => self::event('提现状态更新', '您好 {username},\n\n您的提现申请 {withdrawal_number} 当前状态为:{status}。\n金额:{amount}\n{note}', ['username', 'withdrawal_number', 'status', 'amount', 'note']),
'affiliate_commission' => self::event('返佣到账通知', '您好 {username},\n\n您的推广返佣已到账。\n金额:{amount}\n来源订单:{order_number}\n查看收益:{url}', ['username', 'amount', 'order_number', 'url']),
'creator_income' => self::event('创作分成到账通知', '您好 {username},\n\n您的创作分成已到账。\n金额:{amount}\n来源订单:{order_number}\n查看收益:{url}', ['username', 'amount', 'order_number', 'url']),
'transfer_received' => self::event('收到转账通知', '您好 {username},\n\n您收到来自 {sender} 的{asset}转账:{amount}\n备注:{note}\n查看钱包:{url}', ['username', 'sender', 'asset', 'amount', 'note', 'url']),
'referral_reward' => self::event('推广奖励到账通知', '您好 {username},\n\n您获得了一笔推广奖励:{amount}\n查看收益:{url}', ['username', 'amount', 'url']),
'comment_approved' => self::event('评论已通过审核', '您好 {username},\n\n您在《{title}》下发布的评论已通过审核。\n查看评论:{url}', ['username', 'title', 'url']),
'comment_reply' => self::event('评论回复通知', '您好 {username},\n\n您的评论收到了新的回复。\n文章:{title}\n回复内容:{content}\n查看评论:{url}', ['username', 'title', 'content', 'url']),
'post_result' => self::event('投稿审核结果', '您好 {username},\n\n您的内容《{title}》审核结果:{status}。\n查看内容:{url}', ['username', 'title', 'status', 'url']),
'phone_changed' => self::event('手机号变更通知', '您好 {username},\n\n您的账号绑定手机号已变更。如非本人操作,请立即联系站点管理员。', ['username', 'site_name']),
'auth_apply_result' => self::event('身份认证审核结果', '您好 {username},\n\n您的身份认证申请处理结果:{status}。\n备注:{note}\n查看账号:{url}', ['username', 'status', 'note', 'url']),
'user_ban' => self::event('账号状态通知', '您好 {username},\n\n您的账号状态已更新为:{status}。\n说明:{note}', ['username', 'status', 'note']),
'report_result' => self::event('举报处理结果', '您好 {username},\n\n您提交的举报已有处理结果:{status}。\n说明:{note}\n查看详情:{url}', ['username', 'status', 'note', 'url']),
];
}
/** @return array<string, mixed> */
private static function event(string $title, string $content, array $placeholders, bool $enabled = true): array {
$content = str_replace('\\n', "\n", $content);
return compact('title', 'content', 'placeholders', 'enabled');
}
/** @return array<string, mixed> */
public static function defaults(): array {
$site = (string) get_bloginfo('name');
$definitions = self::definitions();
$defaults = [
'mail_smtps' => false,
'mail_name' => '',
'mail_passwd' => '',
'mail_smtp_name' => '',
'mail_host' => '',
'mail_port' => 465,
'mail_smtpsecure' => 'ssl',
'mail_showname' => $site,
'mail_title_prefix' => '[' . $site . ']',
'mail_description' => '此信为系统邮件,请不要直接回复。',
'mail_more_content' => sprintf('<a href="%s">访问网站</a> | <a href="%s">登录账号</a>', esc_url(home_url('/')), esc_url(wp_login_url())),
];
foreach ($definitions as $event => $definition) {
$defaults["email_{$event}_enabled"] = (bool) $definition['enabled'];
}
return $defaults;
}
/** @return array<string, mixed> */
public static function build_schema(): array {
$defaults = self::defaults();
$definitions = self::definitions();
$groups = [
['key' => 'smtp', 'title' => '邮件 SMTP', 'description' => 'WordPress 邮件由此配置发送;不要与其它 SMTP 插件同时启用。', 'fields' => [
['key' => 'mail_smtps', 'label' => '启用 SMTP', 'type' => 'switch', 'default' => $defaults['mail_smtps']],
['key' => 'mail_name', 'label' => '发信人邮箱账号', 'type' => 'input', 'default' => $defaults['mail_name'], 'dependsOn' => ['key' => 'mail_smtps', 'value' => true]],
['key' => 'mail_passwd', 'label' => 'SMTP 服务邮箱密码', 'type' => 'input', 'inputType' => 'password', 'secret' => true, 'default' => '', 'dependsOn' => ['key' => 'mail_smtps', 'value' => true]],
['key' => 'mail_smtp_name', 'label' => 'SMTP 用户名', 'type' => 'input', 'default' => $defaults['mail_smtp_name'], 'dependsOn' => ['key' => 'mail_smtps', 'value' => true]],
['key' => 'mail_host', 'label' => '邮件服务器地址', 'type' => 'input', 'default' => $defaults['mail_host'], 'dependsOn' => ['key' => 'mail_smtps', 'value' => true]],
['key' => 'mail_port', 'label' => 'SMTP 服务器端口', 'type' => 'number', 'default' => $defaults['mail_port'], 'min' => 1, 'max' => 65535, 'dependsOn' => ['key' => 'mail_smtps', 'value' => true]],
['key' => 'mail_smtpsecure', 'label' => '加密方式', 'type' => 'select', 'default' => $defaults['mail_smtpsecure'], 'options' => [['label' => 'SSL', 'value' => 'ssl'], ['label' => 'TLS', 'value' => 'tls'], ['label' => '不加密', 'value' => '']], 'dependsOn' => ['key' => 'mail_smtps', 'value' => true]],
]],
['key' => 'branding', 'title' => '邮件品牌', 'fields' => [
['key' => 'mail_showname', 'label' => '发件人名称', 'type' => 'input', 'default' => $defaults['mail_showname']],
['key' => 'mail_title_prefix', 'label' => '主题前缀', 'type' => 'input', 'default' => $defaults['mail_title_prefix']],
['key' => 'mail_description', 'label' => '邮件底部说明', 'type' => 'textarea', 'rows' => 3, 'default' => $defaults['mail_description']],
['key' => 'mail_more_content', 'label' => '邮件附加内容(支持基础 HTML)', 'type' => 'textarea', 'rows' => 3, 'sanitize_type' => 'html', 'default' => $defaults['mail_more_content']],
]],
];
$admin = ['links_submit_admin', 'order_paid_admin', 'withdraw_submitted_admin', 'post_pending_admin', 'auth_apply_admin', 'ban_appeal_admin', 'report_admin'];
$user = array_values(array_diff(array_keys($definitions), $admin));
$groups[] = self::event_group('admin', '管理员邮件推送', $admin, $definitions, $defaults);
$groups[] = self::event_group('user', '用户邮件推送', $user, $definitions, $defaults);
$groups[] = ['key' => 'test', 'title' => '测试邮件', 'description' => '保存 SMTP 配置后再发送测试邮件。', 'fields' => [
['key' => 'email_test_to', 'label' => '测试收件地址', 'type' => 'input', 'default' => ''],
['key' => 'email_test_send', 'label' => '发送测试邮件', 'type' => 'button', 'buttonType' => 'primary', 'buttonText' => '发送测试邮件', 'ui_only' => true],
]];
return ['key' => 'email', 'title' => '邮件事件与 SMTP', 'version' => '3.0.0', 'option_key' => 'aksrt_settings', 'groups' => $groups];
}
/** @return array<string, mixed> */
private static function event_group(string $key, string $title, array $events, array $definitions, array $defaults): array {
$fields = [];
foreach ($events as $event) {
$definition = $definitions[$event];
$fields[] = ['key' => "email_{$event}_enabled", 'label' => "{$definition['title']}:启用", 'type' => 'switch', 'default' => $defaults["email_{$event}_enabled"]];
}
return ['key' => $key, 'title' => $title, 'fields' => $fields];
}
}