Files
live-hub-py/docs/HUYA_精英宝典-9.1-全流程分析.md
T

7.0 KiB
Raw Blame History

虎牙精英宝典 9.1 全流程分析(Python / 脱敏)

branch/field: HUYA_ELITE_FULL_FLOW_9_1

1. 样本与完整性

  • 主样本:/Users/yml/Desktop/抓包/hy/9.1/9.1
  • SHA-256807fb951f9daa21e77f33618f1409a99b9b44da829966f328ec8b0614f599d55
  • 格式:Charles 会话 ZIP 归档,不是普通 HAR。
  • 归档成员 2327*-meta.json 1472;请求体 552;响应体 303。
  • 状态:COMPLETE 1443EXCEPTION 16RECEIVING_REQUEST_BODY 12RECEIVING_RESPONSE_BODY 1。
  • 结论:该包覆盖扫码登录后的 Web 会话、宝典初始化、游戏账号绑定、积分兑换、商城下单、支付宝二维码和支付后订单状态;比旧的 Reqable/Charles 样本完整。

9.1_all 适合静态资源检索,但没有统一 flow、headers、状态和时序索引。协议重建以 ZIP 为主,静态页面以 1197-res.html 等正文为辅。

2. 业务固定值与动态值

本次页面确认的业务值:sid=2203、宝典 actId=25135、绑定活动 bActId=9271、任务模块 moduleId=20051、外部联运活动 17096、游戏 cjm、组件 gid=3203、宝典商品 spu=hy-5879340、商品 SKU 5370360、供应商 87401

运行时必须重新取得:UID、Cookie、WSS baseinfo、WUP requestId、wsLaunch guid、游戏账号信息、getLiveLinkParamt/code/sig、支付宝 payOrderId/ctoken、订单号和二维码状态。样本中的这些动态值不能硬编码,也不能用旧 Cookie 重放。

3. 登录与宝典初始化

  1. 扫码登录链在登录样本中完成后,POST /web/cookie/verifyentry 859)返回 HTTP 业务成功结构,随后浏览器访问宝典页面(entry 1197HTTP 200)。
  2. 宝典主 WSS 为 d35bf373-ws.va.huya.comentry 828),完成 launch.wsLaunchmobileui.getConfig、心跳/确认和业务 RPC。
  3. 主链首先调用 checkUserBindGameAccountgetActInfogetActUserTaskDetailgetUserScoregetUserPrizeRecordsgetEntityPrizeFieldMapgetModuleAddressgetLiveLinkParam
  4. getActInfo 返回 status 200,活动名“活动+购买任务”,活动时间戳区间、模块 20051、外部活动 17096、游戏 cjm 和组件 3203。

WSS 帧为二进制 WebSocket payload,前 6 字节是 command/sequencebody 是 WUP/TAF。项目已有 WssMessage.decode()_decode_wup_body(),同一连接的 requestId 运行时递增;不要把 frame sequence 或样本 requestId 当业务主键。

4. 积分兑换闭环

4.1 绑定和前置查询

  • 首次绑定响应显示游戏“和平精英”;绑定状态会经历未绑定、已绑定和确认后状态,confirmBindActAccount 返回 status=200,msg=请求成功
  • getLiveLinkParam 返回外部活动 17096gameIdList=cjmlivePlatId=huya 和动态 t/code/sig。签名算法证据不足,客户端只转发实时响应。
  • getActPrizeDetail(sid=2203,pid=12861) 返回奖品“幸运币礼包(小)”,兑换积分 20,库存/时间/限制字段来自服务端。

4.2 写入与回查

请求:webActUI.scoreExchangePrize,字段为 userIdsid=2203pid=12861ipclientEnvsourceisRole=1。本样本的空 ip/source/clientEnv 是一次浏览器操作结果,不应成为固定规则。

响应:status=200,msg=请求成功,返回兑换订单标识和 exchangeInfo(pid=12861,exchangeScore=20,desc=兑换奖品:幸运币礼包(小))。敏感订单标识已省略。

