订单号、资金流水号、提现单号此前各自带前缀配置,同一笔业务在不同界面会
呈现多个号码口径,对账与客诉排查都要先做一次前缀换算。现收敛为单一流水号
分配器,不再按业务类型区分号码形态。
- 删除 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 文件通过。
119 lines
12 KiB
PHP
119 lines
12 KiB
PHP
<?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];
|
||
}
|
||
}
|