From f9076ea5df1c9b9928245f4ea93b95a7140002d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=90=9D=E5=8D=9C?= Date: Sat, 14 Mar 2026 11:13:14 +0000 Subject: [PATCH] chore: add safeFullUrlWithQuery helper for platform orders links --- .../admin/platform_orders/index.blade.php | 131 ++++++++++++------ 1 file changed, 85 insertions(+), 46 deletions(-) diff --git a/resources/views/admin/platform_orders/index.blade.php b/resources/views/admin/platform_orders/index.blade.php index 8b04e42..25769cf 100644 --- a/resources/views/admin/platform_orders/index.blade.php +++ b/resources/views/admin/platform_orders/index.blade.php @@ -17,6 +17,45 @@ $selfWithoutBack .= '?' . \Illuminate\Support\Arr::query($currentQuery); } + // back 安全护栏(全页通用): + // - 仅允许站内相对路径(/ 开头) + // - 拒绝引号/尖括号(由于本页大量 href 采用 `{!! !!}` 原样输出,必须严控注入风险) + // - 拒绝 nested back=(避免 URL 膨胀/绕过) + $incomingBackForLinks = (string) request()->query('back', ''); + $safeBackForLinks = (str_starts_with($incomingBackForLinks, '/') + && !preg_match('/["\'<>]/', $incomingBackForLinks) + && !preg_match('/(?:^|[?&])back=/', $incomingBackForLinks)) + ? $incomingBackForLinks + : ''; + + // 安全版“保留当前 query 并覆盖字段”的链接构造器: + // - 强制使用站内相对路径(不包含域名) + // - back 仅保留安全值(否则移除),避免 `{!! !!}` 输出时发生属性注入 + $safeFullUrlWithQuery = function (array $overrides = []) use ($safeBackForLinks) { + $q = request()->query(); + + if ($safeBackForLinks !== '') { + $q['back'] = $safeBackForLinks; + } else { + unset($q['back']); + } + + foreach ($overrides as $k => $v) { + if ($v === null) { + unset($q[$k]); + } else { + $q[$k] = $v; + } + } + + $url = '/' . ltrim(request()->path(), '/'); + if (count($q) > 0) { + $url .= '?' . \Illuminate\Support\Arr::query($q); + } + + return $url; + }; + // 线索上下文(从开通线索跳转而来):用于提示“当前范围已锁定线索”,以及生成一键清除入口 $incomingLeadId = (int) request()->query('lead_id', 0); $clearLeadQuery = $currentQuery; @@ -295,66 +334,66 @@

已支付 / 已生效

已同步 / 未同步

同步失败数

BMPA 失败数

批量标记支付并生效失败(meta 失败标记)

可同步订单

已支付 + 已生效 + 未同步

近24小时批量同步

基于 meta.batch_activation.at

近24小时批量BMPA

基于 meta.batch_mark_paid_and_activate.at

近24小时批量生效

基于 meta.batch_mark_activated.at

部分退款 / 已退款

@@ -365,16 +404,16 @@

有退款订单 / 无退款订单

口径:refund_summary.total_amount 存在或 refund_receipts 有记录

有回执订单 / 回执总额

- {{ $summaryStats['receipt_orders'] ?? 0 }} + {{ $summaryStats['receipt_orders'] ?? 0 }} / ¥{{ number_format((float) ($summaryStats['total_receipt_amount'] ?? 0), 2) }}
有回执口径:payment_summary.total_amount 存在或 payment_receipts 有记录
@@ -382,7 +421,7 @@

无回执订单

无 payment_summary 且无 payment_receipts
@@ -391,9 +430,9 @@
建议按以下顺序治理当前筛选集合:
    -
  1. 先处理 对账不一致:优先补齐支付回执,并核对回执渠道/金额,确保回执总额与已付金额一致。
  2. -
  3. 再处理 退款不一致:优先补齐退款回执/核对退款轨迹/修正退款状态(带审计)。
  4. -
  5. 最后处理 可同步:确认无对账/退款异常、无同步失败原因后,再批量同步订阅。
  6. +
  7. 先处理 对账不一致:优先补齐支付回执,并核对回执渠道/金额,确保回执总额与已付金额一致。
  8. +
  9. 再处理 退款不一致:优先补齐退款回执/核对退款轨迹/修正退款状态(带审计)。
  10. +
  11. 最后处理 可同步:确认无对账/退款异常、无同步失败原因后,再批量同步订阅。