写入后浏览器按顺序回查 getUserScoregetUserPrizeRecordsgetEntityPrizeFieldMapgetModuleAddress。实测积分从可用 300 变为 280,兑换记录新增该奖品、20 分和当日日期;这证明兑换链在该包中闭合。UI 应以回查值为准,并对 isCanExchange、活动时间、库存、今日/用户限制和可用积分做二次校验。

5. 开通宝典与支付闭环

商城 WSS 为 wsapi.huya.com(entry 1431),初始化后业务顺序为:

  1. getGoodsInfoV5(pid=直播间上下文, spuId=hy-5879340, skuId=5370360):商品名“精英宝典”,说明“得300积分丨解锁道具兑换权益”,标价 3000(分);响应关联活动绑定信息和 bActId=9271
  2. getSupplierInfoV5(supplierId=87401):返回“和平精英官方小店”。
  3. listPayChannelV5:可用渠道为 ZfbWeixin
  4. checkHyProtocolV5:协议检查成功,状态 200。
  5. PlayMallUI.getMyPromotioncalcOrderPromotion:本单无返利,订单金额为 3000 分/人民币 30.00 的商城商品金额。
  6. checkUserBuyAuth:状态 200,允许创建订单。
  7. createOrderV5:状态 200,返回商城内部订单标识、支付前订单状态和应付金额;样本值已脱敏。
  8. payOrderSubmitV5(order, channel=Zfb, payType=QrCode):状态 200,返回支付宝网关跳转 URL、支付流水标识和回调地址。URL 中包含 RSA2 签名,客户端应把它当作服务端生成的短期跳转值,不能自行拼接或重签。
  9. orderDetailV5(orderId) 多次轮询:前期订单状态为待支付,支付确认后变为完成状态(状态码 50),支付金额保持 3000;batchQueryBuyAfterConfig 随后返回商城后置配置。
  10. 支付 HTTP 链:支付宝网关 -> unitradeprod.alipay.com/appAssign.htm -> excashier.alipay.com/standard/auth.htm -> queryQRStatus.json。首次查询返回 qrStatus=normal,后续查询返回已登录/已确认状态(qrStatus=2),二维码状态由支付宝控制,不能由客户端伪造。

订单状态 50 是商城订单完成证据;宝典页面的购买任务积分/权益应再调用 getUserScoregetActUserTaskDetail 和相关宝典查询确认,不能仅凭支付宝页面成功推断权益到账。

6. Python 实现建议

仓库现有 core.huya.wss_client.HuyaWssClientcore.huya.http_client.HuyaHttpClientactivity_structs.pyshop_structs.py 已覆盖 WUP/TAF 结构及大部分查询。scripts/huya_elite_client.py 可作为查询入口:

client.snapshot()  # 活动、任务、绑定、奖品、积分、记录
# 用户明确确认后:实时 getActPrizeDetail -> scoreExchangePrize -> 三项回查
# 开通:getGoodsInfoV5 -> checkUserBuyAuth -> createOrderV5
#       -> payOrderSubmitV5 -> orderDetailV5 轮询 -> 宝典权益回查

建议将状态机拆为 login_sessionelite_snapshotexchangepurchase 四步;所有动态字段从前序响应传递,错误时保留服务端 status/msg,不猜测签名算法。写操作默认幂等保护:同一用户、同一 pid 在收到成功响应后不重复提交,只做回查。

7. 证据边界

  • 归档已证明兑换成功和商城订单完成,但没有提供支付宝私钥、服务端签名算法或可脱离当前登录态的重放凭据。
  • getEntityPrizeFieldMap/getModuleAddress 在本次兑换奖品上返回无地址,不代表所有实物奖品都无需地址;实际奖品类型必须按最新响应决定。
  • 订单完成到宝典积分到账可能存在异步延迟,工作台应轮询业务接口而非只看支付状态。