当前页面采集:分享短链在 Agent 侧展开,goods_id 裁决保留在服务端 #108

Closed
opened 2026-08-27 14:46:14 +08:00 by ila · 4 comments
Owner

所属与来源

  • 关联工单:#101 Agent 当前 PDD 商品页临时采集、#105 剪贴板等待、#106 分享点击稳定与诊断、#107 前台恢复。
  • 来源:用户于 2026-08-27 反馈 #107 上线后 PDD 已能切到前台,但当前页面采集仍然拿不到 goods_id;经代码分析后用户确认采用「短链展开放 Agent、goods_id 裁决权留服务端」的分工,要求建独立工单实施。
  • 类型:Android Agent + Server / 当前页面采集 / 商品身份解析链路缺陷。
  • 设计证据:不新增页面、组件、导航与用户流程;不改动 docs/08-agent-api-contract.md 中 identify 接口的请求与响应字段(仍为 shareUrl 入参、goodsId/url/pddProductId 出参),属于恢复既有预期行为的缺陷修复,不另做原型。

当前事实与根因(提交 ea970c7 复核)

goods_id 全程只由服务端产生,Agent 不参与认定。链路为:剪贴板文本 → PddShareLinkExtractor.extract(android/app/src/main/java/cn/ilapage/goauto/agent/automation/CurrentPageCollection.kt:113)→ identifyCurrentPageCollectionTask(shareUrl) → 服务端 ResolvePDDShareURL(server/app/goauto/task/current_page.go:262)→ goods_id。#107 只修了前台切换,这条解析链未改动。

服务端短链分支存在三个叠加问题:

  1. 只承认 HTTP 3xx:拿 response.Request.URL 作为最终地址(current_page.go:294)。PDD p.pinduoduo.com/xxxx 短链通常返回 200 HTML,靠页面内 JS/meta 跳转,最终 URL 仍是短链,goods_id 为空 → PDD_SHARE_LINK_INVALID「商品链接中没有有效 goods_id」。
  2. 响应正文被 io.Copy(io.Discard, ...) 丢弃(current_page.go:289),即使正文含 goods_id 也从不解析。
  3. UA 为 GoAuto-Agent-Link-Resolver/1.0(current_page.go:285),配合机房 IP,极易命中 PDD 风控页或落地页。

覆盖缺口:server/app/goauto/task/current_page_test.go:66 用注入的假 resolver,:132 只覆盖 mobile.yangkeduo.com/goods.html?goods_id= 长链与非法输入;真实短链的 HTTP 展开在任何提交上都没有被验证过。

Agent 端另有两个次级缺陷:

  1. PddShareLinkExtractor 的正则为 https://[^\s]+(CurrentPageCollection.kt:114),只裁剪尾部标点。PDD 复制文案若为「…https://p.pinduoduo.com/xxx,快来拼」这类链接后无空格的形式,中文会被并入 URL,URI 解析仍通过(host 合法),于是把坏链接发给服务端。
  2. extract 用 singleOrNull(CurrentPageCollection.kt:123),文案含两个合法链接时直接放弃,而不是优先选商品链接。

目标

  1. 把「展开短链」这一环境相关的取数动作放到 Agent 侧执行:手机真实网络环境成功率显著高于服务器。
  2. goods_id 的最终认定、归一化、商品建档与并发互斥全部保留在服务端,Agent 不得认定或猜测 goods_id。
  3. Agent 侧链接提取对真实 PDD 复制文案更健壮。
  4. 服务端短链解析降级为兜底,并补齐测试覆盖。