说明:本页“批量同步/批量生效/清理失败标记”等工具动作会透传当前筛选条件;建议先缩小到明确集合再操作。
@@ -406,7 +445,7 @@
¥{{ number_format($delta, 2) }}
{{ $summaryStats['reconciliation_delta_note'] ?? '回执总额 - 订单已付总额' }}(当前筛选范围)
@php $tol = (float) config('saasshop.amounts.tolerance', 0.01); @endphp
当前容差:¥{{ number_format($tol, 2) }}
@@ -417,7 +456,7 @@

退款不一致订单

@php $refundTol = (float) config('saasshop.amounts.tolerance', 0.01); @endphp
口径:状态=refunded 但退款总额 + 容差 < 已付;或状态!=refunded 且退款总额 >= 已付 + 容差
@@ -446,12 +485,12 @@ 原因过长,请复制到筛选框 - 进入同步失败集合 + 进入同步失败集合 @else - {{ $reasonText }} + {{ $reasonText }} ({{ $count }}) - 切到可同步重试 + 切到可同步重试 @endif @else (空原因) @@ -488,12 +527,12 @@ 原因过长,请复制到筛选框 - 进入失败集合 + 进入失败集合 @else - {{ $reasonText }} + {{ $reasonText }} ({{ $count }}) - 切到可处理集合重试 + 切到可处理集合重试 @endif @else (空原因) @@ -538,13 +577,13 @@
当前筛选包含 @if($hasReconcileMismatchFilter) - 对账不一致 + 对账不一致 @endif @if($hasReconcileMismatchFilter && $hasRefundInconsistentFilter) @endif @if($hasRefundInconsistentFilter) - 退款不一致 + 退款不一致 @endif 。建议先完成金额/状态治理(补回执/核对退款/修正状态)后,再执行批量同步订阅等工具动作。
@@ -556,7 +595,7 @@
注意:当前同时勾选了「只看可同步」—— 这类订单会被批量同步订阅命中。若仍存在对账/退款异常,建议先进入治理集合处理完毕,再回到可同步集合执行批量同步。
@@ -569,8 +608,8 @@
当前集合为「无回执」且已勾选「只看可同步」。为保证收费闭环可治理,建议先补齐支付回执留痕,再执行批量同步订阅。
@@ -582,8 +621,8 @@
当前筛选包含「同步失败/失败原因」范围。建议先治理失败原因(修复数据或重试同步),再执行批量同步订阅等工具动作。
@@ -595,8 +634,8 @@
当前筛选包含「批量标记支付并生效失败/失败原因」范围。建议先补齐回执/核对退款/修正状态后,再切到 pending+unpaid 集合重试批量标记支付。
@@ -987,7 +1026,7 @@ @if($order->merchant) - {{ $order->merchant->name }} + {{ $order->merchant->name }} @else 未关联站点 @endif @@ -995,7 +1034,7 @@ @php $planName = $order->plan_name ?: ($order->plan?->name ?? '未设置'); @endphp @if($order->plan) - {{ $planName }} + {{ $planName }} @else {{ $planName }} @endif @@ -1019,11 +1058,11 @@ $syncErr = (string) (data_get($order->meta, 'subscription_activation_error.message') ?? ''); @endphp @if($syncedId > 0) - 已同步 + 已同步 @elseif($syncErr !== '') - 同步失败 + 同步失败 @else - 未同步 + 未同步 @endif @@ -1037,7 +1076,7 @@ {{ $order->siteSubscription->subscription_no }}
- 订阅ID:{{ $order->siteSubscription->id }} + 订阅ID:{{ $order->siteSubscription->id }}
@else - @@ -1065,9 +1104,9 @@ @if($syncErrTooLong) {{ mb_substr($syncErrMsg, 0, $SYNC_FAILED_REASON_TRUNCATE_LEN) }}
原因过长,请复制到筛选框
- 进入同步失败集合 + 进入同步失败集合 @else - {{ mb_substr($syncErrMsg, 0, $SYNC_FAILED_REASON_TRUNCATE_LEN) }} + {{ mb_substr($syncErrMsg, 0, $SYNC_FAILED_REASON_TRUNCATE_LEN) }} @endif @endif @@ -1078,9 +1117,9 @@ @if($bmpaErrTooLong) {{ mb_substr($bmpaErrMsg, 0, $SYNC_FAILED_REASON_TRUNCATE_LEN) }}
原因过长,请复制到筛选框
- 进入批量标记支付失败集合 + 进入批量标记支付失败集合 @else - {{ mb_substr($bmpaErrMsg, 0, $SYNC_FAILED_REASON_TRUNCATE_LEN) }} + {{ mb_substr($bmpaErrMsg, 0, $SYNC_FAILED_REASON_TRUNCATE_LEN) }} @endif @endif