Home 结账页访问日志

记录 home 模块四种结账类型(标准 / 单页 / 渐进式 / COD)GET 页面访问,写入 ThinkPHP Log::info,经 seaslog / slslog 同步至 SLS。

目标与范围

约定
模块app/home(不含 homeapi)
请求GET 结账相关页面渲染
业务状态页面正常渲染 = 200订单未找到 = 404
404 判定ExceptionOEM + ErrorConst::DATA_NOT_FOUND(不记店铺不存在等)
结账类型standard / one_page / single_page / cod(对齐 OrderModel::CHECKOUT_PROCESS_*
写入方式Log::info(json_encode(...))config/log.php 默认通道 → SLS

覆盖路由

checkout_type路径示例控制器方法
standard/{store}/checkouts/{token}Order::checkout
standard/checkouts/success/{token}Order::success
standard/checkouts/gateway/{token}Order::gateway
one_page/{store}/one-page-checkouts/{token}OrderOnePage::index
single_page/{store}/single-page-checkouts/{token}OrderSinglePage::index
single_page/{store}/single-page-checkouts/{token}/gatewayOrderSinglePage::gateway
cod/{store}/cod-checkouts/{token}OrderCodPage::index
cod/cod-checkouts/success/{token}OrderCodPage::success

不记录:POST 提交、支付回调、302 跳转(空购物车 / 已支付 / 需登录)、/checkouts/addaddress(虽渲染 checkout 模板但不在路由白名单)、非 DATA_NOT_FOUNDshowfailure

架构:fetch 钩子 + 分散 404

flowchart TD
    subgraph log200 [200]
        F[HomeBaseController.fetch checkout 模板]
        F --> R{GET 且路由白名单}
        R -->|命中| L200[CheckoutAccessLogService.tryLogSuccess]
    end
    subgraph log404 [404]
        C1[Order / OrderOnePage / OrderSinglePage catch]
        C2[ExceptionHandle.handlerDefaultException]
        C1 --> T[tryLogNotFound]
        C2 --> T
        T --> V{DATA_NOT_FOUND 且路由白名单}
        V -->|是| L404[Log 404]
    end

为何不用中间件

中间件只能拿到 HTTP 状态码,无法区分「HTTP 200 的错误提示页」与「正常结账页渲染」;业务 404 需在知晓 DATA_NOT_FOUND 的位置记录。

为何不用逐控制器打 200

所有结账页(含 success / gateway)最终均 fetch('checkout', ...),在 HomeBaseController::fetch 统一打 200,避免 8 个方法各写一行且易漏 success / gateway。

核心实现

CheckoutAccessLogService

路径:common/services/CheckoutAccessLogService.php

方法作用
resolveFromRequest()pathinfo 正则解析 checkout_typecheckout_token;非 GET 或未命中白名单返回 null
tryLogSuccess()渲染成功后写 access_status=200
tryLogNotFound()订单未找到时写 access_status=404

日志字段(snake_case):

{
  "tag": "checkout_page_access",
  "ip": "...",
  "domain": "...",
  "checkout_token": "...",
  "access_status": 200,
  "checkout_type": "standard",
  "url": "..."
}

外层 seaslog 还会附带 store_idtrace_id 等,无需重复写入。

SLS 检索示例:

tag: checkout_page_access AND checkout_type: one_page AND access_status: 404

200 记录点(1 处)

app/home/HomeBaseController.phpfetch() 渲染 checkout 模板成功后:

if ($isCheckoutTemplate) {
    (new CheckoutAccessLogService())->tryLogSuccess($this->request);
}

404 记录点

位置场景
Order.php 内层 catch_checkCheckoutCart 抛错,包装 RedirectException 之前
Order.php 外层 catchcheckout 其它异常
OrderOnePage.php / OrderSinglePage.php catch_checkCheckoutCart 后直接 showfailure
ExceptionHandle::handlerDefaultExceptionOrder::success 等无 try/catch 路径,orderFetchDATA_NOT_FOUND 进入全局异常处理

404 在控制器 catch 中直接调用 tryLogNotFound,不使用额外封装方法。

涉及文件

文件改动
common/services/CheckoutAccessLogService.php新增
app/home/HomeBaseController.phpfetch 挂钩 200
app/home/ExceptionHandle.phphandlerDefaultException 记 404
app/home/controller/Order.php内外层 catch 各 1 行
app/home/controller/OrderOnePage.phpcatch 1 行
app/home/controller/OrderSinglePage.phpindex + gateway catch 各 1 行

验证清单

  1. 四种类型 index GET、正常 token → access_status=200
  2. /checkouts/success/{token}/checkouts/gateway/{token}/cod-checkouts/success/{token} → 200
  3. 无效 token(在线三种 index)→ 404
  4. 无效 token 访问 success → 404(经 ExceptionHandle
  5. /checkouts/addaddress GET → 无日志
  6. 空购物车 redirect → 无日志
  7. POST checkout → 无日志

维护注意

  • 新增结账 URL 形态时,须同步更新 CheckoutAccessLogService::resolveFromRequest() 白名单。
  • Order::gateway 部分路径订单不存在时抛 DB_ERROR 而非 DATA_NOT_FOUND,按本期规则不记 404
  • 与既有 Logger::info('Checkout token:...') 错误日志并存,互不替代。