From b06b622eb39a67c20d4bdc608aa4aa43234f460f Mon Sep 17 00:00:00 2001 From: yml2213 Date: Mon, 9 Nov 2026 21:25:53 +0800 Subject: [PATCH] =?UTF-8?q?fix(huya):=20=E4=BF=AE=E5=A4=8D=E7=B2=BE?= =?UTF-8?q?=E8=8B=B1=E5=AE=9D=E5=85=B8=E7=BB=91=E5=AE=9A=E5=90=8E=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E8=AF=86=E5=88=AB=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_huya_elite_query.py | 59 ++++++++++++++++++++++-- web/backend/services/huya_runner_bind.py | 19 ++++---- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/tests/test_huya_elite_query.py b/tests/test_huya_elite_query.py index d02ccfa..f18af34 100644 --- a/tests/test_huya_elite_query.py +++ b/tests/test_huya_elite_query.py @@ -135,12 +135,20 @@ class _FakeGameRole: class _FakeBindAccountData: - def __init__(self, nick: str, role_name: str): + def __init__( + self, + nick: str, + role_name: str, + *, + is_bind_account: int = 1, + is_bind_role: int = 1, + is_need_act_check: int = 0, + ): self.gameAccount = _FakeGameAccount(nick) self.gameRole = _FakeGameRole(role_name, "苹果(iOS)", "手Q") - self.isBindAcount = 1 - self.isBindRole = 1 - self.isNeedActCheck = 0 + self.isBindAcount = is_bind_account + self.isBindRole = is_bind_role + self.isNeedActCheck = is_need_act_check self.changBindTime = 0 @@ -152,13 +160,22 @@ class _FakeBindResponse: msg: str = "", nick: str = "微信用户", role_name: str = "吃鸡199706", + is_bind_account: int = 1, + is_bind_role: int = 1, + is_need_act_check: int = 0, ): self.status = status self.msg = msg self.gameName = "和平精英" self.gameAuthScene = "" self.changeBindDay = 7 - self.accountData = _FakeBindAccountData(nick, role_name) + self.accountData = _FakeBindAccountData( + nick, + role_name, + is_bind_account=is_bind_account, + is_bind_role=is_bind_role, + is_need_act_check=is_need_act_check, + ) def to_dict(self) -> dict: return { @@ -976,6 +993,38 @@ def test_bind_protocol_prefers_configured_gid_and_keeps_legacy_fallback(): } +def test_inner_bind_probe_keeps_gid_and_empties_outer_act_id(monkeypatch): + """官方页面第二路查询必须是 gid=3203 + outerActId='',才能取到角色名。""" + calls: list[dict] = [] + responses = [ + _FakeBindResponse(role_name="", is_bind_role=0, is_need_act_check=1), + _FakeBindResponse(role_name="和平精英角色", is_bind_role=1), + ] + client = _CkProbeClient(None) + + def fake_check(**kwargs): + calls.append(kwargs) + return responses[len(calls) - 1] + + monkeypatch.setattr(client, "check_user_bind_game_account", fake_check) + runner, _marks = _task_runner(monkeypatch, "query_game_name") + status, _query = runner._resolve_bind_status( + client, + UID, + COOKIE, + b_act_id_int=0, + outer_act_id="17096", + gid=3203, + is_use_outer_act_id=0, + scene="undefined", + ) + assert status.accountData.gameRole.roleName == "和平精英角色" + assert calls[0]["outer_act_id"] == "17096" + assert calls[0]["gid"] == 3203 + assert calls[1]["outer_act_id"] == "" + assert calls[1]["gid"] == 3203 + + def test_confirm_bind_uses_latest_har_protocol(monkeypatch): """确认绑定复用抓包里的 gid=3203 / bActId=0 / outerActId=17096。""" client = _BindConfirmClient() diff --git a/web/backend/services/huya_runner_bind.py b/web/backend/services/huya_runner_bind.py index cf9fad2..c27f756 100644 --- a/web/backend/services/huya_runner_bind.py +++ b/web/backend/services/huya_runner_bind.py @@ -174,16 +174,12 @@ class BindMixin: chosen_status = outer_status account_data = outer_status.accountData - # 最新抓包协议只用外层查询(gid + outerActId)。旧的内层兜底会带上 - # gid=0/outerActId=空,被服务端判 501「参数错误」,仅在旧协议下保留。 - should_check_inner = ( - not gid - and not self._has_bind_role(outer_status) - and bool( - account_data.isNeedActCheck - or not account_data.isBindAcount - or not account_data.isBindRole - ) + # 官方页面会同时查两路:gid + outerActId,以及 gid + outerActId=空。 + # 角色名通常由第二路返回;第二路必须保留 gid,不能传成 gid=0。 + should_check_inner = not self._has_bind_role(outer_status) and bool( + account_data.isNeedActCheck + or not account_data.isBindAcount + or not account_data.isBindRole ) if should_check_inner: inner_status = client.check_user_bind_game_account( @@ -191,6 +187,9 @@ class BindMixin: cookie=cookie, b_act_id=b_act_id_int, is_use_outer_act_id=0, + gid=gid, + outer_act_id="", + scene=scene, ) if inner_status is not None: query_result["inner_bind_status"] = inner_status.to_dict()