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}/gateway | OrderSinglePage::gateway |
cod | /{store}/cod-checkouts/{token} | OrderCodPage::index |
cod | /cod-checkouts/success/{token} | OrderCodPage::success |
不记录:POST 提交、支付回调、302 跳转(空购物车 / 已支付 / 需登录)、/checkouts/addaddress(虽渲染 checkout 模板但不在路由白名单)、非 DATA_NOT_FOUND 的 showfailure。
架构: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_type、checkout_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_id、trace_id 等,无需重复写入。
SLS 检索示例:
tag: checkout_page_access AND checkout_type: one_page AND access_status: 404
200 记录点(1 处)
app/home/HomeBaseController.php — fetch() 渲染 checkout 模板成功后:
if ($isCheckoutTemplate) {
(new CheckoutAccessLogService())->tryLogSuccess($this->request);
}404 记录点
| 位置 | 场景 |
|---|---|
Order.php 内层 catch | _checkCheckoutCart 抛错,包装 RedirectException 之前 |
Order.php 外层 catch | checkout 其它异常 |
OrderOnePage.php / OrderSinglePage.php catch | _checkCheckoutCart 后直接 showfailure 前 |
ExceptionHandle::handlerDefaultException | Order::success 等无 try/catch 路径,orderFetch 抛 DATA_NOT_FOUND 进入全局异常处理 |
404 在控制器 catch 中直接调用 tryLogNotFound,不使用额外封装方法。
涉及文件
| 文件 | 改动 |
|---|---|
common/services/CheckoutAccessLogService.php | 新增 |
app/home/HomeBaseController.php | fetch 挂钩 200 |
app/home/ExceptionHandle.php | handlerDefaultException 记 404 |
app/home/controller/Order.php | 内外层 catch 各 1 行 |
app/home/controller/OrderOnePage.php | catch 1 行 |
app/home/controller/OrderSinglePage.php | index + gateway catch 各 1 行 |
验证清单
- 四种类型 index GET、正常 token →
access_status=200 /checkouts/success/{token}、/checkouts/gateway/{token}、/cod-checkouts/success/{token}→ 200- 无效 token(在线三种 index)→ 404
- 无效 token 访问 success → 404(经
ExceptionHandle) /checkouts/addaddressGET → 无日志- 空购物车 redirect → 无日志
- POST checkout → 无日志
维护注意
- 新增结账 URL 形态时,须同步更新
CheckoutAccessLogService::resolveFromRequest()白名单。 Order::gateway部分路径订单不存在时抛DB_ERROR而非DATA_NOT_FOUND,按本期规则不记 404。- 与既有
Logger::info('Checkout token:...')错误日志并存,互不替代。