fix: 兼容多微信选择器核单返回 (#261)

This commit is contained in:
chengma
2026-08-18 09:35:54 +08:00
parent 160f5cd183
commit ff925286b9
2 changed files with 170 additions and 2 deletions
@@ -53,6 +53,12 @@ _NON_UNPAID_MARKERS = ("已付款", "交易成功", "交易完成", "已取消",
_SAFE_NAVIGATION_LABELS = ("个人中心", "我的订单", "待付款")
_ORDER_DETAIL_PAY_LABELS = ("去支付",)
_ORDER_DETAIL_CANCEL_LABELS = ("取消订单",)
_ANDROID_CHOOSER_PACKAGE = "android"
_ANDROID_CHOOSER_TITLES = ("选择要使用的应用",)
_ANDROID_CHOOSER_ACTIVITIES = (
"com.android.internal.app.ChooserActivity",
"com.android.internal.app.ResolverActivity",
)
class PddPurchaseReconcileError(RuntimeError):
@@ -138,6 +144,26 @@ def _is_single_order_detail(root: ET.Element) -> bool:
return pay_count == 1 and cancel_count <= 1 and len(order_numbers) <= 1
def _is_android_wechat_chooser(root: ET.Element) -> bool:
"""严格识别覆盖在 PDD 上方的 Android 微信应用选择器。"""
if _foreground_package_from_tree(root) != _ANDROID_CHOOSER_PACKAGE:
return False
labels = tuple(_label(node) for node in root.iter("node"))
has_title = any(label in _ANDROID_CHOOSER_TITLES for label in labels)
has_wechat_candidate = any(
label == "微信" or label.startswith("微信分身") for label in labels
)
return has_title and has_wechat_candidate
def _is_known_android_chooser_activity(activity: str) -> bool:
"""前台 Activity 只接受 Android 标准选择器,避免误退未知系统页。"""
normalized = str(activity or "").strip()
return not normalized or normalized in _ANDROID_CHOOSER_ACTIVITIES
def _parse_bounds(value: str) -> Optional[Bounds]:
match = _BOUNDS_PATTERN.fullmatch(str(value or "").strip())
if match is None:
@@ -465,6 +491,7 @@ class U2PddPurchaseReconcileAdapter(PddPurchaseReconcileAdapter):
checked_foreground = False
started_pdd = False
pressed_back = False
pressed_chooser_back = False
clicked_navigation: set[str] = set()
last_reason = "等待 PDD 待付款页稳定"
while self._monotonic() <= deadline:
@@ -474,6 +501,29 @@ class U2PddPurchaseReconcileAdapter(PddPurchaseReconcileAdapter):
last_reason = "读取手机控件树超时"
break
if not _package_hint_from_tree(root):
if _is_android_wechat_chooser(root):
if pressed_chooser_back:
raise PddPurchaseReconcileError(
"RECONCILE_ANDROID_CHOOSER_STUCK",
"Android 微信应用选择器在一次安全返回后仍未关闭,请人工返回 PDD 核单",
)
current = device.app_current()
chooser_activity = str(current.get("activity") or "")
if not _is_known_android_chooser_activity(
chooser_activity
):
raise PddPurchaseReconcileError(
"RECONCILE_ANDROID_CHOOSER_UNRECOGNIZED",
"检测到疑似微信应用选择页,但前台 Activity 不在安全白名单,请人工处理",
)
if self._monotonic() > deadline:
last_reason = "确认 Android 微信应用选择器超时"
break
device.press("back")
pressed_chooser_back = True
last_reason = "已关闭 Android 微信应用选择器,等待 PDD 待付款详情加载"
self._settle()
continue
if not checked_foreground:
current_package = _foreground_package_from_tree(root)
if not current_package: