diff --git a/android/app/src/main/java/cn/ilapage/goauto/agent/automation/PurchaseLiveAutomation.kt b/android/app/src/main/java/cn/ilapage/goauto/agent/automation/PurchaseLiveAutomation.kt index b13d1dd..18779ff 100644 --- a/android/app/src/main/java/cn/ilapage/goauto/agent/automation/PurchaseLiveAutomation.kt +++ b/android/app/src/main/java/cn/ilapage/goauto/agent/automation/PurchaseLiveAutomation.kt @@ -163,9 +163,12 @@ class PurchaseLiveAutomation( return unknown("PURCHASE_ORDER_UNEXPECTED_APP", "核单期间出现未授权应用") } if (restoredFromWechat) pddObservedAfterWechatRestore = true - val paymentVisible = isKnownPddPaymentActivity(snapshot) val orderContextVisible = currentLabels.any { label -> ORDER_CONTEXT_MARKERS.any(label::contains) } val unpaidContextVisible = currentLabels.any { label -> UNPAID_MARKERS.any(label::contains) } + // PDD can reuse its payment Activity for a read-only unpaid order page. + // Visible order-result evidence takes precedence over the Activity name: + // it permits only bounded reading gestures below, never a payment click. + val paymentVisible = isKnownPddPaymentActivity(snapshot) && !orderContextVisible && !unpaidContextVisible if (paymentVisible) { if (!backedOutOfPayment) { backedOutOfPayment = true diff --git a/android/app/src/test/java/cn/ilapage/goauto/agent/PurchaseLiveAutomationTest.kt b/android/app/src/test/java/cn/ilapage/goauto/agent/PurchaseLiveAutomationTest.kt index fe4a2f8..206f043 100644 --- a/android/app/src/test/java/cn/ilapage/goauto/agent/PurchaseLiveAutomationTest.kt +++ b/android/app/src/test/java/cn/ilapage/goauto/agent/PurchaseLiveAutomationTest.kt @@ -168,6 +168,22 @@ class PurchaseLiveAutomationTest { assertFalse(driver.clicked.any { it.contains("支付") }) } + @Test + fun `unpaid order evidence on reused payment activity scrolls read only instead of backing out`() { + val driver = LiveDriver(postSubmitCaptureSequence = listOf("order-folded-payment-activity")) + val automation = PurchaseLiveAutomation(driver, pause = {}) + val address = automation.updateShippingAddress("_cg59") + automation.finalConfirmation(input().copy(addressSuffix = "_cg59"), address) + automation.submitOrderOnce() + + val order = automation.readOrderResult() + + assertEquals("PDD-202608210001", order?.orderNo) + assertEquals(0, driver.postSubmitBackCount) + assertEquals(1, driver.genericSwipes) + assertFalse(driver.clicked.any { it.contains("支付") }) + } + @Test fun `ambiguous order detail entries stop without navigating`() { val driver = LiveDriver(orderDetailEntryAfterSubmit = true, duplicateOrderDetailEntry = true) @@ -442,6 +458,9 @@ class PurchaseLiveAutomationTest { )) "order" -> snapshot(listOf(node("status", "待付款"), node("order", "订单号:PDD-202608210001"), node("time", "下单时间:2026-08-21 10:30:00"), node("pay", "立即支付", clickable = true))) "order-folded" -> snapshot(listOf(node("status", "待付款"), node("pay", "立即支付", clickable = true))) + "order-folded-payment-activity" -> UiSnapshot(PDD, "com.xunmeng.pinduoduo.app_pay.core.PayActivity", listOf( + node("status", "待付款"), node("pay", "立即支付", clickable = true), + )) "order-no-time" -> snapshot(listOf(node("status", "待付款"), node("order", "订单号:PDD-202608210001"), node("pay", "去支付", clickable = true))) "success" -> snapshot(buildList { add(node("success-title", "购买成功")) @@ -527,7 +546,7 @@ class PurchaseLiveAutomationTest { } override fun swipePurchase(direction: SwipeDirection, durationMs: Long): Boolean { genericSwipes++ - if (page == "order-folded" && direction == SwipeDirection.UP) page = "order" + if (page in setOf("order-folded", "order-folded-payment-activity") && direction == SwipeDirection.UP) page = "order" return true } override fun swipePurchaseIn(target: SnapshotNode, direction: SwipeDirection, durationMs: Long): Boolean {