非目标

  • 不修改 identify 接口的请求与响应字段,不修改数据库结构。
  • 不修改分享点击、剪贴板读取、诊断与前台恢复逻辑(#105 / #106 / #107 范围)。
  • Agent 不解析页面正文、不做 OCR/VLM、不猜测 goods_id、不选择相似商品。
  • 不涉及采购、地址、创建订单与支付。
  • 不修改 Admin、Web 与采集规则格式。

分工原则(本工单的设计前提)

  • 取数在 Agent:短链展开依赖真实 App 环境、家宽 IP 与真实 UA,属环境相关取数,不属业务决策,因此不受 #46「规格匹配决策权在服务端」的约束。同时避免在服务端新增一条主动出网到 PDD 域名的通道。
  • 裁决在服务端:域名白名单、^[0-9]{5,32}$ 格式校验、归一化为 https://mobile.yangkeduo.com/goods.html?goods_id=、查建 pdd_product、同商品并发任务互斥,一步都不下放到 Agent。Agent 只上报它看到的链接,服务端决定这条链接算不算数。

实施方案

Agent 侧

  1. 链接提取加固:
    • URL 正则收紧为 URL 合法字符集,遇到中文、全角标点等非法字符即截断,不再依赖尾部 trim 兜底;
    • 多个合法链接时,优先选择带 goods_id 参数的商品长链,其次选择白名单短链;仍然为零候选或候选相互冲突(指向不同 goods_id)时明确失败,不做任意挑选;
    • 域名白名单沿用 p.pinduoduo.com 与 mobile.yangkeduo.com。
  2. 新增短链展开步骤(在 identify 调用之前):
    • 已经是含 goods_id 的长链时直接上报,不发起任何网络请求;
    • 仅当是白名单短链时,用 HttpURLConnection(与 AgentApiClient 一致,不引入新依赖)发起 GET,手动跟随 3xx,最多 4 跳,连接与读取超时各不超过 5 秒;
    • 每一跳都必须重新校验 scheme=https、域名在白名单、无 userinfo、端口为空或 443,任一不满足立即失败;
    • 最终 URL 含 goods_id 时上报该长链;跟随结束仍无 goods_id 时,允许在受限正文(上限 64KB)中用受限正则提取 goods_id,只接受数字并交由服务端再校验;
    • 请求不携带 Cookie、不携带任何本项目凭据、不复用 AgentApiClient 的鉴权头;UA 使用普通移动端 UA 常量。
  3. 展开失败时明确失败,返回 PDD_SHARE_LINK_INVALID,不回退为「把短链原样上报」以外的任何猜测行为;短链原样上报仍然允许(由服务端兜底解析),但必须记入诊断。
  4. 诊断复用 #106 的 AgentDiagnosticStore,新增链接解析阶段的结构化原因(LONG_LINK_DIRECT / SHORT_LINK_EXPANDED / SHORT_LINK_FAILED / LINK_AMBIGUOUS / LINK_NOT_FOUND)。诊断不得记录链接原文、goods_id、剪贴板正文与页面正文。

Server 侧

  1. IdentifyCurrentPage 的校验、归一化、建档与互斥逻辑保持不变,继续以服务端结果为准;Agent 上报的链接一律重新校验,不因来自 Agent 而放宽。
  2. ResolvePDDShareURL 的短链 HTTP 分支保留为兜底路径(Agent 只能给出短链时仍会用到),同时修正其明显缺陷:允许读取受限正文并从中提取 goods_id,UA 改为普通移动端 UA;域名白名单、跳转上限、超时与「正文不落盘」保持不变。
  3. 补测试:用 httptest 覆盖 302 跳转到长链、200 + 正文内含 goods_id、200 无 goods_id、跳转到白名单外域名、跳转次数超限五种响应,断言错误码与归一化结果。

安全边界

  • Agent 的短链展开请求不携带 Cookie、Token、账号与任何个人数据;不复用服务端鉴权连接。
  • 每一跳都做域名白名单与 scheme/端口/userinfo 校验,不跟随白名单外域名。
  • 链接原文、页面正文、剪贴板正文一律不落盘、不入日志、不写诊断。
  • Agent 不认定 goods_id;服务端对 Agent 上报的一切内容重新校验。
  • 不使用 OCR/VLM,不猜测商品,不采购、不改地址、不创建订单、不支付。

验收标准

  • PDD 复制得到含 goods_id 的长链时,Agent 不发起额外网络请求,直接上报并成功识别。
  • PDD 复制得到 p.pinduoduo.com 短链时,Agent 在手机侧展开为含 goods_id 的长链并成功识别。
  • 复制文案中链接后紧跟中文且无空格时,提取到的链接不含中文字符。
  • 复制文案含多个链接时,优先选中商品长链;候选指向不同 goods_id 时明确失败。
  • 展开过程中出现白名单外域名、超过 4 跳或超时,均明确失败且不崩溃。
  • Agent 只能给出短链时,服务端兜底解析仍可工作,且五种 httptest 响应的错误码与归一化结果符合预期。
  • 服务端对 Agent 上报链接的白名单、格式、归一化与并发互斥校验未被放宽(以现有服务端测试全部通过为准)。
  • 诊断记录不含链接原文、goods_id、剪贴板正文与页面正文。
  • 采集成功后续流程(详情采集与提交)行为不变。

验证方式

  • ./gradlew :app:testDebugUnitTest(Agent 单元测试,含链接提取与短链展开的纯函数测试)。
  • go test ./app/goauto/task/... ./app/goauto/product/...(服务端)。
  • 真机验证:一加 PKG110 或等价设备,分别验证长链与短链两类复制文案;记录设备型号、Agent 版本、规则快照与任务号。
  • 真机、多设备与云环境未覆盖的部分必须在工单如实记录。

风险与回退

  • PDD 后续改版可能再次改变复制文案与短链形态;本方案把易变部分(域名白名单、goods_id 格式、归一化)保留在服务端,Agent 侧只保留「跟随跳转」这一不随改版而变的动作,以降低重发 APK 的概率。
  • Agent 侧新增出网请求可能受个别设备网络策略影响;失败时服务端兜底解析仍在,且失败可从诊断区分。
  • 回退方式:还原本工单提交即可回到「服务端主解析」的旧行为,不涉及数据结构与接口变更。

文档影响

  • 待实施时确认:若 Wiki 中描述了当前页面采集的商品身份解析责任划分,需同步更新对应页面(解析在 Agent、裁决在服务端);docs/08-agent-api-contract.md 的字段不变,若其中有解析责任的文字描述则一并更新。无长期事实变化时在工单说明原因并跳过 Wiki 同步。

状态

待实施(由 Codex 执行)。

## 所属与来源 - 关联工单:#101 Agent 当前 PDD 商品页临时采集、#105 剪贴板等待、#106 分享点击稳定与诊断、#107 前台恢复。 - 来源:用户于 2026-08-27 反馈 #107 上线后 PDD 已能切到前台,但当前页面采集仍然拿不到 goods_id;经代码分析后用户确认采用「短链展开放 Agent、goods_id 裁决权留服务端」的分工,要求建独立工单实施。 - 类型:Android Agent + Server / 当前页面采集 / 商品身份解析链路缺陷。 - 设计证据:不新增页面、组件、导航与用户流程;不改动 `docs/08-agent-api-contract.md` 中 `identify` 接口的请求与响应字段(仍为 `shareUrl` 入参、`goodsId`/`url`/`pddProductId` 出参),属于恢复既有预期行为的缺陷修复,不另做原型。 ## 当前事实与根因(提交 ea970c7 复核) goods_id 全程只由服务端产生,Agent 不参与认定。链路为:剪贴板文本 → `PddShareLinkExtractor.extract`(`android/app/src/main/java/cn/ilapage/goauto/agent/automation/CurrentPageCollection.kt:113`)→ `identifyCurrentPageCollectionTask(shareUrl)` → 服务端 `ResolvePDDShareURL`(`server/app/goauto/task/current_page.go:262`)→ `goods_id`。#107 只修了前台切换,这条解析链未改动。 服务端短链分支存在三个叠加问题: 1. 只承认 HTTP 3xx:拿 `response.Request.URL` 作为最终地址(`current_page.go:294`)。PDD `p.pinduoduo.com/xxxx` 短链通常返回 200 HTML,靠页面内 JS/meta 跳转,最终 URL 仍是短链,`goods_id` 为空 → `PDD_SHARE_LINK_INVALID`「商品链接中没有有效 goods_id」。 2. 响应正文被 `io.Copy(io.Discard, ...)` 丢弃(`current_page.go:289`),即使正文含 goods_id 也从不解析。 3. UA 为 `GoAuto-Agent-Link-Resolver/1.0`(`current_page.go:285`),配合机房 IP,极易命中 PDD 风控页或落地页。 覆盖缺口:`server/app/goauto/task/current_page_test.go:66` 用注入的假 resolver,`:132` 只覆盖 `mobile.yangkeduo.com/goods.html?goods_id=` 长链与非法输入;真实短链的 HTTP 展开在任何提交上都没有被验证过。 Agent 端另有两个次级缺陷: 4. `PddShareLinkExtractor` 的正则为 `https://[^\s]+`(`CurrentPageCollection.kt:114`),只裁剪尾部标点。PDD 复制文案若为「…https://p.pinduoduo.com/xxx,快来拼」这类链接后无空格的形式,中文会被并入 URL,`URI` 解析仍通过(host 合法),于是把坏链接发给服务端。 5. `extract` 用 `singleOrNull`(`CurrentPageCollection.kt:123`),文案含两个合法链接时直接放弃,而不是优先选商品链接。 ## 目标 1. 把「展开短链」这一环境相关的取数动作放到 Agent 侧执行:手机真实网络环境成功率显著高于服务器。 2. goods_id 的最终认定、归一化、商品建档与并发互斥全部保留在服务端,Agent 不得认定或猜测 goods_id。 3. Agent 侧链接提取对真实 PDD 复制文案更健壮。 4. 服务端短链解析降级为兜底,并补齐测试覆盖。 ## 非目标 - 不修改 `identify` 接口的请求与响应字段,不修改数据库结构。 - 不修改分享点击、剪贴板读取、诊断与前台恢复逻辑(#105 / #106 / #107 范围)。 - Agent 不解析页面正文、不做 OCR/VLM、不猜测 goods_id、不选择相似商品。 - 不涉及采购、地址、创建订单与支付。 - 不修改 Admin、Web 与采集规则格式。 ## 分工原则(本工单的设计前提) - **取数在 Agent**:短链展开依赖真实 App 环境、家宽 IP 与真实 UA,属环境相关取数,不属业务决策,因此不受 #46「规格匹配决策权在服务端」的约束。同时避免在服务端新增一条主动出网到 PDD 域名的通道。 - **裁决在服务端**:域名白名单、`^[0-9]{5,32}$` 格式校验、归一化为 `https://mobile.yangkeduo.com/goods.html?goods_id=`、查建 `pdd_product`、同商品并发任务互斥,一步都不下放到 Agent。Agent 只上报它看到的链接,服务端决定这条链接算不算数。 ## 实施方案 ### Agent 侧 1. 链接提取加固: - URL 正则收紧为 URL 合法字符集,遇到中文、全角标点等非法字符即截断,不再依赖尾部 trim 兜底; - 多个合法链接时,优先选择带 `goods_id` 参数的商品长链,其次选择白名单短链;仍然为零候选或候选相互冲突(指向不同 goods_id)时明确失败,不做任意挑选; - 域名白名单沿用 `p.pinduoduo.com` 与 `mobile.yangkeduo.com`。 2. 新增短链展开步骤(在 `identify` 调用之前): - 已经是含 `goods_id` 的长链时直接上报,不发起任何网络请求; - 仅当是白名单短链时,用 `HttpURLConnection`(与 `AgentApiClient` 一致,不引入新依赖)发起 GET,手动跟随 3xx,最多 4 跳,连接与读取超时各不超过 5 秒; - 每一跳都必须重新校验 scheme=https、域名在白名单、无 userinfo、端口为空或 443,任一不满足立即失败; - 最终 URL 含 `goods_id` 时上报该长链;跟随结束仍无 `goods_id` 时,允许在受限正文(上限 64KB)中用受限正则提取 `goods_id`,只接受数字并交由服务端再校验; - 请求不携带 Cookie、不携带任何本项目凭据、不复用 `AgentApiClient` 的鉴权头;UA 使用普通移动端 UA 常量。 3. 展开失败时明确失败,返回 `PDD_SHARE_LINK_INVALID`,不回退为「把短链原样上报」以外的任何猜测行为;短链原样上报仍然允许(由服务端兜底解析),但必须记入诊断。 4. 诊断复用 #106 的 `AgentDiagnosticStore`,新增链接解析阶段的结构化原因(`LONG_LINK_DIRECT / SHORT_LINK_EXPANDED / SHORT_LINK_FAILED / LINK_AMBIGUOUS / LINK_NOT_FOUND`)。诊断不得记录链接原文、goods_id、剪贴板正文与页面正文。 ### Server 侧 5. `IdentifyCurrentPage` 的校验、归一化、建档与互斥逻辑保持不变,继续以服务端结果为准;Agent 上报的链接一律重新校验,不因来自 Agent 而放宽。 6. `ResolvePDDShareURL` 的短链 HTTP 分支保留为兜底路径(Agent 只能给出短链时仍会用到),同时修正其明显缺陷:允许读取受限正文并从中提取 `goods_id`,UA 改为普通移动端 UA;域名白名单、跳转上限、超时与「正文不落盘」保持不变。 7. 补测试:用 `httptest` 覆盖 302 跳转到长链、200 + 正文内含 goods_id、200 无 goods_id、跳转到白名单外域名、跳转次数超限五种响应,断言错误码与归一化结果。 ## 安全边界 - Agent 的短链展开请求不携带 Cookie、Token、账号与任何个人数据;不复用服务端鉴权连接。 - 每一跳都做域名白名单与 scheme/端口/userinfo 校验,不跟随白名单外域名。 - 链接原文、页面正文、剪贴板正文一律不落盘、不入日志、不写诊断。 - Agent 不认定 goods_id;服务端对 Agent 上报的一切内容重新校验。 - 不使用 OCR/VLM,不猜测商品,不采购、不改地址、不创建订单、不支付。 ## 验收标准 - [ ] PDD 复制得到含 `goods_id` 的长链时,Agent 不发起额外网络请求,直接上报并成功识别。 - [ ] PDD 复制得到 `p.pinduoduo.com` 短链时,Agent 在手机侧展开为含 `goods_id` 的长链并成功识别。 - [ ] 复制文案中链接后紧跟中文且无空格时,提取到的链接不含中文字符。 - [ ] 复制文案含多个链接时,优先选中商品长链;候选指向不同 goods_id 时明确失败。 - [ ] 展开过程中出现白名单外域名、超过 4 跳或超时,均明确失败且不崩溃。 - [ ] Agent 只能给出短链时,服务端兜底解析仍可工作,且五种 httptest 响应的错误码与归一化结果符合预期。 - [ ] 服务端对 Agent 上报链接的白名单、格式、归一化与并发互斥校验未被放宽(以现有服务端测试全部通过为准)。 - [ ] 诊断记录不含链接原文、goods_id、剪贴板正文与页面正文。 - [ ] 采集成功后续流程(详情采集与提交)行为不变。 ## 验证方式 - `./gradlew :app:testDebugUnitTest`(Agent 单元测试,含链接提取与短链展开的纯函数测试)。 - `go test ./app/goauto/task/... ./app/goauto/product/...`(服务端)。 - 真机验证:一加 PKG110 或等价设备,分别验证长链与短链两类复制文案;记录设备型号、Agent 版本、规则快照与任务号。 - 真机、多设备与云环境未覆盖的部分必须在工单如实记录。 ## 风险与回退 - PDD 后续改版可能再次改变复制文案与短链形态;本方案把易变部分(域名白名单、goods_id 格式、归一化)保留在服务端,Agent 侧只保留「跟随跳转」这一不随改版而变的动作,以降低重发 APK 的概率。 - Agent 侧新增出网请求可能受个别设备网络策略影响;失败时服务端兜底解析仍在,且失败可从诊断区分。 - 回退方式:还原本工单提交即可回到「服务端主解析」的旧行为,不涉及数据结构与接口变更。 ## 文档影响 - 待实施时确认:若 Wiki 中描述了当前页面采集的商品身份解析责任划分,需同步更新对应页面(解析在 Agent、裁决在服务端);`docs/08-agent-api-contract.md` 的字段不变,若其中有解析责任的文字描述则一并更新。无长期事实变化时在工单说明原因并跳过 Wiki 同步。 ## 状态 待实施(由 Codex 执行)。
Author
Owner

开始实施(2026-08-27)

已核对 #101/#105/#106/#107、当前 Android/Server 解析链与采集业务规则。按工单范围实施:

  • Android 加固复制文案 URL 提取,并在手机侧用无项目凭据的受限请求展开 PDD 短链;
  • goods_id 最终校验、规范化、商品建档和并发互斥继续全部由服务端裁决;
  • 服务端保留短链兜底,补 200 HTML 正文解析和五类 httptest;
  • 诊断只新增枚举阶段/原因,不保存链接、goods_id、剪贴板或正文。

不修改数据库、identify 接口字段、任务创建顺序、Admin、规则、采购或支付能力。

## 开始实施(2026-08-27) 已核对 #101/#105/#106/#107、当前 Android/Server 解析链与采集业务规则。按工单范围实施: - Android 加固复制文案 URL 提取,并在手机侧用无项目凭据的受限请求展开 PDD 短链; - goods_id 最终校验、规范化、商品建档和并发互斥继续全部由服务端裁决; - 服务端保留短链兜底,补 200 HTML 正文解析和五类 httptest; - 诊断只新增枚举阶段/原因,不保存链接、goods_id、剪贴板或正文。 不修改数据库、identify 接口字段、任务创建顺序、Admin、规则、采购或支付能力。
Author
Owner

实现完成,待验收(2026-08-27)

实现

  • Agent 更新为 0.9.5(versionCode 18)。
  • 复制文案 URL 提取改为 ASCII URL 合法字符范围,链接后紧跟中文或全角标点时会就地截断。
  • 多链接选择规则:
    • 优先含 5~32 位数字 goods_id 的白名单长链;
    • 同一 goods_id 的重复长链可合并;
    • 不同 goods_id 或多个不同短链明确判为歧义,不任意挑选。
  • 长链直接提交,不发起额外展开请求。
  • p.pinduoduo.com 短链优先在 Agent 手机网络侧展开:
    • 使用独立 HttpURLConnection,不携带 Cookie、项目 Token、账号或个人数据;
    • 普通移动端 UA,连接/读取超时各 5 秒;
    • 手动跟随最多 4 跳,每跳重新校验 HTTPS、白名单主机、端口和 userinfo;
    • 最多读取 64KB 正文,只用受限正则提取数字 goods_id,然后仍交给服务端复核;
    • 展开失败时记录结构化原因并把原短链交给服务端兜底,不猜测商品。
  • 服务端 identify 字段和最终裁决保持不变:重新校验链接、5~32 位数字格式、标准 URL、商品查建与同商品并发互斥。
  • 服务端短链兜底改用移动端 UA,除 3xx 最终 URL 外也读取最多 64KB 的 200 HTML 正文;正文中出现零个或多个冲突 goods_id 均拒绝。
  • 诊断新增 LINK_RESOLUTION 及五个固定原因;数据结构没有链接、goods_id、剪贴板正文或响应正文字段。
  • 本工单未改变 #101 的任务创建顺序,未修改数据库、Admin、规则、采购、地址、订单或支付能力。

自动化验证

  • cd android && .\gradlew.bat :app:testDebugUnitTest :app:assembleDebug:通过。
  • Android 覆盖:长链零网络请求、短链 302/正文展开、中文紧邻截断、长链优先、身份冲突、白名单外跳转、超过 4 跳、超时及诊断原因。
  • cd server && go test ./app/goauto/task/... ./app/goauto/product/...:通过。
  • cd server && go test ./...:通过。
  • 服务端 httptest 覆盖:302 到长链、200 正文 goods_id、200 无 goods_id、跳转到白名单外、超过 4 跳。
  • python dev_scripts/harness.py check --strict、git diff --check:通过。

真机

  • 一加 PKG110 安装前确认 Agent 在线空闲。
  • 已覆盖安装 0.9.5 / versionCode 18,无障碍服务保持启用。
  • 未自动创建业务采集任务:没有明确指定本次授权测试商品,因此长链与短链完整真机采集仍待人工验收;未覆盖多设备与云环境。

Wiki

已更新线上页面并回读 revision:

  • Architecture-and-Code-Map:2f4a3a546d12
  • Business-Rules-and-Glossary:2c2d84b24108
  • Local-Development-and-Verification:3ba5cf24adcd
  • Android-Agent-API-Contract:7645ee794b5b

python dev_scripts/harness.py sync 与唯一一轮 sync --check 均通过。

提交

  • 20775cc1bfd74d3539a4bc54ec723b176b540e3e fix: resolve PDD share links on Agent (#108)

工单保持打开,等待人工验收。

## 实现完成,待验收(2026-08-27) ### 实现 - Agent 更新为 **0.9.5(versionCode 18)**。 - 复制文案 URL 提取改为 ASCII URL 合法字符范围,链接后紧跟中文或全角标点时会就地截断。 - 多链接选择规则: - 优先含 5~32 位数字 `goods_id` 的白名单长链; - 同一 goods_id 的重复长链可合并; - 不同 goods_id 或多个不同短链明确判为歧义,不任意挑选。 - 长链直接提交,不发起额外展开请求。 - `p.pinduoduo.com` 短链优先在 Agent 手机网络侧展开: - 使用独立 `HttpURLConnection`,不携带 Cookie、项目 Token、账号或个人数据; - 普通移动端 UA,连接/读取超时各 5 秒; - 手动跟随最多 4 跳,每跳重新校验 HTTPS、白名单主机、端口和 userinfo; - 最多读取 64KB 正文,只用受限正则提取数字 goods_id,然后仍交给服务端复核; - 展开失败时记录结构化原因并把原短链交给服务端兜底,不猜测商品。 - 服务端 `identify` 字段和最终裁决保持不变:重新校验链接、5~32 位数字格式、标准 URL、商品查建与同商品并发互斥。 - 服务端短链兜底改用移动端 UA,除 3xx 最终 URL 外也读取最多 64KB 的 200 HTML 正文;正文中出现零个或多个冲突 goods_id 均拒绝。 - 诊断新增 `LINK_RESOLUTION` 及五个固定原因;数据结构没有链接、goods_id、剪贴板正文或响应正文字段。 - 本工单未改变 #101 的任务创建顺序,未修改数据库、Admin、规则、采购、地址、订单或支付能力。 ### 自动化验证 - `cd android && .\gradlew.bat :app:testDebugUnitTest :app:assembleDebug`:通过。 - Android 覆盖:长链零网络请求、短链 302/正文展开、中文紧邻截断、长链优先、身份冲突、白名单外跳转、超过 4 跳、超时及诊断原因。 - `cd server && go test ./app/goauto/task/... ./app/goauto/product/...`:通过。 - `cd server && go test ./...`:通过。 - 服务端 httptest 覆盖:302 到长链、200 正文 goods_id、200 无 goods_id、跳转到白名单外、超过 4 跳。 - `python dev_scripts/harness.py check --strict`、`git diff --check`:通过。 ### 真机 - 一加 PKG110 安装前确认 Agent 在线空闲。 - 已覆盖安装 **0.9.5 / versionCode 18**,无障碍服务保持启用。 - 未自动创建业务采集任务:没有明确指定本次授权测试商品,因此长链与短链完整真机采集仍待人工验收;未覆盖多设备与云环境。 ### Wiki 已更新线上页面并回读 revision: - Architecture-and-Code-Map:`2f4a3a546d12` - Business-Rules-and-Glossary:`2c2d84b24108` - Local-Development-and-Verification:`3ba5cf24adcd` - Android-Agent-API-Contract:`7645ee794b5b` `python dev_scripts/harness.py sync` 与唯一一轮 `sync --check` 均通过。 ### 提交 - `20775cc1bfd74d3539a4bc54ec723b176b540e3e fix: resolve PDD share links on Agent (#108)` 工单保持打开,等待人工验收。
Author
Owner

后续关联

  • 2026-08-27:#108 上线后(Agent 0.9.5、提交 20775cc)实测仍无法解析链接。根因不在展开实现,而在触发条件:两端都按 host == "p.pinduoduo.com" 判断是否需要展开,而 PDD 实际复制到的是 https://mobile.yangkeduo.com/goods2.html?ps=...,域名在白名单内但 query 无 goods_id,于是在 Agent 端 select() 返回 NOT_FOUND、服务端 current_page.go:279 直接拒绝,展开逻辑从未被执行。
  • 已另建 #109 处理:触发条件改为「白名单域名 + query 无 goods_id」,Agent 与服务端同步修改,并对齐两端正文正则(消除 refer_goods_id 误匹配)。
  • #108 确立的分工(展开在 Agent、goods_id 裁决在服务端)不变。
## 后续关联 - 2026-08-27:#108 上线后(Agent 0.9.5、提交 `20775cc`)实测仍无法解析链接。根因不在展开实现,而在触发条件:两端都按 `host == "p.pinduoduo.com"` 判断是否需要展开,而 PDD 实际复制到的是 `https://mobile.yangkeduo.com/goods2.html?ps=...`,域名在白名单内但 query 无 `goods_id`,于是在 Agent 端 `select()` 返回 `NOT_FOUND`、服务端 `current_page.go:279` 直接拒绝,展开逻辑从未被执行。 - 已另建 #109 处理:触发条件改为「白名单域名 + query 无 goods_id」,Agent 与服务端同步修改,并对齐两端正文正则(消除 `refer_goods_id` 误匹配)。 - #108 确立的分工(展开在 Agent、goods_id 裁决在服务端)不变。
Author
Owner

用户于 2026-08-28 明确确认本工单验收通过。按项目流程记录验收结论并关闭工单;本次仅更新工单状态,无新增长期文档事实,不重复同步 Wiki。

用户于 2026-08-28 明确确认本工单验收通过。按项目流程记录验收结论并关闭工单;本次仅更新工单状态,无新增长期文档事实,不重复同步 Wiki。
ila closed this issue 2026-08-28 15:07:12 +08:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#108