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 文件通过。
This commit is contained in:
1 parent
8b999444b2
commit
aad83072a8
30 files changed
+126
-144
No files matched your search
@@ -52,7 +52,7 @@ final class PayFlows {
|
||||
echo '<p class="description">' . esc_html__('仅展示已经确认发生的现金、余额和积分变动;流水不可编辑。', 'aksrt') . '</p>';
|
||||
echo '<form method="get" style="margin:12px 0;display:flex;gap:6px;align-items:center;flex-wrap:wrap;">';
|
||||
echo '<input type="hidden" name="page" value="' . esc_attr(self::PAGE_SLUG) . '">';
|
||||
echo '<input type="search" name="s" value="' . esc_attr($keyword) . '" placeholder="' . esc_attr__('流水号 / 订单号 / 提现单号 / 渠道交易号', 'aksrt') . '" style="min-width:280px;">';
|
||||
echo '<input type="search" name="s" value="' . esc_attr($keyword) . '" placeholder="' . esc_attr__('账本流水号 / 流水号 / 渠道交易号', 'aksrt') . '" style="min-width:280px;">';
|
||||
echo '<input type="number" min="1" name="user_id" value="' . esc_attr($user_id > 0 ? (string) $user_id : '') . '" placeholder="' . esc_attr__('用户 ID', 'aksrt') . '" class="small-text">';
|
||||
echo '<select name="event_type"><option value="">' . esc_html__('全部事件', 'aksrt') . '</option>';
|
||||
foreach ($query->event_types() as $key => $label) {
|
||||
@@ -70,7 +70,7 @@ final class PayFlows {
|
||||
echo '</form>';
|
||||
echo '<p>' . esc_html(sprintf(__('共 %d 条流水', 'aksrt'), (int) $result['total'])) . '</p>';
|
||||
echo '<table class="wp-list-table widefat fixed striped"><thead><tr>';
|
||||
echo '<th style="width:180px">' . esc_html__('流水号 / 时间', 'aksrt') . '</th>';
|
||||
echo '<th style="width:180px">' . esc_html__('账本流水号 / 时间', 'aksrt') . '</th>';
|
||||
echo '<th style="width:130px">' . esc_html__('事件', 'aksrt') . '</th>';
|
||||
echo '<th>' . esc_html__('用户与分录', 'aksrt') . '</th>';
|
||||
echo '<th>' . esc_html__('关联业务', 'aksrt') . '</th>';
|
||||
|
||||
@@ -99,7 +99,7 @@ class PayIncome {
|
||||
echo '<input type="number" min="0" name="user_id" value="' . esc_attr($user_id > 0 ? (string) $user_id : '') . '" placeholder="' . esc_attr__('用户 ID', 'aksrt') . '" class="small-text" /> ';
|
||||
echo '<input type="number" min="0" name="post_id" value="' . esc_attr($post_id > 0 ? (string) $post_id : '') . '" placeholder="' . esc_attr__('文章 ID', 'aksrt') . '" class="small-text" /> ';
|
||||
echo '<select name="currency"><option value="">' . esc_html__('全部货币', 'aksrt') . '</option><option value="CNY"' . selected($currency, 'CNY', false) . '>CNY</option><option value="points"' . selected($currency, 'points', false) . '>' . esc_html__('积分', 'aksrt') . '</option></select> ';
|
||||
echo '<input type="search" name="order_number" value="' . esc_attr($order_number) . '" placeholder="' . esc_attr__('订单号', 'aksrt') . '" /> ';
|
||||
echo '<input type="search" name="order_number" value="' . esc_attr($order_number) . '" placeholder="' . esc_attr__('流水号', 'aksrt') . '" /> ';
|
||||
echo '<input type="date" name="date_from" value="' . esc_attr($date_from) . '" /> — <input type="date" name="date_to" value="' . esc_attr($date_to) . '" /> ';
|
||||
submit_button(__('筛选', 'aksrt'), 'secondary', '', false);
|
||||
if ($user_id > 0) {
|
||||
@@ -127,7 +127,7 @@ class PayIncome {
|
||||
$pages = max(1, (int) ($result['max_pages'] ?? 1));
|
||||
|
||||
echo '<table class="wp-list-table widefat fixed striped"><thead><tr>';
|
||||
echo '<th><input type="checkbox" form="aksrt-pay-batch-settle-income" aria-label="' . esc_attr__('全选待结算记录', 'aksrt') . '" /></th><th>ID</th><th>' . esc_html__('用户', 'aksrt') . '</th><th>' . esc_html__('订单号', 'aksrt') . '</th><th>' . esc_html__('金额', 'aksrt') . '</th><th>' . esc_html__('状态', 'aksrt') . '</th><th>' . esc_html__('时间', 'aksrt') . '</th><th>' . esc_html__('操作', 'aksrt') . '</th>';
|
||||
echo '<th><input type="checkbox" form="aksrt-pay-batch-settle-income" aria-label="' . esc_attr__('全选待结算记录', 'aksrt') . '" /></th><th>ID</th><th>' . esc_html__('用户', 'aksrt') . '</th><th>' . esc_html__('流水号', 'aksrt') . '</th><th>' . esc_html__('金额', 'aksrt') . '</th><th>' . esc_html__('状态', 'aksrt') . '</th><th>' . esc_html__('时间', 'aksrt') . '</th><th>' . esc_html__('操作', 'aksrt') . '</th>';
|
||||
echo '</tr></thead><tbody>';
|
||||
if (!$items) {
|
||||
echo '<tr><td colspan="8">' . esc_html__('暂无分成记录', 'aksrt') . '</td></tr>';
|
||||
|
||||
@@ -167,7 +167,7 @@ class PayOrders {
|
||||
}
|
||||
echo '</select> ';
|
||||
echo '<input type="number" min="0" name="user_id" value="' . esc_attr($user_id > 0 ? (string) $user_id : '') . '" placeholder="' . esc_attr__('用户 ID', 'aksrt') . '" class="small-text" /> ';
|
||||
echo '<input type="search" name="s" value="' . esc_attr($search) . '" placeholder="' . esc_attr__('订单号 / 流水号 / 类型 / 用户', 'aksrt') . '" /> ';
|
||||
echo '<input type="search" name="s" value="' . esc_attr($search) . '" placeholder="' . esc_attr__('流水号 / 账本流水号 / 类型 / 用户', 'aksrt') . '" /> ';
|
||||
submit_button(__('筛选', 'aksrt'), 'secondary', '', false);
|
||||
if ($product_id > 0 || $product_type !== '' || $user_id > 0 || $pay_method !== '') {
|
||||
$filter_bits = [];
|
||||
@@ -200,7 +200,7 @@ class PayOrders {
|
||||
|
||||
echo '<table class="wp-list-table widefat fixed striped">';
|
||||
echo '<thead><tr>';
|
||||
echo '<th>' . esc_html__('订单号', 'aksrt') . '</th>';
|
||||
echo '<th>' . esc_html__('流水号', 'aksrt') . '</th>';
|
||||
echo '<th>' . esc_html__('用户', 'aksrt') . '</th>';
|
||||
echo '<th>' . esc_html__('商品信息', 'aksrt') . '</th>';
|
||||
echo '<th>' . esc_html__('金额 / 支付方式', 'aksrt') . '</th>';
|
||||
@@ -295,8 +295,8 @@ class PayOrders {
|
||||
|
||||
echo '<table class="widefat striped" style="max-width:960px;"><tbody>';
|
||||
$rows = [
|
||||
__('订单号', 'aksrt') => $order_number,
|
||||
__('支付流水号', 'aksrt') => $flow_number !== '' ? $flow_number : '—',
|
||||
__('流水号', 'aksrt') => $order_number,
|
||||
__('账本流水号', 'aksrt') => $flow_number !== '' ? $flow_number : '—',
|
||||
__('用户', 'aksrt') => $user ? $user->display_name . ' (#' . $user_id . ')' : (string) $user_id,
|
||||
__('商品类型', 'aksrt') => (string) ($order['product_type'] ?? ''),
|
||||
__('商品 ID', 'aksrt') => (string) ($order['product_id'] ?? ''),
|
||||
|
||||
@@ -83,7 +83,7 @@ class PayWithdrawals {
|
||||
);
|
||||
}
|
||||
echo '</select> ';
|
||||
echo '<input type="search" name="s" value="' . esc_attr($keyword) . '" placeholder="' . esc_attr__('提现单号 / 用户 ID', 'aksrt') . '" /> ';
|
||||
echo '<input type="search" name="s" value="' . esc_attr($keyword) . '" placeholder="' . esc_attr__('流水号 / 用户 ID', 'aksrt') . '" /> ';
|
||||
echo '<input type="number" min="1" name="user_id" value="' . esc_attr($user_filter > 0 ? (string) $user_filter : '') . '" placeholder="' . esc_attr__('用户 ID', 'aksrt') . '" class="small-text" /> ';
|
||||
echo '<label>' . esc_html__('从', 'aksrt') . ' <input type="date" name="date_from" value="' . esc_attr($date_from) . '"></label> ';
|
||||
echo '<label>' . esc_html__('至', 'aksrt') . ' <input type="date" name="date_to" value="' . esc_attr($date_to) . '"></label> ';
|
||||
@@ -113,7 +113,7 @@ class PayWithdrawals {
|
||||
|
||||
echo '<table class="wp-list-table widefat fixed striped">';
|
||||
echo '<thead><tr>';
|
||||
echo '<th>' . esc_html__('提现单号', 'aksrt') . '</th>';
|
||||
echo '<th>' . esc_html__('流水号', 'aksrt') . '</th>';
|
||||
echo '<th>' . esc_html__('用户', 'aksrt') . '</th>';
|
||||
echo '<th>' . esc_html__('金额明细', 'aksrt') . '</th>';
|
||||
echo '<th>' . esc_html__('渠道 / 账户', 'aksrt') . '</th>';
|
||||
|
||||
@@ -12,8 +12,8 @@ defined('ABSPATH') || exit;
|
||||
*
|
||||
* 页面结构 1:1 复刻参考主题 Zibll 的「支付&付费」section(知识付费 / 余额充值 /
|
||||
* VIP会员 / 创作分成 / 推广返佣 / 收款接口),并按产品需求新增「提现策略」子页。
|
||||
* 收款接口仅保留支付宝、微信、PayPal、Stripe、易支付;订单前缀 / 流水号前缀 /
|
||||
* 提现单号前缀配置保留并收口在收款接口页。
|
||||
* 收款接口仅保留支付宝、微信、PayPal、Stripe、易支付;订单、资金流水与提现
|
||||
* 统一使用同一套流水号,无可配置前缀。
|
||||
*/
|
||||
class SchemaPayment {
|
||||
|
||||
@@ -61,7 +61,7 @@ class SchemaPayment {
|
||||
['key' => 'pay_mark', 'label' => '付费标记', 'type' => 'input', 'default' => '付费'],
|
||||
['key' => 'payment_show_ip', 'label' => '显示用户IP', 'type' => 'switch', 'default' => false],
|
||||
['key' => 'payment_show_device', 'label' => '显示设备信息', 'type' => 'switch', 'default' => false],
|
||||
['key' => 'payment_show_order_no', 'label' => '显示订单号', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'payment_show_order_no', 'label' => '显示流水号', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'payment_show_create_time', 'label' => '显示创建时间', 'type' => 'switch', 'default' => true],
|
||||
['key' => 'payment_show_pay_time', 'label' => '显示支付时间', 'type' => 'switch', 'default' => true],
|
||||
]],
|
||||
@@ -406,9 +406,6 @@ class SchemaPayment {
|
||||
['key' => 'pay_sdk_custom_title', 'label' => '自定义收款标题', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'pay_sdk_custom_title_s', 'value' => true], 'help' => '可使用变量:订单类型 %order_type%,例如:%order_type%-AKSRT;注意控制总长度,太长会导致部分接口报错'],
|
||||
]],
|
||||
['key' => 'order', 'title' => '订单与编号', 'fields' => [
|
||||
['key' => 'payment_order_prefix', 'label' => '订单前缀', 'type' => 'input', 'default' => 'AKSRT', 'help' => '订单号生成前缀'],
|
||||
['key' => 'payment_flow_prefix', 'label' => '流水号前缀', 'type' => 'input', 'sanitize_type' => 'business_prefix', 'default' => 'AK', 'maxlength' => 12, 'help' => '仅允许字母、数字、下划线和短横线,最多 12 位。'],
|
||||
['key' => 'payment_withdrawal_prefix', 'label' => '提现单号前缀', 'type' => 'input', 'sanitize_type' => 'business_prefix', 'default' => 'TX', 'maxlength' => 12, 'help' => '仅允许字母、数字、下划线和短横线,最多 12 位。'],
|
||||
['key' => 'payment_order_expiry', 'label' => '订单支付时效(分钟)', 'type' => 'number', 'default' => 30, 'min' => 5, 'max' => 1440, 'help' => '用户下单后,最大支付时间,超过后订单将自动关闭(不能低于5分钟)'],
|
||||
['key' => 'pay_wait_float_s', 'label' => '浮窗显示待支付订单', 'type' => 'switch', 'default' => true, 'help' => '将用户待支付订单一直显示在右上角,提醒用户付款'],
|
||||
]],
|
||||
|
||||
@@ -892,9 +892,6 @@ class SchemaProvider {
|
||||
}
|
||||
$type = (string) ($field['type'] ?? 'text');
|
||||
$sanitize_type = (string) ($field['sanitize_type'] ?? '');
|
||||
if ($sanitize_type === 'business_prefix') {
|
||||
return \AKSRT\Finance\BusinessNumber::normalize_prefix($value, (string) ($field['default'] ?? 'AK'));
|
||||
}
|
||||
if ($sanitize_type !== '') {
|
||||
return $this->sanitize_value($value, $sanitize_type);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user