实现 site_interact 加购与购物车校验(Playwright 通道)
探针实测发现 httpx 因 TLS/HTTP2 指纹被 Rakuten 拒认(cookie 有效但 站点不识别 session),site_interact 改为全程 Playwright + storage_state。 add_to_cart 与 verify_cart 已实测可用:从商品页 __INITIAL_STATE__ 抽 purchase 块、调用方补 variant_id 与 choice、POST basketDomain、用 cart count JSONP API 与 SPA 渲染后的 cart 页校验。enter_checkout 及之后仍 NotImplementedError:Rakuten 对 checkout 要求 session upgrade(重输密码), 是自动 checkout 的硬墙,未实测过墙方案前留接口缝。 SiteInteractor 类持有 Playwright BrowserContext,由 WorkerRunner 实例 持有、container/main 接线、lifespan 管理生命周期。测试侧 23 个用例, 全套件 333 passed,架构边界守住。 附 5 个探针脚本(scripts/probe_*.py),记录实测路径与响应结构。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -30,11 +30,12 @@ from typing import TYPE_CHECKING
|
||||
|
||||
from app.shared.errors import AppError, OrderGuardError
|
||||
from app.shared.task_state import OrderState, TaskStatus
|
||||
from app.trading.worker import site_interact, verify
|
||||
from app.trading.worker import verify
|
||||
from app.trading.worker.client import GatewayClient
|
||||
from app.trading.worker.evidence import EvidenceStore
|
||||
from app.trading.worker.local_db import LocalDB
|
||||
from app.trading.worker.models import LeaseTask
|
||||
from app.trading.worker.site_interact import SiteInteractor
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.shared.config import Settings
|
||||
@@ -67,11 +68,13 @@ class WorkerRunner:
|
||||
gateway_client: GatewayClient,
|
||||
local_db: LocalDB,
|
||||
evidence: EvidenceStore,
|
||||
site: SiteInteractor,
|
||||
):
|
||||
self._settings = settings
|
||||
self._gateway = gateway_client
|
||||
self._db = local_db
|
||||
self._evidence = evidence
|
||||
self._site = site
|
||||
self._running = False
|
||||
|
||||
def stop(self) -> None:
|
||||
@@ -231,7 +234,7 @@ class WorkerRunner:
|
||||
# 步骤 1:加购
|
||||
await self._run_step(
|
||||
task, step_no=1, step_name="cart-add",
|
||||
action=lambda: site_interact.add_to_cart(task),
|
||||
action=lambda: self._site.add_to_cart(task),
|
||||
state=OrderState.IN_CART,
|
||||
detail="已加入购物车",
|
||||
)
|
||||
@@ -239,14 +242,14 @@ class WorkerRunner:
|
||||
# 步骤 2:校验购物车
|
||||
await self._run_step(
|
||||
task, step_no=2, step_name="cart-check",
|
||||
action=lambda: site_interact.verify_cart(task),
|
||||
action=lambda: self._site.verify_cart(task),
|
||||
state=OrderState.IN_CART,
|
||||
detail="购物车已校验",
|
||||
)
|
||||
|
||||
# 步骤 3:进入下单确认页 + 金额守卫
|
||||
checkout_html = await site_interact.enter_checkout(task)
|
||||
summary = await site_interact.parse_checkout(checkout_html)
|
||||
checkout_html = await self._site.enter_checkout(task)
|
||||
summary = await self._site.parse_checkout(checkout_html)
|
||||
self._enforce_amount_guard(task, summary.payable_yen)
|
||||
await self._run_step(
|
||||
task, step_no=3, step_name="order-confirm",
|
||||
@@ -261,7 +264,7 @@ class WorkerRunner:
|
||||
)
|
||||
|
||||
# 步骤 4:提交下单
|
||||
site_order_id = await site_interact.submit_order(task)
|
||||
site_order_id = await self._site.submit_order(task)
|
||||
await self._run_step(
|
||||
task, step_no=4, step_name="order-submit",
|
||||
action=self._noop(),
|
||||
@@ -273,7 +276,7 @@ class WorkerRunner:
|
||||
# 步骤 5:付款
|
||||
await self._run_step(
|
||||
task, step_no=5, step_name="payment",
|
||||
action=lambda: site_interact.pay(task, site_order_id),
|
||||
action=lambda: self._site.pay(task, site_order_id),
|
||||
state=OrderState.AWAITING_PAYMENT,
|
||||
site_order_id=site_order_id,
|
||||
payable_yen=summary.payable_yen,
|
||||
@@ -294,7 +297,7 @@ class WorkerRunner:
|
||||
|
||||
# 步骤 6:付款后监控(非阻塞,常驻轮询;当前未实现)
|
||||
try:
|
||||
await site_interact.monitor(task, site_order_id)
|
||||
await self._site.monitor(task, site_order_id)
|
||||
except NotImplementedError:
|
||||
logger.info("付款后监控未实现,跳过:task_id=%s", task.task_id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user